fret-desktop-window.py

#
import flet
from flet import (
    AppBar,
    Card,
    Column,
    Container,
    NavigationRail,
    NavigationRailDestination,
    Page,
    PopupMenuButton,
    PopupMenuItem,
    Row,
    Text,
    icons,
)
#

A desktop app layout with a menu on the left.

class DesktopAppLayout(Row):
#
#
    def __init__(
        self,
        title,
        page,
        pages,
        *args,
        window_size=(800, 600),
        **kwargs,
    ):
        super().__init__(*args, **kwargs)

        self.page = page
        self.pages = pages

        self.expand = True

        self.navigation_items = [navigation_item for navigation_item, _ in pages]
        self.navigation_rail = self.build_navigation_rail()
        self.update_destinations()
        self._menu_extended = True
        self.navigation_rail.extended = True

        self.menu_panel = Row(
            controls=[
                self.navigation_rail,
            ],
            spacing=0,
            tight=True,
        )

        page_contents = [page_content for _, page_content in pages]
        self.content_area = Column(page_contents, expand=True)

        self._was_portrait = self.is_portrait()
        self._panel_visible = self.is_landscape()

        self.set_content()

        self._change_displayed_page()

        self.page.on_resize = self.handle_resize

        self.page.appbar = self.create_appbar()

        self.window_size = window_size
        self.page.window_width, self.page.window_height = self.window_size

        self.page.title = title
#
    def select_page(self, page_number):
        self.navigation_rail.selected_index = page_number
        self._change_displayed_page()
#
    def _navigation_change(self, e):
        self._change_displayed_page()
        self.page.update()
#
    def _change_displayed_page(self):
        page_number = self.navigation_rail.selected_index
        for i, content_page in enumerate(self.content_area.controls):
#

update selected page

            content_page.visible = page_number == i
#
    def build_navigation_rail(self):
        return NavigationRail(
            selected_index=0,
            label_type="none",
            on_change=self._navigation_change,
#

bgcolor=colors.SURFACE_VARIANT,

        )
#
    def update_destinations(self):
        self.navigation_rail.destinations = self.navigation_items
        self.navigation_rail.label_type = "all"
#
    def handle_resize(self, e):
        pass
#
    def set_content(self):
        self.controls = [self.menu_panel, self.content_area]
        self.update_destinations()
        self.navigation_rail.extended = self._menu_extended
        self.menu_panel.visible = self._panel_visible
#
    def is_portrait(self) -> bool:
#

Return true if window/display is narrow return self.page.window_height >= self.page.window_width

        return self.page.height >= self.page.width
#
    def is_landscape(self) -> bool:
#

Return true if window/display is wide

        return self.page.width > self.page.height
#
    def create_appbar(self) -> AppBar:
        appbar = AppBar(
#

leading=menu_button, leading_width=40, bgcolor=colors.SURFACE_VARIANT,

            toolbar_height=48,
#

elevation=8,

        )

        appbar.actions = [
            Row(
                [
                    PopupMenuButton(
                        icon=icons.HELP,
                        items=[
                            PopupMenuItem(
                                icon=icons.CONTACT_SUPPORT,
                                text="Ask a question",
                            ),
                            PopupMenuItem(
                                icon=icons.BUG_REPORT,
                                text="Report a bug",
                            ),
                        ],
                    )
                ]
            )
        ]
        return appbar
#
def create_page(title: str, body: str):
    return Row(
        controls=[
            Column(
                horizontal_alignment="stretch",
                controls=[
                    Card(content=Container(Text(title, weight="bold"), padding=8)),
                    Text(body),
                ],
                expand=True,
            ),
        ],
        expand=True,
    )
#
def main(page: Page):
    pages = [
        (
            NavigationRailDestination(
                icon=icons.LANDSCAPE_OUTLINED,
                selected_icon=icons.LANDSCAPE,
                label="Menu Item A",
            ),
            create_page(
                "Example Page A",
                "This is an example page. It is a simple desktop layout with a menu on the left.",
            ),
        ),
        (
            NavigationRailDestination(
                icon=icons.PORTRAIT_OUTLINED,
                selected_icon=icons.PORTRAIT,
                label="Menu Item B",
            ),
            create_page(
                "Example Page B",
                "This is an example page. It is a simple desktop layout with a menu on the left.",
            ),
        ),
        (
            NavigationRailDestination(
                icon=icons.INSERT_EMOTICON_OUTLINED,
                selected_icon=icons.INSERT_EMOTICON,
                label="Example Page C",
            ),
            create_page(
                "Example Page C",
                "This is an example page. It is a simple desktop layout with a menu on the left.",
            ),
        ),
    ]

    menu_layout = DesktopAppLayout(
        page=page,
        pages=pages,
        title="Basic Desktop App Layout",
        window_size=(1280, 720),
    )

    page.add(menu_layout)


if __name__ == "__main__":
    flet.app(
        target=main,
    )