Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified sdk/python/examples/tutorials/todo/media/app-4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
89 changes: 77 additions & 12 deletions sdk/python/examples/tutorials/todo/todo.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from dataclasses import field
from pickle import ADDITEMS
from typing import Callable

import flet as ft
Expand Down Expand Up @@ -27,11 +28,13 @@ def init(self):
controls=[
ft.IconButton(
icon=ft.Icons.CREATE_OUTLINED,
icon_color=ft.Colors.GREEN_ACCENT_400,
tooltip="Edit To-Do",
on_click=self.edit_clicked,
),
ft.IconButton(
ft.Icons.DELETE_OUTLINE,
icon=ft.Icons.DELETE_OUTLINE,
icon_color=ft.Colors.RED_ACCENT_200,
tooltip="Delete To-Do",
on_click=self.delete_clicked,
),
Expand All @@ -57,7 +60,7 @@ def init(self):
self.controls = [self.display_view, self.edit_view]

def edit_clicked(self, e):
self.edit_name.value = self.display_task.label
self.edit_name.value = self.display_task.label # type: ignore
self.display_view.visible = False
self.edit_view.visible = True
self.update()
Expand All @@ -80,7 +83,11 @@ def delete_clicked(self, e):
class TodoApp(ft.Column):
# application's root control is a Column containing all other controls
def init(self):
self.new_task = ft.TextField(hint_text="Whats needs to be done?", expand=True)
self.new_task = ft.TextField(
hint_text="Whats needs to be done?",
expand=True,
on_change=self.task_changed,
)
self.tasks = ft.Column()

self.filter = ft.TabBar(
Expand All @@ -100,45 +107,102 @@ def init(self):
)

self.width = 600
self.items_left = ft.Text("")

self.btn = ft.FloatingActionButton(
width=50,
height=50,
mouse_cursor=ft.MouseCursor.BASIC,
icon=ft.Icons.ADD,
on_click=self.add_clicked,
disabled=True,
visible=False,
)

self.controls = [
ft.Row(
alignment=ft.MainAxisAlignment.CENTER,
controls=[
self.new_task,
ft.FloatingActionButton(
icon=ft.Icons.ADD, on_click=self.add_clicked
),
ft.Text(
"Todos",
size=24,
color=ft.Colors.GREY_500,
weight=ft.FontWeight.NORMAL,
)
],
),
ft.Row(
controls=[self.new_task, self.btn],
),
ft.Column(
spacing=25,
controls=[
self.filter_tabs,
self.tasks,
],
),
ft.Row(
alignment=ft.MainAxisAlignment.SPACE_BETWEEN,
vertical_alignment=ft.CrossAxisAlignment.CENTER,
controls=[
self.items_left,
ft.OutlinedButton(
content="Clear completed",
on_click=self.clear_completed,
style=ft.ButtonStyle(mouse_cursor=ft.MouseCursor.CLICK),
),
],
),
]

def add_clicked(self, e):
if not self.new_task.value:
return

task = Task(
task_name=self.new_task.value,
on_status_change=self.task_status_change,
on_delete=self.task_delete,
)
self.tasks.controls.append(task)
self.new_task.value = ""
self.task_changed(None)
self.update()

def task_status_change(self):
self.update()

def task_changed(self, e):
has_text = bool((self.new_task.value or "").strip())
self.btn.icon = ft.Icons.ADD
self.btn.content = None
self.btn.visible = has_text
self.btn.mouse_cursor = (
ft.MouseCursor.CLICK if has_text else ft.MouseCursor.BASIC
)
self.btn.disabled = not has_text
self.btn.update()

def task_delete(self, task):
self.tasks.controls.remove(task)
self.update()

def get_tasks(self) -> list[Task]:
return [task for task in self.tasks.controls if isinstance(task, Task)]

def clear_completed(self):
self.tasks.controls = [task for task in self.get_tasks() if not task.completed]
self.update()

def before_update(self):
status = self.filter.tabs[self.filter_tabs.selected_index].label
for task in self.tasks.controls:
task.visible = (
tasks = self.get_tasks()
active_count = sum(1 for t in tasks if not t.completed)
self.items_left.value = (
f"{active_count} active item{'s' if active_count != 1 else ''} left"
)
status = self.filter.tabs[self.filter_tabs.selected_index].label # type: ignore
for task in tasks:
task.visible = ( # type: ignore
status == "all"
or (status == "active" and not task.completed)
or (status == "completed" and task.completed)
Expand All @@ -149,7 +213,7 @@ def tabs_changed(self, e):


def main(page: ft.Page):
page.title = "To-Do App"
page.title = "ToDo App"
page.horizontal_alignment = ft.CrossAxisAlignment.CENTER
page.update()

Expand All @@ -160,4 +224,5 @@ def main(page: ft.Page):
page.add(app)


ft.run(main)
if __name__ == "__main__":
ft.run(main)