7 Commits

Author SHA1 Message Date
paul
bdd3bab3a5 corrected grid weight and grid config position in toolbar 2025-03-30 05:46:03 +05:30
paul
53aaa8a670 fix: fixed grid row col on load 2025-03-30 05:23:18 +05:30
paul
64631caaaa fix: fixed setState warning 2025-03-29 21:03:02 +05:30
paul
8e1f042350 fix: fixed parentLayout taking place on changing layout 2025-03-29 21:00:45 +05:30
paul
128a7c49b9 updated readme 2025-03-28 18:48:41 +05:30
paul
e0fa421459 Merge branch 'customtk-fixes' 2025-03-28 17:14:51 +05:30
Art/Paul
d64f87847c Merge pull request #12 from PaulleDemon/customtk-fixes
fixing customtk layout
2025-03-28 17:13:21 +05:30
9 changed files with 97 additions and 25 deletions

View File

@@ -30,7 +30,7 @@ https://github.com/user-attachments/assets/ac91aa98-843d-4578-b646-88e66bc113de
<sub>**Don't like background music? fell free to mute it**</sub> <sub>**Don't like background music? fell free to mute it**</sub>
## Try PyUIBuilder ## Try PyUIBuilder
Try [PyUIBuilder](https://pyuibuilder.pages.dev/) Try [PyUIBuilder](https://pyuibuilder.com)
## Table of contents ## Table of contents
@@ -53,7 +53,7 @@ Try [PyUIBuilder](https://pyuibuilder.pages.dev/)
## Docs - Getting started ## Docs - Getting started
Read the docs on the [Docs page](https://pyuibuilder-docs.pages.dev/) Read the docs on the [Docs page](https://docs.pyuibuilder.com/)
## Example app ## Example app
@@ -109,7 +109,7 @@ While there are a lot of features, here are few you need to know.
* Framework agnostic - Can outputs code in multiple frameworks. * Framework agnostic - Can outputs code in multiple frameworks.
* Pre-built UI widgets * Pre-built UI widgets
* Plugins to extend 3rd party UI libraries * Plugins to extend 3rd party UI libraries
* Supports layout managers, such as flex, grid and absolute positioning [read docs](https://pyuibuilder-docs.pages.dev/) * Supports layout managers, such as flex, grid and absolute positioning [read docs](https://docs.pyuibuilder.com/)
* Generates python Code. * Generates python Code.
* Support to upload local assets. * Support to upload local assets.
* Generates requirements.txt file when needed * Generates requirements.txt file when needed

View File

@@ -249,7 +249,7 @@
</ul> </ul>
<a <a
href="https://pyuibuilder.pages.dev/" href="https://pyuibuilder.com"
target="_blank" target="_blank"
rel="noreferrer noopener" rel="noreferrer noopener"
class=" !tw-bg-[#0F1727] tw-duration-[0.3s] hover:tw-transition-transform hover:tw-scale-[1.01] !tw-mt-auto !tw-text-white tw-gap-2 tw-text-lg tw-rounded-md tw-w-full tw-flex tw-place-content-center tw-p-2 tw-mx-2" class=" !tw-bg-[#0F1727] tw-duration-[0.3s] hover:tw-transition-transform hover:tw-scale-[1.01] !tw-mt-auto !tw-text-white tw-gap-2 tw-text-lg tw-rounded-md tw-w-full tw-flex tw-place-content-center tw-p-2 tw-mx-2"

View File

@@ -214,6 +214,7 @@ class Widget extends React.Component {
this.stateUpdateCallback = null // allowing other components such as toolbar to subscribe to changes in this widget this.stateUpdateCallback = null // allowing other components such as toolbar to subscribe to changes in this widget
this.resizeObserver = null this.resizeObserver = null
} }
@@ -704,8 +705,7 @@ class Widget extends React.Component {
} }
getLayout(){ getLayout(){
return this.getAttrValue("layout") || {layout: Layouts.PLACE}
return this.getAttrValue("layout") || Layouts.PLACE
} }
setLayout(value) { setLayout(value) {

View File

@@ -2,6 +2,7 @@
export const Tkinter_TO_WEB_CURSOR_MAPPING = { export const Tkinter_TO_WEB_CURSOR_MAPPING = {
"": "",
"arrow": "default", "arrow": "default",
"circle": "wait", "circle": "wait",
"clock": "wait", "clock": "wait",

View File

@@ -686,9 +686,14 @@ export class CustomTkBase extends Widget {
setLayout(value) { setLayout(value) {
const { layout, direction, grid = { rows: 1, cols: 1 }, gap = 10, align } = value const { layout, direction, grid = { rows: 1, cols: 1 }, gap = 10, align } = value
const gridRow = this.getAttrValue("gridConfig.noOfRows") || 3 // suppose its loaded using this.load, we need this
const gridCol = this.getAttrValue("gridConfig.noOfCols") || 3
if (layout === Layouts.GRID){ if (layout === Layouts.GRID){
const rowWeight = this.getAttrValue("gridWeights.rowWeights") || undefined // suppose its loaded via this.load
const colWeight = this.getAttrValue("gridWeights.colWeights") || undefined // suppose its loaded via this.load
const {...restAttrs} = this.state.attrs const {...restAttrs} = this.state.attrs
@@ -702,7 +707,7 @@ export class CustomTkBase extends Widget {
label: "No of rows", label: "No of rows",
tool: Tools.NUMBER_INPUT, tool: Tools.NUMBER_INPUT,
toolProps: { placeholder: "no of rows", max: 1000, min: 1 }, toolProps: { placeholder: "no of rows", max: 1000, min: 1 },
value: 3, value: gridRow,
onChange: (value) => { onChange: (value) => {
this.setAttrValue("gridConfig.noOfRows", value) this.setAttrValue("gridConfig.noOfRows", value)
@@ -728,7 +733,7 @@ export class CustomTkBase extends Widget {
label: "No of cols", label: "No of cols",
tool: Tools.NUMBER_INPUT, tool: Tools.NUMBER_INPUT,
toolProps: { placeholder: "no of cols", max: 1000, min: 1 }, toolProps: { placeholder: "no of cols", max: 1000, min: 1 },
value: 3, value: gridCol,
onChange: (value) => { onChange: (value) => {
this.setAttrValue("gridConfig.noOfCols", value) this.setAttrValue("gridConfig.noOfCols", value)
@@ -752,7 +757,7 @@ export class CustomTkBase extends Widget {
// placeholder: "weight", // placeholder: "weight",
// defaultWeightMapping: this.getAttrValue("gridWeights.rowWeights"), // defaultWeightMapping: this.getAttrValue("gridWeights.rowWeights"),
}, },
value: undefined, value: rowWeight,
Component: DynamicGridWeightInput, Component: DynamicGridWeightInput,
onChange: (value) => { onChange: (value) => {
@@ -780,7 +785,7 @@ export class CustomTkBase extends Widget {
// placeholder: "weight", // placeholder: "weight",
// defaultWeightMapping: {0: {weight: 0, gridNo: 0}} // defaultWeightMapping: {0: {weight: 0, gridNo: 0}}
}, },
value: undefined, value: colWeight,
Component: DynamicGridWeightInput, Component: DynamicGridWeightInput,
onChange: (value) => { onChange: (value) => {
@@ -811,8 +816,6 @@ export class CustomTkBase extends Widget {
}else if (layout === Layouts.FLEX){ }else if (layout === Layouts.FLEX){
const {gridConfig, gridWeights, ...restAttrs} = this.state.attrs const {gridConfig, gridWeights, ...restAttrs} = this.state.attrs
console.log("Flex: ", restAttrs)
this.updateState((prevState) => ({attrs: {...restAttrs}})) this.updateState((prevState) => ({attrs: {...restAttrs}}))
} }
@@ -886,6 +889,18 @@ export class CustomTkBase extends Widget {
} }
getToolbarAttrs(){
const {layout, gridConfig, gridWeights, ...toolBarAttrs} = super.getToolbarAttrs()
// places layout at the end
return ({
id: this.__id,
...toolBarAttrs,
layout,
gridConfig,
gridWeights
})
}
serialize(){ serialize(){
return ({ return ({
@@ -938,6 +953,7 @@ export class CustomTkBase extends Widget {
pos pos
} }
const {layout} = attrs
this.setState(newData, () => { this.setState(newData, () => {
let layoutAttrs = this.setParentLayout(parentLayout).attrs || {} let layoutAttrs = this.setParentLayout(parentLayout).attrs || {}
@@ -973,6 +989,10 @@ export class CustomTkBase extends Widget {
if (selected){ if (selected){
this.select() this.select()
} }
if (layout){
this.setLayout(layout)
}
}) })

View File

@@ -161,6 +161,20 @@ class Frame extends CustomTkBase{
] ]
} }
getToolbarAttrs(){
const {layout, gridConfig, gridWeights, ...toolBarAttrs} = super.getToolbarAttrs()
// places layout at the end
return ({
id: this.__id,
...toolBarAttrs,
padding: this.state.attrs.padding,
margin: this.state.attrs.margin,
layout,
gridConfig,
gridWeights
})
}
renderContent(){ renderContent(){
// console.log("bounding rect: ", this.getBoundingRect()) // console.log("bounding rect: ", this.getBoundingRect())

View File

@@ -2,6 +2,7 @@
export const Tkinter_TO_WEB_CURSOR_MAPPING = { export const Tkinter_TO_WEB_CURSOR_MAPPING = {
"": "",
"arrow": "default", "arrow": "default",
"circle": "wait", "circle": "wait",
"clock": "wait", "clock": "wait",

View File

@@ -687,9 +687,13 @@ export class TkinterBase extends Widget {
setLayout(value) { setLayout(value) {
const { layout, direction, grid = { rows: 1, cols: 1 }, gap = 10, align } = value const { layout, direction, grid = { rows: 1, cols: 1 }, gap = 10, align } = value
const gridRow = this.getAttrValue("gridConfig.noOfRows") || 3 // suppose its loaded using this.load, we need this
const gridCol = this.getAttrValue("gridConfig.noOfCols") || 3
if (layout === Layouts.GRID){ if (layout === Layouts.GRID){
const rowWeight = this.getAttrValue("gridWeights.rowWeights") || undefined // suppose its loaded via this.load
const colWeight = this.getAttrValue("gridWeights.colWeights") || undefined // suppose its loaded via this.load
const {...restAttrs} = this.state.attrs const {...restAttrs} = this.state.attrs
@@ -703,7 +707,7 @@ export class TkinterBase extends Widget {
label: "No of rows", label: "No of rows",
tool: Tools.NUMBER_INPUT, tool: Tools.NUMBER_INPUT,
toolProps: { placeholder: "no of rows", max: 1000, min: 1 }, toolProps: { placeholder: "no of rows", max: 1000, min: 1 },
value: 3, value: gridRow,
onChange: (value) => { onChange: (value) => {
this.setAttrValue("gridConfig.noOfRows", value) this.setAttrValue("gridConfig.noOfRows", value)
@@ -729,7 +733,7 @@ export class TkinterBase extends Widget {
label: "No of cols", label: "No of cols",
tool: Tools.NUMBER_INPUT, tool: Tools.NUMBER_INPUT,
toolProps: { placeholder: "no of cols", max: 1000, min: 1 }, toolProps: { placeholder: "no of cols", max: 1000, min: 1 },
value: 3, value: gridCol,
onChange: (value) => { onChange: (value) => {
this.setAttrValue("gridConfig.noOfCols", value) this.setAttrValue("gridConfig.noOfCols", value)
@@ -753,7 +757,7 @@ export class TkinterBase extends Widget {
// placeholder: "weight", // placeholder: "weight",
// defaultWeightMapping: this.getAttrValue("gridWeights.rowWeights"), // defaultWeightMapping: this.getAttrValue("gridWeights.rowWeights"),
}, },
value: undefined, value: rowWeight,
Component: DynamicGridWeightInput, Component: DynamicGridWeightInput,
onChange: (value) => { onChange: (value) => {
@@ -781,7 +785,7 @@ export class TkinterBase extends Widget {
// placeholder: "weight", // placeholder: "weight",
// defaultWeightMapping: {0: {weight: 0, gridNo: 0}} // defaultWeightMapping: {0: {weight: 0, gridNo: 0}}
}, },
value: undefined, value: colWeight,
Component: DynamicGridWeightInput, Component: DynamicGridWeightInput,
onChange: (value) => { onChange: (value) => {
@@ -812,8 +816,6 @@ export class TkinterBase extends Widget {
}else if (layout === Layouts.FLEX){ }else if (layout === Layouts.FLEX){
const {gridConfig, gridWeights, ...restAttrs} = this.state.attrs const {gridConfig, gridWeights, ...restAttrs} = this.state.attrs
console.log("Flex: ", restAttrs)
this.updateState((prevState) => ({attrs: {...restAttrs}})) this.updateState((prevState) => ({attrs: {...restAttrs}}))
} }
@@ -827,8 +829,8 @@ export class TkinterBase extends Widget {
flexDirection: "column", flexDirection: "column",
// flexDirection: direction, // flexDirection: direction,
gap: `${gap}px`, gap: `${gap}px`,
gridTemplateColumns: "repeat(3, max-content)", gridTemplateColumns: `repeat(${gridRow}, max-content)`,
gridTemplateRows: "repeat(3, max-content)", gridTemplateRows: `repeat(${gridCol}, max-content)`,
// gridTemplateColumns: "repeat(auto-fill, minmax(100px, auto))", // gridTemplateColumns: "repeat(auto-fill, minmax(100px, auto))",
// gridTemplateRows: "repeat(auto-fill, minmax(100px, auto))", // gridTemplateRows: "repeat(auto-fill, minmax(100px, auto))",
} }
@@ -888,6 +890,19 @@ export class TkinterBase extends Widget {
} }
getToolbarAttrs(){
const {layout, gridConfig, gridWeights, ...toolBarAttrs} = super.getToolbarAttrs()
// places layout at the end
return ({
id: this.__id,
...toolBarAttrs,
layout,
gridConfig,
gridWeights
})
}
serialize(){ serialize(){
return ({ return ({
...super.serialize(), ...super.serialize(),
@@ -938,8 +953,10 @@ export class TkinterBase extends Widget {
...layoutUpdates, ...layoutUpdates,
pos pos
} }
const {layout} = attrs
this.setState(newData, () => { this.setState(newData, () => {
let layoutAttrs = this.setParentLayout(parentLayout).attrs || {} let layoutAttrs = this.setParentLayout(parentLayout).attrs || {}
@@ -965,15 +982,21 @@ export class TkinterBase extends Widget {
if (newAttrs?.styling?.backgroundColor){ if (newAttrs?.styling?.backgroundColor){
// TODO: find a better way to apply innerStyles // TODO: find a better way to apply innerStyles (we may not need this anymore)
this.setWidgetInnerStyle("backgroundColor", newAttrs.styling.backgroundColor.value) this.setWidgetInnerStyle("backgroundColor", newAttrs.styling.backgroundColor.value)
} }
this.updateState({ attrs: newAttrs }, callback) this.updateState({ attrs: newAttrs }, callback)
// FIXME: when changing layouts all the widgets are being selected // FIXME: when changing layouts all the widgets are being selected
if (selected){ if (selected){
this.select() this.select()
} }
if (layout){
this.setLayout(layout)
}
}) })

View File

@@ -161,7 +161,20 @@ class Frame extends TkinterBase{
] ]
} }
getToolbarAttrs(){
const {layout, gridConfig, gridWeights, ...toolBarAttrs} = super.getToolbarAttrs()
// places layout at the end
return ({
id: this.__id,
...toolBarAttrs,
padding: this.state.attrs.padding,
margin: this.state.attrs.margin,
layout,
gridConfig,
gridWeights
})
}
renderContent(){ renderContent(){
// console.log("bounding rect: ", this.getBoundingRect()) // console.log("bounding rect: ", this.getBoundingRect())