@@ -1095,6 +1095,131 @@ def get_points(self):
1095
1095
return points
1096
1096
1097
1097
1098
+ class LockableBbox (BboxBase ):
1099
+ """
1100
+ A :class:`Bbox` where some elements may be locked at certain values.
1101
+
1102
+ When the child bounding box changes, the bounds of this bbox will update
1103
+ accordingly with the exception of the locked elements.
1104
+ """
1105
+ def __init__ (self , bbox , x0 = None , y0 = None , x1 = None , y1 = None , ** kwargs ):
1106
+ """
1107
+ Parameters
1108
+ ----------
1109
+ bbox : Bbox
1110
+ The child bounding box to wrap.
1111
+
1112
+ x0 : float or None
1113
+ The locked value for x0, or None to leave unlocked.
1114
+
1115
+ y0 : float or None
1116
+ The locked value for y0, or None to leave unlocked.
1117
+
1118
+ x1 : float or None
1119
+ The locked value for x1, or None to leave unlocked.
1120
+
1121
+ y1 : float or None
1122
+ The locked value for y1, or None to leave unlocked.
1123
+
1124
+ """
1125
+ if not bbox .is_bbox :
1126
+ raise ValueError ("'bbox' is not a bbox" )
1127
+
1128
+ BboxBase .__init__ (self , ** kwargs )
1129
+ self ._bbox = bbox
1130
+ self .set_children (bbox )
1131
+ self ._points = None
1132
+ fp = [x0 , y0 , x1 , y1 ]
1133
+ mask = [val is None for val in fp ]
1134
+ self ._locked_points = np .ma .array (fp , np .float_ ,
1135
+ mask = mask ).reshape ((2 , 2 ))
1136
+
1137
+ def __repr__ (self ):
1138
+ return "LockableBbox(%r, %r)" % (self ._bbox , self ._locked_points )
1139
+
1140
+ def get_points (self ):
1141
+ if self ._invalid :
1142
+ points = self ._bbox .get_points ()
1143
+ self ._points = np .where (self ._locked_points .mask ,
1144
+ points ,
1145
+ self ._locked_points )
1146
+ self ._invalid = 0
1147
+ return self ._points
1148
+ get_points .__doc__ = Bbox .get_points .__doc__
1149
+
1150
+ if DEBUG :
1151
+ _get_points = get_points
1152
+
1153
+ def get_points (self ):
1154
+ points = self ._get_points ()
1155
+ self ._check (points )
1156
+ return points
1157
+
1158
+ @property
1159
+ def locked_x0 (self ):
1160
+ """
1161
+ float or None: The value used for the locked x0.
1162
+ """
1163
+ if self ._locked_points .mask [0 , 0 ]:
1164
+ return None
1165
+ else :
1166
+ return self ._locked_points [0 , 0 ]
1167
+
1168
+ @locked_x0 .setter
1169
+ def locked_x0 (self , x0 ):
1170
+ self ._locked_points .mask [0 , 0 ] = x0 is None
1171
+ self ._locked_points .data [0 , 0 ] = x0
1172
+ self .invalidate ()
1173
+
1174
+ @property
1175
+ def locked_y0 (self ):
1176
+ """
1177
+ float or None: The value used for the locked y0.
1178
+ """
1179
+ if self ._locked_points .mask [0 , 1 ]:
1180
+ return None
1181
+ else :
1182
+ return self ._locked_points [0 , 1 ]
1183
+
1184
+ @locked_y0 .setter
1185
+ def locked_y0 (self , y0 ):
1186
+ self ._locked_points .mask [0 , 1 ] = y0 is None
1187
+ self ._locked_points .data [0 , 1 ] = y0
1188
+ self .invalidate ()
1189
+
1190
+ @property
1191
+ def locked_x1 (self ):
1192
+ """
1193
+ float or None: The value used for the locked x1.
1194
+ """
1195
+ if self ._locked_points .mask [1 , 0 ]:
1196
+ return None
1197
+ else :
1198
+ return self ._locked_points [1 , 0 ]
1199
+
1200
+ @locked_x1 .setter
1201
+ def locked_x1 (self , x1 ):
1202
+ self ._locked_points .mask [1 , 0 ] = x1 is None
1203
+ self ._locked_points .data [1 , 0 ] = x1
1204
+ self .invalidate ()
1205
+
1206
+ @property
1207
+ def locked_y1 (self ):
1208
+ """
1209
+ float or None: The value used for the locked y1.
1210
+ """
1211
+ if self ._locked_points .mask [1 , 1 ]:
1212
+ return None
1213
+ else :
1214
+ return self ._locked_points [1 , 1 ]
1215
+
1216
+ @locked_y1 .setter
1217
+ def locked_y1 (self , y1 ):
1218
+ self ._locked_points .mask [1 , 1 ] = y1 is None
1219
+ self ._locked_points .data [1 , 1 ] = y1
1220
+ self .invalidate ()
1221
+
1222
+
1098
1223
class Transform (TransformNode ):
1099
1224
"""
1100
1225
The base class of all :class:`TransformNode` instances that
0 commit comments