Skip to content

Add FlipInput selector #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 30, 2021
Merged

Add FlipInput selector #28

merged 6 commits into from
Mar 30, 2021

Conversation

kmatch98
Copy link
Contributor

flip_input

Adds a flip-style input selector widget.

@ladyada ladyada requested a review from FoamyGuy March 23, 2021 18:07
@FoamyGuy
Copy link
Contributor

@kmatch98 these look awesome! I will dive in and take a closer look at this one after a few of the prior PRs. Should get to it within the next few days.

Thanks again for churning out so many great widgets!

Copy link
Contributor

@FoamyGuy FoamyGuy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this @kmatch98

I have a few suggestions.

This branch also needs main merged into it to catch up a few of the rst files.

@kmatch98
Copy link
Contributor Author

kmatch98 commented Mar 26, 2021

Thanks for the positive feedback and the detailed notes. I’ll work on adopting your suggested defaults. Also I think I should add a couple drawings to clarify some of the parameters.

A couple of things where I’d like your feedback that are more philosophical or strategic about widgets in general.

I think we should add either some debouncing logic on these, or perhaps some sort of rate limit.
If animation_time is None these trip very quickly, it becomes easier to accidentally double up when pressing the button.

This seems like a question that could raise its head in many different widgets. Generalized, the question is how much “smarts” are in the main event loop and how much resides down in the widgets. Of course there is no right answer since each way can work just fine. I think the question is “how will beginning users best be served” to use these? Do we want a consistent expectation and strategy on how these things will behave. Or do we provide a menu of options? Also if folks accidentally have denounce on the main loop and in the defaults of the Widget it might cause unexpected behavior if folks don’t realize it.

A related note, I struggle sometimes how much details and structural options to put into a widget since it can feel overwhelming. The question is extended for your suggestion on response behavior, do we want options of debounce behavior to have a home inside the widget.

The second issues you raise is related to font scaling. Now we have one tool to do this with rotozoom. Do you think bitmaptools.rotozoom will be a standard we can assume exists on all boards with displays? So far we have trained people to make the font sizes they want. This gets more complicated if we open up text scaling. I think it’s a good idea but I just don’t understand yet all the ramifications to what folks expect from label, bitmap_label and every other thing that uses text. Any thoughts and suggestions are welcome.

I’m eager to hear your thoughts, and of course we can’t predict everything but we can always try something and see where it leads us.

@kmatch98
Copy link
Contributor Author

I resolve all issues except for the request for debouncing. Your inputs are welcome.

@FoamyGuy
Copy link
Contributor

I don't know exactly how the modules for different devices are chosen but I would think it's fairly safe to assume any device that has displayio is likely to have bitmaptools.rotozoom unless the size constraints don't allow for it.

It's an interesting question about how much logic to put into the object vs. the main loop. I'm not sure that I have the definite answer. One thing to consider is the adafruit_debouncer library. it could likely be used in the main loop to provide the logic for debouncing. To the extent that it does exist within the object I think it should be easy to configure or disable if user want to take more direct control of the behavior. I think offering a cool_down mechanism might be a good way to handle it. That way the user can set how slow or not they want the repeating actions to occur.

@kmatch98
Copy link
Contributor Author

I updated per your suggestions on cool_down and adding a state variable to handle the option for cool_down < 0 requires the button to be released() before it is pressed again. Here's the example code that I used to exercise these options.

I didn't change the simpletest example, since this is bordering into more complex areas. I can add this as a more advanced example, if desired.

# SPDX-FileCopyrightText: 2021 Kevin Matocha
#
# SPDX-License-Identifier: MIT
#############################
"""
This is a basic demonstration of a FlipInput widget.
"""

# pylint: disable=invalid-name

import time
import board
import displayio
import adafruit_touchscreen
from adafruit_bitmap_font import bitmap_font
from adafruit_displayio_layout.widgets.flip_input import FlipInput

display = board.DISPLAY  # create the display on the PyPortal,
# otherwise change this to setup the display
# for display chip driver and pinout you have (e.g. ILI9341)

# setup the touchscreen
ts = adafruit_touchscreen.Touchscreen(
    board.TOUCH_XL,
    board.TOUCH_XR,
    board.TOUCH_YD,
    board.TOUCH_YU,
    calibration=((5200, 59000), (5800, 57000)),
    size=(display.width, display.height),
)

# Select the font file for use
font_file = "fonts/DSEG14Classic-Regular-64-ModS.pcf"
my_font = bitmap_font.load_font(font_file)

my_flip1 = FlipInput(
    display,
    anchor_point=[0.0, 0.0],
    anchored_position=[50, 40],
    color=0xFF2222, # reddish orange color
    value_list=[ # list of month strings, using three characters
        "JAN",
        "FEB",
        "MAR",
        "APR",
        "MAY",
        "JUN",
        "JUL",
        "AUG",
        "SEP",
        "OCT",
        "NOV",
        "DEC",
    ],
    font_scale=5,
    horizontal=False, # use vertical arrows
    animation_time=0.0,
    cool_down=0.25, # add a little time before responding to the next touch
)

my_flip2 = FlipInput(
    display,
    anchor_point=[0.0, 0.0],
    anchored_position=[220, 40],
    color=0xFF2222, # reddish orange color
    value_list=["{0:02d}".format(x) for x in range(1, 31 + 1)],
                # use a list of strings from 01 through 31
                # use the {0:02d} format string to always use two digits (e.g. '03')
    font_scale=5,
    horizontal=False, # use vertical arrows
    animation_time=0.0,
    cool_down=-1.0, # requires button to be released prior to next activation
)

my_flip3 = FlipInput(
    display,
    anchor_point=[0.5, 1.0],
    anchored_position=[320 // 2, 240 - 10],
    color=0xFF2222, # reddish orange color
    value_list=["{}".format(x) for x in range(1985, 2022, 1)],
                # use a list with values of stringsfrom 1985 to 2022
    font=my_font,
    horizontal=True, # use horizontal arrows
    animation_time=0.8,  # add more time since the animation covers a longer distance
)

# Pick an interesting date to start
#
# You can set the value by direct integer indexes of the list or by a string
# Here are three ways to set the values:
my_flip1.value = 9  # use direct integer indexing to set the value to the 10th month
my_flip2.value = my_flip2.value_list.index("21")  # find the index yourself by
# searching the value_list
my_flip3.value = "2015"  # or set the value based on a string that is in the value_list

# Create the group to display and append the FlipInput widgets
my_group = displayio.Group(max_size=3)
my_group.append(my_flip1)
my_group.append(my_flip2)
my_group.append(my_flip3)

display.show(my_group)  # add high level Group to the display
display.auto_refresh = True

while True:

    p = ts.touch_point
    # print("touch_point p: {}".format(p)) # print the touch point

    if p:  # if touched, check if any of the widgets was triggered
        if my_flip1.contains(p):
            my_flip1.selected(p)
        else:
            my_flip1.released()

        if my_flip2.contains(p):
            my_flip2.selected(p)
        else:
            my_flip2.released()

        if my_flip3.contains(p):
            my_flip3.selected(p)
        else:
            my_flip3.released()

    else:
        my_flip1.released()
        my_flip2.released()
        my_flip3.released()

    time.sleep(0.05)  # small delay seems to improve touch response

Copy link
Contributor

@FoamyGuy FoamyGuy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

I tested the latest version successfully with:

Adafruit CircuitPython 6.2.0-beta.4 on 2021-03-18; Adafruit PyPortal with samd51j20

Thanks for another awesome new widget @kmatch98 !

@FoamyGuy FoamyGuy merged commit 7aed2e7 into adafruit:main Mar 30, 2021
@jposada202020
Copy link
Contributor

@kmatch98 Thanks kmatch :)

adafruit-adabot added a commit to adafruit/Adafruit_CircuitPython_Bundle that referenced this pull request Mar 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants