diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js index 1340cf9..1ebe6f9 100644 --- a/src/canvas/canvas.js +++ b/src/canvas/canvas.js @@ -224,6 +224,8 @@ class Canvas extends React.Component { } } + console.log("inner widget: ", innerWidget, target) + return innerWidget } @@ -253,7 +255,6 @@ class Canvas extends React.Component { } mouseDownEvent(event) { - this.mousePos = { x: event.clientX, y: event.clientY } let selectedWidget = this.getWidgetFromTarget(event.target) @@ -1217,7 +1218,7 @@ class Canvas extends React.Component { * NOTE: this would cause entire widgetList to remount * NOTE: this would cause the toolbar to loose active widget */ - updateWidgetData = (widgetId, latestData) => { + updateWidgetData = (widgetId) => { const widgetObj = this.getWidgetById(widgetId)?.current // console.log("Data unmount: ", this.widgets, this.widgetRefs, widgetObj, widgetId, widgetObj?.serialize(), latestData) @@ -1256,6 +1257,33 @@ class Canvas extends React.Component { } + // FIXME: this must update the childrens corectly + updateWidgetAndChildren = (widgetId) => { + const serializeWidgetRecursively = (widget) => { + const widgetObj = this.getWidgetById(widget.id)?.current; + if (!widgetObj) return widget; // If no widget reference found, return unchanged + + return { + ...widget, + initialData: { + ...widget.initialData, + ...widgetObj.serialize() + }, + children: widget.children?.map(serializeWidgetRecursively) || [] // Recursively serialize children + }; + }; + + this.setWidgets(prevWidgets => { + const updateWidgets = (widgets) => { + return widgets.map(widget => + widget.id === widgetId ? serializeWidgetRecursively(widget) : widget + ); + }; + + return updateWidgets(prevWidgets); + }); + }; + renderWidget = (widget) => { @@ -1305,7 +1333,8 @@ class Canvas extends React.Component { onPanToWidget={this.panToWidget} - requestWidgetDataUpdate={this.updateWidgetData} + requestWidgetDataUpdate={this.updateWidgetAndChildren} + // requestWidgetDataUpdate={this.updateWidgetData} // onWidgetUpdate={this.onActiveWidgetUpdate} // onWidgetUpdate={this.updateWidgetDataOnUnmount} // onUnmount={this.updateWidgetDataOnUnmount} diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js index 56173cd..6718567 100644 --- a/src/canvas/widgets/base.js +++ b/src/canvas/widgets/base.js @@ -635,12 +635,12 @@ class Widget extends React.Component { const elementRect = this.elementRef.current.getBoundingClientRect() // console.log("winner: ", this.props.parentWidgetRef.current.getBoundingRect()) - const parentRect = this.props.parentWidgetRef.current.getBoundingRect() + const parentRect = this.props.parentWidgetRef.current?.getBoundingRect() // FIXME: (low priority) once the place is moved and back to flex the position the updated position is not reflected let pos = { - x: (elementRect.left - parentRect.left) / this.canvasMetaData.zoom, - y: (elementRect.top - parentRect.top) / this.canvasMetaData.zoom + x: (elementRect.left - (parentRect?.left || 0)) / this.canvasMetaData.zoom, + y: (elementRect.top - (parentRect?.top || 0)) / this.canvasMetaData.zoom } this.setPos(pos.x, pos.y) @@ -849,7 +849,7 @@ class Widget extends React.Component { let layoutUpdates = { - parentLayout: parentLayout.layout || null + parentLayout: parentLayout?.layout || null } if (parentLayout?.layout === Layouts.FLEX || parentLayout?.layout === Layouts.GRID){ diff --git a/src/frameworks/tkinter/widgets/base.js b/src/frameworks/tkinter/widgets/base.js index fb8fd78..fee9ec1 100644 --- a/src/frameworks/tkinter/widgets/base.js +++ b/src/frameworks/tkinter/widgets/base.js @@ -23,7 +23,7 @@ export class TkinterBase extends Widget { this.state = { ...this.state, packAttrs: { - side: "left", + side: "top", anchor: "nw" } } @@ -186,7 +186,9 @@ export class TkinterBase extends Widget { // FIXME: force parent rerender because, here only child get rerendered, if only parent get rerendered the widget would move this.setAttrValue("flexManager.side", value, () => { this.updateState((prevState) => ({packAttrs: {...prevState.packAttrs, side: value}}), () => { - this.props.requestWidgetDataUpdate(this.__id) + console.log("parent: ",this.props.parentWidgetRef.current.__id) + + this.props.requestWidgetDataUpdate(this.props.parentWidgetRef.current.__id) this.stateChangeSubscriberCallback() // call this to notify the toolbar that the widget has changed state // this.props.parentWidgetRef.current.forceRerender() }) @@ -205,7 +207,10 @@ export class TkinterBase extends Widget { this.setAttrValue("flexManager.anchor", value, () => { console.log("anchor updated") this.updateState((prevState) => ({packAttrs: {...prevState.packAttrs, anchor: value}}), () => { - this.props.requestWidgetDataUpdate(this.__id) + + this.props.requestWidgetDataUpdate(this.props.parentWidgetRef.current.__id) + + // this.props.requestWidgetDataUpdate(this.__id) this.stateChangeSubscriberCallback() // call this to notify the toolbar that the widget has changed state // this.props.parentWidgetRef.current.forceRerender() }) @@ -381,24 +386,24 @@ export class TkinterBase extends Widget { const rowStyle = { display: "flex", - gap: "10px" + gap: "10px", } const columnStyle = { display: "flex", flexDirection: "column", - gap: "10px" + gap: "10px", } switch (side) { case "top": - return { gridColumn: "1 / -1", alignSelf: "stretch", width: "100%", ...baseStyle, ...columnStyle }; + return { gridColumn: "1 / -1", alignSelf: "stretch", ...baseStyle, ...columnStyle }; case "bottom": - return { gridColumn: "1 / -1", alignSelf: "stretch", width: "100%", ...baseStyle, ...columnStyle }; + return { gridColumn: "1 / -1", alignSelf: "stretch", ...baseStyle, ...columnStyle }; case "left": - return { gridRow: "2", gridColumn: "1", justifySelf: "stretch", height: "100%", ...baseStyle, ...rowStyle }; + return { gridRow: "2", gridColumn: "1", justifySelf: "stretch", ...baseStyle, ...rowStyle }; case "right": - return { gridRow: "2", gridColumn: "3", justifySelf: "stretch", height: "100%", ...baseStyle, ...rowStyle }; + return { gridRow: "2", gridColumn: "3", justifySelf: "stretch", ...baseStyle, ...rowStyle }; case "center": return { gridRow: "2", gridColumn: "2", alignSelf: "center", justifySelf: "center", ...baseStyle, }; default: @@ -438,9 +443,92 @@ export class TkinterBase extends Widget { return { ...baseStyle, alignSelf: "stretch", // Forces stretching in grid rows justifySelf: "stretch", // Forces stretching in grid columns - // flexGrow: fill ? 1 : 0 + flexGrow: (fillX || fillY) ? 1 : 0 }; } + + + /** + * adds the layout to achieve the pack from tkinter refer: https://www.youtube.com/watch?v=rbW1iJO1psk + * @param {*} widgets + * @param {*} index + * @returns + */ + renderPackWidgetsRecursively = (widgets, index = 0, lastSide="") => { + console.log("widgets: ", widgets, index) + + //FIXME: when the first element is left, the second is top the second should also have its own container + if (index >= widgets.length) return null + + + const widget = widgets[index] + const widgetRef = widget.ref?.current + if (!widgetRef) return null // Ensure ref exists before accessing + + const side = widgetRef.getPackAttrs()?.side || "top" + + const direction = (s) => { + return (s === "bottom" + ? "column-reverse" + : s === "top" + ? "column" + : s === "right" + ? "row-reverse" + : "row") + } + + const currentWidgetDirection = direction(side) + + + const isSameSide = lastSide === side + lastSide = side; // Update last side for next recursion + + // console.log("current widget direction: ", isSameSide, currentWidgetDirection) + + if (isSameSide) { + return ( + <> + {/*
{widget}
*/} +
+ {widget} +
+ + {/* {widget} */} + {this.renderPackWidgetsRecursively(widgets, index + 1, side)} + + ) + } + + // If next widget has a different side, create a new container for it + return ( +
+ +
+ {widget} +
+ + {/*
+
*/} + {this.renderPackWidgetsRecursively(widgets, index + 1, side)} + {/* FIXME: why is the pack widgets recursively outside container? */} +
+ + ); + + }; + /** * @@ -449,38 +537,11 @@ export class TkinterBase extends Widget { renderTkinterLayout(){ const {layout, direction, gap} = this.getLayout() if (layout === Layouts.FLEX){ + + return ( <> - {(this.props.children.length > 0) && ["top", "bottom", "left", "right"].map((pos) => { - - const filteredChildren = this.props.children.filter((item) => { - const widgetRef = item.ref?.current - if (!widgetRef) return false // Ensure ref exists before accessing - - const packAttrs = widgetRef.getPackAttrs()// Cache value - return (packAttrs.side || "left") === pos - }) - const isColumn = pos === "top" || pos === "bottom"; - return ( -
- {/* {filteredChildren} */} - {filteredChildren.map((widget) => { - const widgetRef = widget.ref?.current; - const anchor = widgetRef ? widgetRef.getPackAttrs().anchor : "nw"; - return ( -
- {widget} -
- ); - })} -
- ) - })} + {this.renderPackWidgetsRecursively(this.props.children)} ) } @@ -506,13 +567,16 @@ export class TkinterBase extends Widget { let widgetStyle = { ...this.state.widgetInnerStyling, - // display: layout !== Layouts.PLACE ? "grid" : "block", - display: display, + display: layout !== Layouts.PLACE ? layout : "block", + flexDirection: "column", // flexDirection: direction, gap: `${gap}px`, // flexWrap: "wrap", - gridTemplateColumns: layout === Layouts.FLEX ? "auto 1fr auto" : "repeat(auto-fill, minmax(100px, 1fr))", - gridTemplateRows: layout === Layouts.FLEX ? "auto 1fr auto" : "repeat(auto-fill, minmax(100px, 1fr))", + + gridTemplateColumns: "repeat(auto-fill, minmax(100px, 1fr))", + gridTemplateRows: "repeat(auto-fill, minmax(100px, 1fr))", + // gridTemplateColumns: layout === Layouts.FLEX ? "minmax(auto, 1fr) 1fr minmax(auto, 1fr)" : "repeat(auto-fill, minmax(100px, 1fr))", + // gridTemplateRows: layout === Layouts.FLEX ? "minmax(auto, 1fr) 1fr minmax(auto, 1fr)" : "repeat(auto-fill, minmax(100px, 1fr))", // gridAutoRows: 'minmax(100px, auto)', // Rows with minimum height of 100px, and grow to fit content // gridAutoCols: 'minmax(100px, auto)', // Cols with minimum height of 100px, and grow to fit content } @@ -528,7 +592,7 @@ export class TkinterBase extends Widget { getInnerRenderStyling(){ let {width, height, minWidth, minHeight} = this.getRenderSize() - + const {layout: parentLayout, direction, gap} = this.getParentLayout() || {} // if (parentLayout === Layouts.FLEX){ @@ -543,7 +607,7 @@ export class TkinterBase extends Widget { // } // } - + const styling = { ...this.state.widgetInnerStyling, width,