Skip to content
This repository was archived by the owner on Dec 23, 2021. It is now read-only.

Commit 9a1adc9

Browse files
authored
moved tarball files to clue dir (#333)
1 parent 19ce7da commit 9a1adc9

File tree

4 files changed

+282
-1
lines changed

4 files changed

+282
-1
lines changed
Binary file not shown.

src/base_circuitpython/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@
33
import sys
44

55
abs_path = pathlib.Path(__file__).parent.absolute()
6+
clue_path = os.path.join(abs_path, "../clue")
67
sys.path.insert(0, os.path.join(abs_path))
8+
sys.path.insert(0, os.path.join(clue_path))
+280
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,280 @@
1+
# The MIT License (MIT)
2+
#
3+
# Copyright (c) 2019 Scott Shawcroft for Adafruit Industries LLC
4+
#
5+
# Permission is hereby granted, free of charge, to any person obtaining a copy
6+
# of this software and associated documentation files (the "Software"), to deal
7+
# in the Software without restriction, including without limitation the rights
8+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
# copies of the Software, and to permit persons to whom the Software is
10+
# furnished to do so, subject to the following conditions:
11+
#
12+
# The above copyright notice and this permission notice shall be included in
13+
# all copies or substantial portions of the Software.
14+
#
15+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
# THE SOFTWARE.
22+
"""
23+
`adafruit_display_text.label`
24+
====================================================
25+
26+
Displays text labels using CircuitPython's displayio.
27+
28+
* Author(s): Scott Shawcroft
29+
30+
Implementation Notes
31+
--------------------
32+
33+
**Hardware:**
34+
35+
**Software and Dependencies:**
36+
37+
* Adafruit CircuitPython firmware for the supported boards:
38+
https://github.com/adafruit/circuitpython/releases
39+
40+
"""
41+
42+
import displayio
43+
44+
__version__ = "0.0.0-auto.0"
45+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Text.git"
46+
47+
48+
class Label(displayio.Group):
49+
"""A label displaying a string of text. The origin point set by ``x`` and ``y``
50+
properties will be the left edge of the bounding box, and in the center of a M
51+
glyph (if its one line), or the (number of lines * linespacing + M)/2. That is,
52+
it will try to have it be center-left as close as possible.
53+
54+
:param Font font: A font class that has ``get_bounding_box`` and ``get_glyph``.
55+
Must include a capital M for measuring character size.
56+
:param str text: Text to display
57+
:param int max_glyphs: The largest quantity of glyphs we will display
58+
:param int color: Color of all text in RGB hex
59+
:param double line_spacing: Line spacing of text to display"""
60+
61+
def __init__(
62+
self,
63+
font,
64+
*,
65+
x=0,
66+
y=0,
67+
text=None,
68+
max_glyphs=None,
69+
color=0xFFFFFF,
70+
background_color=None,
71+
line_spacing=1.25,
72+
**kwargs
73+
):
74+
if not max_glyphs and not text:
75+
raise RuntimeError("Please provide a max size, or initial text")
76+
if not max_glyphs:
77+
max_glyphs = len(text)
78+
super().__init__(max_size=max_glyphs, auto_write=False, **kwargs)
79+
self.width = max_glyphs
80+
self.font = font
81+
self._text = None
82+
self._anchor_point = (0, 0)
83+
self.x = x
84+
self.y = y
85+
86+
self.palette = displayio.Palette(2)
87+
if background_color is not None:
88+
self.palette[0] = background_color
89+
self.palette.make_opaque(0)
90+
self._transparent_background = False
91+
else:
92+
self.palette[0] = 0
93+
self.palette.make_transparent(0)
94+
self._transparent_background = True
95+
self.palette[1] = color
96+
97+
bounds = self.font.get_bounding_box()
98+
self.height = bounds[1]
99+
self._line_spacing = line_spacing
100+
self._boundingbox = None
101+
102+
if text is not None:
103+
self._update_text(str(text))
104+
105+
def _update_text(self, new_text): # pylint: disable=too-many-locals
106+
x = 0
107+
y = 0
108+
i = 0
109+
old_c = 0
110+
y_offset = int(
111+
(
112+
self.font.get_glyph(ord("M")).height
113+
- new_text.count("\n") * self.height * self.line_spacing
114+
)
115+
/ 2
116+
)
117+
# print("y offset from baseline", y_offset)
118+
left = right = top = bottom = 0
119+
for character in new_text:
120+
if character == "\n":
121+
y += int(self.height * self._line_spacing)
122+
x = 0
123+
continue
124+
glyph = self.font.get_glyph(ord(character))
125+
if not glyph:
126+
continue
127+
right = max(right, x + glyph.width)
128+
if y == 0: # first line, find the Ascender height
129+
top = min(top, -glyph.height + y_offset)
130+
bottom = max(bottom, y - glyph.dy + y_offset)
131+
position_y = y - glyph.height - glyph.dy + y_offset
132+
position_x = x + glyph.dx
133+
if (
134+
not self._text
135+
or old_c >= len(self._text)
136+
or character != self._text[old_c]
137+
):
138+
try:
139+
face = displayio.TileGrid(
140+
glyph.bitmap,
141+
pixel_shader=self.palette,
142+
default_tile=glyph.tile_index,
143+
tile_width=glyph.width,
144+
tile_height=glyph.height,
145+
position=(position_x, position_y),
146+
)
147+
except TypeError:
148+
face = displayio.TileGrid(
149+
glyph.bitmap,
150+
pixel_shader=self.palette,
151+
default_tile=glyph.tile_index,
152+
tile_width=glyph.width,
153+
tile_height=glyph.height,
154+
x=position_x,
155+
y=position_y,
156+
)
157+
if i < len(self):
158+
self[i] = face
159+
else:
160+
self.append(face)
161+
elif self._text and character == self._text[old_c]:
162+
try:
163+
self[i].position = (position_x, position_y)
164+
except AttributeError:
165+
self[i].x = position_x
166+
self[i].y = position_y
167+
168+
x += glyph.shift_x
169+
170+
# TODO skip this for control sequences or non-printables.
171+
i += 1
172+
old_c += 1
173+
# skip all non-prinables in the old string
174+
while (
175+
self._text
176+
and old_c < len(self._text)
177+
and (
178+
self._text[old_c] == "\n"
179+
or not self.font.get_glyph(ord(self._text[old_c]))
180+
)
181+
):
182+
old_c += 1
183+
# Remove the rest
184+
while len(self) > i:
185+
self.pop()
186+
self._text = new_text
187+
self._boundingbox = (left, top, left + right, bottom - top)
188+
189+
@property
190+
def bounding_box(self):
191+
"""An (x, y, w, h) tuple that completely covers all glyphs. The
192+
first two numbers are offset from the x, y origin of this group"""
193+
return tuple(self._boundingbox)
194+
195+
@property
196+
def line_spacing(self):
197+
"""The amount of space between lines of text, in multiples of the font's
198+
bounding-box height. (E.g. 1.0 is the bounding-box height)"""
199+
return self._line_spacing
200+
201+
@line_spacing.setter
202+
def line_spacing(self, spacing):
203+
if self._line_spacing != spacing:
204+
self._line_spacing = spacing
205+
self._Group__trigger_draw()
206+
207+
@property
208+
def color(self):
209+
"""Color of the text as an RGB hex number."""
210+
return self.palette[1]
211+
212+
@color.setter
213+
def color(self, new_color):
214+
self.palette[1] = new_color
215+
self._Group__trigger_draw()
216+
217+
@property
218+
def background_color(self):
219+
"""Color of the background as an RGB hex number."""
220+
if not self._transparent_background:
221+
return self.palette[0]
222+
return None
223+
224+
@background_color.setter
225+
def background_color(self, new_color):
226+
if new_color is not None:
227+
self.palette[0] = new_color
228+
self.palette.make_opaque(0)
229+
self._transparent_background = False
230+
else:
231+
self.palette[0] = 0
232+
self.palette.make_transparent(0)
233+
self._transparent_background = True
234+
235+
self._Group__trigger_draw()
236+
237+
@property
238+
def text(self):
239+
"""Text to display."""
240+
return self._text
241+
242+
@text.setter
243+
def text(self, new_text):
244+
# APR 2, 2O2O ->
245+
# Added manual trigger to update text since
246+
# on-screen text updating is a lot faster this way.
247+
248+
# Previously, the group was set to auto_write=True
249+
# and each letter in the group was individually
250+
# drawn and sent to the front-end display.
251+
if new_text != self._text:
252+
self._update_text(str(new_text))
253+
self._Group__trigger_draw()
254+
255+
@property
256+
def anchor_point(self):
257+
"""Point that anchored_position moves relative to.
258+
Tuple with decimal percentage of width and height.
259+
(E.g. (0,0) is top left, (1.0, 0.5): is middle right.)"""
260+
return self._anchor_point
261+
262+
@anchor_point.setter
263+
def anchor_point(self, new_anchor_point):
264+
if self._anchor_point != new_anchor_point:
265+
self._Group__trigger_draw()
266+
267+
@property
268+
def anchored_position(self):
269+
"""Position relative to the anchor_point. Tuple containing x,y
270+
pixel coordinates."""
271+
return (
272+
self.x - self._boundingbox[2] * self._anchor_point[0],
273+
self.y - self._boundingbox[3] * self._anchor_point[1],
274+
)
275+
276+
@anchored_position.setter
277+
def anchored_position(self, new_position):
278+
self.x = int(new_position[0] - (self._boundingbox[2] * self._anchor_point[0]))
279+
self.y = int(new_position[1] - (self._boundingbox[3] * self._anchor_point[1]))
280+
self._Group__trigger_draw()

src/requirements.txt

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ PyObjC; platform_system == "darwin"
77
uflash==1.3.0
88
adafruit-circuitpython-fancyled==1.3.3
99
Pillow==7.0.0
10-
adafruit-circuitpython-display-text-DSX_CUSTOM_MAR172020.tar.gz
1110
adafruit-circuitpython-bitmap_font==1.1.0
1211
adafruit-circuitpython-display-shapes==1.2.0
1312
adafruit-circuitpython-neopixel==5.0.0

0 commit comments

Comments
 (0)