@@ -307,6 +307,7 @@ def __init__(self, layout: QtWidgets.QLayout):
307307 ]
308308
309309 self .properties = {}
310+ self .changed_property_names = set ()
310311 self .propertiesChanged .connect (
311312 lambda : self .target
312313 and main_figure (
@@ -354,15 +355,19 @@ def selectFont(self):
354355 font , x = QtWidgets .QFontDialog .getFont (font0 , self )
355356
356357 self .properties ["fontname" ] = font .family ()
358+ self .changed_property_names .add ("fontname" )
357359 if font .weight () != font0 .weight ():
358360 self .properties ["fontweight" ] = self .convertQtWeightToMplWeight (
359361 font .weight ()
360362 )
363+ self .changed_property_names .add ("fontweight" )
361364 if font .pointSizeF () != font0 .pointSizeF ():
362365 self .properties ["fontsize" ] = font .pointSizeF ()
366+ self .changed_property_names .add ("fontsize" )
363367 if font .italic () != font0 .italic ():
364368 style = "italic" if font .italic () else "normal"
365369 self .properties ["fontstyle" ] = style
370+ self .changed_property_names .add ("fontstyle" )
366371
367372 self .propertiesChanged .emit ()
368373 # main_figure(self.target).canvas.draw()
@@ -401,6 +406,7 @@ def setTarget(self, element: Artist | List[Artist]):
401406 value = getattr (current_element , "get_" + name2 )()
402407 self .properties [name ] = value
403408
409+ self .changed_property_names = set ()
404410 self .target = current_element
405411 finally :
406412 self .noSignal = False
@@ -417,28 +423,33 @@ def delete(self):
417423 def changeWeight (self , checked : bool ):
418424 """set bold or normal"""
419425 self .properties ["fontweight" ] = "bold" if checked else "normal"
426+ self .changed_property_names .add ("fontweight" )
420427 self .propertiesChanged .emit ()
421428
422429 def changeStyle (self , checked : bool ):
423430 """set italic or normal"""
424431 self .properties ["fontstyle" ] = "italic" if checked else "normal"
432+ self .changed_property_names .add ("fontstyle" )
425433 self .propertiesChanged .emit ()
426434
427435 def changeColor (self , color : str ):
428436 """set the text color"""
429437 self .properties ["color" ] = color
438+ self .changed_property_names .add ("color" )
430439 self .propertiesChanged .emit ()
431440
432441 def changeAlign (self , align : str ):
433442 """set the text algin"""
434443 self .properties ["horizontalalignment" ] = align
444+ self .changed_property_names .add ("horizontalalignment" )
435445 self .propertiesChanged .emit ()
436446
437447 def changeFontSize (self , value : int ):
438448 """set the font size"""
439449 if self .noSignal :
440450 return
441451 self .properties ["fontsize" ] = value
452+ self .changed_property_names .add ("fontsize" )
442453 self .propertiesChanged .emit ()
443454
444455
@@ -946,6 +957,44 @@ def getFontProperties(self):
946957 prop_copy2 [name ] = value
947958 return (", " .join ("%s=%s" % (k , v ) for k , v in prop_copy .items ())), prop_copy2
948959
960+ def tickLabelFontChanged (self , element : Axes , properties : dict ):
961+ """check if the current major tick labels differ from the requested font"""
962+ for label in getattr (element , "get_" + self .axis + "ticklabels" )():
963+ for name , value in properties .items ():
964+ getter = getattr (label , "get_" + name )
965+ if getter () != value :
966+ return True
967+ return False
968+
969+ def getChangedFontProperties (self , element : Axes ):
970+ labels = getattr (element , "get_" + self .axis + "ticklabels" )()
971+ if len (labels ) == 0 :
972+ return {}
973+ changed_properties = {}
974+ changed_property_names = self .input_font .changed_property_names
975+ if not changed_property_names :
976+ return {}
977+ for name , name2 , type_ , default_ in self .input_font .property_names :
978+ if (
979+ name not in changed_property_names
980+ or name not in self .input_font .properties
981+ ):
982+ continue
983+ value = self .input_font .properties [name ]
984+ if any (getattr (label , "get_" + name )() != value for label in labels ):
985+ changed_properties [name ] = value
986+
987+ return changed_properties
988+
989+ def getFontPropertyString (self , properties : dict ):
990+ prop_copy = {}
991+ for name , value in properties .items ():
992+ if isinstance (value , str ):
993+ prop_copy [name ] = '"' + value + '"'
994+ else :
995+ prop_copy [name ] = value
996+ return ", " .join ("%s=%s" % (k , v ) for k , v in prop_copy .items ())
997+
949998 def fontStateChanged (self ):
950999 self .ticksChanged ()
9511000 # fig.change_tracker.addChange(axes, ".legend(%s)" % (", ".join("%s=%s" % (k, v) for k, v in prop_copy.items())))
@@ -975,9 +1024,12 @@ def ticksChanged(self):
9751024 for element in main_figure (self .element ).selection .targets
9761025 if element .target != self .element and isinstance (element .target , Axes )
9771026 ]
1027+ changed_font_properties = [
1028+ self .getChangedFontProperties (element ) for element in elements
1029+ ]
9781030
9791031 changed = False
980- for elem in elements :
1032+ for elem , font_properties in zip ( elements , changed_font_properties ) :
9811033 current_ticks = getattr (elem , "get_" + self .axis + "ticks" )()
9821034 current_ticklabels = [
9831035 t .get_text () for t in getattr (elem , "get_" + self .axis + "ticklabels" )()
@@ -987,19 +1039,138 @@ def ticksChanged(self):
9871039 or (current_ticks != ticks ).any ()
9881040 or len (current_ticklabels ) != len (labels )
9891041 or current_ticklabels != labels
1042+ or bool (font_properties )
9901043 ):
9911044 changed = True
9921045 if changed is False :
9931046 return
9941047
995- with UndoRedo (elements , "Axes Ticks" ):
996- for element in elements :
997- kwargs = {}
998- kwargs [f"{ self .axis } ticks" ] = ticks
999- kwargs [f"{ self .axis } ticklabels" ] = labels
1000- kwargs [f"{ self .axis } lim" ] = self .range
1001- element .set (** kwargs )
1048+ if not any (changed_font_properties ):
1049+ with UndoRedo (elements , "Axes Ticks" ):
1050+ for element in elements :
1051+ kwargs = {}
1052+ kwargs [f"{ self .axis } ticks" ] = ticks
1053+ kwargs [f"{ self .axis } ticklabels" ] = labels
1054+ kwargs [f"{ self .axis } lim" ] = self .range
1055+ element .set (** kwargs )
1056+ return
10021057
1058+ old_properties = []
1059+ for element in elements :
1060+ axis = getattr (element , "get_" + self .axis + "axis" )()
1061+ ticklabels = [
1062+ t .get_text ()
1063+ for t in getattr (element , "get_" + self .axis + "ticklabels" )()
1064+ ]
1065+ ticklabel_properties = [
1066+ {
1067+ name : getattr (t , "get_" + name )()
1068+ for name , name2 , type_ , default_ in self .input_font .property_names
1069+ }
1070+ for t in getattr (element , "get_" + self .axis + "ticklabels" )()
1071+ ]
1072+ old_properties .append (
1073+ [
1074+ axis .major .locator ,
1075+ axis .major .formatter ,
1076+ getattr (element , "get_" + self .axis + "lim" )(),
1077+ getattr (element , "get_" + self .axis + "ticks" )(),
1078+ ticklabels ,
1079+ ticklabel_properties ,
1080+ ]
1081+ )
1082+
1083+ def undo ():
1084+ for element , properties in zip (elements , old_properties ):
1085+ (
1086+ locator ,
1087+ formatter ,
1088+ lim ,
1089+ old_ticks ,
1090+ old_labels ,
1091+ old_label_properties ,
1092+ ) = properties
1093+ axis = getattr (element , "get_" + self .axis + "axis" )()
1094+ current_ticks = getattr (element , "get_" + self .axis + "ticks" )()
1095+ current_ticklabels = [
1096+ t .get_text ()
1097+ for t in getattr (element , "get_" + self .axis + "ticklabels" )()
1098+ ]
1099+ font_only = (
1100+ len (current_ticks ) == len (old_ticks )
1101+ and (current_ticks == old_ticks ).all ()
1102+ and len (current_ticklabels ) == len (old_labels )
1103+ and current_ticklabels == old_labels
1104+ )
1105+ if font_only :
1106+ old_texts = getattr (element , "get_" + self .axis + "ticklabels" )()
1107+ else :
1108+ getattr (element , "set_" + self .axis + "ticks" )(old_ticks )
1109+ old_texts = getattr (element , "set_" + self .axis + "ticklabels" )(
1110+ old_labels
1111+ )
1112+ for text , properties in zip (old_texts , old_label_properties ):
1113+ text .update (properties )
1114+ getattr (element , "set_" + self .axis + "lim" )(lim )
1115+ axis .set_major_locator (locator )
1116+ axis .set_major_formatter (formatter )
1117+ self .fig .change_tracker .addNewAxesChange (element )
1118+
1119+ def redo ():
1120+ for element , properties in zip (elements , changed_font_properties ):
1121+ current_ticks = getattr (element , "get_" + self .axis + "ticks" )()
1122+ current_ticklabels = [
1123+ t .get_text ()
1124+ for t in getattr (element , "get_" + self .axis + "ticklabels" )()
1125+ ]
1126+ font_only = (
1127+ len (current_ticks ) == len (ticks )
1128+ and (current_ticks == ticks ).all ()
1129+ and len (current_ticklabels ) == len (labels )
1130+ and current_ticklabels == labels
1131+ )
1132+ if font_only and not properties :
1133+ continue
1134+ if font_only :
1135+ for text in getattr (element , "get_" + self .axis + "ticklabels" )():
1136+ text .update (properties )
1137+ else :
1138+ getattr (element , "set_" + self .axis + "ticks" )(ticks )
1139+ getattr (element , "set_" + self .axis + "ticklabels" )(
1140+ labels , ** properties
1141+ )
1142+ getattr (element , "set_" + self .axis + "lim" )(self .range )
1143+ min , max = getattr (element , "get_" + self .axis + "lim" )()
1144+ if min != self .range [0 ] or max != self .range [1 ]:
1145+ self .fig .change_tracker .addChange (
1146+ element ,
1147+ ".set_" + self .axis + "lim(%s, %s)" % (str (min ), str (max )),
1148+ )
1149+ else :
1150+ self .fig .change_tracker .addChange (
1151+ element ,
1152+ ".set_"
1153+ + self .axis
1154+ + "lim(%s, %s)" % (str (self .range [0 ]), str (self .range [1 ])),
1155+ )
1156+
1157+ self .fig .change_tracker .addChange (
1158+ element ,
1159+ ".set_" + self .axis + "ticks([%s], [%s]%s)"
1160+ % (
1161+ ", " .join (self .str (t ) for t in ticks ),
1162+ ", " .join ('"' + label + '"' for label in labels ),
1163+ (
1164+ ", " + self .getFontPropertyString (properties )
1165+ if properties
1166+ else ""
1167+ ),
1168+ ),
1169+ )
1170+
1171+ self .fig .change_tracker .addEdit ([undo , redo , "ticks" ])
1172+ redo ()
1173+ self .fig .canvas .draw ()
10031174 return
10041175 if 0 :
10051176 getattr (element , "set_" + self .axis + "lim" )(self .range )
0 commit comments