fixed getInnerRenderStyle for Tkinter widgets and positioning

This commit is contained in:
paul
2024-09-29 19:17:11 +05:30
parent a9a996e108
commit 5b2d5d82cd
11 changed files with 149 additions and 54 deletions

View File

@@ -95,7 +95,7 @@ export class CheckBox extends TkinterWidgetBase{
renderContent(){
return (
<div className="tw-flex tw-p-1 tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden"
style={this.state.widgetInnerStyling}
style={this.getInnerRenderStyling()}
>
<div className="tw-flex tw-gap-2 tw-w-full tw-h-full tw-place-items-center tw-place-content-center">
@@ -132,7 +132,8 @@ export class RadioButton extends TkinterWidgetBase{
this.state = {
...this.state,
size: { width: 120, height: 'fit' },
size: { width: 80, height: 30 },
fitContent: { width: true, height: true },
widgetName: "Radio button",
attrs: {
...this.state.attrs,
@@ -204,33 +205,34 @@ export class RadioButton extends TkinterWidgetBase{
return (
<div className="tw-flex tw-p-1 tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden"
style={this.state.widgetInnerStyling}
style={this.getInnerRenderStyling()}
>
{
inputs.map((value, index) => {
return (
<div key={index} className="tw-flex tw-gap-2 tw-w-full tw-h-full tw-place-items-center ">
<div className="tw-border-solid tw-border-[#D9D9D9] tw-border-2
tw-min-w-[20px] tw-min-h-[20px] tw-w-[20px] tw-h-[20px]
tw-text-blue-600 tw-flex tw-items-center tw-justify-center
tw-rounded-full tw-overflow-hidden tw-p-1">
{
selectedRadio === index &&
<div className="tw-rounded-full tw-bg-blue-600 tw-w-full tw-h-full">
<div className="tw-flex tw-flex-col tw-gap-2 tw-w-fit tw-h-fit">
{
inputs.map((value, index) => {
return (
<div key={index} className="tw-flex tw-gap-2 tw-w-full tw-h-full tw-place-items-center ">
<div className="tw-border-solid tw-border-[#D9D9D9] tw-border-2
tw-min-w-[20px] tw-min-h-[20px] tw-w-[20px] tw-h-[20px]
tw-text-blue-600 tw-flex tw-items-center tw-justify-center
tw-rounded-full tw-overflow-hidden tw-p-1">
{
selectedRadio === index &&
<div className="tw-rounded-full tw-bg-blue-600 tw-w-full tw-h-full">
</div>
}
</div>
}
</div>
<span className="tw-text-base" style={{color: this.state.widgetInnerStyling.foregroundColor}}>
{value}
</span>
</div>
<span className="tw-text-base" style={{color: this.state.widgetInnerStyling.foregroundColor}}>
{value}
</span>
</div>
)
})
}
)
})
}
</div>
</div>
)
}

View File

@@ -1,14 +1,12 @@
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 { convertObjectToKeyValueString, removeKeyFromObject } from "../../../utils/common"
import { Tkinter_TO_WEB_CURSOR_MAPPING } from "../constants/cursor"
import { Tkinter_To_GFonts } from "../constants/fontFamily"
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
// FIXME: the font code is not correctly generated
export class TkinterBase extends Widget {
@@ -23,16 +21,60 @@ export class TkinterBase extends Widget {
getLayoutCode(){
const {layout: parentLayout, direction, gap} = this.getParentLayout()
const absolutePositioning = this.getAttrValue("positioning")
let layoutManager = `pack()`
if (parentLayout === Layouts.FLEX){
layoutManager = `pack(side=${direction === "row" ? "tk.LEFT" : "tk.TOP"})`
if (parentLayout === Layouts.PLACE || absolutePositioning){
const config = {
x: this.state.pos.x,
y: this.state.pos.y,
}
if (!this.state.fitContent.width){
config["width"] = this.state.size.width
}
if (!this.state.fitContent.height){
config["height"] = this.state.size.height
}
const configStr = convertObjectToKeyValueString(config)
layoutManager = `place(${configStr})`
}if (parentLayout === Layouts.FLEX){
const config = {
side: direction === "row" ? "tk.LEFT" : "tk.TOP",
}
const fillX = this.getAttrValue("flexManager.fillX")
const fillY = this.getAttrValue("flexManager.fillY")
const expand = this.getAttrValue("flexManager.expand")
if (fillX){
config['fill'] = "'x'"
}
if (fillY){
config['fill'] = "'y'"
}
if (fillX && fillY){
config['fill'] = "'both'"
}
if (expand){
config['expand'] = 'True'
}
layoutManager = `pack(${convertObjectToKeyValueString(config)})`
}else if (parentLayout === Layouts.GRID){
const row = this.getAttrValue("gridManager.row")
const col = this.getAttrValue("gridManager.col")
layoutManager = `grid(row=${row}, col=${col})`
}else{
layoutManager = `place(x=${this.state.pos.x}, y=${this.state.pos.y})`
}
return layoutManager
@@ -53,18 +95,36 @@ export class TkinterBase extends Widget {
this.removeAttr("gridManager")
this.removeAttr("flexManager")
this.removeAttr("positioning")
if (parentLayout === Layouts.FLEX || parentLayout === Layouts.GRID) {
updates = {
...updates,
positionType: PosType.NONE
positionType: PosType.NONE,
}
// Allow optional absolute positioning if the parent layout is flex or grid
const updateAttrs = {
...this.state.attrs,
positioning: {
label: "Absolute positioning",
tool: Tools.CHECK_BUTTON,
value: false,
onChange: (value) => {
this.setAttrValue("positioning", value)
this.updateState({
positionType: value ? PosType.ABSOLUTE : PosType.NONE,
})
}
}
}
if (parentLayout === Layouts.FLEX){
updates = {
...updates,
attrs: {
...this.state.attrs,
...updateAttrs,
flexManager: {
label: "Flex Manager",
display: "horizontal",
@@ -77,9 +137,8 @@ export class TkinterBase extends Widget {
const widgetStyle = {
...this.state.widgetOuterStyling,
flexGrow: value ? 1 : 0,
minWidth: 0
}
this.updateState({
widgetOuterStyling: widgetStyle,
})
@@ -129,7 +188,7 @@ export class TkinterBase extends Widget {
updates = {
...updates,
attrs: {
...this.state.attrs,
...updateAttrs,
gridManager: {
label: "Grid manager",
display: "horizontal",
@@ -231,6 +290,34 @@ export class TkinterBase extends Widget {
return updates
}
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
}
/**
* loads the data
* @param {object} data
@@ -465,7 +552,7 @@ export class TkinterWidgetBase extends TkinterBase{
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"), ]
code["font"] = `("${this.getAttrValue("font.fontFamily")}", ${this.getAttrValue("font.fontSize") || 12}, )`
}
if (this.getAttrValue("cursor"))

View File

@@ -68,7 +68,7 @@ class Button extends TkinterWidgetBase{
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md
tw-border tw-border-solid tw-border-gray-400 tw-overflow-hidden">
<div className="tw-p-2 tw-w-full tw-flex tw-place-content-center tw-place-items-center tw-h-full tw-text-center"
style={this.state.widgetInnerStyling}>
style={this.getInnerRenderStyling()}>
{/* {this.props.children} */}
<div className="tw-text-sm" style={{color: this.getAttrValue("styling.foregroundColor")}}>
{this.getAttrValue("buttonLabel")}

View File

@@ -64,7 +64,8 @@ export class Input extends TkinterWidgetBase{
renderContent(){
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-items-center" style={this.state.widgetInnerStyling}>
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-items-center"
style={this.getInnerRenderStyling()}>
<div className="tw-text-sm tw-text-gray-300">
{this.getAttrValue("placeHolder")}
</div>
@@ -136,7 +137,8 @@ export class Text extends TkinterWidgetBase{
renderContent(){
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start " style={this.state.widgetInnerStyling}>
<div className="tw-p-2 tw-w-full tw-h-full tw-content-start "
style={this.getInnerRenderStyling()}>
<div className="tw-text-sm tw-text-gray-300">
{this.getAttrValue("placeHolder")}
</div>

View File

@@ -77,12 +77,12 @@ class Label extends TkinterWidgetBase{
const code = []
if (image.name){
code.push(`${variableName}_img = Image.open("${getPythonAssetPath(image.name, "image")}")`)
code.push(`${variableName}_img = Image.open(${getPythonAssetPath(image.name, "image")})`)
code.push(`${variableName}_img = ImageTk.PhotoImage(${variableName}_img)`)
labelInitialization = `tk.Label(master=${parent}, image="${variableName}_img", text="${labelText}")`
}
code.push("\n")
// code.push("\n")
code.push(labelInitialization)
return [
...code,

View File

@@ -79,7 +79,8 @@ class MainWindow extends TkinterBase{
</div>
</div>
</div>
<div className="tw-p-2 tw-w-full tw-relative tw-h-full tw-overflow-hidden tw-content-start" style={this.state.widgetInnerStyling}>
<div className="tw-p-2 tw-w-full tw-relative tw-h-full tw-overflow-hidden tw-content-start"
style={this.state.widgetInnerStyling}>
{this.props.children}
</div>
</div>

View File

@@ -93,7 +93,7 @@ class OptionMenu extends TkinterWidgetBase{
return (
<div className="tw-flex tw-p-1 tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden"
style={this.state.widgetInnerStyling}
style={this.getInnerRenderStyling()}
onClick={this.toggleDropDownOpen}
>
<div className="tw-flex tw-justify-between tw-gap-1">

View File

@@ -135,7 +135,7 @@ class Slider extends TkinterWidgetBase{
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="flex flex-col items-center justify-center h-screen
bg-gray-100" style={this.state.widgetInnerStyling}>
bg-gray-100" style={this.getInnerRenderStyling()}>
<div className="w-full max-w-md">
<input
type="range"

View File

@@ -108,7 +108,8 @@ class SpinBox extends TkinterWidgetBase{
renderContent(){
return (
<div className="tw-w-flex tw-flex-col tw-w-full tw-h-full tw-rounded-md tw-overflow-hidden">
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-items-center tw-justify-between" style={this.state.widgetInnerStyling}>
<div className="tw-p-2 tw-w-full tw-h-full tw-flex tw-place-items-center tw-justify-between"
style={this.getInnerRenderStyling()}>
<div className="tw-text-sm ">
{this.getAttrValue("spinProps.default")}
</div>