@@ -240,47 +240,97 @@ def _do_paint(self, widget):
240240
241241 painter .end ()
242242
243+ def _resolve_dynamic_size (self , value : int , img_px : QPixmap , is_width : bool ) -> int :
244+ if value >= 0 :
245+ return value
246+ if img_px is None or img_px .isNull ():
247+ return 100 if is_width else 30
248+ img_size = img_px .width () if is_width else img_px .height ()
249+ special_sizes = {
250+ - 1 : img_size ,
251+ - 2 : img_size + 23 ,
252+ - 3 : img_size + 33 ,
253+ - 4 : img_size + 10 ,
254+ - 5 : img_size ,
255+ - 6 : img_size ,
256+ - 7 : img_size ,
257+ }
258+ return special_sizes .get (value , img_size )
259+
260+ def _resolve_dynamic_pos (self , value : int , img_px : QPixmap , is_x : bool ) -> int :
261+ if value >= 0 :
262+ return value
263+ iface = self .project .current_interface
264+ canvas_w = iface .settings .width if iface else 800
265+ canvas_h = iface .settings .height if iface else 600
266+ img_w = img_px .width () if img_px and not img_px .isNull () else 100
267+ img_h = img_px .height () if img_px and not img_px .isNull () else 30
268+ if is_x :
269+ special_positions = {
270+ - 7 : canvas_w - 150 ,
271+ - 6 : 20 ,
272+ }
273+ else :
274+ special_positions = {
275+ - 7 : 455 ,
276+ - 6 : canvas_h - img_h - 35 ,
277+ }
278+ return special_positions .get (value , value )
279+
243280 def _draw_widget (self , painter : QPainter , widget_id : str ):
244281 w = self .project .get_widget (widget_id )
245282 if not w :
246283 return
247284
248285 props = w .properties
249- x = int ( props .get ("mX" , 0 ) * self . _zoom )
250- y = int ( props .get ("mY" , 0 ) * self . _zoom )
251- width = int ( props .get ("mWidth" , 100 ) * self . _zoom )
252- height = int ( props .get ("mHeight" , 30 ) * self . _zoom )
286+ raw_x = props .get ("mX" , 0 )
287+ raw_y = props .get ("mY" , 0 )
288+ raw_width = props .get ("mWidth" , 100 )
289+ raw_height = props .get ("mHeight" , 30 )
253290
254291 img_drawn = False
292+ img_px = None
255293 for img_key in ["mButtonImage" , "mComponentImage" , "mUncheckedImage" , "mTrackImage" , "mImage" ]:
256294 img_ref = props .get (img_key , "" )
257295 if not img_ref and img_key == "mButtonImage" and w .class_name == "NewLawnButton" :
258296 img_ref = props .get ("mUniformImage" , "" )
259297 if img_ref :
260- px = self ._load_pixmap (img_ref )
261- if px and not px .isNull ():
262- stretch = False
263- if w .class_name == "ImageBox" :
264- stretch = props .get ("mStretch" , False )
265-
266- if stretch :
267- scaled = px .scaled (width , height , Qt .AspectRatioMode .IgnoreAspectRatio ,
268- Qt .TransformationMode .SmoothTransformation )
269- painter .drawPixmap (x , y , scaled )
270- else :
271- scale_x = props .get ("mScaleX" , 1.0 )
272- scale_y = props .get ("mScaleY" , 1.0 )
273- if scale_x != 1.0 or scale_y != 1.0 :
274- scaled = px .scaled (int (px .width () * scale_x * self ._zoom ),
275- int (px .height () * scale_y * self ._zoom ),
276- Qt .AspectRatioMode .IgnoreAspectRatio ,
277- Qt .TransformationMode .SmoothTransformation )
278- painter .drawPixmap (x , y , scaled )
279- else :
280- painter .drawPixmap (x , y , px )
281- img_drawn = True
298+ img_px = self ._load_pixmap (img_ref )
299+ if img_px and not img_px .isNull ():
282300 break
283301
302+ x = self ._resolve_dynamic_pos (raw_x , img_px , True )
303+ y = self ._resolve_dynamic_pos (raw_y , img_px , False )
304+ width = self ._resolve_dynamic_size (raw_width , img_px , True )
305+ height = self ._resolve_dynamic_size (raw_height , img_px , False )
306+
307+ x = int (x * self ._zoom )
308+ y = int (y * self ._zoom )
309+ width = int (width * self ._zoom )
310+ height = int (height * self ._zoom )
311+
312+ if img_px and not img_px .isNull ():
313+ stretch = False
314+ if w .class_name == "ImageBox" :
315+ stretch = props .get ("mStretch" , False )
316+
317+ if stretch :
318+ scaled = img_px .scaled (width , height , Qt .AspectRatioMode .IgnoreAspectRatio ,
319+ Qt .TransformationMode .SmoothTransformation )
320+ painter .drawPixmap (x , y , scaled )
321+ else :
322+ scale_x = props .get ("mScaleX" , 1.0 )
323+ scale_y = props .get ("mScaleY" , 1.0 )
324+ if scale_x != 1.0 or scale_y != 1.0 :
325+ scaled = img_px .scaled (int (img_px .width () * scale_x * self ._zoom ),
326+ int (img_px .height () * scale_y * self ._zoom ),
327+ Qt .AspectRatioMode .IgnoreAspectRatio ,
328+ Qt .TransformationMode .SmoothTransformation )
329+ painter .drawPixmap (x , y , scaled )
330+ else :
331+ painter .drawPixmap (x , y , img_px )
332+ img_drawn = True
333+
284334 if not img_drawn :
285335 color = _WIDGET_COLORS .get (w .class_name , QColor (200 , 200 , 200 , 80 ))
286336 painter .setBrush (QBrush (color ))
@@ -368,10 +418,26 @@ def _hit_test_widget(self, pos: QPoint, widget_id: str) -> str:
368418 if result :
369419 return result
370420 props = w .properties
371- x = int (props .get ("mX" , 0 ) * self ._zoom )
372- y = int (props .get ("mY" , 0 ) * self ._zoom )
373- width = int (props .get ("mWidth" , 100 ) * self ._zoom )
374- height = int (props .get ("mHeight" , 30 ) * self ._zoom )
421+ raw_x = props .get ("mX" , 0 )
422+ raw_y = props .get ("mY" , 0 )
423+ raw_width = props .get ("mWidth" , 100 )
424+ raw_height = props .get ("mHeight" , 30 )
425+
426+ img_px = None
427+ for img_key in ["mButtonImage" , "mComponentImage" , "mUncheckedImage" , "mTrackImage" , "mImage" ]:
428+ img_ref = props .get (img_key , "" )
429+ if not img_ref and img_key == "mButtonImage" and w .class_name == "NewLawnButton" :
430+ img_ref = props .get ("mUniformImage" , "" )
431+ if img_ref :
432+ img_px = self ._load_pixmap (img_ref )
433+ if img_px and not img_px .isNull ():
434+ break
435+
436+ x = int (self ._resolve_dynamic_pos (raw_x , img_px , True ) * self ._zoom )
437+ y = int (self ._resolve_dynamic_pos (raw_y , img_px , False ) * self ._zoom )
438+ width = int (self ._resolve_dynamic_size (raw_width , img_px , True ) * self ._zoom )
439+ height = int (self ._resolve_dynamic_size (raw_height , img_px , False ) * self ._zoom )
440+
375441 if QRect (x , y , width , height ).contains (pos ):
376442 return w .id
377443 return ""
@@ -383,10 +449,26 @@ def _hit_handle(self, pos: QPoint) -> str:
383449 if not w :
384450 return ""
385451 props = w .properties
386- x = int (props .get ("mX" , 0 ) * self ._zoom )
387- y = int (props .get ("mY" , 0 ) * self ._zoom )
388- width = int (props .get ("mWidth" , 100 ) * self ._zoom )
389- height = int (props .get ("mHeight" , 30 ) * self ._zoom )
452+ raw_x = props .get ("mX" , 0 )
453+ raw_y = props .get ("mY" , 0 )
454+ raw_width = props .get ("mWidth" , 100 )
455+ raw_height = props .get ("mHeight" , 30 )
456+
457+ img_px = None
458+ for img_key in ["mButtonImage" , "mComponentImage" , "mUncheckedImage" , "mTrackImage" , "mImage" ]:
459+ img_ref = props .get (img_key , "" )
460+ if not img_ref and img_key == "mButtonImage" and w .class_name == "NewLawnButton" :
461+ img_ref = props .get ("mUniformImage" , "" )
462+ if img_ref :
463+ img_px = self ._load_pixmap (img_ref )
464+ if img_px and not img_px .isNull ():
465+ break
466+
467+ x = int (self ._resolve_dynamic_pos (raw_x , img_px , True ) * self ._zoom )
468+ y = int (self ._resolve_dynamic_pos (raw_y , img_px , False ) * self ._zoom )
469+ width = int (self ._resolve_dynamic_size (raw_width , img_px , True ) * self ._zoom )
470+ height = int (self ._resolve_dynamic_size (raw_height , img_px , False ) * self ._zoom )
471+
390472 handles = self ._get_handles (x , y , width , height , 8 )
391473 names = ["tl" , "tr" , "bl" , "br" , "tm" , "bm" , "ml" , "mr" ]
392474 for name , handle in zip (names , handles ):
0 commit comments