Skip to content

Commit

Permalink
[Update] Strategy Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
fasilwdr committed Jun 7, 2024
1 parent b77809c commit 0a766ef
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 125 deletions.
106 changes: 39 additions & 67 deletions core/base.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,21 @@
# core/base.py
import flet as ft


class Control:
"""
A class to represent a control in a Flet application.
Attributes:
flet_control: The actual Flet control instance.
visible (bool): Whether the control is visible.
overlay (bool): Whether the control is an overlay.
dialog (bool): Whether the control is a dialog.
sequence (int): The sequence number for ordering controls.
"""
def __init__(self, flet_control, visible: bool = True, overlay: bool = False, dialog: bool = False, sequence: int = 1):
self.flet_control = flet_control
self.visible = visible
self.overlay = overlay
self.dialog = dialog
self.sequence = sequence

def __getattr__(self, item):
# Delegate attribute access to the actual Flet control
return getattr(self.flet_control, item)

def __setattr__(self, key, value):
if key in ["flet_control", "visible", "overlay", "dialog", "sequence"]: # Avoid infinite recursion for internal attributes
super().__setattr__(key, value)
else:
setattr(self.flet_control, key, value)
import inspect


class Model:
route = None
controls = []
back_route = None
appbar = None
bottom_appbar = None
auto_scroll = None
bgcolor = None
drawer = None
end_drawer = None
fullscreen_dialog = False
fullscreen_dialog = None
floating_action_button = None
floating_action_button_location = None
navigation_bar = None
horizontal_alignment = ft.CrossAxisAlignment.START
on_scroll_interval = 10
Expand All @@ -50,60 +25,38 @@ class Model:
on_scroll = None
spacing = 10
vertical_alignment = ft.MainAxisAlignment.START
overlay_controls = []

def __init__(self, page):
self.page = page

def __post_init__(self):
self.post_init()

def on_view_pop(self, e):
self.page.go(self.back_route)

def init(self):
# self.bgcolor = ft.colors.PRIMARY
pass

def post_init(self):
pass

def create_view(self):
controls = []
# Collect all Control instances
control_instances = []
for attr_name in dir(self):
attr = getattr(self, attr_name)
if isinstance(attr, Control):
control_instances.append(attr)

# Sort the controls based on their sequence
sorted_controls = sorted(control_instances, key=lambda x: x.sequence)

# Add sorted controls to the view
for control in sorted_controls:
actual_flet_control = control.flet_control
for event in ['on_click', 'on_hover', 'on_long_press', 'on_change', 'on_dismiss']:
if hasattr(actual_flet_control, event):
callback_name = getattr(actual_flet_control, event)
if isinstance(callback_name, str):
method = getattr(self, callback_name, None)
if method:
setattr(actual_flet_control, event, method)
if control.visible and not control.overlay and not control.dialog:
controls.append(actual_flet_control)
if control.overlay:
self.page.overlay.append(actual_flet_control)
if control.dialog:
self.page.dialog = actual_flet_control
if self.appbar and self.back_route:
controls = self.controls
if self.overlay_controls:
for overlay in self.overlay_controls:
self.page.overlay.append(overlay)
if self.back_route:
self.page.on_view_pop = self.on_view_pop
self.appbar.leading = ft.IconButton(icon=ft.icons.ARROW_BACK, on_click=lambda e: self.page.go(self.back_route))
if self.on_keyboard_event:
self.page.on_keyboard_event = None
self.page.on_keyboard_event = self.on_keyboard_event

self.init()
return ft.View(

#Add Overlay Controls to bind event handlers
controls_to_bind = controls + self.overlay_controls
# Dynamically bind event handlers
self.bind_event_handlers(controls_to_bind)

view = ft.View(
route=self.route,
controls=controls,
appbar=self.appbar,
Expand All @@ -114,15 +67,34 @@ def create_view(self):
end_drawer=self.end_drawer,
fullscreen_dialog=self.fullscreen_dialog,
floating_action_button=self.floating_action_button,
floating_action_button_location=self.floating_action_button_location,
horizontal_alignment=self.horizontal_alignment,
on_scroll_interval=self.on_scroll_interval,
padding=self.padding,
scroll=self.scroll,
spacing=self.spacing,
vertical_alignment=self.vertical_alignment,
navigation_bar=self.navigation_bar,
on_scroll=self.on_scroll
on_scroll=self.on_scroll,
)
self.post_init()
return view

def bind_event_handlers(self, controls):
# Event handler attributes to look for
event_attrs = ['on_click', 'on_hover', 'on_long_press', 'on_change', 'on_dismiss']

for control in controls:
for attr in event_attrs:
if hasattr(control, attr):
handler = getattr(control, attr)
if isinstance(handler, str) and hasattr(self, handler):
# Bind the event handler
setattr(control, attr, getattr(self, handler))

# If the control has nested controls, bind their event handlers too
if hasattr(control, 'controls'):
self.bind_event_handlers(control.controls)


def view_model(page):
Expand All @@ -131,4 +103,4 @@ def view_model(page):
if cls.route == page.route:
return cls(page).create_view() # Pass the page object to the class
# If no matching class is found
raise ValueError("No view available for the given route")
raise ValueError("No view available for the given route")
96 changes: 43 additions & 53 deletions views/main_view.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#main_view
import flet as ft
from core.base import Model, Control
from core.base import Model
from core.controls import UserError, UserInfo, UserWarning
import datetime

Expand All @@ -10,9 +10,6 @@ class MainView(Model):
vertical_alignment = ft.MainAxisAlignment.CENTER
horizontal_alignment = ft.CrossAxisAlignment.CENTER

# def init(self):
# print("init")

appbar = ft.AppBar(
leading=ft.Icon(ft.icons.PALETTE),
leading_width=40,
Expand Down Expand Up @@ -53,24 +50,7 @@ class MainView(Model):
],
)

#DatePicker
def change_date(self, e):
print(f"Date picker changed, value is {self.date_picker.value}")

def date_picker_dismissed(self, e):
print(f"Date picker dismissed, value is {self.date_picker.value}")

date_picker = Control(
ft.DatePicker(
on_change="change_date",
on_dismiss="date_picker_dismissed",
first_date=datetime.datetime(2023, 10, 1),
last_date=datetime.datetime(2024, 10, 1),
),
overlay=True
)

#Banner
# Banner
def close_banner(e):
e.control.page.close_banner()
print("banner closed")
Expand All @@ -88,12 +68,12 @@ def close_banner(e):
],
)

#AlertDialog
dlg = Control(ft.AlertDialog(
# AlertDialog
dlg = ft.AlertDialog(
title=ft.Text("Hello, you!"), on_dismiss=lambda e: print("Dialog dismissed!")
), dialog=True)
)

dlg_modal = Control(ft.AlertDialog(
dlg_modal = ft.AlertDialog(
modal=True,
title=ft.Text("Please confirm"),
content=ft.Text("Do you really want to delete all those files?"),
Expand All @@ -103,22 +83,6 @@ def close_banner(e):
],
actions_alignment=ft.MainAxisAlignment.END,
on_dismiss=lambda e: print("Modal dialog dismissed!"),
))

#BottomSheet
bottom_sheet = ft.BottomSheet(
ft.Container(
ft.Column(
[
ft.Text("This is sheet's content!"),
ft.ElevatedButton("Close bottom sheet", on_click=lambda e: e.control.page.close_bottom_sheet()),
],
tight=True,
),
padding=10,
),
open=True,
on_dismiss=lambda e: print("Bottom Sheet dismissed!"),
)

actions = ft.Dropdown(
Expand All @@ -135,18 +99,42 @@ def close_banner(e):
ft.dropdown.Option("Go to Second Page"),
],
)
text = ft.TextField(label="Text")
sample = Control(
ft.ResponsiveRow(
controls=[
ft.Text("Check how to perform the flet controls in this Flet-Model", size=15, text_align="center", color=ft.colors.PRIMARY),
actions,
text
]
# BottomSheet
bottom_sheet = ft.BottomSheet(
ft.Container(
ft.Column(
[
ft.Text("This is sheet's content!"),
ft.ElevatedButton("Close bottom sheet", on_click=lambda e: e.control.page.close_bottom_sheet()),
],
tight=True,
),
padding=10,
),
sequence=1
open=True,
on_dismiss=lambda e: print("Bottom Sheet dismissed!"),
)
check_button = Control(ft.ElevatedButton(text="Check", on_click="on_click_check_button"), sequence=2)

# DatePicker
def change_date(self, e):
print(f"Date picker changed, value is {self.date_picker.value}")

def date_picker_dismissed(self, e):
print(f"Date picker dismissed, value is {self.date_picker.value}")

date_picker = ft.DatePicker(
on_change="change_date",
on_dismiss="date_picker_dismissed",
first_date=datetime.datetime(2023, 10, 1),
last_date=datetime.datetime(2024, 10, 1),
)

overlay_controls = [date_picker]

controls = [
actions,
ft.ElevatedButton("Go", on_click='on_click_check_button')
]

def on_click_check_button(self, e):
if self.actions.value == 'Check UserError (SnackBar)':
Expand All @@ -155,7 +143,7 @@ def on_click_check_button(self, e):
return UserInfo(self.page, "Info Message")
elif self.actions.value == 'Check UserWarning (SnackBar)':
return UserWarning(self.page, "Warning Message")
elif self.actions.value == 'Open Drawer':
if self.actions.value == 'Open Drawer':
self.page.show_drawer(self.drawer)
elif self.actions.value == 'Go to Second Page':
self.page.go('/second')
Expand All @@ -171,3 +159,5 @@ def on_click_check_button(self, e):
self.page.show_bottom_sheet(self.bottom_sheet)




16 changes: 11 additions & 5 deletions views/second_view.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
#main_view
import flet as ft
from core.base import Model, Control
from core.base import Model


class SecondView(Model):
route = '/second'
back_route = '/'

vertical_alignment = ft.MainAxisAlignment.CENTER
horizontal_alignment = ft.CrossAxisAlignment.CENTER

# def init(self):
# print("init")

appbar = ft.AppBar(
leading=ft.Icon(ft.icons.PALETTE),
leading_width=40,
title=ft.Text("Second View"),
center_title=True,
bgcolor=ft.colors.SURFACE_VARIANT)
go_button = Control(ft.ElevatedButton(text="Go Main View", on_click="on_click_go_button"), sequence=1)

def on_click_go_button(self, e):
self.page.go('/')

controls = [
ft.Text("Second Page"),
ft.ElevatedButton("Go Home", on_click=lambda e: e.control.page.go('/'))
]

0 comments on commit 0a766ef

Please sign in to comment.