@@ -50,8 +50,8 @@ def onClick(event):
50
50
id = list (element )[0 ]
51
51
values = element [id ]
52
52
x1 = values ['left' ]
53
- x2 = x1 + values ['width' ]
54
- y1 = values ['top' ]
53
+ x2 = x1 + values ['width' ] + getScreenLeft ( values [ 'parent' ])
54
+ y1 = values ['top' ] + getScreenTop ( values [ 'parent' ])
55
55
y2 = y1 + values ['height' ]
56
56
if x >= x1 and x < x2 and y >= y1 and y < y2 :
57
57
if id in elements :
@@ -110,26 +110,26 @@ def getValue(args, item):
110
110
return args [item ]
111
111
return item
112
112
113
- def renderIntoRectangle (widgetType , values , offset , args ):
113
+ def renderIntoRectangle (widgetType , values , parent , args ):
114
114
global zlist
115
115
left = getValue (args , values ['left' ]) if 'left' in values else 10
116
+ screenLeft = left + getScreenLeft (parent )
116
117
top = getValue (args , values ['top' ]) if 'top' in values else 10
117
- left = offset ['dx' ] + left
118
- top = offset ['dy' ] + top
118
+ screenTop = top + getScreenTop (parent )
119
119
width = getValue (args , values ['width' ]) if 'width' in values else 100
120
120
height = getValue (args , values ['height' ]) if 'height' in values else 100
121
- right = left + width
122
- bottom = top + height
121
+ right = screenLeft + width
122
+ bottom = screenTop + height
123
123
fill = values ['fill' ] if 'fill' in values else None
124
124
outline = values ['outline' ] if 'outline' in values else None
125
125
if outline != None :
126
126
outlineWidth = getValue (args , values ['outlineWidth' ]) if 'outlineWidth' in values else 1
127
127
else :
128
128
outlineWidth = 0
129
129
if widgetType == 'rectangle' :
130
- widgetId = getCanvas ().create_rectangle (left , top , right , bottom , fill = fill , outline = outline , width = outlineWidth )
130
+ widgetId = getCanvas ().create_rectangle (screenLeft , screenTop , right , bottom , fill = fill , outline = outline , width = outlineWidth )
131
131
elif widgetType == 'ellipse' :
132
- widgetId = getCanvas ().create_oval (left , top , right , bottom , fill = fill , outline = outline , width = outlineWidth )
132
+ widgetId = getCanvas ().create_oval (screenLeft , screenTop , right , bottom , fill = fill , outline = outline , width = outlineWidth )
133
133
else :
134
134
return f'Unknown widget type \' { widgetType } \' '
135
135
if 'name' in values :
@@ -144,6 +144,7 @@ def renderIntoRectangle(widgetType, values, offset, args):
144
144
"top" : top ,
145
145
"width" : width ,
146
146
"height" : height ,
147
+ "parent" : parent ,
147
148
"children" : []
148
149
}
149
150
elements [widgetName ] = widgetSpec
@@ -154,23 +155,23 @@ def renderIntoRectangle(widgetType, values, offset, args):
154
155
for item in children :
155
156
if item in values :
156
157
child = values [item ]
157
- childSpec = renderWidget (child , { 'dx' : left , 'dy' : top } , args )
158
+ childSpec = renderWidget (child , widgetSpec , args )
158
159
widgetSpec ['children' ].append (childSpec ['name' ])
159
160
else :
160
161
child = values [children ]
161
- childSpec = renderWidget (child , { 'dx' : left , 'dy' : top } , args )
162
+ childSpec = renderWidget (child , widgetSpec , args )
162
163
widgetSpec ['children' ].append (childSpec ['name' ])
163
164
return widgetSpec
164
165
165
- def renderText (values , offset , args ):
166
+ def renderText (values , parent , args ):
166
167
left = getValue (args , values ['left' ]) if 'left' in values else 10
168
+ screenLeft = left + getScreenLeft (parent )
167
169
top = getValue (args , values ['top' ]) if 'top' in values else 10
168
- left = offset ['dx' ] + left
169
- top = offset ['dy' ] + top
170
+ screenTop = top + getScreenTop (parent )
170
171
width = getValue (args , values ['width' ]) if 'width' in values else 100
171
172
height = getValue (args , values ['height' ]) if 'height' in values else 100
172
- right = left + width
173
- bottom = top + height
173
+ right = screenLeft + width
174
+ bottom = screenTop + height
174
175
shape = getValue (args , values ['shape' ]) if 'shape' in values else 'rectangle'
175
176
fill = getValue (args , values ['fill' ]) if 'fill' in values else None
176
177
outline = getValue (args , values ['outline' ]) if 'outline' in values else None
@@ -180,7 +181,7 @@ def renderText(values, offset, args):
180
181
fontFace = getValue (args , values ['fontFace' ]) if 'fontFace' in values else 'Helvetica'
181
182
fontWeight = getValue (args , values ['fontWeight' ]) if 'fontWeight' in values else 'normal'
182
183
fontSize = round (height * 2 / 5 ) if shape == 'ellipse' else round (height * 3 / 5 )
183
- fontTop = top + height / 2
184
+ fontTop = screenTop + height / 2
184
185
if 'fontSize' in values :
185
186
fontSize = getValue (args , values ['fontSize' ])
186
187
fontTop = top + round (fontSize * 5 / 4 )
@@ -198,10 +199,10 @@ def renderText(values, offset, args):
198
199
if xoff < 3 :
199
200
xoff = 3
200
201
if shape == 'ellipse' :
201
- containerId = getCanvas ().create_oval (left , top , right , bottom , fill = fill , outline = outline , width = outlineWidth )
202
+ containerId = getCanvas ().create_oval (screenLeft , screenTop , right , bottom , fill = fill , outline = outline , width = outlineWidth )
202
203
else :
203
- containerId = getCanvas ().create_rectangle (left , top , right , bottom , fill = fill , outline = outline , width = outlineWidth )
204
- textId = canvas .create_text (left + xoff , fontTop + adjust , fill = color , font = f'"{ fontFace } " { fontSize } { fontWeight } ' , text = text , anchor = anchor )
204
+ containerId = getCanvas ().create_rectangle (screenLeft , screenTop , right , bottom , fill = fill , outline = outline , width = outlineWidth )
205
+ textId = canvas .create_text (screenLeft + xoff , fontTop + adjust , fill = color , font = f'"{ fontFace } " { fontSize } { fontWeight } ' , text = text , anchor = anchor )
205
206
if 'name' in values :
206
207
widgetName = getValue (args , values ['name' ])
207
208
else :
@@ -214,24 +215,25 @@ def renderText(values, offset, args):
214
215
"left" : left ,
215
216
"top" : top ,
216
217
"width" : width ,
217
- "height" : height
218
+ "height" : height ,
219
+ "parent" : parent
218
220
}
219
221
elements [widgetName ] = widgetSpec
220
222
zlist .append ({widgetName : widgetSpec })
221
223
return widgetSpec
222
224
223
- def renderImage (values , offset , args ):
225
+ def renderImage (values , parent , args ):
224
226
global images
225
227
left = getValue (args , values ['left' ]) if 'left' in values else 10
228
+ screenLeft = left + getScreenLeft (parent )
226
229
top = getValue (args , values ['top' ]) if 'top' in values else 10
227
- left = offset ['dx' ] + left
228
- top = offset ['dy' ] + top
230
+ screenTop = top + getScreenTop (parent )
229
231
width = getValue (args , values ['width' ]) if 'width' in values else 100
230
232
height = getValue (args , values ['height' ]) if 'height' in values else 100
231
- right = left + width
232
- bottom = top + height
233
+ right = screenLeft + width
234
+ bottom = screenTop + height
233
235
src = getValue (args , values ['src' ]) if 'src' in values else None
234
- containerId = getCanvas ().create_rectangle (left , top , right , bottom , width = 0 )
236
+ containerId = getCanvas ().create_rectangle (screenLeft , screenTop , right , bottom , width = 0 )
235
237
if 'name' in values :
236
238
widgetName = values ['name' ]
237
239
else :
@@ -243,7 +245,8 @@ def renderImage(values, offset, args):
243
245
"left" : left ,
244
246
"top" : top ,
245
247
"width" : width ,
246
- "height" : height
248
+ "height" : height ,
249
+ "parent" : parent
247
250
}
248
251
elements [widgetName ] = widgetSpec
249
252
zlist .append ({widgetName : widgetSpec })
@@ -252,45 +255,44 @@ def renderImage(values, offset, args):
252
255
img = (Image .open (src ))
253
256
resized_image = img .resize ((width , height ), Image .ANTIALIAS )
254
257
new_image = ImageTk .PhotoImage (resized_image )
255
- imageid = getCanvas ().create_image (left , top , anchor = 'nw' , image = new_image )
258
+ imageid = getCanvas ().create_image (screenLeft , screenTop , anchor = 'nw' , image = new_image )
256
259
images [containerId ] = {'id' : imageid , "image" : new_image }
257
260
return widgetSpec
258
261
259
262
# Create a canvas or render a widget
260
- def renderWidget (widget , offset , args ):
263
+ def renderWidget (widget , parent , args ):
261
264
widgetType = widget ['type' ]
262
265
if widgetType in ['rectangle' , 'ellipse' ]:
263
- return renderIntoRectangle (widgetType , widget , offset , args )
266
+ return renderIntoRectangle (widgetType , widget , parent , args )
264
267
elif widgetType == 'text' :
265
- return renderText (widget , offset , args )
268
+ return renderText (widget , parent , args )
266
269
elif widgetType == 'image' :
267
- return renderImage (widget , offset , args )
270
+ return renderImage (widget , parent , args )
268
271
269
272
# Render a complete specification
270
- def renderSpec (spec , offset , args ):
273
+ def renderSpec (spec , parent , args ):
271
274
widgets = spec ['#' ]
272
275
# If a list, iterate it
273
276
if type (widgets ) is list :
274
277
for widget in widgets :
275
- renderWidget (spec [widget ], offset , args )
278
+ renderWidget (spec [widget ], parent , args )
276
279
# Otherwise, process the single widget
277
280
else :
278
- renderWidget (spec [widgets ], offset , args )
281
+ renderWidget (spec [widgets ], parent , args )
279
282
280
283
# Main entry point
281
- offset = {'dx' : 0 , 'dy' : 0 }
282
284
if parent != screen :
283
285
RuntimeError (None , 'Can\' t yet render into parent widget' )
284
286
285
287
# If it'a string, process it
286
288
if type (spec ) is str :
287
- renderSpec (json .loads (spec ), offset , {})
289
+ renderSpec (json .loads (spec ), None , {})
288
290
289
291
# If it's a 'dict', extract the spec and the args
290
292
if type (spec ) is dict :
291
293
args = spec ['args' ]
292
294
spec = json .loads (spec ['spec' ])
293
- renderSpec (spec , offset , args )
295
+ renderSpec (spec , None , args )
294
296
295
297
# Get the widget whose name is given
296
298
def getElement (name ):
@@ -328,3 +330,15 @@ def moveElementTo(name, left, top):
328
330
def getAttribute (name , attribute ):
329
331
element = getElement (name )
330
332
return element [attribute ]
333
+
334
+ # Get the screen left position of an element
335
+ def getScreenLeft (element ):
336
+ if element == None :
337
+ return 0
338
+ return element ['left' ] + getScreenLeft (element ['parent' ])
339
+
340
+ # Get the screen top position of an element
341
+ def getScreenTop (element ):
342
+ if element == None :
343
+ return 0
344
+ return element ['top' ] + getScreenTop (element ['parent' ])
0 commit comments