Skip to content

Instantly share code, notes, and snippets.

@kmatch98
Created September 27, 2020 15:49
Show Gist options
  • Save kmatch98/aa900d78487e7f83135adf3c6702b19d to your computer and use it in GitHub Desktop.
Save kmatch98/aa900d78487e7f83135adf3c6702b19d to your computer and use it in GitHub Desktop.
Adafruit Button Trials 2020_09_27
# The MIT License (MIT)
#
# Copyright (c) 2019 Limor Fried for Adafruit Industries
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
"""
`adafruit_button`
================================================================================
UI Buttons for displayio
* Author(s): Limor Fried
Implementation Notes
--------------------
**Software and Dependencies:**
* Adafruit CircuitPython firmware for the supported boards:
https://github.com/adafruit/circuitpython/releases
"""
from micropython import const
import displayio
from adafruit_display_text.label import Label
from adafruit_display_shapes.rect import Rect
from adafruit_display_shapes.roundrect import RoundRect
__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_Display_Button.git"
def _check_color(color):
# if a tuple is supplied, convert it to a RGB number
if isinstance(color, tuple):
r, g, b = color
return int((r << 16) + (g << 8) + (b & 0xFF))
return color
class Button(displayio.Group):
# pylint: disable=too-many-instance-attributes, too-many-locals
"""Helper class for creating UI buttons for ``displayio``.
:param x: The x position of the button.
:param y: The y position of the button.
:param width: The width of the button in pixels.
:param height: The height of the button in pixels.
:param name: The name of the button.
:param style: The style of the button. Can be RECT, ROUNDRECT, SHADOWRECT, SHADOWROUNDRECT.
Defaults to RECT.
:param fill_color: The color to fill the button. Defaults to 0xFFFFFF.
:param outline_color: The color of the outline of the button.
:param label: The text that appears inside the button. Defaults to not displaying the label.
:param label_font: The button label font.
:param label_color: The color of the button label text. Defaults to 0x0.
:param selected_fill: Inverts the fill color.
:param selected_outline: Inverts the outline color.
:param selected_label: Inverts the label color.
"""
RECT = const(0)
ROUNDRECT = const(1)
SHADOWRECT = const(2)
SHADOWROUNDRECT = const(3)
def __init__(
self,
*,
x=0,
y=0,
width=None,
height=None,
name=None,
style=RECT,
fill_color=0xFFFFFF,
outline_color=0x0,
label=None,
label_font=None,
label_color=0x0,
selected_fill=None,
selected_outline=None,
selected_label=None
):
super().__init__(x=x, y=y)
self.x = x
self.y = y
self._width = width
self._height = height
self._font = label_font
self._selected = False
self.name = name
#self._label = label
self._label_object = None
self.body = self.fill = self.shadow = None
self.fill_color = _check_color(fill_color)
self.outline_color = _check_color(outline_color)
self._label_color = label_color
self._label_font = label_font
# Selecting inverts the button colors!
self.selected_fill = _check_color(selected_fill)
self.selected_outline = _check_color(selected_outline)
self.selected_label = _check_color(selected_label)
self.style=style
self._update_button(label) # Create the button elements.
def _update_button(self, label):
if (self._width is not None) and (self._height is not None):
# store any existing text if there is not a new label
if self._label_object and self and (self[-1] == self._label_object) and (label is None):
label=self._label_object.text
for _ in range(len(self)): # clear any existing items in the current button Group
self.pop()
print("len self: {}".format(len(self)))
if self.selected_fill is None and self.fill_color is not None:
self.selected_fill = (~self.fill_color) & 0xFFFFFF
if self.selected_outline is None and self.outline_color is not None:
self.selected_outline = (~self.outline_color) & 0xFFFFFF
if (self.outline_color is not None) or (self.fill_color is not None):
if self.style == Button.RECT:
self.body = Rect(
0,
0,
self._width,
self._height,
fill=self.fill_color,
outline=self.outline_color,
)
elif self.style == Button.ROUNDRECT:
self.body = RoundRect(
0,
0,
self._width,
self._height,
r=10,
fill=self.fill_color,
outline=self.outline_color,
)
elif self.style == Button.SHADOWRECT:
self.shadow = Rect(2, 2, self._width - 2, self._height - 2, fill=self.outline_color)
self.body = Rect(
0,
0,
self._width - 2,
self._height - 2,
fill=self.fill_color,
outline=self.outline_color,
)
elif self.style == Button.SHADOWROUNDRECT:
self.shadow = RoundRect(
2, 2, self._width - 2, self._height - 2, r=10, fill=self.outline_color
)
self.body = RoundRect(
0,
0,
self._width - 2,
self._height - 2,
r=10,
fill=self.fill_color,
outline=self.outline_color,
)
if self.shadow:
self.append(self.shadow)
self.append(self.body)
self.label=label
@property
def width(self):
return self._width
@width.setter
def width(self, width):
self._width=width
self._update_button(self._label_text)
@property
def height(self):
return self._height
@height.setter
def height(self, height):
self._height=height
self._update_button(self._label_text)
@property
def label(self):
"""The text label of the button"""
return self._label_text
@label.setter
def label(self, newtext):
self._label_text=newtext
print("newtext: {}".format(newtext))
if (self._width is not None) and (self._height is not None):
if self._label_object and self and (self[-1] == self._label_object):
self.pop()
self._label_object = None
if not newtext or (self._label_color is None): # no new text
return # nothing to do!
if not self._label_font:
raise RuntimeError("Please provide label font")
# This is odd usage, since the input value of label was a text string, and now it is defined as a Label object.
self._label_object = Label(self._label_font, text=newtext, line_spacing=0.75)
dims = self._label_object.bounding_box
while (dims[2] >= self.width or dims[3] >= self.height):
# ensure label is within bounds of button, shrink text length if required.
newtext=newtext[:-1]
if newtext is None:
raise RuntimeError("Button not large enough for label")
break
self._label_object = Label(self._label_font, text=newtext, line_spacing=0.75)
dims = self._label_object.bounding_box
if len(newtext) < len(self._label_text):
print("(adafruit_button) Warning: Button label was truncated to fit inside button")
self._label_object.anchor_point=(0.5,0.5)
self._label_object.anchored_position=(self.width//2, self.height//2)
self._label_object.color = self._label_color
self.append(self._label_object)
if (self.selected_label is None) and (self._label_color is not None):
self.selected_label = (~self._label_color) & 0xFFFFFF
@property
def selected(self):
"""Selected inverts the colors."""
return self._selected
@selected.setter
def selected(self, value):
if value == self._selected:
return # bail now, nothing more to do
self._selected = value
if self._selected:
new_fill = self.selected_fill
new_out = self.selected_outline
new_label = self.selected_label
if self.style == Button.SHADOWROUNDRECT:
self.shadow.x=0
self.shadow.y=0
self.shadow.fill=self.selected_outline
self.body.x=2
self.body.y=2
else:
new_fill = self.fill_color
new_out = self.outline_color
new_label = self._label_color
if self.style == Button.SHADOWROUNDRECT:
self.shadow.x=2
self.shadow.y=2
self.shadow.fill=self.outline_color
self.shadow.outline=self.outline_color
self.body.x=0
self.body.y=0
# update all relevant colors!
if self.body is not None:
self.body.fill = new_fill
self.body.outline = new_out
if self._label_object is not None:
self._label_object.color = new_label
@property
def group(self):
"""Return self for compatibility with old API."""
print(
"Warning: The group property is being deprecated. "
"User code should be updated to add the Button directly to the "
"Display or other Groups."
)
return self
def contains(self, point):
"""Used to determine if a point is contained within a button. For example,
``button.contains(touch)`` where ``touch`` is the touch point on the screen will allow for
determining that a button has been touched.
"""
return (self.x <= point[0] <= self.x + self.width) and (
self.y <= point[1] <= self.y + self.height
)
import os
import board
import displayio
from adafruit_bitmap_font import bitmap_font
from adafruit_button import Button
import adafruit_touchscreen
from grid_layout import GridLayout
# These pins are used as both analog and digital! XL, XR and YU must be analog
# and digital capable. YD just need to be digital
ts = adafruit_touchscreen.Touchscreen(
board.TOUCH_XL,
board.TOUCH_XR,
board.TOUCH_YD,
board.TOUCH_YU,
calibration=((5200, 59000), (5800, 57000)),
size=(320, 240),
)
# the current working directory (where this file is)
cwd = ("/" + __file__).rsplit("/", 1)[0]
fonts = [
file
for file in os.listdir(cwd + "/fonts/")
if (file.endswith(".bdf") and not file.startswith("._"))
]
for i, filename in enumerate(fonts):
fonts[i] = cwd + "/fonts/" + filename
print(fonts)
THE_FONT = "/fonts/Arial-16.bdf"
DISPLAY_STRING = "Button Text"
# Make the display context
splash = displayio.Group(max_size=20)
board.DISPLAY.auto_refresh=False
board.DISPLAY.show(splash)
BUTTON_WIDTH = 80
BUTTON_HEIGHT = 40
BUTTON_MARGIN = 20
##########################################################################
# Make a background color fill
color_bitmap = displayio.Bitmap(320, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = 0x404040
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0)
print(bg_sprite.x, bg_sprite.y)
splash.append(bg_sprite)
##########################################################################
# Load the font
font = bitmap_font.load_font(THE_FONT)
buttons = []
# Default button styling:
button_0 = Button(
# x=BUTTON_MARGIN,
# y=BUTTON_MARGIN,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label="butn0",
label_font=font,
)
buttons.append(button_0)
# a button with no indicators at all
button_1 = Button(
# x=BUTTON_MARGIN * 2 + BUTTON_WIDTH,
# y=BUTTON_MARGIN,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label_font=font,
label="butn1",
label_color=0x00FF00,
fill_color=0x0,
outline_color=None,
)
buttons.append(button_1)
# various colorings
button_2 = Button(
# x=BUTTON_MARGIN * 3 + 2 * BUTTON_WIDTH,
# y=BUTTON_MARGIN,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label="butn2",
label_font=font,
label_color=0x0000FF,
fill_color=0x00FF00,
outline_color=0xFF0000,
)
buttons.append(button_2)
# Transparent button with text
button_3 = Button(
# x=BUTTON_MARGIN,
# y=BUTTON_MARGIN * 2 + BUTTON_HEIGHT,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label="butn3",
label_font=font,
label_color=0x0,
fill_color=None,
outline_color=None,
)
buttons.append(button_3)
# a roundrect
button_4 = Button(
# x=BUTTON_MARGIN * 2 + BUTTON_WIDTH,
# y=BUTTON_MARGIN * 2 + BUTTON_HEIGHT,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label="butn4",
label_font=font,
style=Button.ROUNDRECT,
)
buttons.append(button_4)
# a shadowrect
button_5 = Button(
# x=BUTTON_MARGIN * 3 + BUTTON_WIDTH * 2,
# y=BUTTON_MARGIN * 2 + BUTTON_HEIGHT,
# width=BUTTON_WIDTH,
# height=BUTTON_HEIGHT,
label="butn5",
label_font=font,
style=Button.SHADOWRECT,
)
buttons.append(button_5)
# a shadowroundrect
button_6 = Button(
#x=BUTTON_MARGIN,
#y=BUTTON_MARGIN * 3 + BUTTON_HEIGHT * 2,
#width=BUTTON_WIDTH,
#height=BUTTON_HEIGHT,
label="butn6",
label_font=font,
style=Button.SHADOWROUNDRECT,
selected_label=0x0,
selected_fill=0x707070,
selected_outline=0xa0a0a0,
)
buttons.append(button_6)
#for b in buttons:
# splash.append(b)
print("width: {}".format(board.DISPLAY.width))
layout = GridLayout(
x=320-240, y=240-200,
width=240, height=200,
grid_size=(3,4), child_padding=8,
max_children=10
)
layout.add_sub_view(button_0, grid_position=(0,0), view_grid_size=(1,1))
layout.add_sub_view(button_1, grid_position=(1,0), view_grid_size=(1,1))
layout.add_sub_view(button_2, grid_position=(2,0), view_grid_size=(1,1))
layout.add_sub_view(button_3, grid_position=(0,1), view_grid_size=(1,1))
layout.add_sub_view(button_4, grid_position=(1,1), view_grid_size=(2,1))
layout.add_sub_view(button_5, grid_position=(0,2), view_grid_size=(1,2))
layout.add_sub_view(button_6, grid_position=(1,2), view_grid_size=(2,2))
splash.append(layout)
board.DISPLAY.refresh()
board.DISPLAY.auto_refresh=True
while True:
p = ts.touch_point
if p:
print(p)
for i, b in enumerate(buttons):
if b.contains(p):
print("Button %d pressed" % i)
b.selected = True
else:
b.selected = False
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment