Skip to content

Commit 37321cc

Browse files
Merge pull request #1 from adafruit/main
Updating Master Branch
2 parents 2f6251f + 7aed2e7 commit 37321cc

18 files changed

+1664
-31
lines changed

LICENSES/OFL-1.1.txt

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
Copyright (c) <dates>, <Copyright Holder> (<URL|email>),
2+
with Reserved Font Name <Reserved Font Name>.
3+
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>),
4+
with Reserved Font Name <additional Reserved Font Name>.
5+
Copyright (c) <dates>, <additional Copyright Holder> (<URL|email>).
6+
7+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
8+
This license is copied below, and is also available with a FAQ at:
9+
http://scripts.sil.org/OFL
10+
11+
12+
-----------------------------------------------------------
13+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
14+
-----------------------------------------------------------
15+
16+
PREAMBLE
17+
The goals of the Open Font License (OFL) are to stimulate worldwide
18+
development of collaborative font projects, to support the font creation
19+
efforts of academic and linguistic communities, and to provide a free and
20+
open framework in which fonts may be shared and improved in partnership
21+
with others.
22+
23+
The OFL allows the licensed fonts to be used, studied, modified and
24+
redistributed freely as long as they are not sold by themselves. The
25+
fonts, including any derivative works, can be bundled, embedded,
26+
redistributed and/or sold with any software provided that any reserved
27+
names are not used by derivative works. The fonts and derivatives,
28+
however, cannot be released under any other type of license. The
29+
requirement for fonts to remain under this license does not apply
30+
to any document created using the fonts or their derivatives.
31+
32+
DEFINITIONS
33+
"Font Software" refers to the set of files released by the Copyright
34+
Holder(s) under this license and clearly marked as such. This may
35+
include source files, build scripts and documentation.
36+
37+
"Reserved Font Name" refers to any names specified as such after the
38+
copyright statement(s).
39+
40+
"Original Version" refers to the collection of Font Software components as
41+
distributed by the Copyright Holder(s).
42+
43+
"Modified Version" refers to any derivative made by adding to, deleting,
44+
or substituting -- in part or in whole -- any of the components of the
45+
Original Version, by changing formats or by porting the Font Software to a
46+
new environment.
47+
48+
"Author" refers to any designer, engineer, programmer, technical
49+
writer or other person who contributed to the Font Software.
50+
51+
PERMISSION & CONDITIONS
52+
Permission is hereby granted, free of charge, to any person obtaining
53+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
54+
redistribute, and sell modified and unmodified copies of the Font
55+
Software, subject to the following conditions:
56+
57+
1) Neither the Font Software nor any of its individual components,
58+
in Original or Modified Versions, may be sold by itself.
59+
60+
2) Original or Modified Versions of the Font Software may be bundled,
61+
redistributed and/or sold with any software, provided that each copy
62+
contains the above copyright notice and this license. These can be
63+
included either as stand-alone text files, human-readable headers or
64+
in the appropriate machine-readable metadata fields within text or
65+
binary files as long as those fields can be easily viewed by the user.
66+
67+
3) No Modified Version of the Font Software may use the Reserved Font
68+
Name(s) unless explicit written permission is granted by the corresponding
69+
Copyright Holder. This restriction only applies to the primary font name as
70+
presented to the users.
71+
72+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
73+
Software shall not be used to promote, endorse or advertise any
74+
Modified Version, except to acknowledge the contribution(s) of the
75+
Copyright Holder(s) and the Author(s) or with their explicit written
76+
permission.
77+
78+
5) The Font Software, modified or unmodified, in part or in whole,
79+
must be distributed entirely under this license, and must not be
80+
distributed under any other license. The requirement for fonts to
81+
remain under this license does not apply to any document created
82+
using the Font Software.
83+
84+
TERMINATION
85+
This license becomes null and void if any of the above conditions are
86+
not met.
87+
88+
DISCLAIMER
89+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
90+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
91+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
92+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
93+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
94+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
95+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
96+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
97+
OTHER DEALINGS IN THE FONT SOFTWARE.
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
# SPDX-FileCopyrightText: 2021 Kevin Matocha
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
6+
`annotation`
7+
================================================================================
8+
A widget for annotating other widgets or freeform positions.
9+
10+
* Author(s): Kevin Matocha
11+
12+
Implementation Notes
13+
--------------------
14+
15+
**Hardware:**
16+
17+
**Software and Dependencies:**
18+
19+
* Adafruit CircuitPython firmware for the supported boards:
20+
https://github.com/adafruit/circuitpython/releases
21+
22+
"""
23+
24+
# pylint: disable=too-many-arguments, too-many-locals, unused-argument
25+
26+
from terminalio import FONT
27+
from adafruit_display_text import bitmap_label
28+
from adafruit_display_shapes.line import Line
29+
from adafruit_displayio_layout.widgets.widget import Widget
30+
31+
32+
class Annotation(Widget):
33+
"""A widget to be used to annotate other widgets with text and lines, but can also
34+
be used freeform by using ``(x,y)`` parameter.
35+
36+
:param int x: x-direction pixel position for the end of the annotation line for
37+
freeform positioning, ``(x,y)`` will be ignored if a ``widget`` and ``anchor_point`` and/or
38+
``anchored_position`` are provided.
39+
:param int y: y-direction pixel position for the end of the annotation line for
40+
freeform positioning.
41+
42+
:param Widget widget: the widget to be annotated, all dimensions are relative to
43+
this widget. The annotation line position will be defined by either
44+
the ``anchor_point`` (in relative dimensions of the size of the widget)
45+
or the ``anchored_position`` (in raw pixel dimensions relative to the origin
46+
of the widget).
47+
48+
:param str text: text to be displayed in the annotation.
49+
:param Font font: font to be used for the text.
50+
51+
:param anchor_point: starting point for the annotation line, where ``anchor_point`` is an
52+
(A,B) tuple in relative units of the size of the widget,
53+
for example (0.0, 0.0) is the upper left corner, and (1.0, 1.0) is the lower
54+
right corner of the widget. If ``anchor_point`` is `None`, then ``anchored_position``
55+
is used to set the annotation line starting point, in widget size relative units
56+
(default is (0.0, 0.0)).
57+
:type anchor_point: Tuple[float, float]
58+
59+
:param anchored_position: pixel position starting point for the annotation line
60+
where ``anchored_position`` is an (x,y) tuple in pixel units relative to the
61+
upper left corner of the widget, in pixel units (default is None).
62+
:type anchored_position: Tuple[int, int]
63+
64+
:param position_offset: Used to *nudge* the line position to where you want, this
65+
is an (x,y) pixel offset added to the annotation line starting
66+
point, either set by ``anchor_point`` or ``anchored_position`` (in pixel units).
67+
:type position_offset: Tuple[int, int]
68+
69+
:param int delta_x: the pixel x-offset for the second end of the line where the text
70+
will reside, in pixel units (default: -15).
71+
:param int delta_y: the pixel y-offset for the second end of the line where the text
72+
will reside, in pixel units (default: -10).
73+
74+
:param int stroke: the annotation line width (in pixels). [NOT currently implemented]
75+
76+
:param int line_color: the color of the annotation line (default: 0xFFFFFF).
77+
:param int text_color: the color of the text, if set to `None` color will be
78+
set to ``line_color`` (default: same as ``line_color``).
79+
80+
:param text_offset: a (x,y) pixel offset to adjust text position relative
81+
to annotation line, in pixel units (default: (0,-1)).
82+
:type text_offset: Tuple[int, int]
83+
84+
:param Boolean text_under: set `True` for text to be placed below the
85+
annotation line (default: False).
86+
87+
.. figure:: annotation_example.png
88+
:scale: 125 %
89+
:align: center
90+
:alt: Example of the annotation widget.
91+
92+
Example of the annotation widget showing two widget
93+
annotations (using ``widget`` and ``anchor_point`` input parameters) and a
94+
freeform annotation (using ``x`` and ``y`` input parameters).
95+
96+
File location: *examples/displayio_layout_annotation_simpletest.py*
97+
"""
98+
99+
def __init__(
100+
self,
101+
x=None,
102+
y=None,
103+
text=None,
104+
font=FONT,
105+
delta_x=-15,
106+
delta_y=-10,
107+
widget=None,
108+
anchor_point=(0.0, 0.0),
109+
anchored_position=None,
110+
position_offset=(0, 0),
111+
stroke=3, # Not currently implemented in adafruit_display_shapes/line.py
112+
line_color=0xFFFFFF,
113+
text_color=None,
114+
text_offset=(0, -1),
115+
text_under=False,
116+
):
117+
118+
if widget:
119+
if (x is not None) or (y is not None):
120+
print(
121+
"Note: Overriding (x,y) values with widget, anchor_point"
122+
" and/or anchored_position"
123+
)
124+
widget_width = widget.bounding_box[2]
125+
widget_height = widget.bounding_box[3]
126+
if anchor_point is not None:
127+
line_x0 = (
128+
widget.x
129+
+ round(widget_width * anchor_point[0])
130+
+ position_offset[0]
131+
)
132+
line_y0 = (
133+
widget.y
134+
+ round(widget_height * anchor_point[1])
135+
+ position_offset[1]
136+
)
137+
elif anchored_position is not None:
138+
line_x0 = widget.x + anchored_position[0] + position_offset[0]
139+
line_y0 = widget.y + anchored_position[1] + position_offset[1]
140+
else:
141+
raise ValueError("Must supply either anchor_point or anchored_position")
142+
elif (x is not None) and (y is not None):
143+
line_x0 = x
144+
line_y0 = y
145+
else:
146+
raise ValueError(
147+
"Must supply either (x,y) or widget and anchor_point or anchored_position"
148+
)
149+
150+
line_x1 = line_x0 + delta_x
151+
line_y1 = line_y0 + delta_y
152+
153+
text_anchor_point = (0.0, 1.0) # default: set text anchor to left corner
154+
underline_x_multiplier = 1
155+
156+
if delta_x < 0: # line is heading to the left, set text anchor to right corner
157+
text_anchor_point = (1.0, 1.0)
158+
underline_x_multiplier = -1
159+
160+
if (
161+
text_under
162+
): # if text is under the line, set to text_anchor_point to upper edge
163+
text_anchor_point = (text_anchor_point[0], 0.0)
164+
165+
if text_color is None:
166+
text_color = line_color
167+
168+
self._label = bitmap_label.Label(
169+
text=text,
170+
font=font,
171+
color=text_color,
172+
anchor_point=text_anchor_point,
173+
anchored_position=(line_x1 + text_offset[0], line_y1 + text_offset[1]),
174+
)
175+
176+
label_width = self._label.bounding_box[2]
177+
line_x2 = line_x1 + label_width * underline_x_multiplier + text_offset[0]
178+
# lengthen the line if the text is offset
179+
line_y2 = line_y1
180+
181+
self._line0 = Line(line_x0, line_y0, line_x1, line_y1, color=line_color)
182+
self._line1 = Line(line_x1, line_y1, line_x2, line_y2, color=line_color)
183+
184+
super().__init__(max_size=3)
185+
# Group elements:
186+
# 0. Line0 - from (x,y) to (x+delta_x, y+delta_y)
187+
# 1. Line1 - horizontal line for text
188+
# 2. Label
189+
190+
self.append(self._line0)
191+
self.append(self._line1)
192+
self.append(self._label)

adafruit_displayio_layout/widgets/dial.py

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -48,47 +48,56 @@ class Dial(Widget):
4848
4949
:param int width: requested width, in pixels
5050
:param int height: requested height, in pixels
51-
:param int padding: keepout padding amount around the border, in pixels
51+
:param int padding: keepout padding amount around the border, in pixels,
52+
default is 12
5253
53-
:param float sweep_angle: dial rotation, in degrees, maximum value is 360 degrees
54-
:param float start_angle: starting angle, in degrees. Defaults
55-
to `None` for symmetry along vertical axis. Vertical is defined as 0 degrees.
54+
:param float sweep_angle: dial rotation, in degrees, maximum value is 360 degrees,
55+
default is 90 degrees
56+
:param float start_angle: starting angle, in degrees. Set to `None` for symmetry along
57+
vertical axis. Vertical is defined as 0 degrees.
5658
Negative values are counter-clockwise degrees; positive values
57-
are clockwise degrees.
59+
are clockwise degrees. Defaults to `None`.
5860
59-
:param float min_value: the minimum value displayed on the dial
60-
:param float max_value: the maximum value displayed the dial
61+
:param float min_value: the minimum value displayed on the dial, default is 0.0
62+
:param float max_value: the maximum value displayed the dial, default is 100.0
6163
:param float value: the value to display (if None, defaults to ``min_value``)
6264
6365
:param Boolean display_value: set `True` to display a value label on the dial
64-
:param Font value_font: the font for the value label
65-
:param int value_color: the color for the value label
66+
:param Font value_font: the font for the value label, defaults to
67+
``terminalio.FONT``
68+
:param int value_color: the color for the value label, defaults to 0xFF0000
6669
:param str value_format_string: the format string for displaying the value label
6770
(defaults to ':0.0f' to show the value rounded to the nearest whole number)
68-
:param (float,float) value_label_anchor_point: anchor point on the label
69-
:param (float,float) value_label_anchor_point_on_widget: anchor point on the widget where the
70-
label will be placed
71+
:param (float,float) value_label_anchor_point: anchor point on the label, default
72+
value is (0.5, -1.0) where the y-value of -1.0 signifies the text baseline
73+
:param (float,float) value_label_anchor_point_on_widget: anchor point on the
74+
widget where the label will be placed, default value is (0.5, 0.5)
7175
72-
:param int needle_width: requested pixel width of the triangular needle
76+
:param int needle_width: requested pixel width of the triangular needle,
77+
default = 7
7378
:param int needle_color: color value for the needle, defaults to red (0xFF0000)
74-
75-
:param int tick_color: tick line color (24-bit hex value)
76-
:param int major_ticks: number of major ticks
77-
:param int major_tick_stroke: major tick line stroke width, in pixels
78-
:param int major_tick_length: major tick length, in pixels
79-
:param str major_tick_labels: array of strings for the major tick labels
79+
:param Boolean limit_rotation: Set True to limit needle rotation to between the
80+
``min_value`` and ``max_value``, set to False for unlimited rotation, default is True
81+
82+
:param int tick_color: tick line color (24-bit hex value), defaults to 0xFFFFFF
83+
:param int major_ticks: number of major ticks, default = 5
84+
:param int major_tick_stroke: major tick line stroke width, in pixels, default = 3
85+
:param int major_tick_length: major tick length, in pixels, default = 10
86+
:param str major_tick_labels: array of strings for the major tick labels,
87+
default is ("0", "25", "50", "75", "100")
8088
:param float tick_label_scale: the scaling of the tick labels, default = 1.0
81-
:param Font tick_label_font: font to be used for major tick labels
82-
:param int tick_label_color: color for the major tick labels
89+
:param Font tick_label_font: font to be used for major tick labels, default
90+
is ``terminalio.FONT``
91+
:param int tick_label_color: color for the major tick labels, default is 0xFFFFFF
8392
:param Boolean angle_tick_labels: set True to rotate the major tick labels to
84-
match the tick angle
93+
match the tick angle, default is True
8594
86-
:param int minor_ticks: number of minor ticks (per major tick)
87-
:param int minor_tick_stroke: minor tick line stroke width, in pixels
88-
:param int minor_tick_length: minor tick length, in pixels
95+
:param int minor_ticks: number of minor ticks (per major tick), default = 5
96+
:param int minor_tick_stroke: minor tick line stroke width, in pixels, default = 1
97+
:param int minor_tick_length: minor tick length, in pixels, default = 5
8998
9099
:param int background_color: background color (RGB tuple
91-
or 24-bit hex value), set None for transparent
100+
or 24-bit hex value), set `None` for transparent, default is `None`
92101
93102
94103
:param (float,float) anchor_point: (X,Y) values from 0.0 to 1.0 to define the dial's
@@ -169,6 +178,7 @@ def __init__(
169178
needle_width=7,
170179
# triangle with this base width, best if this is odd
171180
needle_color=0x880000,
181+
limit_rotation=True,
172182
value=None,
173183
value_font=None,
174184
display_value=False,
@@ -245,6 +255,7 @@ def __init__(
245255
self._clip_needle = clip_needle
246256
self._needle_width_requested = needle_width
247257
self._needle_color = needle_color
258+
self._limit_rotation = limit_rotation
248259
self._background_color = background_color
249260

250261
self._major_tick_labels = major_tick_labels
@@ -552,6 +563,9 @@ def _get_offset_position(self, position):
552563
return angle_offset
553564

554565
def _update_needle(self, value):
566+
if self._limit_rotation: # constrain between min_value and max_value
567+
value = max(min(self._value, self._max_value), self._min_value)
568+
555569
self._draw_position(
556570
value / (self._max_value - self._min_value)
557571
) # convert to position (0.0 to 1.0)

0 commit comments

Comments
 (0)