From 2c7a1ada48205c7d6eb208db728da860d785148b Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 27 Sep 2024 19:22:33 +0530 Subject: [PATCH] added more attributes and generateCode to more widgets --- public/index.html | 9 -- src/canvas/widgets/base.js | 2 +- src/frameworks/tkinter/constants/styling.js | 7 ++ .../tkinter/widgets/ checkButton.js | 47 ++------ src/frameworks/tkinter/widgets/base.js | 104 ++++++++++++++++-- src/frameworks/tkinter/widgets/button.js | 31 ++---- src/frameworks/tkinter/widgets/input.js | 67 ++++------- src/frameworks/tkinter/widgets/label.js | 30 +---- src/frameworks/tkinter/widgets/mainWindow.js | 4 +- src/frameworks/tkinter/widgets/optionMenu.js | 59 +++++----- src/frameworks/tkinter/widgets/slider.js | 46 +++++--- src/frameworks/tkinter/widgets/spinBox.js | 49 ++++----- src/utils/common.js | 15 ++- 13 files changed, 252 insertions(+), 218 deletions(-) diff --git a/public/index.html b/public/index.html index 10b26d7..f3cb60d 100644 --- a/public/index.html +++ b/public/index.html @@ -41,15 +41,6 @@
- diff --git a/src/canvas/widgets/base.js b/src/canvas/widgets/base.js index e54510e..ee05595 100644 --- a/src/canvas/widgets/base.js +++ b/src/canvas/widgets/base.js @@ -20,7 +20,7 @@ import { isNumeric, removeKeyFromObject } from "../../utils/common" // FIXME: the drag drop indicator is not going invisible if the drop happens on the child // FIXME: once the width and height is set to fit-content, it can no longer be resized -const ATTRS_KEYS = ['value', 'label', 'tool', 'onChange', 'toolProps'] // these are attrs keywords, don't use these keywords as keys while defining the attrs property +const ATTRS_KEYS = ['value', 'label', 'tool', 'onChange', 'options', 'toolProps'] // these are attrs keywords, don't use these keywords as keys while defining the attrs property or serializing /** diff --git a/src/frameworks/tkinter/constants/styling.js b/src/frameworks/tkinter/constants/styling.js index 40b1103..d5d41bb 100644 --- a/src/frameworks/tkinter/constants/styling.js +++ b/src/frameworks/tkinter/constants/styling.js @@ -5,4 +5,11 @@ export const RELIEF = [ "SUNKEN", "GROOVE", "RIDGE" +] + + +export const JUSTIFY = [ + "LEFT", + "CENTER", + "RIGHT" ] \ No newline at end of file diff --git a/src/frameworks/tkinter/widgets/ checkButton.js b/src/frameworks/tkinter/widgets/ checkButton.js index 5937be3..2cc42e3 100644 --- a/src/frameworks/tkinter/widgets/ checkButton.js +++ b/src/frameworks/tkinter/widgets/ checkButton.js @@ -1,12 +1,11 @@ -import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" +import { convertObjectToKeyValueString, removeKeyFromObject } from "../../../utils/common" import { CheckSquareFilled } from "@ant-design/icons" -import {TkinterBase} from "./base" +import { TkinterWidgetBase } from "./base" -export class CheckBox extends TkinterBase{ +export class CheckBox extends TkinterWidgetBase{ static widgetType = "check_button" constructor(props) { @@ -63,12 +62,11 @@ export class CheckBox extends TkinterBase{ generateCode(variableName, parent){ const labelText = this.getAttrValue("checkLabel") - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") - + const config = convertObjectToKeyValueString(this.getConfigCode()) + const code = [ `${variableName} = tk.Checkbutton(master=${parent}, text="${labelText}")`, - `${variableName}.config(bg="${bg}", fg="${fg}")`, + `${variableName}.config(${config})`, ] if (this.getAttrValue("defaultChecked")){ @@ -122,43 +120,22 @@ export class CheckBox extends TkinterBase{ } -export class RadioButton extends TkinterBase{ +export class RadioButton extends TkinterWidgetBase{ + // FIXME: the radio buttons are not visible because of the default heigh provided static widgetType = "radio_button" constructor(props) { super(props) - this.droppableTags = null // disables drops - - // const {layout, ...newAttrs} = this.state.attrs // Removes the layout attribute - - let newAttrs = removeKeyFromObject("layout", this.state.attrs) - newAttrs = removeKeyFromObject("styling.backgroundColor", newAttrs) - this.minSize = {width: 50, height: 30} - this.state = { ...this.state, size: { width: 120, height: 'fit' }, widgetName: "Radio button", attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, - - + ...this.state.attrs, radios: { label: "Radio Group", tool: Tools.INPUT_RADIO_LIST, @@ -180,8 +157,8 @@ export class RadioButton extends TkinterBase{ generateCode(variableName, parent){ - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") + const config = convertObjectToKeyValueString(this.getConfigCode()) + const code = [ `${variableName}_var = tk.IntVar()`, @@ -193,7 +170,7 @@ export class RadioButton extends TkinterBase{ const radioBtnVariable = `${variableName}_${idx}` code.push(`\n`) code.push(`${radioBtnVariable} = tk.Radiobutton(master=${parent}, variable=${variableName}_var, text="${radio_text}")`) - code.push(`${radioBtnVariable}.config(bg="${bg}", fg="${fg}", value=${idx})`) + code.push(`${radioBtnVariable}.config(${config}, value=${idx})`) code.push(`${radioBtnVariable}.${this.getLayoutCode()}`) }) diff --git a/src/frameworks/tkinter/widgets/base.js b/src/frameworks/tkinter/widgets/base.js index e6be48a..b6860d3 100644 --- a/src/frameworks/tkinter/widgets/base.js +++ b/src/frameworks/tkinter/widgets/base.js @@ -4,7 +4,7 @@ import Widget from "../../../canvas/widgets/base" import { removeKeyFromObject } from "../../../utils/common" import { Tkinter_TO_WEB_CURSOR_MAPPING } from "../constants/cursor" import { Tkinter_To_GFonts } from "../constants/fontFamily" -import { RELIEF } from "../constants/styling" +import { JUSTIFY, RELIEF } from "../constants/styling" // TODO: add full width and full height in base widget // TODO: the pack should configure width and height of widgets @@ -204,7 +204,7 @@ export class TkinterBase extends Widget { ...layoutUpdates } - console.log("new data: ", newData) + console.log("new data: ", newData, data) this.setState(newData, () => { let layoutAttrs = this.setParentLayout(parentLayout) || {} @@ -286,12 +286,66 @@ export class TkinterWidgetBase extends TkinterBase{ label: "Relief", tool: Tools.SELECT_DROPDOWN, options: RELIEF.map((val) => ({value: val, label: val})), - value: "Arial", + value: "", onChange: (value) => { - this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value]) - this.setAttrValue("font.fontFamily", value) + // this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value]) + this.setAttrValue("styling.relief", value) } - } + }, + // justify: { + // label: "Justify", + // tool: Tools.SELECT_DROPDOWN, + // options: JUSTIFY.map((val) => ({value: val, label: val})), + // value: "", + // onChange: (value) => { + // this.setWidgetInnerStyle("text-align", value) + // this.setAttrValue("styling.justify", value) + // } + // } + }, + padding: { + label: "padding", + padX: { + label: "Pad X", + tool: Tools.NUMBER_INPUT, + toolProps: {min: 1, max: 140}, + value: null, + onChange: (value) => { + // this.setWidgetInnerStyle("paddingLeft", `${value}px`) + // this.setWidgetInnerStyle("paddingRight", `${value}px`) + + const widgetStyle = { + ...this.state.widgetInnerStyling, + paddingLeft: `${value}px`, + paddingRight: `${value}px` + } + this.setState({ + + widgetInnerStyling: widgetStyle + }) + + + this.setAttrValue("padding.padX", value) + } + }, + padY: { + label: "Pad Y", + tool: Tools.NUMBER_INPUT, + toolProps: {min: 1, max: 140}, + value: null, + onChange: (value) => { + const widgetStyle = { + ...this.state.widgetInnerStyling, + paddingTop: `${value}px`, + paddingBottom: `${value}px` + } + this.setState({ + + widgetInnerStyling: widgetStyle + }) + this.setAttrValue("padding.padX", value) + } + }, }, font: { label: "font", @@ -309,9 +363,8 @@ export class TkinterWidgetBase extends TkinterBase{ label: "font size", tool: Tools.NUMBER_INPUT, toolProps: {min: 1, max: 140}, - value: 14, + value: null, onChange: (value) => { - console.log("font size: ", value) this.setWidgetInnerStyle("fontSize", `${value}px`) this.setAttrValue("font.fontSize", value) } @@ -321,7 +374,7 @@ export class TkinterWidgetBase extends TkinterBase{ label: "Cursor", tool: Tools.SELECT_DROPDOWN, toolProps: {placeholder: "select cursor"}, - value: Tkinter_TO_WEB_CURSOR_MAPPING["arrow"], + value: "", options: Object.keys(Tkinter_TO_WEB_CURSOR_MAPPING).map((val) => ({value: val, label: val})), onChange: (value) => { this.setWidgetInnerStyle("cursor", Tkinter_TO_WEB_CURSOR_MAPPING[value]) @@ -330,6 +383,39 @@ export class TkinterWidgetBase extends TkinterBase{ }, } } + + this.getConfigCode = this.getConfigCode.bind(this) + } + + getConfigCode(){ + + const code = { + bg: `"${this.getAttrValue("styling.backgroundColor")}"`, + fg: `"${this.getAttrValue("styling.foregroundColor")}"`, + } + + if (this.getAttrValue("styling.borderWidth")) + code["bd"] = this.getAttrValue("styling.borderWidth") + + if (this.getAttrValue("styling.relief")) + code["relief"] = `"${this.getAttrValue("styling.relief")}"` + + if (this.getAttrValue("font.fontFamily") || this.getAttrValue("font.fontSize")){ + code["font"] = [`"${this.getAttrValue("font.fontFamily")}"`, this.getAttrValue("font.fontSize"), ] + } + + if (this.getAttrValue("cursor")) + code["cursor"] = `"${this.getAttrValue("cursor")}"` + + if (this.getAttrValue("padding.padX")){ + code["padx"] = this.getAttrValue("padding.padX") + } + + if (this.getAttrValue("padding.padY")){ + code["pady"] = this.getAttrValue("padding.padY") + } + + return code } } \ No newline at end of file diff --git a/src/frameworks/tkinter/widgets/button.js b/src/frameworks/tkinter/widgets/button.js index 1ecc097..1b57acb 100644 --- a/src/frameworks/tkinter/widgets/button.js +++ b/src/frameworks/tkinter/widgets/button.js @@ -1,37 +1,21 @@ -import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" -import {TkinterBase} from "./base" +import { convertObjectToKeyValueString } from "../../../utils/common" +import { TkinterWidgetBase } from "./base" -class Button extends TkinterBase{ +class Button extends TkinterWidgetBase{ static widgetType = "button" constructor(props) { super(props) - this.droppableTags = null - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.state = { ...this.state, size: { width: 80, height: 40 }, widgetName: "Button", attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, + ...this.state.attrs, buttonLabel: { label: "Button Label", tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string @@ -53,11 +37,12 @@ class Button extends TkinterBase{ generateCode(variableName, parent){ const labelText = this.getAttrValue("buttonLabel") - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") + + const config = convertObjectToKeyValueString(this.getConfigCode()) + return [ `${variableName} = tk.Button(master=${parent}, text="${labelText}")`, - `${variableName}.config(bg="${bg}", fg="${fg}")`, + `${variableName}.config(${config})`, `${variableName}.${this.getLayoutCode()}` ] } diff --git a/src/frameworks/tkinter/widgets/input.js b/src/frameworks/tkinter/widgets/input.js index 3fa170e..cdb2657 100644 --- a/src/frameworks/tkinter/widgets/input.js +++ b/src/frameworks/tkinter/widgets/input.js @@ -1,38 +1,21 @@ -import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" -import {TkinterBase} from "./base" +import { convertObjectToKeyValueString } from "../../../utils/common" +import { TkinterWidgetBase } from "./base" -export class Input extends TkinterBase{ +export class Input extends TkinterWidgetBase{ static widgetType = "entry" constructor(props) { super(props) - this.droppableTags = null // disables drops - - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.state = { ...this.state, size: { width: 120, height: 40 }, widgetName: "Entry", attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, + ...this.state.attrs, placeHolder: { label: "PlaceHolder", tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string @@ -52,12 +35,13 @@ export class Input extends TkinterBase{ generateCode(variableName, parent){ - const placeHolderText = this.getAttrValue("labelWidget") - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") + const placeHolderText = this.getAttrValue("placeHolder") + + const config = convertObjectToKeyValueString(this.getConfigCode()) + return [ `${variableName} = tk.Entry(master=${parent}, text="${placeHolderText}")`, - `${variableName}.config(bg="${bg}", fg="${fg}")`, + `${variableName}.config(${config})`, `${variableName}.${this.getLayoutCode()}` ] } @@ -92,34 +76,18 @@ export class Input extends TkinterBase{ } -export class Text extends TkinterBase{ +export class Text extends TkinterWidgetBase{ static widgetType = "Text" constructor(props) { super(props) - this.droppableTags = null - - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.state = { ...this.state, size: { width: 120, height: 80 }, attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, + ...this.state.attrs, placeHolder: { label: "PlaceHolder", tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string @@ -138,6 +106,19 @@ export class Text extends TkinterBase{ this.setWidgetName("text") } + generateCode(variableName, parent){ + + const placeHolderText = this.getAttrValue("placeHolder") + + const config = convertObjectToKeyValueString(this.getConfigCode()) + + return [ + `${variableName} = tk.Text(master=${parent}, text="${placeHolderText}")`, + `${variableName}.config(${config})`, + `${variableName}.${this.getLayoutCode()}` + ] + } + getToolbarAttrs(){ const toolBarAttrs = super.getToolbarAttrs() diff --git a/src/frameworks/tkinter/widgets/label.js b/src/frameworks/tkinter/widgets/label.js index ae676cd..470aa65 100644 --- a/src/frameworks/tkinter/widgets/label.js +++ b/src/frameworks/tkinter/widgets/label.js @@ -1,8 +1,6 @@ -import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" -import {TkinterBase, TkinterWidgetBase} from "./base" -import { Layouts } from "../../../canvas/constants/layouts" +import { convertObjectToKeyValueString } from "../../../utils/common" +import { TkinterWidgetBase } from "./base" class Label extends TkinterWidgetBase{ @@ -12,29 +10,13 @@ class Label extends TkinterWidgetBase{ constructor(props) { super(props) - this.droppableTags = null - - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.state = { ...this.state, widgetName: "Label", size: { width: 80, height: 40 }, attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, + ...this.state.attrs, labelWidget: { label: "Text", tool: Tools.INPUT, @@ -67,11 +49,11 @@ class Label extends TkinterWidgetBase{ generateCode(variableName, parent){ const labelText = this.getAttrValue("labelWidget") - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") + const config = convertObjectToKeyValueString(this.getConfigCode()) + return [ `${variableName} = tk.Label(master=${parent}, text="${labelText}")`, - `${variableName}.config(bg="${bg}", fg="${fg}")`, + `${variableName}.config(${config})`, `${variableName}.${this.getLayoutCode()}` ] } diff --git a/src/frameworks/tkinter/widgets/mainWindow.js b/src/frameworks/tkinter/widgets/mainWindow.js index c2ce836..2051695 100644 --- a/src/frameworks/tkinter/widgets/mainWindow.js +++ b/src/frameworks/tkinter/widgets/mainWindow.js @@ -1,8 +1,9 @@ import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" +import { TkinterBase } from "./base" -class MainWindow extends Widget{ +class MainWindow extends TkinterBase{ static widgetType = "main_window" @@ -29,6 +30,7 @@ class MainWindow extends Widget{ } } + } componentDidMount(){ diff --git a/src/frameworks/tkinter/widgets/optionMenu.js b/src/frameworks/tkinter/widgets/optionMenu.js index e6c4530..e1b82ed 100644 --- a/src/frameworks/tkinter/widgets/optionMenu.js +++ b/src/frameworks/tkinter/widgets/optionMenu.js @@ -1,47 +1,27 @@ -import Widget from "../../../canvas/widgets/base" - import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" -import { ArrowDownOutlined, DownOutlined } from "@ant-design/icons" -import {TkinterBase} from "./base" +import { DownOutlined } from "@ant-design/icons" +import { TkinterWidgetBase} from "./base" +import { convertObjectToKeyValueString } from "../../../utils/common" -class OptionMenu extends TkinterBase{ +class OptionMenu extends TkinterWidgetBase{ static widgetType = "option_menu" - // FIXME: the radio buttons are not visible because of the default heigh provided + constructor(props) { super(props) - this.droppableTags = null // disables drops - // const {layout, ...newAttrs} = this.state.attrs // Removes the layout attribute - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.minSize = {width: 50, height: 30} - - + this.state = { ...this.state, isDropDownOpen: false, widgetName: "Option menu", size: { width: 120, height: 'fit' }, attrs: { - ...newAttrs, - styling: { - label: "styling", - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, - + ...this.state.attrs, defaultValue: { label: "Default Value", tool: Tools.INPUT, @@ -50,17 +30,19 @@ class OptionMenu extends TkinterBase{ this.setAttrValue("options", {inputs, selectedRadio}) } }, - options: { + widgetOptions: { label: "Options", tool: Tools.INPUT_RADIO_LIST, value: {inputs: ["option 1"], selectedRadio: -1}, onChange: ({inputs, selectedRadio}) => { - this.setAttrValue("options", {inputs, selectedRadio}) + this.setAttrValue("widgetOptions", {inputs, selectedRadio}) } } } } + + console.log("attrs1: ", this.state.attrs) } componentDidMount(){ @@ -68,11 +50,28 @@ class OptionMenu extends TkinterBase{ this.setWidgetInnerStyle("backgroundColor", "#fff") } + generateCode(variableName, parent){ + + + const config = convertObjectToKeyValueString(this.getConfigCode()) + + const defaultValue = this.getAttrValue("defaultValue") + const options = JSON.stringify(this.getAttrValue("widgetOptions").inputs) + + return [ + `${variableName}_options = ${options}`, + `${variableName} = tk.OptionMenu(master=${parent}, ${defaultValue}, *${variableName}_options)`, + `${variableName}.config(${config})`, + `${variableName}.${this.getLayoutCode()}` + ] + } + getToolbarAttrs(){ const toolBarAttrs = super.getToolbarAttrs() const attrs = this.state.attrs + console.log("attrs: ", attrs) return ({ id: this.__id, widgetName: toolBarAttrs.widgetName, @@ -90,7 +89,7 @@ class OptionMenu extends TkinterBase{ renderContent(){ - const {inputs, selectedRadio} = this.getAttrValue("options") + const {inputs, selectedRadio} = this.getAttrValue("widgetOptions") return (
{ - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) + // this.setWidgetInnerStyle("color", value) + this.setAttrValue("styling.troughColor", value) } } }, @@ -75,6 +72,25 @@ class Slider extends TkinterBase{ this.setAttrValue("styling.backgroundColor", "#fff") } + generateCode(variableName, parent){ + // TODO: add orientation + + const config = this.getConfigCode() + + config["_from"] = this.getAttrValue("scale.min") + config["to"] = this.getAttrValue("scale.max") + config["resolution"] = this.getAttrValue("scale.step") + + const defaultValue = this.getAttrValue("defaultValue") + + return [ + `${variableName}_var = tk.DoubleVar(${defaultValue})`, + `${variableName} = tk.Scale(master=${parent}, variable=${variableName}_var)`, + `${variableName}.config(${config})`, + `${variableName}.${this.getLayoutCode()}` + ] + } + getToolbarAttrs(){ const toolBarAttrs = super.getToolbarAttrs() diff --git a/src/frameworks/tkinter/widgets/spinBox.js b/src/frameworks/tkinter/widgets/spinBox.js index c452711..9f12602 100644 --- a/src/frameworks/tkinter/widgets/spinBox.js +++ b/src/frameworks/tkinter/widgets/spinBox.js @@ -1,39 +1,23 @@ import Widget from "../../../canvas/widgets/base" import Tools from "../../../canvas/constants/tools" -import { removeKeyFromObject } from "../../../utils/common" +import { convertObjectToKeyValueString, removeKeyFromObject } from "../../../utils/common" import { DownOutlined, UpOutlined } from "@ant-design/icons" -import {TkinterBase} from "./base" +import {TkinterBase, TkinterWidgetBase} from "./base" -class SpinBox extends TkinterBase{ +class SpinBox extends TkinterWidgetBase{ static widgetType = "spin_box" constructor(props) { super(props) - this.droppableTags = null // disables drops - - const newAttrs = removeKeyFromObject("layout", this.state.attrs) - this.state = { ...this.state, size: { width: 70, height: 'fit' }, widgetName: "Spin box", attrs: { - ...newAttrs, - styling: { - ...newAttrs.styling, - foregroundColor: { - label: "Foreground Color", - tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string - value: "#000", - onChange: (value) => { - this.setWidgetInnerStyle("color", value) - this.setAttrValue("styling.foregroundColor", value) - } - } - }, + ...this.state.attrs, spinProps: { label: "Properties", display: "horizontal", @@ -81,14 +65,27 @@ class SpinBox extends TkinterBase{ const min = this.getAttrValue("spinProps.min") const max = this.getAttrValue("spinProps.max") const step = this.getAttrValue("spinProps.step") - const defaultValue = this.getAttrValue("spinProps.defaultValue") + const defaultValue = this.getAttrValue("spinProps.default") + + const config = { + from_: min, + to: max, + increment: step, + value: defaultValue, + ...this.getConfigCode() + } + + const code = [] + let spinBox = `${variableName} = tk.Spinbox(master=${parent})` + if (defaultValue){ + code.push(`${variableName}_var = tk.IntVar(${defaultValue})`) + spinBox = `${variableName} = tk.Spinbox(master=${parent}, textvariable=${variableName}_var)` + } + code.push(spinBox) - const bg = this.getAttrValue("styling.backgroundColor") - const fg = this.getAttrValue("styling.foregroundColor") return [ - `${variableName} = tk.Spinbox(master=${parent})`, - `${variableName}.config(bg="${bg}", fg="${fg}", from_=${min}, to=${max}, - increment=${step})`, + ...code, + `${variableName}.config(${convertObjectToKeyValueString(config)})`, `${variableName}.${this.getLayoutCode()}` ] } diff --git a/src/utils/common.js b/src/utils/common.js index 8d34487..5b98a0c 100644 --- a/src/utils/common.js +++ b/src/utils/common.js @@ -57,5 +57,16 @@ export function isNumeric(str) { if (typeof str != "string") return false // we only process strings! return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)... !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail - } - \ No newline at end of file +} + + +/** + * given an object with key value returns key1=value1, key2=value2 format + * @param {Object} obj + * @returns + */ +export function convertObjectToKeyValueString(obj){ + return Object.entries(obj) + .map(([key, value]) => `${key}=${value}`) + .join(', ') +} \ No newline at end of file