diff --git a/scripting/absytree_internal.nim b/scripting/absytree_internal.nim index 485c5bfe..9899e265 100644 --- a/scripting/absytree_internal.nim +++ b/scripting/absytree_internal.nim @@ -634,6 +634,8 @@ proc editor_getActiveEditor2_EditorId_App_impl*(): EditorId = discard proc editor_loadCurrentConfig_void_App_impl*() = discard +proc editor_logRootNode_void_App_impl*() = + discard proc editor_sourceCurrentDocument_void_App_impl*() = discard proc editor_getEditor_EditorId_int_impl*(index: int): EditorId = diff --git a/scripting/absytree_internal_wasm.nim b/scripting/absytree_internal_wasm.nim index 82ff57f6..0b7eea23 100644 --- a/scripting/absytree_internal_wasm.nim +++ b/scripting/absytree_internal_wasm.nim @@ -404,6 +404,7 @@ proc editor_getActivePopup_EditorId_impl(): EditorId {.importc.} proc editor_getActiveEditor_EditorId_impl(): EditorId {.importc.} proc editor_getActiveEditor2_EditorId_App_impl(): EditorId {.importc.} proc editor_loadCurrentConfig_void_App_impl() {.importc.} +proc editor_logRootNode_void_App_impl() {.importc.} proc editor_sourceCurrentDocument_void_App_impl() {.importc.} proc editor_getEditor_EditorId_int_impl(index: int): EditorId {.importc.} proc editor_scriptIsTextEditor_bool_EditorId_impl(editorId: EditorId): bool {.importc.} diff --git a/scripting/editor_api.nim b/scripting/editor_api.nim index 969ca59e..ac9a187f 100644 --- a/scripting/editor_api.nim +++ b/scripting/editor_api.nim @@ -153,6 +153,8 @@ proc loadCurrentConfig*() = ## Javascript backend only! ## Opens the config file in a new view. editor_loadCurrentConfig_void_App_impl() +proc logRootNode*() = + editor_logRootNode_void_App_impl() proc sourceCurrentDocument*() = ## Javascript backend only! ## Runs the content of the active editor as javascript using `eval()`. diff --git a/scripting/editor_api_wasm.nim b/scripting/editor_api_wasm.nim index 03201999..0fff2389 100644 --- a/scripting/editor_api_wasm.nim +++ b/scripting/editor_api_wasm.nim @@ -811,6 +811,13 @@ proc loadCurrentConfig*() = argsJsonString.cstring) +proc editor_logRootNode_void_App_wasm(arg: cstring): cstring {.importc.} +proc logRootNode*() = + var argsJson = newJArray() + let argsJsonString = $argsJson + let res {.used.} = editor_logRootNode_void_App_wasm(argsJsonString.cstring) + + proc editor_sourceCurrentDocument_void_App_wasm(arg: cstring): cstring {.importc.} proc sourceCurrentDocument*() = var argsJson = newJArray() diff --git a/src/app.nim b/src/app.nim index fb6bba02..d7a1d8f0 100644 --- a/src/app.nim +++ b/src/app.nim @@ -1,5 +1,5 @@ import std/[sequtils, strformat, strutils, tables, unicode, options, os, algorithm, json, macros, macrocache, sugar, streams, deques] -import input, id, events, rect_utils, document, document_editor, popup, timer, event, cancellation_token, dispatch_tables, myjsonutils +import input, id, events, rect_utils, document, document_editor, popup, timer, event, cancellation_token, dispatch_tables, myjsonutils, ui/node import theme, util, custom_logger, custom_async, fuzzy_matching import scripting/[expose, scripting_base] import platform/[platform, filesystem] @@ -1722,6 +1722,10 @@ proc loadCurrentConfig*(self: App) {.expose("editor").} = when defined(js): discard self.createAndAddView(newTextDocument(self.asConfigProvider, "./config/absytree_config.js", fs.loadApplicationFile("./config/absytree_config.js"), true)) +proc logRootNode*(self: App) {.expose("editor").} = + let str = self.platform.builder.root.dump(true) + debug "logRootNode: ", str + proc sourceCurrentDocument*(self: App) {.expose("editor").} = ## Javascript backend only! ## Runs the content of the active editor as javascript using `eval()`. diff --git a/src/ast/cells.nim b/src/ast/cells.nim index b499c7d7..24011d6f 100644 --- a/src/ast/cells.nim +++ b/src/ast/cells.nim @@ -275,6 +275,7 @@ proc cell*(map: NodeCellMap, node: AstNode): Cell = return map.map[node.id] let cell = map.builder.buildCell(map, node, false) map.map[node.id] = cell + map.cells[cell.id] = cell return cell proc findBuilder(self: CellBuilder, class: NodeClass, preferred: Id): CellBuilderFunction = @@ -357,7 +358,7 @@ proc buildCellDefault*(self: CellBuilder, m: NodeCellMap, node: AstNode, useDefa proc buildCell*(self: CellBuilder, map: NodeCellMap, node: AstNode, useDefault: bool = false): Cell = let class = node.nodeClass if class.isNil: - debugf"Unknown class {node.class}" + debugf"Unknown class {node.class} for node {node}" return EmptyCell(node: node) if not useDefault and (let builder = self.findBuilder(class, idNone()); builder.isNotNil): diff --git a/src/ast/types.nim b/src/ast/types.nim index 210da570..44eff20d 100644 --- a/src/ast/types.nim +++ b/src/ast/types.nim @@ -626,7 +626,7 @@ proc replace*(node: AstNode, role: RoleId, index: int, child: AstNode) = if node.model.isNotNil: node.model.notifyNodeInserted(node, child, role, index) -proc removeFromParent*(node: AstNode) = +proc removeFromParent(node: AstNode) = if node.parent.isNil: return node.parent.remove(node) @@ -644,6 +644,7 @@ proc replaceWithDefault*(node: AstNode, fillDefaultChildren: bool = false): Opti if fillDefaultChildren: child.fillDefaultChildren(node.language) + # debugf"replaceWithDefault: replacing {node} with {child}" node.parent.replace(node.role, node.index, child) return child.some @@ -658,11 +659,13 @@ proc deleteOrReplaceWithDefault*(node: AstNode, fillDefaultChildren: bool = fals if fillDefaultChildren: child.fillDefaultChildren(node.language) + # debugf"deleteOrReplaceWithDefault: replacing {node} with {child}" node.parent.replace(node.role, node.index, child) return child.some else: + # debugf"deleteOrReplaceWithDefault: removing {node} from parent" node.removeFromParent() return AstNode.none diff --git a/src/model_document.nim b/src/model_document.nim index 399b217b..31fb2993 100644 --- a/src/model_document.nim +++ b/src/model_document.nim @@ -267,7 +267,7 @@ template selection*(self: ModelDocumentEditor): CellSelection = self.mSelection proc updateScrollOffset(self: ModelDocumentEditor, oldCell: Cell) = if self.cellWidgetContext.isNotNil: let newCell = self.selection.last.targetCell - if oldCell.isNotNil and self.cellWidgetContext.cellToWidget.contains(oldCell.id): + if self.scrolledNode.isNotNil: if newCell.isNotNil and self.cellWidgetContext.cellToWidget.contains(newCell.id): let newUINode = self.cellWidgetContext.cellToWidget[newCell.id] let newY = newUINode.transformBounds(self.scrolledNode.parent).y @@ -281,8 +281,13 @@ proc updateScrollOffset(self: ModelDocumentEditor, oldCell: Cell) = self.scrollOffset = self.scrolledNode.parent.h - buffer * self.app.platform.builder.textHeight else: - self.targetCellPath = self.selection.last.targetCell.rootPath.path - self.scrollOffset = self.scrolledNode.parent.h / 2 + discard + # todo + # echo fmt"new cell doesn't exist, scroll offset {self.scrollOffset}, {self.targetCellPath}" + # self.targetCellPath = self.selection.last.targetCell.rootPath.path + # self.scrollOffset = self.scrolledNode.parent.h / 2 + + self.markDirty() proc `selection=`*(self: ModelDocumentEditor, selection: CellSelection) = assert self.mSelection.first.map.isNotNil @@ -294,7 +299,7 @@ proc `selection=`*(self: ModelDocumentEditor, selection: CellSelection) = else: self.mSelection = selection self.refilterCompletions() - + # debugf"selection = {selection}" self.updateScrollOffset(oldCell) proc updateSelection*(self: ModelDocumentEditor, cursor: CellCursor, extend: bool) = @@ -629,8 +634,10 @@ proc buildNodeCellMap(self: Cell, map: var Table[Id, Cell]) = c.buildNodeCellMap(map) proc rebuildCells(self: ModelDocumentEditor) = + # debugf"rebuildCells" self.nodeCellMap.invalidate() self.logicalLines.setLen 0 + self.markDirty() proc toJson*(self: api.ModelDocumentEditor, opt = initToJsonOptions()): JsonNode = result = newJObject() @@ -1940,10 +1947,10 @@ proc createNewNode*(self: ModelDocumentEditor) {.expose("editor.model").} = debug "createNewNode" if self.createNewNodeAt(self.cursor).getSome(newNode): - self.rebuildCells() self.cursor = self.getFirstEditableCellOfNode(newNode).get debug self.cursor + self.rebuildCells() self.markDirty() proc insertTextAtCursor*(self: ModelDocumentEditor, input: string): bool {.expose("editor.model").} = diff --git a/src/platform/widget_builder_model_document.nim b/src/platform/widget_builder_model_document.nim index 18a6578b..f7f3b025 100644 --- a/src/platform/widget_builder_model_document.nim +++ b/src/platform/widget_builder_model_document.nim @@ -844,7 +844,7 @@ method createUI*(self: ModelDocumentEditor, builder: UINodeBuilder, app: App): s self.markDirty() - # echo self.scrollOffset + # echo fmt"scroll offset {self.scrollOffset}" block: let myCtx = newCellLayoutContext(builder, self.cellWidgetContext, Direction.Center, true) defer: @@ -871,13 +871,14 @@ method createUI*(self: ModelDocumentEditor, builder: UINodeBuilder, app: App): s if self.cellWidgetContext.targetNode.isNotNil: var bounds = self.cellWidgetContext.targetNode.bounds.transformRect(self.cellWidgetContext.targetNode.parent, scrolledNode.parent) # echo fmt"1 target node {bounds}: {self.cellWidgetContext.targetNode.dump}" - currentNode.rawY = currentNode.boundsRaw.y + (self.scrollOffset - bounds.y) + # echo scrolledNode.boundsRaw.y, " -> ", scrolledNode.boundsRaw.y + (self.scrollOffset - bounds.y) + scrolledNode.rawY = scrolledNode.boundsRaw.y + (self.scrollOffset - bounds.y) bounds = self.cellWidgetContext.targetNode.bounds.transformRect(self.cellWidgetContext.targetNode.parent, scrolledNode.parent) # echo fmt"2 target node {bounds}: {self.cellWidgetContext.targetNode.dump}" if self.scrollOffset < cellGenerationBuffer or self.scrollOffset >= h - cellGenerationBuffer: let forward = self.scrollOffset < cellGenerationBuffer - if self.cellWidgetContext.updateTargetPath(currentNode.parent, cell, forward, self.targetCellPath, @[]).getSome(path): + if self.cellWidgetContext.updateTargetPath(scrolledNode.parent, cell, forward, self.targetCellPath, @[]).getSome(path): # echo "update path ", path, " (was ", targetCellPath, ")" self.targetCellPath = path[1] self.scrollOffset = path[0] diff --git a/src/ui/node.nim b/src/ui/node.nim index 6fd1b39c..f482518e 100644 --- a/src/ui/node.nim +++ b/src/ui/node.nim @@ -1083,8 +1083,8 @@ proc postProcessNodeBackwards(builder: UINodeBuilder, node: UINode, offsetX: flo let newPosAbsoluteX = node.boundsActual.x + offsetX let newPosAbsoluteY = node.boundsActual.y + offsetY - let positionDirty = node.lx != newPosAbsoluteX or node.ly != newPosAbsoluteY - let sizeDirty = node.lw != node.boundsActual.w or node.lh != node.boundsActual.h + let positionDirty = node.lx != newPosAbsoluteX or node.ly != newPosAbsoluteY or (node.parent.isNotNil and node.parent.mLastPositionChange == builder.frameIndex) + let sizeDirty = node.lw != node.boundsActual.w or node.lh != node.boundsActual.h or (node.parent.isNotNil and node.parent.mLastSizeChange == builder.frameIndex) let animatingDirty = wasAnimating != (node.id in builder.animatingNodes) if animatingDirty: