Skip to content

Commit a53e5ed

Browse files
authored
Merge pull request #69 from FoamyGuy/paged_layout
adding PageLayout and examples
2 parents cbfcca0 + 50a46d3 commit a53e5ed

File tree

3 files changed

+398
-0
lines changed

3 files changed

+398
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
# SPDX-FileCopyrightText: 2022 Tim Cocks
2+
#
3+
# SPDX-License-Identifier: MIT
4+
5+
"""
6+
`page_layout`
7+
================================================================================
8+
9+
A layout that organizes pages which can be viewed one at a time.
10+
11+
12+
* Author(s): Tim Cocks
13+
14+
Implementation Notes
15+
--------------------
16+
17+
**Hardware:**
18+
19+
**Software and Dependencies:**
20+
21+
* Adafruit CircuitPython firmware for the supported boards:
22+
https://github.com/adafruit/circuitpython/releases
23+
24+
"""
25+
try:
26+
# Used only for typing
27+
# pylint: disable=unused-import
28+
from typing import Tuple
29+
30+
except ImportError:
31+
pass
32+
33+
import displayio
34+
35+
__version__ = "0.0.0-auto.0"
36+
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_DisplayIO_Layout.git"
37+
38+
39+
class PageLayout(displayio.Group):
40+
"""
41+
A layout that organizes children into a grid table structure.
42+
43+
:param int x: x location the layout should be placed. Pixel coordinates.
44+
:param int y: y location the layout should be placed. Pixel coordinates.
45+
"""
46+
47+
def __init__(
48+
self,
49+
x,
50+
y,
51+
):
52+
super().__init__(x=x, y=y)
53+
self.x = x
54+
self.y = y
55+
56+
self._page_content_list = []
57+
self._cur_showing_index = 0
58+
59+
def add_content(self, page_content, page_name=None):
60+
"""Add a child to the grid.
61+
62+
:param page_content: the content for the page typically a Group
63+
:param page_name: the name of this page
64+
65+
:return: None"""
66+
67+
_page_group = displayio.Group()
68+
_page_group.append(page_content)
69+
70+
sub_view_obj = {
71+
"content": _page_group,
72+
"page_name": page_name,
73+
}
74+
75+
if len(self._page_content_list) > 0:
76+
_page_group.hidden = True
77+
78+
self._page_content_list.append(sub_view_obj)
79+
self.append(_page_group)
80+
81+
def _check_args(self, page_name, page_index):
82+
"""
83+
Ensure supplied arguments are valid
84+
85+
:param string page_name: name of a page
86+
:param int page_index: index of a page
87+
:return: None
88+
"""
89+
if page_name is None and page_index is None:
90+
raise AttributeError("Must pass either page_name or page_index")
91+
92+
if page_index is not None and page_name is not None:
93+
raise AttributeError(
94+
"Must pass either page_name or page_index only one or the other"
95+
)
96+
97+
if page_index is not None:
98+
if page_index >= len(self._page_content_list):
99+
raise KeyError(
100+
"KeyError at index {} in list length {}".format(
101+
page_index, len(self._page_content_list)
102+
),
103+
)
104+
105+
if page_name is not None:
106+
_found = False
107+
for page in self._page_content_list:
108+
if not _found:
109+
if page_name == page["page_name"]:
110+
_found = True
111+
112+
if not _found:
113+
raise KeyError("Page with name {} not found".format(page_name))
114+
115+
def get_page(self, page_name=None, page_index=None):
116+
"""
117+
Return a page content based on the name or index. Raises
118+
KeyError if the page was not found in the PageLayout.
119+
120+
:param string page_name: the name of the page to lookup
121+
:param int page_index: the index of the page to lookup
122+
:return: the displayio content object at those coordinates
123+
"""
124+
125+
self._check_args(page_name, page_index)
126+
127+
if page_index is not None:
128+
return self._page_content_list[page_index]
129+
130+
if page_name is not None:
131+
for cell in self._page_content_list:
132+
if cell["page_name"] == page_name:
133+
return cell
134+
135+
raise KeyError(
136+
"PageLayout does not contain page: {}".format(
137+
page_index if page_index else page_name
138+
)
139+
)
140+
141+
def show_page(self, page_name=None, page_index=None):
142+
"""
143+
Show the specified page, and hide all other pages.
144+
145+
:param string page_name: The name of a page to show
146+
:param int page_index: The index of a page to show
147+
:return: None
148+
"""
149+
150+
self._check_args(page_name, page_index)
151+
152+
for cur_index, page in enumerate(self._page_content_list):
153+
if page_name is not None:
154+
if page["page_name"] == page_name:
155+
self._cur_showing_index = cur_index
156+
page["content"].hidden = False
157+
else:
158+
page["content"].hidden = True
159+
160+
if page_index is not None:
161+
if cur_index == page_index:
162+
self._cur_showing_index = cur_index
163+
page["content"].hidden = False
164+
else:
165+
page["content"].hidden = True
166+
167+
@property
168+
def showing_page_index(self):
169+
"""
170+
Index of the currently showing page
171+
:return int: showing_page_index
172+
"""
173+
return self._cur_showing_index
174+
175+
@showing_page_index.setter
176+
def showing_page_index(self, new_index):
177+
self.show_page(page_index=new_index)
178+
179+
@property
180+
def showing_page_name(self):
181+
"""
182+
Name of the currently showing page
183+
:return string: showing_page_name
184+
"""
185+
return self._page_content_list[self._cur_showing_index]["page_name"]
186+
187+
@showing_page_name.setter
188+
def showing_page_name(self, new_name):
189+
self.show_page(page_name=new_name)
190+
191+
@property
192+
def showing_page_content(self):
193+
"""
194+
The content object for the currently showing page
195+
:return Displayable: showing_page_content
196+
"""
197+
return self._page_content_list[self._cur_showing_index]["content"][0]
198+
199+
def next_page(self, loop=True):
200+
"""
201+
Hide the current page and show the next one in the list by index
202+
:param bool loop: whether to loop from the last page back to the first
203+
:return: None
204+
"""
205+
206+
if self._cur_showing_index + 1 < len(self._page_content_list):
207+
self.show_page(page_index=self._cur_showing_index + 1)
208+
else:
209+
if not loop:
210+
print("No more pages")
211+
else:
212+
self.show_page(page_index=0)
213+
214+
def previous_page(self, loop=True):
215+
"""
216+
Hide the current page and show the previous one in the list by index
217+
:param bool loop: whether to loop from the first page to the last one
218+
:return: None
219+
"""
220+
if self._cur_showing_index - 1 >= 0:
221+
self.show_page(page_index=self._cur_showing_index - 1)
222+
else:
223+
if not loop:
224+
print("No more pages")
225+
else:
226+
self.show_page(page_index=len(self._page_content_list) - 1)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# SPDX-FileCopyrightText: 2022 Tim C
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""
5+
Make a PageLayout and illustrate all of it's features
6+
"""
7+
import time
8+
import displayio
9+
import board
10+
import terminalio
11+
from adafruit_display_text.bitmap_label import Label
12+
from adafruit_display_shapes.rect import Rect
13+
from adafruit_display_shapes.circle import Circle
14+
from adafruit_display_shapes.triangle import Triangle
15+
from adafruit_displayio_layout.layouts.page_layout import PageLayout
16+
17+
# built-in display
18+
display = board.DISPLAY
19+
20+
# create and show main_group
21+
main_group = displayio.Group()
22+
display.show(main_group)
23+
24+
# create the page layout
25+
test_page_layout = PageLayout(x=0, y=0)
26+
27+
# make 3 pages of content
28+
page_1_group = displayio.Group()
29+
page_2_group = displayio.Group()
30+
page_3_group = displayio.Group()
31+
32+
# labels
33+
page_1_lbl = Label(
34+
font=terminalio.FONT,
35+
scale=2,
36+
text="This is the first page!",
37+
anchor_point=(0, 0),
38+
anchored_position=(10, 10),
39+
)
40+
page_2_lbl = Label(
41+
font=terminalio.FONT,
42+
scale=2,
43+
text="This page is the second page!",
44+
anchor_point=(0, 0),
45+
anchored_position=(10, 10),
46+
)
47+
page_3_lbl = Label(
48+
font=terminalio.FONT,
49+
scale=2,
50+
text="The third page is fun!",
51+
anchor_point=(0, 0),
52+
anchored_position=(10, 10),
53+
)
54+
55+
# shapes
56+
square = Rect(x=20, y=70, width=40, height=40, fill=0x00DD00)
57+
circle = Circle(50, 100, r=30, fill=0xDD00DD)
58+
triangle = Triangle(50, 0, 100, 50, 0, 50, fill=0xDDDD00)
59+
triangle.x = 80
60+
triangle.y = 70
61+
62+
# add everything to their page groups
63+
page_1_group.append(square)
64+
page_1_group.append(page_1_lbl)
65+
page_2_group.append(page_2_lbl)
66+
page_2_group.append(circle)
67+
page_3_group.append(page_3_lbl)
68+
page_3_group.append(triangle)
69+
70+
# add the pages to the layout, supply your own page names
71+
test_page_layout.add_content(page_1_group, "page_1")
72+
test_page_layout.add_content(page_2_group, "page_2")
73+
test_page_layout.add_content(page_3_group, "page_3")
74+
75+
# add it to the group that is showing on the display
76+
main_group.append(test_page_layout)
77+
78+
# change page with function by name
79+
test_page_layout.show_page(page_name="page_3")
80+
print("showing page index:{}".format(test_page_layout.showing_page_index))
81+
time.sleep(1)
82+
83+
# change page with function by index
84+
test_page_layout.show_page(page_index=0)
85+
print("showing page name: {}".format(test_page_layout.showing_page_name))
86+
time.sleep(1)
87+
88+
# change page by updating the page name property
89+
test_page_layout.showing_page_name = "page_3"
90+
print("showing page index: {}".format(test_page_layout.showing_page_index))
91+
time.sleep(1)
92+
93+
# change page by updating the page index property
94+
test_page_layout.showing_page_index = 1
95+
print("showing page name: {}".format(test_page_layout.showing_page_name))
96+
time.sleep(5)
97+
98+
another_text = Label(
99+
terminalio.FONT,
100+
text="And another thing!",
101+
scale=2,
102+
color=0x00FF00,
103+
anchor_point=(0, 0),
104+
anchored_position=(100, 100),
105+
)
106+
test_page_layout.showing_page_content.append(another_text)
107+
108+
print("starting loop")
109+
while True:
110+
time.sleep(1)
111+
# change page by next page function. It will loop by default
112+
test_page_layout.next_page()

0 commit comments

Comments
 (0)