Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/Action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import * as Hover from "./Hover";
import * as Settings from "./Settings";
import * as Transform from "./Transform";
import * as Pat from "./syntax/Pat";
import * as Projector from "./Projector";
import * as ID from "./syntax/ID";

export type Inject = (_: Action) => void;

Expand All @@ -16,8 +18,8 @@ export type Action =
| { t: "setSelect"; path: Path.t }
| { t: "moveStage"; direction: Direction }
| { t: "moveTool"; direction: Direction }
| { t: "wheelTools"; offset: number}
| { t: "wheelNumTools"; offset: number}
| { t: "wheelTools"; offset: number }
| { t: "wheelNumTools"; offset: number }
| { t: "unsetSelections" }
| {
t: "transformNode";
Expand All @@ -35,6 +37,7 @@ export type Action =
| { t: "applyTransform"; idx: number; direction: "forward" | "reverse" }
| { t: "applyTransformSelected" }
| { t: "flipTransform"; idx: number }
| { t: "Noop" };
| { t: "Noop" }
| { t: "Project"; id: ID.t | undefined; action: Projector.Action };

export type t = Action;
5 changes: 2 additions & 3 deletions src/Animate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ const blah = (s: string) => `
export const init = ():void => {
//TODO: unhardcode id max
var style = document.createElement("style");
for (let id = 0; id < 100; id++) {
for (let id = 0; id < 200; id++) {
style.innerHTML += `#node-${id}.animate { view-transition-name: flip-node-${id}; }\n`;
style.innerHTML += `#main.unsetSelections #sym-${id}, #main.setSelect #sym-${id}, #main.moveStage #sym-${id} { view-transition-name: flip-sym-${id}; }\n`;

style.innerHTML += `#main.unsetSelections #sym-${id} , #main.setSelect #sym-${id}, #main.moveStage #sym-${id} { view-transition-name: flip-sym-${id}; }\n`;
//style.innerHTML += `#main.setSelect #pat-${id} { view-transition-name: flip-pat-${id}; }`;
//style.innerHTML += blah(`flip-node-${id}`);
//style.innerHTML += blah(`flip-pat-${id}`);
Expand Down
23 changes: 2 additions & 21 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,44 +8,25 @@ import { SettingsView } from "./view/SettingsView";
import { Seed } from "./view/SeedView";
import * as ExpToPat from "./syntax/ExpToPat";
import * as Animate from "./Animate";
//import { Toolbar } from "./view/ToolsView";
import * as Tone from "tone";

export type SetModel = SetStoreFunction<Model.t>;


const App: Component = () => {
const [model, setModel] = createStore({ ...Model.init });
Animate.init();
const inject = (a: Action.t) => {
console.log(a);
if (a.t === "setHover" || !document.startViewTransition) {
console.log("sethover dont transition:" + a.t);
go(model, setModel, a);
return;
}
const guy2 = document.getElementById("main");
guy2 ? guy2.classList.add(a.t) : console.log("no guy r add");
let v = document.startViewTransition(() => go(model, setModel, a));
v.finished.then(() =>
guy2 ? guy2.classList.remove(a.t) : console.log("no guy 2 rm")
);
go(model, setModel, a);
};
document.addEventListener("keydown", Keyboard.keydown(inject), false);
document.addEventListener("keyup", Keyboard.keyup(inject), false);
// document.addEventListener("transitionstart", (e) => {
// in_transition = true;
// });
// document.addEventListener("transitionend", (e) => {
// in_transition = false;
// });
return (
<div
id="main"
class={model.settings.theme}
classList={{ selected: model.stage.selection === "unselected" }}
>
{/* <div class="logo" /> */}
{/* Toolbar({ model, inject }) */}
{Seed({ model, inject })}
{SettingsView({ model, inject })}
</div>
Expand Down
2 changes: 2 additions & 0 deletions src/Keyboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ const action_of = (key: string): Action.t | "NoBinding" => {
return { t: "moveTool", direction: "right" };
case " ":
return { t: "applyTransformSelected" };
case "f":
return { t: "Project", action: "toggleEnfoldCurrent", id: undefined };
default:
return "NoBinding";
}
Expand Down
131 changes: 127 additions & 4 deletions src/Projector.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,141 @@
import * as ID from "./syntax/ID";
import * as Exp from "./syntax/Exp";

type PaintColor = "Cyan" | "Magenta" | "Yellow";
//type PaintColor = "Cyan" | "Magenta" | "Yellow";
//type Painter = PaintColor | "Unpainted";

type Painter = PaintColor | "Unpainted";
type Folded = "Folded" | "Enfolded" | "NotFolded";

type Projector = {
painter: Painter;
//painter: Painter;
folded: Folded;
};

type t = Projector;

export const basic: Projector = { folded: "NotFolded" };

export type PMap = Map<ID.t, t>;

export const init: PMap = new Map<ID.t, t>();
export const init: PMap = (() => {
const map = new Map<ID.t, t>();
map.set(77, { folded: "Folded" });
map.set(79, { folded: "Folded" });
map.set(81, { folded: "Folded" });
map.set(20, { folded: "Enfolded" });
map.set(82, { folded: "Folded" });
return map;
})();

export type Action = "toggleFoldCurrent" | "toggleEnfoldCurrent";

export const get = (projectors: PMap, id: ID.t): t => {
const res = projectors.get(id);
return res == undefined ? basic : res;
};

export const update = (id: ID.t, action: Action, projectors: PMap): PMap => {
const map: PMap = new Map(projectors);
const current = get(map, id);
switch (action) {
case "toggleFoldCurrent":
if (current === undefined) {
map.set(id, { folded: "Folded" });
} else {
map.set(id, {
...current,
folded: current.folded === "Folded" ? "NotFolded" : "Folded",
});
}
return map;
case "toggleEnfoldCurrent":
if (current === undefined) {
console.log("Projector.update: id not found, adding new entry:" + id);
map.set(id, { folded: "Enfolded" });
} else {
console.log("Projector.update: id found, changing folding state:" + id);
map.set(id, {
...current,
folded: current.folded === "Enfolded" ? "NotFolded" : "Enfolded",
});
}
return map;
}
};

export const is_folded = (id: ID.t, projectors: PMap): boolean =>
get(projectors, id).folded === "Folded";

export const is_enfolded = (id: ID.t, projectors: PMap): boolean =>
get(projectors, id).folded === "Enfolded";

const get_enfolded = (projectors: PMap, node: Exp.t): Exp.t[] => {
let p = get(projectors, node.id);
if (p.folded == "Enfolded") {
return [node];
} else {
switch (node.t) {
case "Atom":
return [];
case "Comp":
if (p.folded == "Folded") {
return [];
} else {
return node.kids
.map((kid) =>
get_enfolded(projectors, project_folds(projectors, kid))
)
.flat();
}
}
}
};

export const has_enfolded = (projectors: PMap, node: Exp.t): boolean =>
get_enfolded(projectors, node).length > 0;

let get_id = (node: Exp.t) => {
const res = Exp.head_id(node);
return res == undefined ? -1 : res;
};

let summary_head = (node: Exp.t): Exp.t => ({
t: "Atom",
id: get_id(node),
sym: Exp.head(node),
});

let blank_head = (node: Exp.t): Exp.t => ({
t: "Atom",
id: get_id(node),
sym: "",
});

/* TODO: maybe dont allow enfolds inside enfolds */
export const project_folds = (projectors: PMap, node: Exp.t): Exp.t => {
switch (node.t) {
case "Atom":
return node;
case "Comp":
switch (get(projectors, node.id).folded) {
case "Folded":
const enfolded = node.kids
.map((kid) => get_enfolded(projectors, kid))
.flat();
const head =
enfolded.length == 0 ? [summary_head(node)] : [blank_head(node)];
return {
...node,
kids: head.concat(enfolded),
};
default:
return {
...node,
kids: node.kids.map((kid) => project_folds(projectors, kid)),
};
}
}
};

/*
paint plan:
Expand Down
26 changes: 18 additions & 8 deletions src/Stage.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
import { Exp } from "./syntax/Exp";
import * as Exp from "./syntax/Exp";
import * as Statics from "./Statics";
import * as Path from "./syntax/Path";
import * as Projector from "./Projector";
import * as World from "./data/World";
import { is_path_valid } from "./syntax/Node";
import { is_path_valid, id_at } from "./syntax/Node";
import * as ID from "./syntax/ID";

export type selection = "unselected" | Path.t;

export type Stage = {
exp: Exp;
exp: Exp.t;
selection: selection;
info: Statics.InfoMap; //derived from exp
projectors: Projector.PMap; //annotations
};

export type t = Stage;

const exp: Exp = World.init;
const exp: Exp.t = World.init;

export const init: Stage = {
exp,
Expand Down Expand Up @@ -44,7 +45,7 @@ const rev = (path: Path.t): Path.t => {
return blah.reverse();
};

const move_up = (exp: Exp, selection: number[]): Path.t => {
const move_up = (exp: Exp.t, selection: number[]): Path.t => {
if (selection.length === 0) return selection;
const [last, ...tl] = rev(selection);
const new_path = rev([last - 1, ...tl]);
Expand All @@ -54,7 +55,7 @@ const move_up = (exp: Exp, selection: number[]): Path.t => {
} else return selection;
};

const move_down = (exp: Exp, selection: number[]): Path.t => {
const move_down = (exp: Exp.t, selection: number[]): Path.t => {
/* first, try to increment last idx of selection.
if that gives a valid path, return it.
then try to increment second last index, etc.
Expand All @@ -75,15 +76,15 @@ const move_down = (exp: Exp, selection: number[]): Path.t => {
return move_down(exp, Array(selection.length).fill(0));
};

const move_left = (_exp: Exp, selection: number[]): Path.t => {
const move_left = (_exp: Exp.t, selection: number[]): Path.t => {
if (selection.length === 0) {
return selection;
} else {
return selection.slice(0, selection.length - 1);
}
};

const move_right = (exp: Exp, selection: number[]): Path.t => {
const move_right = (exp: Exp.t, selection: number[]): Path.t => {
const new_selection = [...selection, 1];
if (is_path_valid(new_selection, exp)) {
return new_selection;
Expand Down Expand Up @@ -114,3 +115,12 @@ export const move = (
stage: Stage,
direction: "up" | "down" | "left" | "right"
) => put_selection(stage, move_(stage, direction));

export const indicated_id = (stage: Stage): ID.t | undefined =>
stage.selection === "unselected"
? undefined
: id_at(stage.selection, stage.exp);

export const projected_width = (stage: t) =>{
console.log("width: " +Exp.width(Projector.project_folds(stage.projectors, stage.exp)))
return Exp.width(Projector.project_folds(stage.projectors, stage.exp));}
Loading