55"""
66Display Text module helper functions
77"""
8+ from displayio import Group , Palette
89
910
1011def wrap_text_to_pixels (string , max_width , font = None , indent0 = "" , indent1 = "" ):
@@ -141,3 +142,169 @@ def chunks(lst, n):
141142 if the_lines [0 ][0 ] == " " :
142143 the_lines [0 ] = the_lines [0 ][1 :]
143144 return the_lines
145+
146+
147+ class LabelBase (Group ):
148+ def __init__ (
149+ self ,
150+ font ,
151+ x = 0 ,
152+ y = 0 ,
153+ text = "" ,
154+ max_glyphs = None , # This input parameter is ignored, only present for compatibility
155+ # with label.py
156+ color = 0xFFFFFF ,
157+ background_color = None ,
158+ line_spacing = 1.25 ,
159+ background_tight = False ,
160+ padding_top = 0 ,
161+ padding_bottom = 0 ,
162+ padding_left = 0 ,
163+ padding_right = 0 ,
164+ anchor_point = None ,
165+ anchored_position = None ,
166+ save_text = True , # can reduce memory use if save_text = False
167+ scale = 1 ,
168+ base_alignment = False ,
169+ ** kwargs ,
170+ ):
171+ super ().__init__ (max_size = 1 , x = x , y = y , scale = 1 )
172+
173+ self ._font = font
174+ self .palette = Palette (2 )
175+ self ._color = color
176+ self ._background_color = background_color
177+
178+ self ._bounding_box = None
179+ self ._anchor_point = anchor_point
180+ self ._anchored_position = anchored_position
181+
182+ self .local_group = None
183+
184+ self ._text = text
185+
186+ def _get_ascent_descent (self ):
187+ """ Private function to calculate ascent and descent font values """
188+ if hasattr (self .font , "ascent" ):
189+ return self .font .ascent , self .font .descent
190+
191+ # check a few glyphs for maximum ascender and descender height
192+ glyphs = "M j'" # choose glyphs with highest ascender and lowest
193+ try :
194+ self ._font .load_glyphs (glyphs )
195+ except AttributeError :
196+ # Builtin font doesn't have or need load_glyphs
197+ pass
198+ # descender, will depend upon font used
199+ ascender_max = descender_max = 0
200+ for char in glyphs :
201+ this_glyph = self ._font .get_glyph (ord (char ))
202+ if this_glyph :
203+ ascender_max = max (ascender_max , this_glyph .height + this_glyph .dy )
204+ descender_max = max (descender_max , - this_glyph .dy )
205+ return ascender_max , descender_max
206+
207+ def _get_ascent (self ):
208+ return self ._get_ascent_descent ()[0 ]
209+
210+ @property
211+ def font (self ):
212+ """Font to use for text display."""
213+ return self ._font
214+
215+ def _set_font (self , new_font ):
216+ # subclasses should override this
217+ pass
218+
219+ @font .setter
220+ def font (self , new_font ):
221+ self ._set_font (new_font )
222+
223+ @property
224+ def color (self ):
225+ """Color of the text as an RGB hex number."""
226+ return self ._color
227+
228+ @color .setter
229+ def color (self , new_color ):
230+ self ._color = new_color
231+ if new_color is not None :
232+ self .palette [1 ] = new_color
233+ self .palette .make_opaque (1 )
234+ else :
235+ self .palette [1 ] = 0
236+ self .palette .make_transparent (1 )
237+
238+ @property
239+ def background_color (self ):
240+ """Color of the background as an RGB hex number."""
241+ return self ._background_color
242+
243+ @background_color .setter
244+ def background_color (self , new_color ):
245+ self ._background_color = new_color
246+ if new_color is not None :
247+ self .palette [0 ] = new_color
248+ self .palette .make_opaque (0 )
249+ else :
250+ self .palette [0 ] = 0
251+ self .palette .make_transparent (0 )
252+
253+ @property
254+ def anchor_point (self ):
255+ """Point that anchored_position moves relative to.
256+ Tuple with decimal percentage of width and height.
257+ (E.g. (0,0) is top left, (1.0, 0.5): is middle right.)"""
258+ return self ._anchor_point
259+
260+ @anchor_point .setter
261+ def anchor_point (self , new_anchor_point ):
262+ self ._anchor_point = new_anchor_point
263+ self .anchored_position = (
264+ self ._anchored_position
265+ ) # update the anchored_position using setter
266+
267+ @property
268+ def anchored_position (self ):
269+ """Position relative to the anchor_point. Tuple containing x,y
270+ pixel coordinates."""
271+ return self ._anchored_position
272+
273+ @anchored_position .setter
274+ def anchored_position (self , new_position ):
275+ self ._anchored_position = new_position
276+ # Set anchored_position
277+ if (self ._anchor_point is not None ) and (self ._anchored_position is not None ):
278+ self .x = int (
279+ new_position [0 ]
280+ - (self ._bounding_box [0 ] * self .scale )
281+ - round (self ._anchor_point [0 ] * (self ._bounding_box [2 ] * self .scale ))
282+ )
283+ self .y = int (
284+ new_position [1 ]
285+ - (self ._bounding_box [1 ] * self .scale )
286+ - round (self ._anchor_point [1 ] * self ._bounding_box [3 ] * self .scale )
287+ )
288+
289+ @property
290+ def scale (self ):
291+ """Set the scaling of the label, in integer values"""
292+ return self .local_group .scale
293+
294+ @scale .setter
295+ def scale (self , new_scale ):
296+ self .local_group .scale = new_scale
297+ self .anchored_position = self ._anchored_position # update the anchored_position
298+
299+ def _reset_text (self , text , scale ):
300+ # subclasses should override this
301+ pass
302+
303+ @property
304+ def text (self ):
305+ """Text to be displayed."""
306+ return self ._text
307+
308+ @text .setter # Cannot set color or background color with text setter, use separate setter
309+ def text (self , new_text ):
310+ self ._reset_text (text = new_text , scale = self .scale )
0 commit comments