adafruit / Adafruit_CircuitPython_DisplayIO_Layout

A Circuitpython helper library for display element layout using displayio.
MIT License
10 stars 14 forks source link

Feature Request: BoxLayout #74

Closed ElliotGarbus closed 2 weeks ago

ElliotGarbus commented 2 years ago

I would like to request an additional Layout: BoxLayout. Here is a use case from a project I am working on: I am using a GridLayout to simplify laying out the information on the screen. I have defined 4 rows and 1 column in the grid. I want each row to contain multiple Labels and a TileGrid bitmap. The allows me to position these objects without having to manually calculate all of the horizontal positions.

I created a primitive horizontal boxlayout that works with Label and TileGrid to create a Group that can be placed in the GridLayout.

Here is the code I used this works for my limited use case:

class HBoxLayout(Group):
    @property
    def width(self):
        _width = 0
        for w in self:
            if isinstance(w, TileGrid):
                _width += w.width * w.tile_width
            else:
                _width += w.width * w.scale            
        #_width = sum([w.width * w.scale for w in self]) #TileGrid does not have a scale attribute
        return _width

    @property
    def height(self):
        return max([w.height for w in self])  # also needs scale - but not needed for my use case.

    def append(self, layer):
        if not len(self):
            layer.x = 0 # the first widget starts at zero
        else:
            layer.x = self.width 
        super().append(layer)

As you can see in the code above, the HBoxLayout adds height and width properties to Group, and overrides the append method to automatically position "widgets".

Here is a simple example of the class in use:

layout = GridLayout(
    x=128,
    y=0,
    width=168,
    height=128,
    grid_size=(1, 4),
    cell_padding=0,
    divider_lines=False,
    divider_line_color=0x000000,
    cell_anchor_point=(0, 1))

for row in range(4):
    group = HBoxLayout()
    weather_icon = TileGrid(
        icons_small_bmp,
        pixel_shader=icons_small_pal,
        x=0,
        y=-8,
        width=1,
        height=1,
        tile_width=20,
        tile_height=20,
    )
    weather_icon[0] = row
    group.append(label.Label(terminalio.FONT, text=f'{DAYS[row]} ', color=0x000000, scale=2))
    group.append(weather_icon)
    group.append(label.Label(terminalio.FONT, text=' 88/106', color=0x000000, scale=2))
    group.append(label.Label(terminalio.FONT, text='o', y=-6, color=0x000000, scale=1))
    layout.add_content(cell_content=group, grid_position=(0, row), cell_size=(1,1))

magtag.splash.append(layout)
magtag.refresh()
magtag.exit_and_deep_sleep(15)

A more robust solution would include a more general BoxLayout that supports vertical and horizontal orientations.