diff --git a/package-lock.json b/package-lock.json
index 70ead3f..4b594be 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,7 @@
"fabric": "^6.1.0",
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
+ "lodash": "^4.17.21",
"postcss-cli": "^11.0.0",
"re-resizable": "^6.9.17",
"react": "^18.3.1",
@@ -14728,7 +14729,8 @@
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
+ "license": "MIT"
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
diff --git a/package.json b/package.json
index 6fea594..197254d 100644
--- a/package.json
+++ b/package.json
@@ -22,6 +22,7 @@
"fabric": "^6.1.0",
"file-saver": "^2.0.5",
"jszip": "^3.10.1",
+ "lodash": "^4.17.21",
"postcss-cli": "^11.0.0",
"re-resizable": "^6.9.17",
"react": "^18.3.1",
diff --git a/src/canvas/canvas.js b/src/canvas/canvas.js
index d410e26..bb8f751 100644
--- a/src/canvas/canvas.js
+++ b/src/canvas/canvas.js
@@ -1257,7 +1257,6 @@ class Canvas extends React.Component {
}
- // FIXME: this must update the childrens corectly
updateWidgetAndChildren = (widgetId) => {
const serializeWidgetRecursively = (widget) => {
const widgetObj = this.getWidgetById(widget.id)?.current;
diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js
index cb88991..c67fde1 100644
--- a/src/canvas/widgets/base.js
+++ b/src/canvas/widgets/base.js
@@ -1,6 +1,9 @@
import { v4 as uuidv4 } from 'uuid';
import React, { useEffect, useLayoutEffect, useRef, useState } from "react"
+
+import lo from 'lodash'
+
import { NotImplementedError } from "../../utils/errors"
import Tools from "../constants/tools"
@@ -12,7 +15,7 @@ import EditableDiv from "../../components/editableDiv"
import WidgetContainer from "../constants/containers"
import { DragContext } from "../../components/draggable/draggableContext"
-import { isNumeric, removeKeyFromObject } from "../../utils/common"
+import { getGridPosition, isNumeric, removeKeyFromObject } from "../../utils/common"
import { Layout, message } from "antd"
@@ -66,6 +69,8 @@ class Widget extends React.Component {
this.swappableAreaRef = React.createRef() // helps identify if the users intent is to swap or drop inside the widget
this.innerAreaRef = React.createRef() // this is the inner area where swap is prevented and only drop is accepted
+ this.styleAreaRef = React.createRef() // use ref this where inner widget style is applied
+
this.functions = {
"load": { "args1": "number", "args2": "string" }
}
@@ -79,7 +84,7 @@ class Widget extends React.Component {
selected: false,
isWidgetVisible: true,
- forceRerenderId: "",
+ // forceRerenderId: "",
widgetName: widgetName || 'widget', // this will later be converted to variable name
enableRename: false, // will open the widgets editable div for renaming
@@ -225,7 +230,10 @@ class Widget extends React.Component {
if (this.state.attrs.styling.backgroundColor)
this.setWidgetInnerStyle('backgroundColor', this.state.attrs.styling?.backgroundColor.value || "#fff")
- this.load(this.props.initialData || {}) // load the initial data
+ this.load(this.props.initialData || {}, () => {
+ console.log("component remounted: ", this.__id)
+
+ }) // load the initial data
// The elementRect is received only after the elemet is added so, it may not be accurate so use resize handler
// this.resizeObserver = new MutationObserver(this.handleResizeEvents)
@@ -237,28 +245,21 @@ class Widget extends React.Component {
}
- handleResizeEvents = () => {
- if (!this.elementRef.current) return;
-
- const elementRect = this.elementRef.current.getBoundingClientRect();
-
- const parentRect = this.props.parentWidgetRef?.current?.getBoundingRect()
-
-
- const left = ((elementRect.left || 0) - (parentRect?.left || this.props.canvasRectInner?.left)) / this.props.canvasZoom;
- const top = ((elementRect.top || 0) - (parentRect?.top || this.props.canvasRectInner?.top)) / this.props.canvasZoom;
-
- // const left = (elementRect?.left || 0)
- // const top = (elementRect?.top || 0)
-
- this.setState({pos: { x: left, y: top }});
- }
-
componentDidUpdate(prevProps, prevState) {
if (prevProps !== this.props) {
this.canvasMetaData = this.props.canvasMetaData
}
+ const compareAttrs = ['attrs', 'widgetName', 'parentLayout', 'positionType']
+
+ // TODO: maybe find more efficient way to update the canvas about teh child updates???
+ if (!lo.isEqual(lo.pick(prevState, compareAttrs), lo.pick(this.state, compareAttrs))){
+ // THIS IS inefficeint
+ // this.props.requestThisWidgetDataUpdate(this.__id)
+ setTimeout(() => this.props.requestWidgetDataUpdate(this.__id), 1)
+ }
+ // call update widgets
+
}
componentWillUnmount(){
@@ -640,7 +641,8 @@ class Widget extends React.Component {
* @param {Layouts} parentLayout
*/
setParentLayout(parentLayout){
-
+ // FIXME: changing from one layout to another isn't working as expected
+ // TODO: add styleAreaRef to every where there is innerWidgetSTyle
if (!parentLayout){
// if parent layout is null (i,e the widget is on the canvas)
return {}
@@ -672,6 +674,17 @@ class Widget extends React.Component {
this.setPos(pos.x, pos.y)
// console.log("setting pos: ", pos)
+
+ if (layout === Layouts.GRID){
+ setTimeout(() => {
+ const gridPos = getGridPosition(this.elementRef.current, this.props.parentWidgetRef.current.styleAreaRef.current)
+ if (gridPos){
+ this.setAttrValue("gridManager.row", gridPos.row)
+ this.setAttrValue("gridManager.column", gridPos.column)
+ }
+
+ }, 1)
+ }
}else if (layout === Layouts.PLACE){
updates = {
@@ -881,7 +894,9 @@ class Widget extends React.Component {
data = {...data} // create a shallow copy
- const {attrs={}, selected, pos={x: 0, y: 0}, parentLayout=null, ...restData} = data
+ const {attrs={}, selected, pos={x: 0, y: 0}, ...restData} = data
+
+ const parentLayout = this.props.parentWidgetRef?.current?.getLayout() // don't get the parentLayout from serialized data as it may have become stale
let layoutUpdates = {
@@ -1128,23 +1143,7 @@ class Widget extends React.Component {
} else if (container === WidgetContainer.SIDEBAR) {
- // const { initialPos } = posMetaData
- // const canvasInnerRect = this.props.canvasInnerContainerRef.current.getBoundingClientRect()
-
- // const newInitialPos = {
- // x: (initialPos.x - canvasInnerRect.left),
- // y: (initialPos.y - canvasInnerRect.top)
- // }
-
- // posMetaData = {
- // ...posMetaData,
- // initialPos: newInitialPos,
- // }
- // console.log("Dropped on Sidebar: ", this.__id)
-
-
- // const parentRect = this.getBoundingRect()
const canvasRect = this.props.canvasInnerContainerRef.current.getBoundingClientRect()
const {zoom, pan} = this.props.canvasMetaData
diff --git a/src/frameworks/customtk/widgets/button.js b/src/frameworks/customtk/widgets/button.js
index 39970cf..b208378 100644
--- a/src/frameworks/customtk/widgets/button.js
+++ b/src/frameworks/customtk/widgets/button.js
@@ -70,6 +70,7 @@ class Button extends CustomTkWidgetBase{
{/* {this.props.children} */}
diff --git a/src/frameworks/customtk/widgets/checkButton.js b/src/frameworks/customtk/widgets/checkButton.js
index ca626ec..8faeff0 100644
--- a/src/frameworks/customtk/widgets/checkButton.js
+++ b/src/frameworks/customtk/widgets/checkButton.js
@@ -213,6 +213,7 @@ export class RadioButton extends CustomTkWidgetBase{
return (
diff --git a/src/frameworks/customtk/widgets/frame.js b/src/frameworks/customtk/widgets/frame.js
index 61b2105..f1f813d 100644
--- a/src/frameworks/customtk/widgets/frame.js
+++ b/src/frameworks/customtk/widgets/frame.js
@@ -46,7 +46,9 @@ class Frame extends CustomTkBase{
// console.log("widget styling: ", this.state.widgetInnerStyling)
return (
-
diff --git a/src/frameworks/customtk/widgets/input.js b/src/frameworks/customtk/widgets/input.js
index c5c0c38..81f7c20 100644
--- a/src/frameworks/customtk/widgets/input.js
+++ b/src/frameworks/customtk/widgets/input.js
@@ -66,6 +66,7 @@ export class Input extends CustomTkWidgetBase{
return (
{this.getAttrValue("placeHolder")}
diff --git a/src/frameworks/customtk/widgets/label.js b/src/frameworks/customtk/widgets/label.js
index 1e580dc..3a11d6d 100644
--- a/src/frameworks/customtk/widgets/label.js
+++ b/src/frameworks/customtk/widgets/label.js
@@ -129,6 +129,7 @@ class Label extends CustomTkWidgetBase{
}}
>
{/* {this.props.children} */}
{
diff --git a/src/frameworks/customtk/widgets/mainWindow.js b/src/frameworks/customtk/widgets/mainWindow.js
index 43fb927..77e9784 100644
--- a/src/frameworks/customtk/widgets/mainWindow.js
+++ b/src/frameworks/customtk/widgets/mainWindow.js
@@ -81,6 +81,7 @@ class MainWindow extends CustomTkBase{
{this.props.children}
diff --git a/src/frameworks/customtk/widgets/optionMenu.js b/src/frameworks/customtk/widgets/optionMenu.js
index f1265f0..ed2f07b 100644
--- a/src/frameworks/customtk/widgets/optionMenu.js
+++ b/src/frameworks/customtk/widgets/optionMenu.js
@@ -103,6 +103,7 @@ class OptionMenu extends CustomTkWidgetBase{
return (
diff --git a/src/frameworks/customtk/widgets/slider.js b/src/frameworks/customtk/widgets/slider.js
index 50d9266..15bfa67 100644
--- a/src/frameworks/customtk/widgets/slider.js
+++ b/src/frameworks/customtk/widgets/slider.js
@@ -143,7 +143,9 @@ class Slider extends CustomTkWidgetBase{
return (
+ bg-gray-100"
+ ref={this.styleAreaRef}
+ style={this.getInnerRenderStyling()}>
-
diff --git a/src/frameworks/tkinter/widgets/base.js b/src/frameworks/tkinter/widgets/base.js
index d156f67..16ad792 100644
--- a/src/frameworks/tkinter/widgets/base.js
+++ b/src/frameworks/tkinter/widgets/base.js
@@ -61,8 +61,24 @@ export class TkinterBase extends Widget {
}else if (parentLayout === Layouts.FLEX){
- const config = {
- side: direction === "row" ? "tk.LEFT" : "tk.TOP",
+ const packSide = this.getAttrValue("flexManager.side")
+
+ const config = {}
+
+ if (packSide === "" || packSide === "top"){
+
+ config['side'] = `tk.TOP`
+
+ }else if (packSide === "left"){
+
+ config['side'] = `tk.LEFT`
+
+ }else if (packSide === "right"){
+
+ config['side'] = `tk.RIGHT`
+
+ }else{
+ config['side'] = `tk.BOTTOM`
}
if (gap > 0){
@@ -126,19 +142,11 @@ export class TkinterBase extends Widget {
if (!layout){
return {}
}
- super.setParentLayout(layout)
+ let updates = super.setParentLayout(layout)
const {layout: parentLayout, direction, gap} = layout
// show attributes related to the layout manager
- let updates = {
- parentLayout: layout,
- }
-
- // this.removeAttr("gridManager")
- // this.removeAttr("flexManager")
- // this.removeAttr("positioning")
-
// remove gridManager, flexManager positioning
const {gridManager, flexManager, positioning, ...restAttrs} = this.state.attrs
@@ -284,7 +292,6 @@ export class TkinterBase extends Widget {
onChange: (value) => {
const previousRow = this.getWidgetOuterStyle("gridRow") || "1/1"
-
let [_row=1, rowSpan=1] = previousRow.replace(/\s+/g, '').split("/").map(Number)
if (value > rowSpan){
@@ -292,7 +299,6 @@ export class TkinterBase extends Widget {
rowSpan = value
this.setAttrValue("gridManager.rowSpan", rowSpan)
}
-
this.setAttrValue("gridManager.row", value)
this.setWidgetOuterStyle("gridRow", `${value+' / '+rowSpan}`)
}
@@ -565,8 +571,6 @@ export class TkinterBase extends Widget {
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
}
@@ -648,7 +652,10 @@ export class TkinterBase extends Widget {
data = {...data} // create a shallow copy
- const {attrs={}, selected, pos={x: 0, y: 0}, parentLayout=null, ...restData} = data
+ const {attrs={}, selected, pos={x: 0, y: 0}, ...restData} = data
+
+ const parentLayout = this.props.parentWidgetRef?.current?.getLayout()
+
let layoutUpdates = {
parentLayout: parentLayout
diff --git a/src/frameworks/tkinter/widgets/button.js b/src/frameworks/tkinter/widgets/button.js
index abd68b1..83cc638 100644
--- a/src/frameworks/tkinter/widgets/button.js
+++ b/src/frameworks/tkinter/widgets/button.js
@@ -69,6 +69,7 @@ class Button extends TkinterWidgetBase{
{/* {this.props.children} */}
diff --git a/src/frameworks/tkinter/widgets/checkButton.js b/src/frameworks/tkinter/widgets/checkButton.js
index 8bf86a4..3690cf9 100644
--- a/src/frameworks/tkinter/widgets/checkButton.js
+++ b/src/frameworks/tkinter/widgets/checkButton.js
@@ -98,6 +98,7 @@ export class CheckBox extends TkinterWidgetBase{
return (
diff --git a/src/frameworks/tkinter/widgets/frame.js b/src/frameworks/tkinter/widgets/frame.js
index 7fe02d1..b40bab0 100644
--- a/src/frameworks/tkinter/widgets/frame.js
+++ b/src/frameworks/tkinter/widgets/frame.js
@@ -46,7 +46,9 @@ class Frame extends TkinterBase{
// console.log("widget styling: ", this.state.widgetInnerStyling)
return (
-
diff --git a/src/frameworks/tkinter/widgets/input.js b/src/frameworks/tkinter/widgets/input.js
index 3a3a4d5..f768dcf 100644
--- a/src/frameworks/tkinter/widgets/input.js
+++ b/src/frameworks/tkinter/widgets/input.js
@@ -66,6 +66,7 @@ export class Input extends TkinterWidgetBase{
return (
{this.getAttrValue("placeHolder")}
@@ -139,6 +140,7 @@ export class Text extends TkinterWidgetBase{
return (
{this.getAttrValue("placeHolder")}
diff --git a/src/frameworks/tkinter/widgets/label.js b/src/frameworks/tkinter/widgets/label.js
index bdd654a..b76b07f 100644
--- a/src/frameworks/tkinter/widgets/label.js
+++ b/src/frameworks/tkinter/widgets/label.js
@@ -122,6 +122,7 @@ class Label extends TkinterWidgetBase{
}}
>
{/* {this.props.children} */}
{
diff --git a/src/frameworks/tkinter/widgets/mainWindow.js b/src/frameworks/tkinter/widgets/mainWindow.js
index 34c3c21..c6c3a8b 100644
--- a/src/frameworks/tkinter/widgets/mainWindow.js
+++ b/src/frameworks/tkinter/widgets/mainWindow.js
@@ -97,6 +97,7 @@ class MainWindow extends TkinterBase{
{/* {this.props.children} */}
{this.renderTkinterLayout()} {/* This is required for pack layouts, so if your widget accepts child widgets, ensure to add this */}
diff --git a/src/frameworks/tkinter/widgets/optionMenu.js b/src/frameworks/tkinter/widgets/optionMenu.js
index 255047b..ae075e6 100644
--- a/src/frameworks/tkinter/widgets/optionMenu.js
+++ b/src/frameworks/tkinter/widgets/optionMenu.js
@@ -101,6 +101,7 @@ class OptionMenu extends TkinterWidgetBase{
return (
diff --git a/src/frameworks/tkinter/widgets/slider.js b/src/frameworks/tkinter/widgets/slider.js
index fc6cc20..349fece 100644
--- a/src/frameworks/tkinter/widgets/slider.js
+++ b/src/frameworks/tkinter/widgets/slider.js
@@ -138,7 +138,9 @@ class Slider extends TkinterWidgetBase{
return (
+ bg-gray-100"
+ ref={this.styleAreaRef}
+ style={this.getInnerRenderStyling()}>
-
diff --git a/src/utils/common.js b/src/utils/common.js
index 5b98a0c..a8fdb26 100644
--- a/src/utils/common.js
+++ b/src/utils/common.js
@@ -69,4 +69,29 @@ export function convertObjectToKeyValueString(obj){
return Object.entries(obj)
.map(([key, value]) => `${key}=${value}`)
.join(', ')
+}
+
+
+/**
+ *
+ * @param {HTMLElement} widget
+ * @param {HTMLElement} gridContainer
+ * @returns
+ */
+export const getGridPosition = (widget, gridContainer) => {
+ if (!widget || !gridContainer) return null;
+
+ const widgets = Array.from(gridContainer.children); // Get all grid items
+ // const index = widgets.indexOf(widget);
+ const widgetIndex = widgets.indexOf(widget);
+
+ if (widgetIndex === -1) return null; // Widget not found
+
+ const gridStyles = getComputedStyle(gridContainer);
+ const columnCount = gridStyles.gridTemplateColumns.split(' ').length;
+
+ const row = Math.floor(widgetIndex / columnCount) + 1;
+ const column = (widgetIndex % columnCount) + 1;
+
+ return { row, column };
}
\ No newline at end of file