Adding ability for stateful views to 'emit' events to their update functions. enhancing state tree viewer

master
Dustin Swan 2 weeks ago
parent 69407cd25b
commit 6f217a0923
Signed by: dustinswan
GPG Key ID: 30D46587E2100467

@ -210,7 +210,7 @@ textInput = config \
# | Key { key = k } \ { state = state, emit = [\ c.onKeyDown k ] } # | Key { key = k } \ { state = state, emit = [\ c.onKeyDown k ] }
| _ \ { state = state, emit = [] }, | _ \ { state = state, emit = [] },
view = state \ view = state emit \
textBeforeCursor = slice state.text 0 state.cursorPos; textBeforeCursor = slice state.text 0 state.cursorPos;
cursorX = ui.measureText textBeforeCursor; cursorX = ui.measureText textBeforeCursor;
padding = 8; padding = 8;

@ -99,7 +99,7 @@ palette = config \
| _ \ { state = state, emit = [] }) | _ \ { state = state, emit = [] })
| _ \ { state = state, emit = [] }, | _ \ { state = state, emit = [] },
view = state \ view = state emit \
ui.positioned { ui.positioned {
x = (config.viewport.width - windowWidth) / 2, x = (config.viewport.width - windowWidth) / 2,
y = (config.viewport.height - windowHeight) / 2, y = (config.viewport.height - windowHeight) / 2,

@ -1,11 +1,4 @@
inspector = config \ inspector = config \
windowHeight = 400;
windowWidth = 600;
source = getSource config.name;
sourceLines = split "\n" source;
lineHeight = 20;
val = eval config.name; val = eval config.name;
_ = debug "val" val; _ = debug "val" val;
@ -13,36 +6,17 @@ inspector = config \
| Value v \ reflect v | Value v \ reflect v
| _ \ reflect 0; | _ \ reflect 0;
_ = debug "reflected" reflected;
dialogPadding = 0;
textInputHeight = 40; textInputHeight = 40;
contentWidth = windowWidth - (dialogPadding * 2);
contentHeight = windowHeight - (dialogPadding * 2);
ui.column { ui.column {
gap = 0, gap = 0,
children = [ children = [
# display source # tree
scrollable { tree {
value = reflected,
path = config.name,
w = config.w, w = config.w,
h = config.h - textInputHeight, h = config.h - textInputHeight
totalWidth = config.w,
# totalHeight = (len sourceLines) * lineHeight,
totalHeight = 1000,
onScroll = _ \ noOp,
child = tree { value = reflected, depth = 0, path = config.name },
# child = ui.column {
# gap = 0,
# children = map (line \
# ui.positioned {
# x = 8,
# y = 2,
# child = ui.text { content = line, color = "#ccc" }
# }
# ) sourceLines
# }
}, },
# definition bar # definition bar

@ -1,4 +1,32 @@
tree = config \ treeNodeHeight = value path expanded \
lineH = 20;
valueLabel = v \ v
| NumberValue n \ Some n
| StringValue n \ Some n
| ConstructorValue { tag = tag } \ Some tag
| FunctionValue _ \ Some "<fn>"
| _ \ None;
value
| RecordValue entries \
(contains path expanded)
| True \ lineH + (sum (map (entry \
(valueLabel entry.value)
| Some _ \ lineH
| None \ lineH + (treeNodeHeight entry.value (path & "." & entry.key) expanded)
) entries))
| False \ lineH
| ListValue items \
(contains path expanded)
| True \ lineH + (sum (mapWithIndex (item i \
(valueLabel item)
| Some _ \ lineH
| None \ lineH + (treeNodeHeight item (path & "." & (show i)) expanded)
) items))
| False \ lineH
| _ \ lineH;
treeNode = config \
depth = config.depth; depth = config.depth;
indent = depth * 20; indent = depth * 20;
@ -14,51 +42,76 @@ tree = config \
| FunctionValue _ \ Some "<fn>" | FunctionValue _ \ Some "<fn>"
| _ \ None; | _ \ None;
header = isExp label color \
ui.clickable {
onClick = _ \ config.onToggle config.path,
child = simple ((isExp | True \ "▼ " | False \ "▶ ") & label) color
};
isExp = contains config.path config.expanded;
config.value config.value
| NumberValue n \ simple (show n) "#6cf" | NumberValue n \ simple (show n) "#6cf"
| StringValue n \ simple ("\"" & n & "\"") "#f6a" | StringValue n \ simple ("\"" & n & "\"") "#f6a"
| ConstructorValue { tag = tag } \ simple tag "#fc6" | ConstructorValue { tag = tag } \ simple tag "#fc6"
| FunctionValue _ \ simple "<fn>" "#888" | FunctionValue _ \ simple "<fn>" "#888"
| RecordValue entries \ | RecordValue entries \
ui.stateful { ui.column { gap = 0, children = [
key = "tree-" & config.path, header isExp ((show (len entries)) & " fields") "#888",
init = { collapsed = True }, ...(isExp
| True \ [ui.clickable {
update = state event \ event onClick = _ \ noOp,
| Clicked _ \ ( child = ui.column { gap = 0, children = map (entry \
_ = debug "clicked on node" [];
{ state = state.{ collapsed = (not state.collapsed) }, emit = [] }
)
| _ \ { state = state, emit = [] },
view = state \
ui.column {
gap = 0,
children = [
simple ((state.collapsed | True \ "▶ " | False \ "▼ ") & (show (len entries)) & " fields") "#888",
...(state.collapsed
| True \ []
| False \ map (entry \
(valueLabel entry.value) (valueLabel entry.value)
| Some label \ simple (entry.key & " = " & label) "#aaa" | Some label \ simple (entry.key & " = " & label) "#aaa"
| None \ ui.column { gap = 0, children = [ | None \ ui.column { gap = 0, children = [
simple entry.key "#aaa", simple entry.key "#aaa",
tree { value = entry.value, depth = depth + 1, path = config.path & "." & entry.key } treeNode { value = entry.value, depth = depth + 1, path = config.path & "." & entry.key, expanded = config.expanded, onToggle = config.onToggle }
]}
) entries }
}]
| False \ [])
]} ]}
) entries)
]
}
}
| ListValue items \ | ListValue items \
ui.column { ui.column { gap = 0, children = [
gap = 0, header isExp ((show (len items)) & " items") "#888",
children = mapWithIndex (item i \ ...(isExp
| True \ [ui.clickable {
onClick = _ \ noOp,
child = ui.column { gap = 0, children = mapWithIndex (item i \
(valueLabel item) (valueLabel item)
| Some label \ simple ((show i) & ": " & label) "#aaa" | Some label \ simple ((show i) & " : " & label) "#aaa"
| None \ ui.column { gap = 0, children = [ | None \ ui.column { gap = 0, children = [
simple (show i) "#aaa", simple (show i) "#aaa",
tree { value = item, depth = depth + 1 } treeNode { value = item, depth = depth + 1, path = config.path & "." & (show i), expanded = config.expanded, onToggle = config.onToggle }
]}
) items }
}]
| False \ [])
]} ]}
) items
}
| _ \ ui.text { content = "?", color = "#666" }; | _ \ ui.text { content = "?", color = "#666" };
tree = config \
ui.stateful {
key = "tree-" & config.path,
init = { expanded = [] },
update = state event \ event
| Toggle path \ ((contains path state.expanded)
| True \ { state = state.{ expanded = filter (p \ p != path) state.expanded }, emit = [] }
| False \ { state = state.{ expanded = [path, ...state.expanded] }, emit = [] })
| _ \ { state = state, emit = [] },
view = state emit \
onToggle = path \ emit (Toggle path);
totalH = treeNodeHeight config.value config.path state.expanded;
scrollable {
w = config.w,
h = config.h,
totalWidth = config.w,
totalHeight = totalH,
onScroll = _ \ noOp,
child = treeNode { value = config.value, path = config.path, depth = 0, expanded = state.expanded, onToggle = onToggle }
}
};

@ -137,7 +137,7 @@ os =
| Focused \ { state = state, emit = [focusWindow config.index] } | Focused \ { state = state, emit = [focusWindow config.index] }
| ChildFocused \ { state = state, emit = [focusWindow config.index] } | ChildFocused \ { state = state, emit = [focusWindow config.index] }
| _ \ { state = state, emit = [] }, | _ \ { state = state, emit = [] },
view = state \ renderWindow config.window config.isActive view = state emit \ renderWindow config.window config.isActive
}; };
renderWindows = _ \ renderWindows = _ \
@ -203,7 +203,7 @@ os =
{ state = state, emit = [toggleMaximizeFocusedWindow 0] } { state = state, emit = [toggleMaximizeFocusedWindow 0] }
| _ \ { state = state, emit = [] }, | _ \ { state = state, emit = [] },
view = state \ view = state emit \
ui.stack { ui.stack {
children = [ children = [
ui.rect { w = viewport.width, h = viewport.height, color = "#012" }, ui.rect { w = viewport.width, h = viewport.height, color = "#012" },

@ -92,7 +92,9 @@ export function runAppCompiled(canvas: HTMLCanvasElement, store: any) {
setFocus(fullKey); setFocus(fullKey);
} }
const viewResult = instance.view(instance.state); const emit = (event: any) => ({ _tag: 'ComponentEvent', _0: fullKey, _1: event });
const viewResult = instance.view(instance.state)(emit);
const viewUI = { const viewUI = {
kind: 'clickable', kind: 'clickable',
child: viewResult, child: viewResult,
@ -206,6 +208,11 @@ export function runAppCompiled(canvas: HTMLCanvasElement, store: any) {
return; return;
} }
if (event._tag === 'ComponentEvent') {
handleComponentEvent(event._0, event._1);
return;
}
if (event._tag === 'NoOp') if (event._tag === 'NoOp')
return; return;
} }

Loading…
Cancel
Save