Changing the shape of apps. adding better error boundries at stateful components. start fontViewer
This commit is contained in:
parent
d58c39a1ac
commit
cc33b9a015
5 changed files with 197 additions and 117 deletions
55
src/cg/06-fontEditor.cg
Normal file
55
src/cg/06-fontEditor.cg
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
fontEditor = config \
|
||||
defaults = { };
|
||||
c = { ...defaults, ...config };
|
||||
|
||||
size \ ui.stateful {
|
||||
focusable = True,
|
||||
autoFocus = True,
|
||||
|
||||
key = "fontEditor-" & c.path,
|
||||
|
||||
init = existing
|
||||
| Value v \ {
|
||||
map = v.map,
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
}
|
||||
| _ \ {
|
||||
map = [],
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
},
|
||||
|
||||
update = state event \ event
|
||||
| ClickCell { x = x, y = y } \ toggleFocused state.{ selectedRow = y, selectedCol = x }
|
||||
| Key { key = " " } \ toggleFocused state
|
||||
| Key { key = "Enter" } \ toggleFocused state
|
||||
|
||||
| Key { key = "ArrowDown" } \ downArrow state
|
||||
| Key { key = "j" } \ downArrow state
|
||||
| Key { key = "ArrowUp" } \ upArrow state
|
||||
| Key { key = "k" } \ upArrow state
|
||||
| Key { key = "ArrowLeft" } \ leftArrow state
|
||||
| Key { key = "h" } \ leftArrow state
|
||||
| Key { key = "ArrowRight" } \ rightArrow state
|
||||
| Key { key = "l" } \ rightArrow state
|
||||
|
||||
| UpdateWidth w \ (
|
||||
newState = state.{ pixelWidth = (int w) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
|
||||
| UpdateHeight h \ (
|
||||
newState = state.{ pixelHeight = (int h) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
|
||||
| _ \ { state = state, emit = [] },
|
||||
|
||||
view = state emit \
|
||||
ui.text { content = "testing" }
|
||||
};
|
||||
|
|
@ -1,15 +1,19 @@
|
|||
inspector = config \ size \
|
||||
val = eval! config.name;
|
||||
inspector = config \
|
||||
{
|
||||
width = 600,
|
||||
view = size \
|
||||
val = eval! config.name;
|
||||
|
||||
reflected = val
|
||||
| Value v \ reflect v
|
||||
| _ \ reflect 0;
|
||||
reflected = val
|
||||
| Value v \ reflect v
|
||||
| _ \ reflect 0;
|
||||
|
||||
textInputHeight = 40;
|
||||
textInputHeight = 40;
|
||||
|
||||
tree {
|
||||
value = reflected,
|
||||
path = config.name,
|
||||
w = size.w,
|
||||
h = size.h - textInputHeight
|
||||
};
|
||||
tree {
|
||||
value = reflected,
|
||||
path = config.name,
|
||||
w = size.w,
|
||||
h = size.h - textInputHeight
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,113 +35,120 @@ pixelEditor = config \
|
|||
newState = state.{ map = newMap };
|
||||
{ state = newState, emit = saveGlyph newState });
|
||||
|
||||
_ = debug! "c.path" c.path;
|
||||
existing = eval! (c.path);
|
||||
_ = debug! "existing" existing;
|
||||
|
||||
size \ ui.stateful {
|
||||
focusable = True,
|
||||
autoFocus = True,
|
||||
# return App
|
||||
{
|
||||
width = 600,
|
||||
|
||||
key = "pixelEditor-" & c.path,
|
||||
view = size \ ui.stateful {
|
||||
focusable = True,
|
||||
autoFocus = True,
|
||||
|
||||
init = existing
|
||||
| Value v \ {
|
||||
map = v.map,
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
}
|
||||
| _ \ {
|
||||
map = [],
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
},
|
||||
key = "pixelEditor-" & c.path,
|
||||
|
||||
update = state event \ event
|
||||
| ClickCell { x = x, y = y } \ toggleFocused state.{ selectedRow = y, selectedCol = x }
|
||||
| Key { key = " " } \ toggleFocused state
|
||||
| Key { key = "Enter" } \ toggleFocused state
|
||||
init = existing
|
||||
| Value v \ {
|
||||
map = v.map,
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
}
|
||||
| _ \ {
|
||||
map = [],
|
||||
pixelWidth = 5,
|
||||
pixelHeight = 7,
|
||||
cellSize = 30,
|
||||
selectedRow = 0,
|
||||
selectedCol = 0
|
||||
},
|
||||
|
||||
| Key { key = "ArrowDown" } \ downArrow state
|
||||
| Key { key = "j" } \ downArrow state
|
||||
| Key { key = "ArrowUp" } \ upArrow state
|
||||
| Key { key = "k" } \ upArrow state
|
||||
| Key { key = "ArrowLeft" } \ leftArrow state
|
||||
| Key { key = "h" } \ leftArrow state
|
||||
| Key { key = "ArrowRight" } \ rightArrow state
|
||||
| Key { key = "l" } \ rightArrow state
|
||||
update = state event \ event
|
||||
| ClickCell { x = x, y = y } \ toggleFocused state.{ selectedRow = y, selectedCol = x }
|
||||
| Key { key = " " } \ toggleFocused state
|
||||
| Key { key = "Enter" } \ toggleFocused state
|
||||
|
||||
| UpdateWidth w \ (
|
||||
newState = state.{ pixelWidth = (int w) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
| Key { key = "ArrowDown" } \ downArrow state
|
||||
| Key { key = "j" } \ downArrow state
|
||||
| Key { key = "ArrowUp" } \ upArrow state
|
||||
| Key { key = "k" } \ upArrow state
|
||||
| Key { key = "ArrowLeft" } \ leftArrow state
|
||||
| Key { key = "h" } \ leftArrow state
|
||||
| Key { key = "ArrowRight" } \ rightArrow state
|
||||
| Key { key = "l" } \ rightArrow state
|
||||
|
||||
| UpdateHeight h \ (
|
||||
newState = state.{ pixelHeight = (int h) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
| UpdateWidth w \ (
|
||||
newState = state.{ pixelWidth = (int w) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
|
||||
| _ \ { state = state, emit = [] },
|
||||
| UpdateHeight h \ (
|
||||
newState = state.{ pixelHeight = (int h) };
|
||||
{ state = newState, emit = saveGlyph newState })
|
||||
|
||||
view = state emit \
|
||||
| _ \ { state = state, emit = [] },
|
||||
|
||||
grid = ui.column {
|
||||
children = map (rIdx \
|
||||
ui.row {
|
||||
children = map (cIdx \
|
||||
on = contains { x = cIdx, y = rIdx } state.map;
|
||||
color = (on |True\ "#000" |False\ "rgba(255,255,255,0.2)");
|
||||
view = state emit \
|
||||
|
||||
selected = and (rIdx == state.selectedRow) (cIdx == state.selectedCol);
|
||||
strokeColor = (selected | True \ "#f00" | False \ "rgba(0,0,0,0.2)");
|
||||
grid = ui.column {
|
||||
children = map (rIdx \
|
||||
ui.row {
|
||||
children = map (cIdx \
|
||||
on = contains { x = cIdx, y = rIdx } state.map;
|
||||
color = (on |True\ "#000" |False\ "rgba(255,255,255,0.2)");
|
||||
|
||||
ui.clickable {
|
||||
onClick = \ emit (ClickCell { x = cIdx, y = rIdx }),
|
||||
child = ui.rect { w = state.cellSize, h = state.cellSize, color = color, strokeWidth = 1, strokeColor = strokeColor }
|
||||
}
|
||||
) (range 0 state.pixelWidth)
|
||||
}
|
||||
) (range 0 state.pixelHeight)
|
||||
};
|
||||
selected = and (rIdx == state.selectedRow) (cIdx == state.selectedCol);
|
||||
strokeColor = (selected | True \ "#f00" | False \ "rgba(0,0,0,0.2)");
|
||||
|
||||
headerHeight = 30;
|
||||
ui.clickable {
|
||||
onClick = \ emit (ClickCell { x = cIdx, y = rIdx }),
|
||||
child = ui.rect { w = state.cellSize, h = state.cellSize, color = color, strokeWidth = 1, strokeColor = strokeColor }
|
||||
}
|
||||
) (range 0 state.pixelWidth)
|
||||
}
|
||||
) (range 0 state.pixelHeight)
|
||||
};
|
||||
|
||||
header = ui.row {
|
||||
gap = 10,
|
||||
headerHeight = 30;
|
||||
|
||||
children = [
|
||||
ui.positioned { x = 0, y = 8, child = ui.text { content = c.path, color = "#fff" } },
|
||||
header = ui.row {
|
||||
gap = 10,
|
||||
|
||||
textInput {
|
||||
key = "width-input",
|
||||
w = 40,
|
||||
h = headerHeight,
|
||||
color = "#fff",
|
||||
backgroundColor = "rgba(0,0,0,0.2)",
|
||||
onSubmit = v \ emit (UpdateWidth v),
|
||||
initialValue = (show state.pixelWidth)
|
||||
},
|
||||
children = [
|
||||
ui.positioned { x = 0, y = 8, child = ui.text { content = c.path, color = "#fff" } },
|
||||
|
||||
ui.positioned { x = 0, y = 8, child = ui.text { content = "x", color = "#aaa" } },
|
||||
textInput {
|
||||
key = "width-input",
|
||||
w = 40,
|
||||
h = headerHeight,
|
||||
color = "#fff",
|
||||
backgroundColor = "rgba(0,0,0,0.2)",
|
||||
onSubmit = v \ emit (UpdateWidth v),
|
||||
initialValue = (show state.pixelWidth)
|
||||
},
|
||||
|
||||
textInput {
|
||||
key = "height-input",
|
||||
w = 40,
|
||||
h = headerHeight,
|
||||
color = "#fff",
|
||||
backgroundColor = "rgba(0,0,0,0.2)",
|
||||
onSubmit = v \ emit (UpdateHeight v),
|
||||
initialValue = (show state.pixelHeight)
|
||||
}
|
||||
]
|
||||
};
|
||||
ui.positioned { x = 0, y = 8, child = ui.text { content = "x", color = "#aaa" } },
|
||||
|
||||
ui.column {
|
||||
children = [
|
||||
header,
|
||||
center size.w size.h grid
|
||||
]
|
||||
}
|
||||
textInput {
|
||||
key = "height-input",
|
||||
w = 40,
|
||||
h = headerHeight,
|
||||
color = "#fff",
|
||||
backgroundColor = "rgba(0,0,0,0.2)",
|
||||
onSubmit = v \ emit (UpdateHeight v),
|
||||
initialValue = (show state.pixelHeight)
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
ui.column {
|
||||
children = [
|
||||
header,
|
||||
center size.w size.h grid
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ os =
|
|||
osState.wm.scrollOffset := scrollToWindow index
|
||||
];
|
||||
|
||||
openWindow = title content \
|
||||
openWindow = title content width \
|
||||
id = osState.nextId;
|
||||
batch [
|
||||
osState.nextId := id + 1,
|
||||
|
|
@ -45,7 +45,7 @@ os =
|
|||
id = id,
|
||||
title = title,
|
||||
content = content,
|
||||
width = osState.wm.defaultWindowWidth,
|
||||
width = width,
|
||||
fullWidth = False
|
||||
}],
|
||||
osState.palette.visible := False,
|
||||
|
|
@ -171,24 +171,28 @@ os =
|
|||
|
||||
isUI = v \ hasField "kind" v;
|
||||
|
||||
openOrFocus = title content \
|
||||
openOrFocus = title content width \
|
||||
index title (map (w \ w.title) osState.windows)
|
||||
| Some i \ focusWindow i
|
||||
| None \ openWindow title content;
|
||||
| None \ openWindow title content width;
|
||||
|
||||
onSelect = input \
|
||||
result = eval! input;
|
||||
result
|
||||
| Defined name \ openOrFocus name (inspector { name = name })
|
||||
dw = osState.wm.defaultWindowWidth;
|
||||
appWidth = app \ hasField "width" app | True \ app.width | false \ dw;
|
||||
eval! input
|
||||
| Defined name \ (
|
||||
app = inspector { name = name };
|
||||
openOrFocus name app.view (appWidth app))
|
||||
|
||||
| Value v \ (isFunction v
|
||||
| True \ openOrFocus input v
|
||||
| False \ (isUI v
|
||||
| True \ openOrFocus input (size \ v)
|
||||
| False \ (getSource input == ""
|
||||
| True \ openOrFocus input (_ \ ui.text { content = show v, color = "white" })
|
||||
| False \ openOrFocus input (inspector { name = input }))))
|
||||
| Err msg \ (_ = debug! "Error" msg; noOp);
|
||||
| Value v \ (hasField "view" v
|
||||
| True \ openOrFocus input v.view (appWidth v)
|
||||
| False \ (getSource input == ""
|
||||
| True \ openOrFocus input (_ \ ui.text { content = show v, color = "white" }) dw
|
||||
| False \ (
|
||||
app = inspector { name = input };
|
||||
openOrFocus input app.view (appWidth app))))
|
||||
|
||||
| Err msg \ (_ = debug! "OS Error" msg; noOp);
|
||||
|
||||
handleFocusLeftEvent = state \
|
||||
newIndex = max 0 (osState.wm.focusedIndex - 1);
|
||||
|
|
|
|||
|
|
@ -97,7 +97,17 @@ export function runAppCompiled(canvas: HTMLCanvasElement, store: any) {
|
|||
}
|
||||
|
||||
const emit = (event: any) => ({ _tag: 'ComponentEvent', _0: fullKey, _1: event });
|
||||
const viewResult = instance.view(instance.state)(emit);
|
||||
let viewResult;
|
||||
try {
|
||||
viewResult = instance.view(instance.state)(emit);
|
||||
} catch (e: any) {
|
||||
viewResult = {
|
||||
kind: 'stack', children: [
|
||||
{ kind: 'rect', w: 9999, h: 60, color: '#400' },
|
||||
{ kind: 'text', content: `Error: ${e.message}`, x: 10, y: 30, color: '#f88' }
|
||||
]
|
||||
};
|
||||
}
|
||||
|
||||
const viewUI = {
|
||||
kind: 'clickable',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue