2024-09-25 17:27:12 +05:30
|
|
|
import { Layouts, PosType } from "../../../canvas/constants/layouts"
|
2024-09-26 11:59:24 +05:30
|
|
|
import Tools from "../../../canvas/constants/tools"
|
|
|
|
|
import Widget from "../../../canvas/widgets/base"
|
2024-09-29 19:17:11 +05:30
|
|
|
import { convertObjectToKeyValueString, removeKeyFromObject } from "../../../utils/common"
|
2024-09-27 16:04:03 +05:30
|
|
|
import { Tkinter_TO_WEB_CURSOR_MAPPING } from "../constants/cursor"
|
|
|
|
|
import { Tkinter_To_GFonts } from "../constants/fontFamily"
|
2024-09-27 19:22:33 +05:30
|
|
|
import { JUSTIFY, RELIEF } from "../constants/styling"
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2024-09-29 19:17:11 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2024-09-27 16:04:03 +05:30
|
|
|
export class TkinterBase extends Widget {
|
2024-09-26 11:59:24 +05:30
|
|
|
|
|
|
|
|
static requiredImports = ['import tkinter as tk']
|
|
|
|
|
|
|
|
|
|
constructor(props) {
|
|
|
|
|
super(props)
|
|
|
|
|
|
|
|
|
|
this.getLayoutCode = this.getLayoutCode.bind(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getLayoutCode(){
|
2024-09-30 15:30:46 +05:30
|
|
|
const {layout: parentLayout, direction, gap, align="start"} = this.getParentLayout()
|
2024-09-26 11:59:24 +05:30
|
|
|
|
2024-09-29 19:17:11 +05:30
|
|
|
const absolutePositioning = this.getAttrValue("positioning")
|
|
|
|
|
|
2024-09-26 11:59:24 +05:30
|
|
|
let layoutManager = `pack()`
|
|
|
|
|
|
2024-09-29 19:17:11 +05:30
|
|
|
if (parentLayout === Layouts.PLACE || absolutePositioning){
|
|
|
|
|
|
|
|
|
|
const config = {
|
|
|
|
|
x: this.state.pos.x,
|
|
|
|
|
y: this.state.pos.y,
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-30 15:30:46 +05:30
|
|
|
config["width"] = this.state.size.width
|
|
|
|
|
config["height"] = this.state.size.height
|
|
|
|
|
|
|
|
|
|
// if (!this.state.fitContent.width){
|
|
|
|
|
// config["width"] = this.state.size.width
|
|
|
|
|
// }
|
|
|
|
|
// if (!this.state.fitContent.height){
|
|
|
|
|
// config["height"] = this.state.size.height
|
|
|
|
|
// }
|
2024-09-29 19:17:11 +05:30
|
|
|
|
|
|
|
|
const configStr = convertObjectToKeyValueString(config)
|
|
|
|
|
|
|
|
|
|
layoutManager = `place(${configStr})`
|
|
|
|
|
|
2024-09-30 15:30:46 +05:30
|
|
|
}else if (parentLayout === Layouts.FLEX){
|
2024-09-29 19:17:11 +05:30
|
|
|
|
|
|
|
|
const config = {
|
|
|
|
|
side: direction === "row" ? "tk.LEFT" : "tk.TOP",
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-30 15:30:46 +05:30
|
|
|
if (gap > 0){
|
|
|
|
|
config["padx"] = gap
|
|
|
|
|
config["pady"] = gap
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (align === "start"){
|
|
|
|
|
config["anchor"] = "'nw'"
|
|
|
|
|
}else if (align === "center"){
|
|
|
|
|
config["anchor"] = "'center'"
|
|
|
|
|
}else if (align === "end"){
|
|
|
|
|
config["anchor"] = "'se'"
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-29 19:17:11 +05:30
|
|
|
const fillX = this.getAttrValue("flexManager.fillX")
|
|
|
|
|
const fillY = this.getAttrValue("flexManager.fillY")
|
|
|
|
|
const expand = this.getAttrValue("flexManager.expand")
|
|
|
|
|
|
|
|
|
|
if (fillX){
|
2024-09-29 20:57:10 +05:30
|
|
|
config['fill'] = `"x"`
|
2024-09-29 19:17:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fillY){
|
2024-09-29 20:57:10 +05:30
|
|
|
config['fill'] = `"y"`
|
2024-09-29 19:17:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fillX && fillY){
|
2024-09-29 20:57:10 +05:30
|
|
|
config['fill'] = `"both"`
|
2024-09-29 19:17:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (expand){
|
2024-09-29 20:57:10 +05:30
|
|
|
config['expand'] = "True"
|
2024-09-29 19:17:11 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
layoutManager = `pack(${convertObjectToKeyValueString(config)})`
|
|
|
|
|
|
2024-09-26 11:59:24 +05:30
|
|
|
}else if (parentLayout === Layouts.GRID){
|
|
|
|
|
const row = this.getAttrValue("gridManager.row")
|
2024-09-30 15:30:46 +05:30
|
|
|
const col = this.getAttrValue("gridManager.column")
|
|
|
|
|
layoutManager = `grid(row=${row}, column=${col})`
|
2024-09-26 11:59:24 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return layoutManager
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-27 23:27:07 +05:30
|
|
|
setParentLayout(layout){
|
2024-09-26 11:59:24 +05:30
|
|
|
|
2024-09-27 23:27:07 +05:30
|
|
|
if (!layout){
|
2024-09-27 16:04:03 +05:30
|
|
|
return {}
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-27 23:27:07 +05:30
|
|
|
const {layout: parentLayout, direction, gap} = layout
|
2024-09-26 11:59:24 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
// show attributes related to the layout manager
|
|
|
|
|
let updates = {
|
2024-09-27 23:27:07 +05:30
|
|
|
parentLayout: layout,
|
2024-09-25 17:27:12 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-29 23:34:26 +05:30
|
|
|
// this.removeAttr("gridManager")
|
|
|
|
|
// this.removeAttr("flexManager")
|
|
|
|
|
// this.removeAttr("positioning")
|
|
|
|
|
|
|
|
|
|
// remove gridManager, flexManager positioning
|
|
|
|
|
const {gridManager, flexManager, positioning, ...restAttrs} = this.state.attrs
|
|
|
|
|
|
2024-09-27 23:27:07 +05:30
|
|
|
if (parentLayout === Layouts.FLEX || parentLayout === Layouts.GRID) {
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2025-03-08 12:02:00 +05:30
|
|
|
// const elementRect = this.elementRef.current.getBoundingClientRect()
|
|
|
|
|
// const canvasInnerRect = this.props.canvasInnerContainerRef.current.getBoundingClientRect()
|
|
|
|
|
// const {zoom, pan} = this.props.canvasMetaData
|
|
|
|
|
// console.log("pan: ", pan, zoom)
|
|
|
|
|
// let pos = {
|
|
|
|
|
// x: ((elementRect.left - canvasInnerRect.left) - pan.x) / zoom ,
|
|
|
|
|
// y: ((elementRect.top - canvasInnerRect.top) - pan.y) / zoom
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// let parent = this.props.parentWidgetRef?.current;
|
|
|
|
|
|
|
|
|
|
// while (parent) {
|
|
|
|
|
// // accounting for nested parents
|
|
|
|
|
// const parentRect = parent.getBoundingRect()
|
|
|
|
|
// pos.x -= ((parentRect.left - canvasInnerRect.left) - pan.x) / zoom
|
|
|
|
|
// pos.y -= ((parentRect.top - canvasInnerRect.top) - pan.y) / zoom
|
|
|
|
|
|
|
|
|
|
// // Move up to the next parent (if any)
|
|
|
|
|
// parent = parent.parentWidgetRef?.current
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
// // this.setPos(pos.x, pos.y)
|
|
|
|
|
// console.log("setting pos: ", pos, elementRect, canvasInnerRect)
|
|
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
updates = {
|
|
|
|
|
...updates,
|
2025-03-08 12:02:00 +05:30
|
|
|
// pos: pos,
|
2024-09-29 19:17:11 +05:30
|
|
|
positionType: PosType.NONE,
|
|
|
|
|
}
|
|
|
|
|
// Allow optional absolute positioning if the parent layout is flex or grid
|
|
|
|
|
const updateAttrs = {
|
2024-09-29 23:34:26 +05:30
|
|
|
...restAttrs,
|
2024-09-29 19:17:11 +05:30
|
|
|
positioning: {
|
|
|
|
|
label: "Absolute positioning",
|
|
|
|
|
tool: Tools.CHECK_BUTTON,
|
|
|
|
|
value: false,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setAttrValue("positioning", value)
|
|
|
|
|
|
|
|
|
|
this.updateState({
|
|
|
|
|
positionType: value ? PosType.ABSOLUTE : PosType.NONE,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-25 17:27:12 +05:30
|
|
|
}
|
2024-09-25 19:20:05 +05:30
|
|
|
|
2024-09-29 17:51:42 +05:30
|
|
|
if (parentLayout === Layouts.FLEX){
|
|
|
|
|
updates = {
|
|
|
|
|
...updates,
|
|
|
|
|
attrs: {
|
2024-09-29 19:17:11 +05:30
|
|
|
...updateAttrs,
|
2024-09-29 17:51:42 +05:30
|
|
|
flexManager: {
|
|
|
|
|
label: "Flex Manager",
|
|
|
|
|
display: "horizontal",
|
|
|
|
|
fillX: {
|
|
|
|
|
label: "Fill X",
|
|
|
|
|
tool: Tools.CHECK_BUTTON,
|
|
|
|
|
value: false,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setAttrValue("flexManager.fillX", value)
|
|
|
|
|
const widgetStyle = {
|
|
|
|
|
...this.state.widgetOuterStyling,
|
|
|
|
|
flexGrow: value ? 1 : 0,
|
|
|
|
|
}
|
2024-09-29 19:17:11 +05:30
|
|
|
|
2024-09-29 17:51:42 +05:30
|
|
|
this.updateState({
|
|
|
|
|
widgetOuterStyling: widgetStyle,
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fillY: {
|
|
|
|
|
label: "Fill Y",
|
|
|
|
|
tool: Tools.CHECK_BUTTON,
|
|
|
|
|
value: false,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setAttrValue("flexManager.fillY", value)
|
|
|
|
|
|
|
|
|
|
const widgetStyle = {
|
|
|
|
|
...this.state.widgetOuterStyling,
|
|
|
|
|
flexGrow: value ? 1 : 0,
|
|
|
|
|
}
|
|
|
|
|
this.updateState({
|
|
|
|
|
widgetOuterStyling: widgetStyle,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
expand: {
|
|
|
|
|
label: "Expand",
|
|
|
|
|
tool: Tools.CHECK_BUTTON,
|
|
|
|
|
value: false,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setAttrValue("flexManager.expand", value)
|
|
|
|
|
|
|
|
|
|
const widgetStyle = {
|
|
|
|
|
...this.state.widgetOuterStyling,
|
|
|
|
|
flexGrow: value ? 1 : 0,
|
|
|
|
|
}
|
|
|
|
|
this.updateState({
|
|
|
|
|
widgetOuterStyling: widgetStyle,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
else if (parentLayout === Layouts.GRID) {
|
2024-09-25 17:27:12 +05:30
|
|
|
// Set attributes related to grid layout manager
|
|
|
|
|
updates = {
|
|
|
|
|
...updates,
|
|
|
|
|
attrs: {
|
2024-09-29 19:17:11 +05:30
|
|
|
...updateAttrs,
|
2024-09-25 17:27:12 +05:30
|
|
|
gridManager: {
|
|
|
|
|
label: "Grid manager",
|
|
|
|
|
display: "horizontal",
|
|
|
|
|
row: {
|
|
|
|
|
label: "Row",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
|
|
|
|
toolProps: { placeholder: "width", max: 1000, min: 1 },
|
|
|
|
|
value: 1,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
|
|
|
|
|
const previousRow = this.getWidgetOuterStyle("gridRow") || "1/1"
|
2024-09-25 19:20:05 +05:30
|
|
|
|
|
|
|
|
let [_row=1, rowSpan=1] = previousRow.replace(/\s+/g, '').split("/").map(Number)
|
|
|
|
|
|
|
|
|
|
if (value > rowSpan){
|
|
|
|
|
// rowSpan should always be greater than or eq to row
|
|
|
|
|
rowSpan = value
|
|
|
|
|
this.setAttrValue("gridManager.rowSpan", rowSpan)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setAttrValue("gridManager.row", value)
|
2024-09-25 17:27:12 +05:30
|
|
|
this.setWidgetOuterStyle("gridRow", `${value+' / '+rowSpan}`)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
rowSpan: {
|
|
|
|
|
label: "Row span",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
|
|
|
|
toolProps: { placeholder: "height", max: 1000, min: 1 },
|
|
|
|
|
value: 1,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
|
|
|
|
|
const previousRow = this.getWidgetOuterStyle("gridRow") || "1/1"
|
2024-09-25 19:20:05 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
const [row=1, _rowSpan=1] = previousRow.replace(/\s+/g, '').split("/").map(Number)
|
2024-09-25 19:20:05 +05:30
|
|
|
|
|
|
|
|
if (value < row){
|
|
|
|
|
value = row + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setAttrValue("gridManager.rowSpan", value)
|
2024-09-25 17:27:12 +05:30
|
|
|
this.setWidgetOuterStyle("gridRow", `${row + ' / ' +value}`)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
column: {
|
|
|
|
|
label: "Column",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
|
|
|
|
toolProps: { placeholder: "height", max: 1000, min: 1 },
|
|
|
|
|
value: 1,
|
|
|
|
|
onChange: (value) => {
|
|
|
|
|
|
|
|
|
|
const previousRow = this.getWidgetOuterStyle("gridColumn") || "1/1"
|
|
|
|
|
|
2024-09-25 19:20:05 +05:30
|
|
|
let [_col=1, colSpan=1] = previousRow.replace(/\s+/g, '').split("/").map(Number)
|
|
|
|
|
|
|
|
|
|
if (value > colSpan){
|
|
|
|
|
// The colSpan has always be equal or greater than col
|
|
|
|
|
colSpan = value
|
|
|
|
|
this.setAttrValue("gridManager.columnSpan", colSpan)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setAttrValue("gridManager.column", value)
|
2024-09-25 17:27:12 +05:30
|
|
|
this.setWidgetOuterStyle("gridColumn", `${value +' / ' + colSpan}`)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
columnSpan: {
|
|
|
|
|
label: "Column span",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
|
|
|
|
toolProps: { placeholder: "height", max: 1000, min: 1 },
|
|
|
|
|
value: 1,
|
|
|
|
|
onChange: (value) => {
|
2024-09-25 19:20:05 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
const previousCol = this.getWidgetOuterStyle("gridColumn") || "1/1"
|
|
|
|
|
|
|
|
|
|
const [col=1, _colSpan=1] = previousCol.replace(/\s+/g, '').split("/").map(Number)
|
|
|
|
|
|
2024-09-25 19:20:05 +05:30
|
|
|
if (value < col){
|
|
|
|
|
value = col + 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.setAttrValue("gridManager.columnSpan", value)
|
2024-09-25 17:27:12 +05:30
|
|
|
this.setWidgetOuterStyle("gridColumn", `${col + ' / ' + value}`)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-27 23:27:07 +05:30
|
|
|
} else if (parentLayout === Layouts.PLACE) {
|
2024-09-25 17:27:12 +05:30
|
|
|
updates = {
|
|
|
|
|
...updates,
|
|
|
|
|
positionType: PosType.ABSOLUTE
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.updateState(updates)
|
|
|
|
|
|
|
|
|
|
return updates
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-29 19:17:11 +05:30
|
|
|
getInnerRenderStyling(){
|
|
|
|
|
let {width, height, minWidth, minHeight} = this.getRenderSize()
|
|
|
|
|
|
|
|
|
|
const {layout: parentLayout, direction, gap} = this.getParentLayout() || {}
|
|
|
|
|
|
|
|
|
|
if (parentLayout === Layouts.FLEX){
|
|
|
|
|
const fillX = this.getAttrValue("flexManager.fillX")
|
|
|
|
|
const fillY = this.getAttrValue("flexManager.fillY")
|
|
|
|
|
|
|
|
|
|
// This is needed if fillX or fillY is true, as the parent is applied flex-grow
|
|
|
|
|
|
|
|
|
|
if (fillX || fillY){
|
|
|
|
|
width = "100%"
|
|
|
|
|
height = "100%"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const styling = {
|
|
|
|
|
...this.state.widgetInnerStyling,
|
|
|
|
|
width,
|
|
|
|
|
height,
|
|
|
|
|
minWidth,
|
|
|
|
|
minHeight
|
|
|
|
|
}
|
|
|
|
|
return styling
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
/**
|
|
|
|
|
* loads the data
|
|
|
|
|
* @param {object} data
|
|
|
|
|
*/
|
2024-09-25 23:29:50 +05:30
|
|
|
load(data, callback=null){
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2025-03-06 19:20:40 +05:30
|
|
|
// TODO: call the base widget
|
|
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
if (Object.keys(data).length === 0) return // no data to load
|
|
|
|
|
|
|
|
|
|
data = {...data} // create a shallow copy
|
|
|
|
|
|
2024-09-27 16:04:03 +05:30
|
|
|
const {attrs, parentLayout=null, ...restData} = data
|
2024-09-25 17:27:12 +05:30
|
|
|
|
|
|
|
|
|
|
|
|
|
let layoutUpdates = {
|
|
|
|
|
parentLayout: parentLayout
|
|
|
|
|
}
|
2024-09-27 16:04:03 +05:30
|
|
|
|
|
|
|
|
if (parentLayout){
|
|
|
|
|
if (parentLayout.layout === Layouts.FLEX || parentLayout.layout === Layouts.GRID){
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2024-09-27 16:04:03 +05:30
|
|
|
layoutUpdates = {
|
|
|
|
|
...layoutUpdates,
|
|
|
|
|
positionType: PosType.NONE
|
|
|
|
|
}
|
2024-09-25 17:27:12 +05:30
|
|
|
|
2024-09-27 16:04:03 +05:30
|
|
|
}else if (parentLayout.layout === Layouts.PLACE){
|
|
|
|
|
layoutUpdates = {
|
|
|
|
|
...layoutUpdates,
|
|
|
|
|
positionType: PosType.ABSOLUTE
|
|
|
|
|
}
|
2024-09-25 17:27:12 +05:30
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const newData = {
|
|
|
|
|
...restData,
|
|
|
|
|
...layoutUpdates
|
|
|
|
|
}
|
2024-09-27 16:04:03 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
|
|
|
|
|
this.setState(newData, () => {
|
2024-09-27 23:27:07 +05:30
|
|
|
let layoutAttrs = this.setParentLayout(parentLayout).attrs || {}
|
|
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
// UPdates attrs
|
|
|
|
|
let newAttrs = { ...this.state.attrs, ...layoutAttrs }
|
|
|
|
|
|
|
|
|
|
// Iterate over each path in the updates object
|
|
|
|
|
Object.entries(attrs).forEach(([path, value]) => {
|
|
|
|
|
const keys = path.split('.')
|
|
|
|
|
const lastKey = keys.pop()
|
|
|
|
|
|
|
|
|
|
// Traverse the nested object within attrs
|
|
|
|
|
let nestedObject = newAttrs
|
|
|
|
|
|
|
|
|
|
keys.forEach(key => {
|
|
|
|
|
nestedObject[key] = { ...nestedObject[key] } // Ensure immutability for each nested level
|
|
|
|
|
nestedObject = nestedObject[key]
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// Set the value at the last key
|
|
|
|
|
if (nestedObject[lastKey])
|
|
|
|
|
nestedObject[lastKey].value = value
|
|
|
|
|
})
|
|
|
|
|
|
2024-09-25 23:29:50 +05:30
|
|
|
|
|
|
|
|
if (newAttrs?.styling?.backgroundColor){
|
|
|
|
|
// TODO: find a better way to apply innerStyles
|
|
|
|
|
this.setWidgetInnerStyle("backgroundColor", newAttrs.styling.backgroundColor.value)
|
|
|
|
|
}
|
2024-09-27 16:04:03 +05:30
|
|
|
|
2024-09-25 23:29:50 +05:30
|
|
|
this.updateState({ attrs: newAttrs }, callback)
|
2024-09-25 17:27:12 +05:30
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
2025-03-06 19:20:40 +05:30
|
|
|
|
2024-09-25 17:27:12 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2024-09-27 16:04:03 +05:30
|
|
|
// 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})),
|
2024-09-27 19:22:33 +05:30
|
|
|
value: "",
|
2024-09-27 16:04:03 +05:30
|
|
|
onChange: (value) => {
|
2024-09-27 19:22:33 +05:30
|
|
|
// this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value])
|
|
|
|
|
this.setAttrValue("styling.relief", value)
|
2024-09-27 16:04:03 +05:30
|
|
|
}
|
2024-09-27 19:22:33 +05:30
|
|
|
},
|
|
|
|
|
// 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)
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-09-27 16:04:03 +05:30
|
|
|
},
|
|
|
|
|
font: {
|
|
|
|
|
label: "font",
|
|
|
|
|
fontFamily: {
|
|
|
|
|
label: "font family",
|
|
|
|
|
tool: Tools.SELECT_DROPDOWN,
|
|
|
|
|
options: Object.keys(Tkinter_To_GFonts).map((val) => ({value: val, label: val})),
|
2024-09-29 17:51:42 +05:30
|
|
|
value: "",
|
2024-09-27 16:04:03 +05:30
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setWidgetInnerStyle("fontFamily", Tkinter_To_GFonts[value])
|
|
|
|
|
this.setAttrValue("font.fontFamily", value)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
fontSize: {
|
|
|
|
|
label: "font size",
|
|
|
|
|
tool: Tools.NUMBER_INPUT,
|
2024-09-29 17:51:42 +05:30
|
|
|
toolProps: {min: 3, max: 140},
|
2024-09-27 19:22:33 +05:30
|
|
|
value: null,
|
2024-09-27 16:04:03 +05:30
|
|
|
onChange: (value) => {
|
|
|
|
|
this.setWidgetInnerStyle("fontSize", `${value}px`)
|
|
|
|
|
this.setAttrValue("font.fontSize", value)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
cursor: {
|
|
|
|
|
label: "Cursor",
|
|
|
|
|
tool: Tools.SELECT_DROPDOWN,
|
|
|
|
|
toolProps: {placeholder: "select cursor"},
|
2024-09-27 19:22:33 +05:30
|
|
|
value: "",
|
2024-09-27 16:04:03 +05:30
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-27 19:22:33 +05:30
|
|
|
|
|
|
|
|
this.getConfigCode = this.getConfigCode.bind(this)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
getConfigCode(){
|
|
|
|
|
|
2024-09-30 15:54:09 +05:30
|
|
|
const config = {
|
2024-09-27 19:22:33 +05:30
|
|
|
bg: `"${this.getAttrValue("styling.backgroundColor")}"`,
|
|
|
|
|
fg: `"${this.getAttrValue("styling.foregroundColor")}"`,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.getAttrValue("styling.borderWidth"))
|
2024-09-30 15:54:09 +05:30
|
|
|
config["bd"] = this.getAttrValue("styling.borderWidth")
|
2024-09-27 19:22:33 +05:30
|
|
|
|
|
|
|
|
if (this.getAttrValue("styling.relief"))
|
2025-01-01 16:43:25 +05:30
|
|
|
config["relief"] = `tk.${this.getAttrValue("styling.relief")}`
|
2024-09-27 19:22:33 +05:30
|
|
|
|
|
|
|
|
if (this.getAttrValue("font.fontFamily") || this.getAttrValue("font.fontSize")){
|
2024-09-30 15:54:09 +05:30
|
|
|
config["font"] = `("${this.getAttrValue("font.fontFamily")}", ${this.getAttrValue("font.fontSize") || 12}, )`
|
2024-09-27 19:22:33 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.getAttrValue("cursor"))
|
2024-09-30 15:54:09 +05:30
|
|
|
config["cursor"] = `"${this.getAttrValue("cursor")}"`
|
2024-09-27 19:22:33 +05:30
|
|
|
|
|
|
|
|
if (this.getAttrValue("padding.padX")){
|
2024-09-30 15:54:09 +05:30
|
|
|
config["padx"] = this.getAttrValue("padding.padX")
|
2024-09-27 19:22:33 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (this.getAttrValue("padding.padY")){
|
2024-09-30 15:54:09 +05:30
|
|
|
config["pady"] = this.getAttrValue("padding.padY")
|
2024-09-27 19:22:33 +05:30
|
|
|
}
|
|
|
|
|
|
2024-09-30 15:54:09 +05:30
|
|
|
// FIXME: add width and height, the scales may not be correct as the width and height are based on characters in pack and grid not pixels
|
|
|
|
|
// if (!this.state.fitContent.width){
|
|
|
|
|
// config["width"] = this.state.size.width
|
|
|
|
|
// }
|
|
|
|
|
// if (!this.state.fitContent.height){
|
|
|
|
|
// config["height"] = this.state.size.height
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
return config
|
2024-09-27 16:04:03 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|