adding more widget attributes

This commit is contained in:
paul
2024-09-27 16:04:03 +05:30
parent 7b4446d9ee
commit 77b1c5a0f0
16 changed files with 251 additions and 58 deletions

View File

@@ -0,0 +1,43 @@
export const Tkinter_TO_WEB_CURSOR_MAPPING = {
"arrow": "default",
"circle": "wait",
"clock": "wait",
"cross": "crosshair",
"dotbox": "not-allowed",
"exchange": "alias",
"fleur": "move",
"heart": "default", // mapping doesn't exist
"man": "default",
"mouse": "default",
"pirate": "default",
"plus": "zoom-in",
"shuttle": "default",
"sizing": "se-resize",
"spider": "default",
"spraycan": "default",
"star": "default",
"target": "cell",
"tcross": "crosshair",
"trek": "default",
"watch": "wait",
"X_cursor": "not-allowed",
"bottom_left_corner": "sw-resize",
"bottom_right_corner": "se-resize",
"bottom_side": "s-resize",
"top_left_corner": "nw-resize",
"top_right_corner": "ne-resize",
"top_side": "n-resize",
"left_side": "w-resize",
"right_side": "e-resize",
"hand1": "pointer",
"hand2": "pointer",
"sb_h_double_arrow": "ew-resize",
"sb_v_double_arrow": "ns-resize",
"center_ptr": "default",
"question_arrow": "help",
"umbrella": "default",
"pencil": "copy",
}

View File

@@ -0,0 +1,20 @@
export const Tkinter_To_GFonts= {
"Arial": "Roboto",
"Courier": "Courier Prime",
"Comic Sans MS": "Comic Neue",
"Fixedsys": "Cousine",
"Helvetica": "Roboto",
"Times": "Merriweather",
"System": "Noto Sans",
"Verdana": "Open Sans",
"Symbol": "Noto Sans Symbols",
"TkDefaultFont": "Noto Sans",
"TkFixedFont": "Source Code Pro",
"TkMenuFont": "Roboto",
"TkHeadingFont": "Montserrat",
"TkTextFont": "Roboto",
"TkTooltipFont": "Lato",
}

View File

@@ -0,0 +1,8 @@
export const RELIEF = [
"FLAT",
"RAISED",
"SUNKEN",
"GROOVE",
"RIDGE"
]

View File

@@ -3,32 +3,29 @@ import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import { CheckSquareFilled } from "@ant-design/icons"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
export class CheckBox extends TkinterBase{
static widgetType = "check_button"
// TODO: remove layouts
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: 30 },
widgetName: "Check box",
attrs: {
...newAttrs,
styling: {
label: "Styling",
...newAttrs.styling,
foregroundColor: {
label: "Foreground Color",
tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string
@@ -60,7 +57,6 @@ export class CheckBox extends TkinterBase{
componentDidMount(){
super.componentDidMount()
// this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("Checkbox")
this.setWidgetInnerStyle("backgroundColor", "#fff0")
}
@@ -126,7 +122,7 @@ export class CheckBox extends TkinterBase{
}
export class RadioButton extends Widget{
export class RadioButton extends TkinterBase{
static widgetType = "radio_button"
@@ -146,10 +142,11 @@ export class RadioButton extends Widget{
this.state = {
...this.state,
size: { width: 120, height: 'fit' },
widgetName: "Radio button",
attrs: {
...newAttrs,
styling: {
label: "styling",
...newAttrs.styling,
foregroundColor: {
label: "Foreground Color",
tool: Tools.COLOR_PICKER, // the tool to display, can be either HTML ELement or a constant string
@@ -178,7 +175,6 @@ export class RadioButton extends Widget{
componentDidMount(){
super.componentDidMount()
// this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("Radio button")
this.setWidgetInnerStyle("backgroundColor", "#fff0")
}
@@ -187,19 +183,26 @@ export class RadioButton extends Widget{
const bg = this.getAttrValue("styling.backgroundColor")
const fg = this.getAttrValue("styling.foregroundColor")
const radios = this.getAttrValue("radios")
// TODO: from here
const code = [
`${variableName}_var = tk.IntVar()`,
`${variableName} = tk.Radiobutton(master=${parent}, text="")`,
`${variableName}.config(bg="${bg}", fg="${fg}")`,
]
`${variableName}_var = tk.IntVar()`,
]
const radios = this.getAttrValue("radios")
if (this.getAttrValue("defaultChecked")){
code.push(`${variableName}.select()`)
radios.inputs.forEach((radio_text, idx) => {
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}.${this.getLayoutCode()}`)
})
const defaultSelected = radios.selectedRadio
if (defaultSelected !== -1){
code.push(`${variableName}_var.set(${defaultSelected})`)
}
code.push(`${variableName}.${this.getLayoutCode()}`)
return code
}

View File

@@ -1,11 +1,15 @@
import { Layouts, PosType } from "../../../canvas/constants/layouts"
import Tools from "../../../canvas/constants/tools"
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"
// TODO: add full width and full height in base widget
// TODO: the pack should configure width and height of widgets
class TkinterBase extends Widget {
export class TkinterBase extends Widget {
static requiredImports = ['import tkinter as tk']
@@ -36,6 +40,10 @@ class TkinterBase extends Widget {
setParentLayout(parentLayout){
if (!parentLayout){
return {}
}
const {layout, direction, gap} = parentLayout
// show attributes related to the layout manager
@@ -168,24 +176,26 @@ class TkinterBase extends Widget {
data = {...data} // create a shallow copy
const {attrs, parentLayout, ...restData} = data
const {attrs, parentLayout=null, ...restData} = data
let layoutUpdates = {
parentLayout: parentLayout
}
if (parentLayout){
if (parentLayout.layout === Layouts.FLEX || parentLayout.layout === Layouts.GRID){
if (parentLayout.layout === Layouts.FLEX || parentLayout.layout === Layouts.GRID){
layoutUpdates = {
...layoutUpdates,
positionType: PosType.NONE
}
layoutUpdates = {
...layoutUpdates,
positionType: PosType.NONE
}
}else if (parentLayout.layout === Layouts.PLACE){
layoutUpdates = {
...layoutUpdates,
positionType: PosType.ABSOLUTE
}else if (parentLayout.layout === Layouts.PLACE){
layoutUpdates = {
...layoutUpdates,
positionType: PosType.ABSOLUTE
}
}
}
@@ -193,6 +203,8 @@ class TkinterBase extends Widget {
...restData,
...layoutUpdates
}
console.log("new data: ", newData)
this.setState(newData, () => {
let layoutAttrs = this.setParentLayout(parentLayout) || {}
@@ -223,7 +235,7 @@ class TkinterBase extends Widget {
// TODO: find a better way to apply innerStyles
this.setWidgetInnerStyle("backgroundColor", newAttrs.styling.backgroundColor.value)
}
this.updateState({ attrs: newAttrs }, callback)
})
@@ -235,4 +247,89 @@ class TkinterBase extends Widget {
}
export default TkinterBase
// base for widgets that have common base properties such as bg, fg, cursor etc
export class TkinterWidgetBase extends TkinterBase{
constructor(props) {
super(props)
this.droppableTags = null // disables drops
const newAttrs = removeKeyFromObject("layout", this.state.attrs)
this.state = {
...this.state,
attrs: {
...newAttrs,
styling: {
...newAttrs.styling,
foregroundColor: {
label: "Foreground Color",
tool: Tools.COLOR_PICKER,
value: "#000",
onChange: (value) => {
this.setWidgetInnerStyle("color", value)
this.setAttrValue("styling.foregroundColor", value)
}
},
borderWidth: {
label: "Border thickness",
tool: Tools.NUMBER_INPUT,
toolProps: {min: 0, max: 10},
value: 0,
onChange: (value) => {
this.setWidgetInnerStyle("border", `${value}px solid black`)
this.setAttrValue("styling.borderWidth", value)
}
},
relief: {
label: "Relief",
tool: Tools.SELECT_DROPDOWN,
options: RELIEF.map((val) => ({value: val, label: val})),
value: "Arial",
onChange: (value) => {
this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value])
this.setAttrValue("font.fontFamily", value)
}
}
},
font: {
label: "font",
fontFamily: {
label: "font family",
tool: Tools.SELECT_DROPDOWN,
options: Object.keys(Tkinter_To_GFonts).map((val) => ({value: val, label: val})),
value: "Arial",
onChange: (value) => {
this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value])
this.setAttrValue("font.fontFamily", value)
}
},
fontSize: {
label: "font size",
tool: Tools.NUMBER_INPUT,
toolProps: {min: 1, max: 140},
value: 14,
onChange: (value) => {
console.log("font size: ", value)
this.setWidgetInnerStyle("fontSize", `${value}px`)
this.setAttrValue("font.fontSize", value)
}
}
},
cursor: {
label: "Cursor",
tool: Tools.SELECT_DROPDOWN,
toolProps: {placeholder: "select cursor"},
value: Tkinter_TO_WEB_CURSOR_MAPPING["arrow"],
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])
this.setAttrValue("cursor", value)
}
},
}
}
}
}

View File

@@ -1,7 +1,7 @@
import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
class Button extends TkinterBase{
@@ -17,6 +17,7 @@ class Button extends TkinterBase{
this.state = {
...this.state,
size: { width: 80, height: 40 },
widgetName: "Button",
attrs: {
...newAttrs,
styling: {
@@ -46,7 +47,6 @@ class Button extends TkinterBase{
componentDidMount(){
super.componentDidMount()
this.setWidgetName("button")
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
}

View File

@@ -1,5 +1,5 @@
import Widget from "../../../canvas/widgets/base"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
class Frame extends TkinterBase{
@@ -12,6 +12,17 @@ class Frame extends TkinterBase{
this.droppableTags = {
exclude: ["image", "video", "media", "toplevel", "main_window"]
}
this.state = {
...this.state,
widgetName: "Frame"
}
}
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#EDECEC")
}
generateCode(variableName, parent){
@@ -25,11 +36,7 @@ class Frame extends TkinterBase{
]
}
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#EDECEC")
this.setWidgetName("frame")
}
renderContent(){
// console.log("widget styling: ", this.state.widgetInnerStyling)

View File

@@ -1,7 +1,7 @@
import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
export class Input extends TkinterBase{
@@ -18,6 +18,7 @@ export class Input extends TkinterBase{
this.state = {
...this.state,
size: { width: 120, height: 40 },
widgetName: "Entry",
attrs: {
...newAttrs,
styling: {
@@ -47,7 +48,6 @@ export class Input extends TkinterBase{
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("Entry")
}
generateCode(variableName, parent){

View File

@@ -1,11 +1,11 @@
import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import TkinterBase from "./base"
import {TkinterBase, TkinterWidgetBase} from "./base"
import { Layouts } from "../../../canvas/constants/layouts"
class Label extends TkinterBase{
class Label extends TkinterWidgetBase{
static widgetType = "label"
@@ -19,6 +19,7 @@ class Label extends TkinterBase{
this.state = {
...this.state,
widgetName: "Label",
size: { width: 80, height: 40 },
attrs: {
...newAttrs,
@@ -50,12 +51,16 @@ class Label extends TkinterBase{
},
}
}
}
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
this.setWidgetName("label")
// this.setWidgetName("label") // Don't do this this causes issues while loading data
}
@@ -89,9 +94,10 @@ class Label extends TkinterBase{
renderContent(){
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-content-start tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-content-center tw-place-items-center " style={this.state.widgetInnerStyling}>
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-content-center tw-place-items-center "
style={this.state.widgetInnerStyling}>
{/* {this.props.children} */}
<div className="tw-text-sm" style={{color: this.getAttrValue("styling.foregroundColor")}}>
<div className="" style={{color: this.getAttrValue("styling.foregroundColor")}}>
{this.getAttrValue("labelWidget")}
</div>
</div>

View File

@@ -18,6 +18,7 @@ class MainWindow extends Widget{
size: { width: 700, height: 400 },
attrs: {
...this.state.attrs,
widgetName: "main",
title: {
label: "Window Title",
tool: Tools.INPUT, // the tool to display, can be either HTML ELement or a constant string
@@ -33,7 +34,7 @@ class MainWindow extends Widget{
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
this.setWidgetName("main")
// this.setWidgetName("main") // Don't do this as this will cause conflicts while loading names
}
generateCode(variableName, parent){

View File

@@ -3,7 +3,7 @@ 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 {TkinterBase} from "./base"
class OptionMenu extends TkinterBase{
@@ -25,6 +25,7 @@ class OptionMenu extends TkinterBase{
this.state = {
...this.state,
isDropDownOpen: false,
widgetName: "Option menu",
size: { width: 120, height: 'fit' },
attrs: {
...newAttrs,
@@ -64,8 +65,6 @@ class OptionMenu extends TkinterBase{
componentDidMount(){
super.componentDidMount()
// this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("Option menu")
this.setWidgetInnerStyle("backgroundColor", "#fff")
}

View File

@@ -1,7 +1,7 @@
import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
class Slider extends TkinterBase{
@@ -17,6 +17,7 @@ class Slider extends TkinterBase{
this.state = {
...this.state,
widgetName: "Scale",
size: { width: 'fit', height: 'fit' },
attrs: {
...newAttrs,
@@ -72,7 +73,6 @@ class Slider extends TkinterBase{
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("Scale")
}
getToolbarAttrs(){

View File

@@ -2,7 +2,7 @@ import Widget from "../../../canvas/widgets/base"
import Tools from "../../../canvas/constants/tools"
import { removeKeyFromObject } from "../../../utils/common"
import { DownOutlined, UpOutlined } from "@ant-design/icons"
import TkinterBase from "./base"
import {TkinterBase} from "./base"
class SpinBox extends TkinterBase{
@@ -19,6 +19,7 @@ class SpinBox extends TkinterBase{
this.state = {
...this.state,
size: { width: 70, height: 'fit' },
widgetName: "Spin box",
attrs: {
...newAttrs,
styling: {
@@ -73,7 +74,6 @@ class SpinBox extends TkinterBase{
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#fff")
this.setWidgetName("SpinBox")
}
generateCode(variableName, parent){

View File

@@ -17,6 +17,7 @@ class TopLevel extends Widget{
this.state = {
...this.state,
size: { width: 450, height: 200 },
widgetName: "top level",
attrs: {
...this.state.attrs,
title: {
@@ -34,7 +35,6 @@ class TopLevel extends Widget{
componentDidMount(){
super.componentDidMount()
this.setAttrValue("styling.backgroundColor", "#E4E2E2")
this.setWidgetName("toplevel")
}
generateCode(variableName, parent){