Skip to content

Commit 2776b8d

Browse files
committed
scrolling functionality moved to bitmap_label. add arguments to docstring
1 parent 553c82b commit 2776b8d

File tree

5 files changed

+163
-195
lines changed

5 files changed

+163
-195
lines changed

adafruit_display_text/bitmap_label.py

Lines changed: 155 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
__version__ = "0.0.0+auto.0"
2828
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
2929

30+
import adafruit_ticks
3031
import displayio
3132
from micropython import const
3233

@@ -66,10 +67,16 @@ class Label(LabelBase):
6667
glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
6768
it will try to have it be center-left as close as possible.
6869
70+
Optionally supports:
71+
- Accented ranges of text with different colors
72+
- Outline stroke around the text
73+
- Fixed-width scrolling "marquee"
74+
6975
:param font: A font class that has ``get_bounding_box`` and ``get_glyph``.
7076
Must include a capital M for measuring character size.
7177
:type font: ~fontio.FontProtocol
72-
:param str text: Text to display
78+
:param str text: The full text to show in the label. If this is longer than
79+
``max_characters`` then the label will scroll to show everything.
7380
:param int|Tuple(int, int, int) color: Color of all text in HEX or RGB
7481
:param int|Tuple(int, int, int)|None background_color: Color of the background, use `None`
7582
for transparent
@@ -97,6 +104,20 @@ class Label(LabelBase):
97104
configurations possibles ``LTR``-Left-To-Right ``RTL``-Right-To-Left
98105
``UPD``-Upside Down ``UPR``-Upwards ``DWR``-Downwards. It defaults to ``LTR``
99106
:param bool verbose: print debugging information in some internal functions. Default to False
107+
:param Optional[Union[Tuple, int]] outline_color: The color of the outline stroke
108+
as RGB tuple, or hex.
109+
:param int outline_size: The size in pixels of the outline stroke.
110+
Defaults to 1 pixel.
111+
:param Optional[displayio.Palette] color_palette: The palette to use for the Label.
112+
Indexes 0, 1, and 2 will be filled with background, foreground, and outline colors
113+
automatically. Indexes 3 and above can be used for accent colors.
114+
:param Optional[int] max_characters: The number of characters that sets the fixed-width.
115+
Default is None for unlimited width and no scrolling
116+
117+
:param float animate_time: The number of seconds in between scrolling animation
118+
frames. Default is 0.3 seconds.
119+
:param int current_index: The index of the first visible character in the label.
120+
Default is 0, the first character. Will increase while scrolling.
100121
101122
"""
102123

@@ -116,6 +137,9 @@ def __init__(
116137
color_palette: Optional[displayio.Palette] = None,
117138
outline_color: Optional[int] = None,
118139
outline_size: int = 1,
140+
max_characters: Optional[int] = None,
141+
animate_time: float = 0.3,
142+
current_index: int = 0,
119143
**kwargs,
120144
) -> None:
121145
self._bitmap = None
@@ -133,6 +157,11 @@ def __init__(
133157

134158
super().__init__(font, **kwargs)
135159

160+
self.animate_time = animate_time
161+
self._current_index = current_index
162+
self._last_animate_time = -1
163+
self._max_characters = max_characters
164+
136165
if color_palette is not None:
137166
if len(color_palette) <= 3:
138167
raise ValueError(
@@ -168,13 +197,16 @@ def __init__(
168197
self._save_text = save_text
169198
self._text = self._replace_tabs(self._text)
170199

171-
# call the text updater with all the arguments.
172-
self._reset_text(
173-
font=font,
174-
text=self._text,
175-
line_spacing=self._line_spacing,
176-
scale=self.scale,
177-
)
200+
if "text" in kwargs:
201+
text = kwargs["text"]
202+
else:
203+
text = ""
204+
if self._max_characters is not None:
205+
if text and text[-1] != " " and len(text) > max_characters:
206+
text = f"{text} "
207+
self._full_text = text
208+
209+
self.update(True)
178210

179211
def _init_outline_stamp(self, outline_size):
180212
self._outline_size = outline_size
@@ -687,6 +719,107 @@ def bitmap(self) -> displayio.Bitmap:
687719
"""
688720
return self._bitmap
689721

722+
def update(self, force: bool = False) -> None:
723+
"""Attempt to update the display. If ``animate_time`` has elapsed since
724+
previews animation frame then move the characters over by 1 index.
725+
Must be called in the main loop of user code.
726+
727+
:param bool force: whether to ignore ``animation_time`` and force the update.
728+
Default is False.
729+
:return: None
730+
"""
731+
_now = adafruit_ticks.ticks_ms()
732+
if force or adafruit_ticks.ticks_less(
733+
self._last_animate_time + int(self.animate_time * 1000), _now
734+
):
735+
if self._max_characters is None:
736+
self._set_text(self._full_text, self.scale)
737+
self._last_animate_time = _now
738+
return
739+
740+
if len(self.full_text) <= self.max_characters:
741+
if self._text != self.full_text:
742+
self._set_text(self.full_text, self.scale)
743+
self._last_animate_time = _now
744+
return
745+
746+
if self.current_index + self.max_characters <= len(self.full_text):
747+
_showing_string = self.full_text[
748+
self.current_index : self.current_index + self.max_characters
749+
]
750+
else:
751+
_showing_string_start = self.full_text[self.current_index :]
752+
_showing_string_end = "{}".format(
753+
self.full_text[
754+
: (self.current_index + self.max_characters) % len(self.full_text)
755+
]
756+
)
757+
758+
_showing_string = f"{_showing_string_start}{_showing_string_end}"
759+
self._set_text(_showing_string, self.scale)
760+
self.current_index += 1
761+
self._last_animate_time = _now
762+
763+
return
764+
765+
@property
766+
def current_index(self) -> int:
767+
"""Index of the first visible character.
768+
769+
:return int: The current index
770+
"""
771+
return self._current_index
772+
773+
@current_index.setter
774+
def current_index(self, new_index: int) -> None:
775+
if self.full_text:
776+
self._current_index = new_index % len(self.full_text)
777+
else:
778+
self._current_index = 0
779+
780+
@property
781+
def full_text(self) -> str:
782+
"""The full text to be shown. If it's longer than ``max_characters`` then
783+
scrolling will occur as needed.
784+
785+
:return str: The full text of this label.
786+
"""
787+
return self._full_text
788+
789+
@full_text.setter
790+
def full_text(self, new_text: str) -> None:
791+
"""
792+
User code should use the ``text`` property instead of this.
793+
"""
794+
if self._max_characters is not None:
795+
if new_text and new_text[-1] != " " and len(new_text) > self.max_characters:
796+
new_text = f"{new_text} "
797+
if new_text != self._full_text:
798+
self._full_text = new_text
799+
self.current_index = 0
800+
self.update(True)
801+
else:
802+
self._full_text = new_text
803+
804+
@property
805+
def max_characters(self):
806+
"""The maximum number of characters to display on screen.
807+
808+
:return int: The maximum character length of this label.
809+
"""
810+
return self._max_characters
811+
812+
@max_characters.setter
813+
def max_characters(self, new_max_characters):
814+
"""Recalculate the full text based on the new max characters.
815+
816+
This is necessary to correctly handle the potential space at the end of
817+
the text.
818+
"""
819+
if new_max_characters != self._max_characters:
820+
self._max_characters = new_max_characters
821+
self.full_text = self.full_text
822+
690823
@property
691824
def outline_color(self):
692825
"""Color of the outline to draw around the text. Or None for no outline."""
@@ -806,3 +939,17 @@ def clear_accent_ranges(self):
806939
"""
807940
self._accent_ranges = []
808941
self._reset_text(text=str(self._text))
942+
943+
@property
944+
def text(self):
945+
"""The full text to be shown. If it's longer than ``max_characters`` then
946+
scrolling will occur as needed.
947+
948+
:return str: The full text of this label.
949+
"""
950+
return self.full_text
951+
952+
@text.setter
953+
def text(self, new_text):
954+
self.full_text = new_text
955+
self.update(True)

adafruit_display_text/scrolling_label.py

Lines changed: 0 additions & 177 deletions
This file was deleted.

0 commit comments

Comments
 (0)