def showChoice(self,
                   ch_idx,
                   game_no=None,
                   round_no=None,
                   rounds_tot=None,
                   won_sf=None,
                   drew_sf=None,
                   lost_sf=None):
        """Show player's choice on NeoPixels or display.
           The display also has game and round info and win/draw summary.
           This removes all the graphical objects and re-adds them which
           causes visible flickering during an update - this could be
           improved by only replacing / updating what needs changing.
        """
        if self.disp is None:
            self.pix.fill(BLACK)
            self.pix[self.choiceToPixIdx(ch_idx)] = CHOICE_COL[ch_idx]
            return

        self.emptyGroup(self.disp_group)
        # Would be slightly better to create this Group once and re-use it
        round_choice_group = Group(max_size=3)

        if round_no is not None:
            title_dob = Label(self.font,
                              text="Game {:d}  Round {:d}/{:d}".format(
                                  game_no, round_no, rounds_tot),
                              scale=2,
                              color=TITLE_TXT_COL_FG)
            title_dob.x = round(
                (self.width - len(title_dob.text) * 2 * self.font_width) // 2)
            title_dob.y = round(self.font_height // 2)
            round_choice_group.append(title_dob)

        if won_sf is not None:
            gamesum_dob = Label(self.font,
                                text="Won {:d} Drew {:d} Lost {:d}".format(
                                    won_sf, drew_sf, lost_sf),
                                scale=2,
                                color=TITLE_TXT_COL_FG)
            gamesum_dob.x = round(
                (self.width - len(gamesum_dob.text) * 2 * self.font_width) //
                2)
            gamesum_dob.y = round(self.height - 2 * self.font_height // 2)
            round_choice_group.append(gamesum_dob)

        s_group = Group(scale=3, max_size=1)
        s_group.x = 32
        s_group.y = (self.height - 3 * self.sprite_size) // 2
        s_group.append(self.sprites[ch_idx])
        round_choice_group.append(s_group)

        self.showGroup(round_choice_group)
    def showChoice(self,
                   ch_idx,
                   game_no=None,
                   round_no=None,
                   rounds_tot=None,
                   won_sf=None,
                   drew_sf=None,
                   lost_sf=None):
        """TODO DOC"""
        if self.disp is None:
            self.pix.fill(BLACK)
            self.pix[self.choiceToPixIdx(ch_idx)] = CHOICE_COL[ch_idx]
            return

        self.emptyGroup(self.disp_group)
        ### Would be slightly better to create this Group once and re-use it
        round_choice_group = Group(max_size=3)

        if round_no is not None:
            title_dob = Label(self.font,
                              text="Game {:d}  Round {:d}/{:d}".format(
                                  game_no, round_no, rounds_tot),
                              scale=2,
                              color=TITLE_TXT_COL_FG)
            title_dob.x = round(
                (self.width - len(title_dob.text) * 2 * self.font_width) // 2)
            title_dob.y = round(self.font_height // 2)
            round_choice_group.append(title_dob)

        if won_sf is not None:
            gamesum_dob = Label(self.font,
                                text="Won {:d} Drew {:d} Lost {:d}".format(
                                    won_sf, drew_sf, lost_sf),
                                scale=2,
                                color=TITLE_TXT_COL_FG)
            gamesum_dob.x = round(
                (self.width - len(gamesum_dob.text) * 2 * self.font_width) //
                2)
            gamesum_dob.y = round(self.height - 2 * self.font_height // 2)
            round_choice_group.append(gamesum_dob)

        s_group = Group(scale=3, max_size=1)
        s_group.x = 32
        s_group.y = (self.height - 3 * self.sprite_size) // 2
        s_group.append(self.sprites[ch_idx])
        round_choice_group.append(s_group)

        self.showGroup(round_choice_group)
def blankScreen(disp, pix):
    # pylint: disable=unused-argument
    """A blank screen used to hide any serial console output."""
    if disp is None:
        return

    disp.show(Group(max_size=1))
    def playerListScreen(self):
        if self.disp is None:
            return

        self.emptyGroup(self.disp_group)
        # The two multiplier allows for rssi as separate label
        playerlist_group = Group(max_size=self.max_players * 2)
        self.showGroup(playerlist_group)
Exemple #5
0
def show_image(path):
    with open(path, 'rb') as f:
        bitmap = OnDiskBitmap(f)
        pixel_shader = ColorConverter()
        sprite = TileGrid(bitmap, pixel_shader=pixel_shader)
        group = Group()
        group.append(sprite)
        board.DISPLAY.show(group)
        board.DISPLAY.wait_for_frame()
Exemple #6
0
def build(
    widget: Label,
    *,
    size: float | int,
    align: align,
    fit_to: bool | str,
) -> tuple[Group, SizeHint]:

    assert isinstance(size, int), (
        "for now, text size on circuitpython must be an " +
        f"int, found object of type {type(size).__name__} with value size={size}"
    )

    is_state = isinstance(widget._text, str)

    LabelType: Type[LabelBase] = BitmapLabel if is_state else GlyphLabel
    kwargs = {"save_text": False} if is_state else {}

    # print(
    #     widget,
    #     widget.text,
    # )
    native_label: LabelBase = LabelType(
        font=FONT,
        text=fit_to if isinstance(fit_to, str) else widget.text,
        scale=size,
        **kwargs,
    )

    native = Group()
    native.append(native_label)

    widget._impl_cache_ = (size, align)

    margin = widget._margin_

    # w, h = (
    #     native_label.bounding_box[2],
    #     native_label.bounding_box[3],
    # )

    # print(
    #     widget,
    #     w / len(widget.text),
    #     (w, h),
    # ),
    return (
        native,
        (
            int(1.15 * native_label.bounding_box[2] * size) + margin * 2,
            int(1.15 * native_label.bounding_box[3] * size) + margin * 2,
        ),
    )
Exemple #7
0
    def _create_labels(self, x_axis, y_axis, days_pos, hours_pos, mins_pos):
        if not (x_axis or y_axis) or (x_axis and y_axis):
            raise ValueError(
                "Must provide either an x or y axis for text labels, not both."
            )

        self.display = Group(max_size=3)

        x_positions = [x_axis] * 3 if x_axis else [days_pos, hours_pos, mins_pos]
        y_positions = [y_axis] * 3 if y_axis else [days_pos, hours_pos, mins_pos]

        for x, y in zip(x_positions, y_positions):
            label = PlaceholderLabel(
                x, y, placeholder=self.placeholder, font=self.font, color=self.color
            )
            self.display.append(label)
Exemple #8
0
    def _update_display(self):
        self._update_display_strings()
        banner = label.Label(FONT, text=BANNER_STRING, color=COLOR)
        state = label.Label(FONT, text=self.state_str, color=COLOR)
        detector_result = label.Label(FONT,
                                      text=self.detection_result_str,
                                      color=COLOR)
        duration = label.Label(FONT, text=self.duration_str, color=COLOR)
        min_pressure_label = label.Label(FONT,
                                         text=self.min_press_str,
                                         color=COLOR)
        high_pressure_label = label.Label(FONT,
                                          text=self.high_press_str,
                                          color=COLOR)
        pressure_label = label.Label(FONT, text=self.press_str, color=COLOR)

        banner.x = 0
        banner.y = 0 + Y_OFFSET

        state.x = 10
        state.y = 10 + Y_OFFSET

        detector_result.x = 10
        detector_result.y = 20 + Y_OFFSET

        duration.x = 10
        duration.y = 30 + Y_OFFSET

        min_pressure_label.x = 0
        min_pressure_label.y = BOTTOM_ROW - 10

        pressure_label.x = DISPLAY_WIDTH - pressure_label.bounding_box[2]
        pressure_label.y = BOTTOM_ROW

        high_pressure_label.x = 0
        high_pressure_label.y = BOTTOM_ROW

        splash = Group()
        splash.append(banner)
        splash.append(state)
        splash.append(detector_result)
        splash.append(duration)
        splash.append(min_pressure_label)
        splash.append(high_pressure_label)
        splash.append(pressure_label)

        self.display.show(splash)
Exemple #9
0
def build(
    widget: Button,
    *,
    radius: int,
    size: float | int,
    fit_to_text: bool,
) -> tuple[Native, tuple[int, int]]:
    """
    Creates the native element for the std tg-gui widget based on the _fixed_style_attrs_.
    Those _fixed_style_attrs_ are passed as kwargs to this function.
    :param widget: the tg-gui widget instance to build the native for
    :param **style_attrs: the fixed style attributes that are set at build time
    :return: a tuple of the native widget and suggested size
    """
    native = Group()

    label = Label(font=FONT, x=0, y=0, text=widget.text, scale=size)
    native.append(label)

    _, _, w, h = label.bounding_box
    w *= size
    h = int(1.15 * h * size)
    r = (
        min(radius, w // 2 - 1, h // 2 - 1)
        if isinstance(radius, int)
        else min(w // 2, h // 2) - 1
    )
    padding = round(1.25 * r)

    widget._impl_cache_ = dict(radius=radius, label_width=w)
    return (
        native,
        (
            w + padding + widget._margin_ * 2,
            int(h * 1.2) + widget._margin_ * 2,
        ),
    )
Exemple #10
0
voltage_value_dob = Label(font=terminalio.FONT,
                          text="----.-",
                          scale=FONT_SCALE,
                          color=0x00c0c0)
voltage_value_dob.y = 30

voltage_units_dob = Label(font=terminalio.FONT,
                          text="mV",
                          scale=FONT_SCALE,
                          color=0x00c0c0)
voltage_units_dob.y = voltage_value_dob.y
voltage_units_dob.x = len(voltage_value_dob.text) * FONT_WIDTH * FONT_SCALE

### 9 elements, 4 added immediately, 4 later, 1 spare for on-screen text
screen_group = Group(max_size=4 + 4 + 1)
if magnetometer is not None:
    screen_group.append(magnet_value_dob)
    screen_group.append(magnet_units_dob)
screen_group.append(voltage_value_dob)
screen_group.append(voltage_units_dob)

### Initialise some displayio objects and append them
### The following four variables are set by these two functions
### voltage_barneg_dob, voltage_sep_dob, voltage_barpos_dob
### magnet_circ_dob
voltage_bar_set(0)
if magnetometer is not None:
    magnet_circ_set(0)

### Start-up splash screen
    def showPlayerVPlayerScreen(self, me_name, op_name, my_ch_idx, op_ch_idx,
                                result, summary, win, draw, void):
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        """Display a win, draw, lose or error message."""
        self.fadeUpDown("down")
        self.emptyGroup(self.disp_group)

        if void:
            error_tot = 3
            error_group = Group(max_size=error_tot + 1)
            # Opponent's name helps pinpoint the error
            op_dob = Label(self.font,
                           text=op_name,
                           scale=2,
                           color=OPP_NAME_COL_FG)
            op_dob.x = 40
            op_dob.y = self.font_height
            error_group.append(op_dob)
            self.showGroup(error_group)
            self.fadeUpDown("up", duration=0.4)
            if result is not None:
                self.sample.play(result)
            font_scale = 2
            # Attempting to put the three pieces of "Error!" text on screen
            # synchronised with the sound sample repeating the word
            for idx in range(error_tot):
                error_dob = Label(self.font,
                                  text="Error!",
                                  scale=font_scale,
                                  color=ERROR_COL_FG)
                error_dob.x = 40
                error_dob.y = 60 + idx * 60
                error_group.append(error_dob)
                time.sleep(0.5)  # Small attempt to synchronise audio with text
                font_scale += 1

        else:
            # Would be slightly better to create this Group once and re-use it
            pvp_group = Group(max_size=3)

            # Add player's name and sprite just off left side of screen
            # and opponent's just off right
            player_detail = [[
                me_name, self.sprites[my_ch_idx], -16 - 3 * self.sprite_size,
                PLAYER_NAME_COL_FG, PLAYER_NAME_COL_BG
            ],
                             [
                                 op_name, self.opp_sprites[op_ch_idx],
                                 16 + self.width, OPP_NAME_COL_FG,
                                 OPP_NAME_COL_BG
                             ]]
            idx_lr = [0, 1]  # index for left and right sprite
            if win:
                player_detail.reverse()  # this player is winner so put last
                idx_lr.reverse()

            # Add some whitespace around winner's name
            player_detail[1][0] = " " + player_detail[1][0] + " "

            for (name, sprite, start_x, fg, bg) in player_detail:
                s_group = Group(scale=2,
                                max_size=2)  # Audio is choppy at scale=3
                s_group.x = start_x
                s_group.y = (self.height - 2 *
                             (self.sprite_size + self.font_height)) // 2

                s_group.append(sprite)
                p_name_dob = Label(
                    self.font,
                    text=name,
                    scale=1,  # This is scaled by the group
                    color=fg,
                    background_color=bg)
                # Centre text below sprite - values are * Group scale
                p_name_dob.x = (self.sprite_size -
                                len(name) * self.font_width) // 2
                p_name_dob.y = self.sprite_size + 4
                s_group.append(p_name_dob)

                pvp_group.append(s_group)

            if draw:
                sum_text = "Draw"
            elif win:
                sum_text = "You win"
            else:
                sum_text = "You lose"
            # Text starts invisible (BLACK) and color is later changed
            summary_dob = Label(self.font, text=sum_text, scale=3, color=BLACK)
            summary_dob.x = round(
                (self.width - 3 * self.font_width * len(sum_text)) / 2)
            summary_dob.y = round(self.height - (3 * self.font_height / 2))
            pvp_group.append(summary_dob)

            self.showGroup(pvp_group)
            self.fadeUpDown("up", duration=0.4)

            # Start audio half way through animations
            if draw:
                # Move sprites onto the screen leaving them at either side
                for idx in range(16):
                    pvp_group[idx_lr[0]].x += 6
                    pvp_group[idx_lr[1]].x -= 6
                    if idx == 8 and result is not None:
                        self.sample.play(result)
                    time.sleep(0.2)
            else:
                # Move sprites together, winning sprite overlaps and covers loser
                for idx in range(16):
                    pvp_group[idx_lr[0]].x += 10
                    pvp_group[idx_lr[1]].x -= 10
                    if idx == 8 and result is not None:
                        self.sample.play(result)
                    time.sleep(0.2)

            self.sample.wait()  # Wait for first sample to finish

            if summary is not None:
                self.sample.play(summary)

            # Flash colours for win, fad up to blue for rest
            if not draw and win:
                colours = [YELLOW_COL, ORANGE_COL, RED_COL] * 5
            else:
                colours = [DRAWLOSE_COL * sc // 15 for sc in range(1, 15 + 1)]
            for col in colours:
                summary_dob.color = col
                time.sleep(0.120)

        self.sample.wait()  # Ensure second sample has completed
# SPDX-License-Identifier: MIT
"""
CircuitPython simple sensor data display demo using LC709203 battery monitor and TFT display
"""
import time
import board
import terminalio
from displayio import Group
from adafruit_display_text import bitmap_label
from adafruit_lc709203f import LC709203F

text_area = bitmap_label.Label(terminalio.FONT, scale=2)
text_area.anchor_point = (0.5, 0.5)
text_area.anchored_position = (board.DISPLAY.width // 2, board.DISPLAY.height // 2)

main_group = Group()

main_group.append(text_area)

print("LC709203F test")
print("Make sure LiPoly battery is plugged into the board!")

sensor = LC709203F(board.I2C())

print("IC version:", hex(sensor.ic_version))

board.DISPLAY.show(main_group)

while True:
    text_area.text = "Battery:\n{:.1f} Volts \n{}%".format(sensor.cell_voltage, sensor.cell_percent)
    time.sleep(1)
Exemple #13
0
    ### Inputs
    _button_a = digitalio.DigitalInOut(board.BUTTON_A)
    _button_a.switch_to_input(pull=digitalio.Pull.UP)
    _button_b = digitalio.DigitalInOut(board.BUTTON_B)
    _button_b.switch_to_input(pull=digitalio.Pull.UP)
    button_left = lambda: not _button_a.value
    button_right = lambda: not _button_b.value

### The 6x14 terminalio classic font
FONT_WIDTH, FONT_HEIGHT = terminalio.FONT.get_bounding_box()

rows = 10
row_y = 30
row_spacing = FONT_HEIGHT + 2
rows_group = Group()

### I have foreground and background colours I can use here

### 1234567890123456789012345678901234567890
### aa:bb:cc:dd:ee:ff -101 12345678901234567
for _ in range(rows):
    row_label = Label(font=terminalio.FONT, text="", color=0xc0c000)
    row_label.y = row_y
    row_y += row_spacing
    rows_group.append(row_label)

summary_label = Label(font=terminalio.FONT, text="", color=0x00c0c0)

summary_label.y = 220
    def showGameResultScreen(self, pla, sco, rounds_tot=None):
        # pylint: disable=unused-argument,too-many-locals,too-many-statements
        """Display a high score table with a visual bubble sort
           slow enough to see the algorithm at work."""
        self.fadeUpDown("down")
        self.emptyGroup(self.disp_group)

        # Score list group + background + question mark for sorting
        gs_group = Group(max_size=4)

        # Pale grey large GAME SCORES background
        bg_scale = 6
        sbg_dob1 = Label(self.font, text="GAME", scale=bg_scale, color=GS_COL)
        sbg_dob1.x = (self.width - 4 * bg_scale * self.font_width) // 2
        sbg_dob1.y = self.height // 4
        sbg_dob2 = Label(self.font,
                         text="SCORES",
                         scale=bg_scale,
                         color=GS_COL)
        sbg_dob2.x = (self.width - 6 * bg_scale * self.font_width) // 2
        sbg_dob2.y = self.height // 4 * 3
        gs_group.append(sbg_dob1)
        gs_group.append(sbg_dob2)
        self.showGroup(gs_group)
        self.fadeUpDown("up")

        # Calculate maximum length player name
        # and see if scores happen to already be in order
        max_len = 0
        prev_score = sco[0]
        descending = True
        for idx, (name, _) in enumerate(pla):
            max_len = max(max_len, len(name))
            if sco[idx] > prev_score:
                descending = False
            prev_score = sco[idx]

        fmt = "{:" + str(max_len) + "s} {:2d}"
        x_pos = (self.width - (max_len + 3) * 2 * self.font_width) // 2
        scale = 2
        spacing = 4 if len(pla) <= 6 else 0
        top_y_pos = round((self.height - len(pla) * scale * self.font_height -
                           (len(pla) - 1) * spacing) / 2 +
                          scale * self.font_height / 2)
        scores_group = Group(max_size=len(pla))
        gs_group.append(scores_group)
        for idx, (name, _) in enumerate(pla):
            op_dob = Label(
                self.font,
                text=fmt.format(name, sco[idx]),
                scale=2,
                color=(PLAYER_NAME_COL_FG if idx == 0 else OPP_NAME_COL_FG))
            op_dob.x = x_pos
            op_dob.y = top_y_pos + idx * (scale * self.font_height + spacing)
            scores_group.append(op_dob)
            time.sleep(0.2)

        # Sort the entries if needed
        sort_scores = list(sco)  # Make an independent local copy
        if not descending:
            empty_group = Group()  # minor hack to aid swaps in scores_group
            step = 3
            qm_dob = Label(self.font, text="?", scale=2, color=QM_SORT_FG)
            qm_dob.x = round(x_pos - 1.5 * scale * self.font_width)
            gs_group.append(qm_dob)
            while True:
                swaps = 0
                for idx in range(0, len(sort_scores) - 1):
                    above_score = sort_scores[idx]
                    above_y = scores_group[idx].y
                    below_y = scores_group[idx + 1].y
                    qm_dob.y = (above_y + below_y) // 2
                    if above_score < sort_scores[idx + 1]:
                        qm_dob.text = "<"
                        qm_dob.color = QM_SORTING_FG
                        swaps += 1

                        # make list of steps
                        range_y = below_y - above_y
                        offsets = list(range(step, range_y + 1, step))
                        # Ensure this goes to the exact final position
                        if offsets[-1] != range_y:
                            offsets.append(range_y)

                        for offset in offsets:
                            scores_group[idx].y = above_y + offset
                            scores_group[idx + 1].y = below_y - offset
                            time.sleep(0.050)

                        # swap the scores around
                        sort_scores[idx] = sort_scores[idx + 1]
                        sort_scores[idx + 1] = above_score

                        # swap the graphical objects around using empty_group
                        # to avoid ValueError: Layer already in a group
                        old_above_dob = scores_group[idx]
                        old_below_dob = scores_group[idx + 1]
                        scores_group[idx + 1] = empty_group
                        scores_group[idx] = old_below_dob
                        scores_group[idx + 1] = old_above_dob

                        qm_dob.text = "?"
                        qm_dob.color = QM_SORT_FG
                        time.sleep(0.2)
                    else:
                        time.sleep(0.6)

                if swaps == 0:
                    break  # Sort complete if no values were swapped
            gs_group.remove(qm_dob)
Exemple #15
0
    cam.size = size
    if cam.width > width:
        continue
    if cam.height > height:
        continue
    try:
        bitmap = Bitmap(cam.width, cam.height, 65535)
        break
    except MemoryError:
        continue

print(width, height, cam.width, cam.height)
if bitmap is None:
    raise SystemExit("Could not allocate a bitmap")

g = Group(scale=1, x=(width - cam.width) // 2, y=(height - cam.height) // 2)
tg = TileGrid(
    bitmap,
    pixel_shader=ColorConverter(input_colorspace=Colorspace.RGB565_SWAPPED))
g.append(tg)
display.show(g)

t0 = time.monotonic_ns()
display.auto_refresh = False
while True:
    cam.capture(bitmap)
    bitmap.dirty()
    display.refresh(minimum_frames_per_second=0)
    t1 = time.monotonic_ns()
    print("fps", 1e9 / (t1 - t0))
    t0 = t1
    def introductionScreen(self):
        # pylint: disable=too-many-locals,too-many-branches,too-many-statements
        """Introduction screen."""
        if self.disp is not None:
            self.emptyGroup(self.disp_group)
            intro_group = Group(max_size=7)
            welcometo_dob = Label(self.font,
                                  text="Welcome To",
                                  scale=3,
                                  color=IWELCOME_COL_FG)
            welcometo_dob.x = (self.width - 10 * 3 * self.font_width) // 2
            # Y pos on screen looks lower than I would expect
            welcometo_dob.y = 3 * self.font_height // 2
            intro_group.append(welcometo_dob)

            extra_space = 8
            spacing = 3 * self.sprite_size + extra_space
            y_adj = (-6, -2, -2)
            for idx, sprite in enumerate(self.sprites):
                s_group = Group(scale=3, max_size=1)
                s_group.x = -96
                s_group.y = round((self.height - 1.5 * self.sprite_size) / 2 +
                                  (idx - 1) * spacing) + y_adj[idx]
                s_group.append(sprite)
                intro_group.append(s_group)

            arena_dob = Label(self.font,
                              text="Arena",
                              scale=3,
                              color=IWELCOME_COL_FG)
            arena_dob.x = (self.width - 5 * 3 * self.font_width) // 2
            arena_dob.y = self.height - 3 * self.font_height // 2
            intro_group.append(arena_dob)

            self.showGroup(intro_group)

        # The color modification here is fragile as it only works
        # if the text colour is blue, i.e. data is in lsb only
        self.sample.play("welcome-to")
        while self.sample.playing():
            if self.disp is not None and intro_group[0].color < WELCOME_COL_FG:
                intro_group[0].color += 0x10
                time.sleep(0.120)

        onscreen_x_pos = 96

        # Move each sprite onto the screen while saying its name with wav file
        anims = (("rock", 10, 1, 0.050), ("paper", 11, 2, 0.050),
                 ("scissors", 7, 3, 0.050))
        for idx, (audio_name, x_shift, grp_idx, delay_s) in enumerate(anims):
            if self.disp is None:
                self.showChoice(idx)  # Use for NeoPixels
            self.sample.play(audio_name)
            # Audio needs to be long enough to finish movement
            while self.sample.playing():
                if self.disp is not None:
                    if intro_group[grp_idx].x < onscreen_x_pos:
                        intro_group[grp_idx].x += x_shift
                        time.sleep(delay_s)

        # Set NeoPixels back to black
        if self.disp is None:
            self.pix.fill(BLACK)

        self.sample.play("arena")
        while self.sample.playing():
            if self.disp is not None and intro_group[4].color < WELCOME_COL_FG:
                intro_group[4].color += 0x10
                time.sleep(0.060)

        # Button Guide for those with a display
        if self.disp is not None:
            left_dob = Label(self.font,
                             text="< Select    ",
                             scale=2,
                             color=INFO_COL_FG,
                             background_color=INFO_COL_BG)
            left_width = len(left_dob.text) * 2 * self.font_width
            left_dob.x = -left_width
            left_dob.y = self.button_y_pos
            intro_group.append(left_dob)

            right_dob = Label(self.font,
                              text=" Transmit >",
                              scale=2,
                              color=INFO_COL_FG,
                              background_color=INFO_COL_BG)
            right_width = len(right_dob.text) * 2 * self.font_width
            right_dob.x = self.width
            right_dob.y = self.button_y_pos
            intro_group.append(right_dob)

            # Move left button text onto screen, then right
            steps = 20
            for x_pos in [
                    left_dob.x + round(left_width * x / steps)
                    for x in range(1, steps + 1)
            ]:
                left_dob.x = x_pos
                time.sleep(0.06)

            for x_pos in [
                    right_dob.x - round(right_width * x / steps)
                    for x in range(1, steps + 1)
            ]:
                right_dob.x = x_pos
                time.sleep(0.06)

            time.sleep(8)  # leave on screen for further 8 seconds
Exemple #17
0
 def on_container_build(_, widget: Widget):
     assert widget._native_ is None
     widget._native_ = group = Group()
     group.hidden = False
    def __init__(
            self,
            font: Union[BuiltinFont, BDF, PCF],
            x: int = 0,
            y: int = 0,
            text: str = "",
            color: int = 0xFFFFFF,
            background_color: int = None,
            line_spacing: float = 1.25,
            background_tight: bool = False,
            padding_top: int = 0,
            padding_bottom: int = 0,
            padding_left: int = 0,
            padding_right: int = 0,
            anchor_point: Tuple[float, float] = None,
            anchored_position: Tuple[int, int] = None,
            scale: int = 1,
            base_alignment: bool = False,
            tab_replacement: Tuple[int, str] = (4, " "),
            label_direction: str = "LTR",
            **kwargs,  # pylint: disable=unused-argument
    ) -> None:
        # pylint: disable=too-many-arguments, too-many-locals

        super().__init__(x=x, y=y, scale=1)

        self._font = font
        self._text = text
        self._palette = Palette(2)
        self._color = 0xFFFFFF
        self._background_color = None
        self._line_spacing = line_spacing
        self._background_tight = background_tight
        self._padding_top = padding_top
        self._padding_bottom = padding_bottom
        self._padding_left = padding_left
        self._padding_right = padding_right
        self._anchor_point = anchor_point
        self._anchored_position = anchored_position
        self._base_alignment = base_alignment
        self._label_direction = label_direction
        self._tab_replacement = tab_replacement
        self._tab_text = self._tab_replacement[1] * self._tab_replacement[0]

        if "max_glyphs" in kwargs:
            print(
                "Please update your code: 'max_glyphs' is not needed anymore.")

        self._ascent, self._descent = self._get_ascent_descent()
        self._bounding_box = None

        self.color = color
        self.background_color = background_color

        # local group will hold background and text
        # the self group scale should always remain at 1, the self._local_group will
        # be used to set the scale of the label
        self._local_group = Group(scale=scale)
        self.append(self._local_group)

        self._baseline = -1.0

        if self._base_alignment:
            self._y_offset = 0
        else:
            self._y_offset = self._ascent // 2
Exemple #19
0
    elif who == "opp":
        sg_idx = rps_dob_idx[1] + c_idx
    else:
        raise ValueError("who is mine or opp")

    # An even number will leave colours on original values
    for _ in range(5 * 2):
        tmp_col = screen_group[sg_idx].color
        screen_group[sg_idx].color = screen_group[sg_idx].background_color
        screen_group[sg_idx].background_color = tmp_col
        time.sleep(0.5)


# The 6x14 terminalio classic font
FONT_WIDTH, FONT_HEIGHT = terminalio.FONT.get_bounding_box()
screen_group = Group()

# The position of the two players RPS Label objects inside screen_group
rps_dob_idx = []

# Create the simple arrow cursors
left_col = 20
right_col = display.width // 2 + left_col
for x_pos in (left_col, right_col):
    y_pos = top_y_pos
    rps_dob_idx.append(len(screen_group))
    for label_text in choices:
        rps_dob = Label(terminalio.FONT,
                        text=label_text,
                        scale=2,
                        color=DEFAULT_TXT_COL_FG,
Exemple #20
0
    elif who == "opp":
        sg_idx = rps_dob_idx[1] + c_idx
    else:
        raise ValueError("who is mine or opp")

    ### An even number will leave colours on original values
    for _ in range(5 * 2):
        tmp_col = screen_group[sg_idx].color
        screen_group[sg_idx].color = screen_group[sg_idx].background_color
        screen_group[sg_idx].background_color = tmp_col
        time.sleep(0.5)


### The 6x14 terminalio classic font
FONT_WIDTH, FONT_HEIGHT = terminalio.FONT.get_bounding_box()
screen_group = Group(max_size=len(choices) * 2 + 1 + 1)

### The position of the two players RPS Label objects inside screen_group
rps_dob_idx = []

### Create the simple arrow cursors
left_col = 20
right_col = display.width // 2 + left_col
for x_pos in (left_col, right_col):
    y_pos = top_y_pos
    rps_dob_idx.append(len(screen_group))
    for label_text in choices:
        rps_dob = Label(terminalio.FONT,
                        text=label_text,
                        scale=2,
                        color=DEFAULT_TXT_COL_FG,
Exemple #21
0
    ### Inputs
    _button_a = digitalio.DigitalInOut(board.BUTTON_A)
    _button_a.switch_to_input(pull=digitalio.Pull.UP)
    _button_b = digitalio.DigitalInOut(board.BUTTON_B)
    _button_b.switch_to_input(pull=digitalio.Pull.UP)
    button_left = lambda: not _button_a.value
    button_right = lambda: not _button_b.value

### The 6x14 terminalio classic font
FONT_WIDTH, FONT_HEIGHT = terminalio.FONT.get_bounding_box()

rows = 10
row_y = 30
row_spacing = FONT_HEIGHT + 2
rows_group = Group(max_size=rows)

### I have foreground and background colours I can use here

### 1234567890123456789012345678901234567890
### aa:bb:cc:dd:ee:ff -101 12345678901234567
for idx in range(rows):
    row_label = Label(
        font=terminalio.FONT,
        text="",
        max_glyphs=40,  ### maximum that will fit 240/6
        color=0xc0c000)
    row_label.y = row_y
    row_y += row_spacing
    rows_group.append(row_label)
                     board.TOUCH_YD,
                     board.TOUCH_YU,
                     calibration=((5200, 59000), (5800, 57000)),
                     size=(screen_width, screen_height))

elif display.rotation == 90:
    ts = Touchscreen(board.TOUCH_YU,
                     board.TOUCH_YD,
                     board.TOUCH_XL,
                     board.TOUCH_XR,
                     calibration=((5200, 59000), (5800, 57000)),
                     size=(240, 320))

elif display.rotation == 180:
    ts = Touchscreen(board.TOUCH_XR,
                     board.TOUCH_XL,
                     board.TOUCH_YU,
                     board.TOUCH_YD,
                     calibration=((5200, 59000), (5800, 57000)),
                     size=(320, 240))

elif display.rotation == 270:
    ts = Touchscreen(board.TOUCH_YD,
                     board.TOUCH_YU,
                     board.TOUCH_XR,
                     board.TOUCH_XL,
                     calibration=((5200, 59000), (5800, 57000)),
                     size=(240, 320))

splash = Group(max_size=10)
class TouchKeys:
    '''Touch keyboard for pyportal usage.'''

    # Settings
    BUTTON_WIDTH, BUTTON_HEIGHT = 48, 40
    BUTTON_COLOR, BUTTON_TEXT_COLOR = LIGHT_GRAY, BLACK
    BUTTON_MARGIN, PADDING = 0, 0
    MAX_CHARS = 300
    LEFT_START, TOP_START = 1, 114
    CAPITALIZED = True

    Coords = namedtuple("Point", "x y")
    buttons = []

    alpha_keys_caps = [
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'Q', 'W', 'E', 'R',
        'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K',
        'L', 'DEL', 'Z', 'X', 'C', 'V', 'B', 'N', 'M', ',', '.', '/', 'CAPS',
        'SYM', ' ', 'RETURN', '???'
    ]

    alpha_keys_lower = [
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'q', 'w', 'e', 'r',
        't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k',
        'l', 'DEL', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 'CAPS',
        'SYM', ' ', 'RETURN', '???'
    ]

    symbol_keys = [
        '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '`', '~', '!', '@',
        '#', '$', '%', '^', '&', '*', '(', ')', '-', '=', '_', '+', '{', '}',
        '[', ']', ';', "'", ':', '"', '<', '>', '?', ',', '.', '/', '\\', '|',
        'ABC', 'RETURN', '???'
    ]

    key_sets = [alpha_keys_caps, alpha_keys_lower, symbol_keys]

    # draw rectangle to hold the text stuff.
    text_area = Rect(0,
                     2,
                     screen_width - 0,
                     108,
                     fill=DARK_GRAY,
                     outline=PINK_ISH)
    # create label area for text to show in.
    text_box = Label(font2,
                     text="",
                     color=LIGHT_GRAY,
                     max_glyphs=MAX_CHARS,
                     x=10,
                     y=16)

    # define all the groups for the OSK for each key set:
    main_group = Group(max_size=(len(alpha_keys_caps) + 4))

    main_group.append(text_area)
    main_group.append(text_box)

    def __init__(self):
        '''load the parts and display the keyboard and text entry box'''
        print('Loading keyboard')
        self.load_buttons(self.key_sets[0])

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        splash.pop()

    def edit_text(self):
        pass

    # Some button functions
    def button_grid(self, row, col):
        return self.Coords(
            self.BUTTON_MARGIN * (row + self.PADDING) +
            self.BUTTON_WIDTH * row + self.LEFT_START,
            self.BUTTON_MARGIN * (col + self.PADDING) +
            self.BUTTON_HEIGHT * col + self.TOP_START)

    def add_button(self,
                   row,
                   col,
                   label,
                   width=1,
                   color=LIGHT_GRAY,
                   text_color=BLACK):
        pos = self.button_grid(row, col)
        new_button = Button(x=pos.x,
                            y=pos.y,
                            width=self.BUTTON_WIDTH * width +
                            self.BUTTON_MARGIN * (width - 1),
                            height=self.BUTTON_HEIGHT,
                            label=label,
                            label_font=font,
                            label_color=text_color,
                            fill_color=color,
                            style=Button.SHADOWRECT)
        self.buttons.append(new_button)
        return new_button

    def find_button(self, label):
        result = None
        for _, btn in enumerate(self.buttons):
            if btn.label == label:
                result = btn
        return result

    def load_buttons(self, key_set):
        x, y = 0, 0
        btn_width = 1
        for char in key_set:
            if y == 4:
                btn_width = 2
                if x > 0:
                    x += 1
            self.add_button(x, y, char, width=btn_width)
            x += 1
            if x == 10:
                x = 0
                y += 1
        for btn in self.buttons:
            self.main_group.append(btn.group)

    def switch_alpha_symbol(self, input_char):
        # print('SWITCH TO ALPHA or SYMBOL KEY SET!')
        if input_char == 'ABC':
            if self.CAPITALIZED:
                cap = 0
            elif not self.CAPITALIZED:
                cap = 1
            # print(f'Cap setting: {cap}')
            for b, btn in enumerate(self.buttons):
                btn.label = self.key_sets[cap][b]
        elif input_char == 'SYM':
            for b, btn in enumerate(self.buttons):
                btn.label = self.key_sets[2][b]
        time.sleep(0.75)

    def delete_text_char(self):
        # print('THIS NEEDS TO DELETE SOMETHING')
        if len(self.text_box.text) > 0:
            self.text_box.text = self.text_box.text[:-1]

    def switch_capitalization(self):
        if self.CAPITALIZED:
            # print('Switch to Lower Case set')
            for b, btn in enumerate(self.buttons):
                # print(self.key_sets[0][b])
                btn.label = self.key_sets[1][b]
        elif not self.CAPITALIZED:
            # print('Switch to Upper Case Set')
            for b, btn in enumerate(self.buttons):
                # print(self.key_sets[1][b])
                btn.label = self.key_sets[0][b]
        self.CAPITALIZED = not self.CAPITALIZED
        time.sleep(0.75)

    def update_text(self, text_from_buttons):
        self.text_box.text += text_from_buttons

    def show(self, target_group):
        '''Get the keyboard to show on the display :crosses fingers:'''
        # print('SHOW ME THE KEYBOARD!')
        target_group.append(self.main_group)
        text_input = ''
        touched = False
        while True:
            touch = ts.touch_point
            if touch:
                # print(touch)
                for btn in self.buttons:
                    if btn.contains(touch) and touched == False:
                        touched = True
                        input_char = btn.label
                        # print(input_char)
                        if input_char == 'DEL':
                            # remove the last char added.
                            text_input = text_input[:-1]
                            self.delete_text_char()
                            # print(text_input)
                        elif input_char == 'CAPS':
                            self.switch_capitalization()
                        elif input_char == 'SYM' or input_char == 'ABC':
                            self.switch_alpha_symbol(input_char)
                        elif input_char == 'RETURN':
                            # return the typed shit to the outside world!
                            return text_input
                        elif input_char == '???':
                            print('Uhh.....')
                        else:
                            self.update_text(input_char)
                            text_input += input_char
                            # print(text_input)
                    elif touched and not btn.contains(touch):
                        # print('buttons released')
                        touched = False
                time.sleep(0.05)