diff --git a/webui/flet/scripts/flet_canvas.py b/webui/flet/scripts/flet_canvas.py index 12bcd5f..2c9459c 100644 --- a/webui/flet/scripts/flet_canvas.py +++ b/webui/flet/scripts/flet_canvas.py @@ -13,6 +13,7 @@ class Canvas(ft.Container): self.padding = self.page.container_padding self.margin = self.page.container_margin + self.overlay.tools.center = self.page.icon_size self.overlay.tools.zoom_in = self.page.icon_size self.overlay.tools.zoom_out = self.page.icon_size @@ -22,6 +23,12 @@ class Canvas(ft.Container): self.center_canvas(self) self.refresh_canvas() + def lock_canvas(self): + self.overlay.canvas_cover.lock_canvas() + + def unlock_canvas(self): + self.overlay.canvas_cover.unlock_canvas() + def refresh_canvas(self): self.overlay.refresh_canvas_overlay() @@ -44,14 +51,18 @@ class Canvas(ft.Container): def align_canvas(self, e): width, height = self.page.get_viewport_size() - self.image_stack.left = (width * 0.5) - (self.image_stack.width * 0.5) + self.image_stack.offset_x - self.image_stack.top = (height * 0.5) - (self.image_stack.height * 0.5) + self.image_stack.offset_y + self.image_stack.left = (width * 0.5) - (self.image_stack.scaled_width * 0.5) + self.image_stack.offset_x + self.image_stack.top = (height * 0.5) - (self.image_stack.scaled_height * 0.5) + self.image_stack.offset_y self.update() - def pan_canvas(self, e: ft.DragUpdateEvent): self.image_stack.offset_x += e.delta_x self.image_stack.offset_y += e.delta_y + width, height = self.page.get_viewport_size() + self.image_stack.offset_x = max(self.image_stack.offset_x, (width - self.image_stack.scaled_width) * 0.5) + self.image_stack.offset_y = max(self.image_stack.offset_y, (height - self.image_stack.scaled_height) * 0.5) + self.image_stack.offset_x = min(self.image_stack.offset_x, (self.image_stack.scaled_width - width) * 0.5) + self.image_stack.offset_y = min(self.image_stack.offset_y, (self.image_stack.scaled_height - height) * 0.5) self.align_canvas(e) def zoom_in(self, e): @@ -59,6 +70,7 @@ class Canvas(ft.Container): self.image_stack.scale = 4.0 else: self.image_stack.scale += 0.05 + self.image_stack.get_scaled_size() self.align_canvas(e) def zoom_out(self, e): @@ -66,26 +78,16 @@ class Canvas(ft.Container): self.image_stack.scale = 0.1 else: self.image_stack.scale -= 0.05 + self.image_stack.get_scaled_size() self.align_canvas(e) -class CanvasOverlay(ft.Stack): - def refresh_canvas_overlay(self): - self.refresh_canvas_size_display() - - def refresh_canvas_size_display(self): - self.canvas_size.content.value = str(self.page.canvas_size) - self.update() - def pan_canvas(e): canvas.pan_canvas(e) -class ImageStack(ft.GestureDetector): +class ImageStack(ft.Container): def add_canvas_background(self): image = self.page.canvas_background canvas_bg = LayerImage( - mouse_cursor = ft.MouseCursor.MOVE, - drag_interval = 50, - on_pan_update = pan_canvas, left = 0, top = 0, width = self.width, @@ -98,16 +100,11 @@ class ImageStack(ft.GestureDetector): gapless_playback = True, ), ) - canvas_offset_x = 0 - canvas_offset_y = 0 self.canvas_bg = canvas_bg self.content.controls.append(canvas_bg) def add_layer_image(self, image): layer_image = LayerImage( - mouse_cursor = ft.MouseCursor.GRAB, - drag_interval = 50, - on_pan_update = self.drag_layer, left = 0, top = 0, width = image.width, @@ -123,15 +120,17 @@ class ImageStack(ft.GestureDetector): self.content.controls.append(layer_image) canvas.layers.append(layer_image) + def get_scaled_size(self): + self.scaled_width = self.width * self.scale + self.scaled_height = self.height * self.scale + def center_layer(self, layer_image): - layer_image.offset_x = 0 - layer_image.offset_y = 0 layer_image.left = (self.width * 0.5) - (layer_image.width * 0.5) layer_image.top = (self.height * 0.5) - (layer_image.height * 0.5) def align_layer(self, layer_image): - layer_image.left = (self.width * 0.5) - (layer_image.width * 0.5) + layer_image.offset_x - layer_image.top = (self.height * 0.5) - (layer_image.height * 0.5) + layer_image.offset_y + layer_image.left = (self.width * 0.5) - (layer_image.width * 0.5) + layer_image.top = (self.height * 0.5) - (layer_image.height * 0.5) def drag_layer(self, e): pass @@ -145,16 +144,22 @@ class ImageStack(ft.GestureDetector): def paint_on_layer(self, e): pass -class LayerImage(ft.GestureDetector): +class LayerImage(ft.Container): pass +class CanvasOverlay(ft.Stack): + def refresh_canvas_overlay(self): + self.refresh_canvas_size_display() + + def refresh_canvas_size_display(self): + self.canvas_size.content.value = str(self.page.canvas_size) + self.update() + + def pan_canvas(e): canvas.pan_canvas(e) image_stack = ImageStack( -# mouse_cursor = ft.MouseCursor.GRAB, - drag_interval = 50, - on_pan_update = pan_canvas, width = 4096, height = 4096, left = 0, @@ -165,6 +170,43 @@ image_stack = ImageStack( image_stack.offset_x = 0 image_stack.offset_y = 0 +image_stack.scaled_width = image_stack.width +image_stack.scaled_height = image_stack.height + + +class CanvasCover(ft.Container): + def lock_canvas(self): + self.bgcolor = 'black' + self.opacity = 0.5, + self.content = self.loading + + def unlock_canvas(self): + self.bgcolor = None + self.opacity = 1.0, + self.content = self.detector + +gesture_detector = ft.GestureDetector( + mouse_cursor = ft.MouseCursor.MOVE, + drag_interval = 10, + on_pan_update = pan_canvas, +) + +canvas_loading = ft.ProgressRing( + width = 50, + height = 50, + stroke_width = 4, + value = None, +) + +canvas_cover = CanvasCover( + content = gesture_detector, + expand = True, + bgcolor = None, + opacity = 1.0, +) + +canvas_cover.detector = gesture_detector +canvas_cover.loading = canvas_loading canvas_size_display = ft.Container( content = ft.Text( @@ -220,21 +262,27 @@ canvas_tools = ft.Container( border_radius = 10, opacity = 0.5, bgcolor = 'black', + disabled = False, ) +canvas_tools.center = center_canvas_button canvas_tools.zoom_in = zoom_in_button canvas_tools.zoom_out = zoom_out_button canvas_overlay = CanvasOverlay( [ + canvas_cover, canvas_size_display, canvas_tools, ], ) +canvas_overlay.canvas_cover = canvas_cover canvas_overlay.canvas_size = canvas_size_display canvas_overlay.tools = canvas_tools + + canvas = Canvas( content = ft.Stack( [ diff --git a/webui/flet/scripts/flet_file_manager.py b/webui/flet/scripts/flet_file_manager.py index edb7ba5..b8e673f 100644 --- a/webui/flet/scripts/flet_file_manager.py +++ b/webui/flet/scripts/flet_file_manager.py @@ -3,6 +3,11 @@ # Flet imports import flet as ft +# other imports +from math import pi +from typing import Dict +from loguru import logger + # utils imports from scripts import flet_utils @@ -18,27 +23,37 @@ class UploadWindow(ft.AlertDialog): file_picker.upload(file_list) def upload_complete(self, e): - e.page.progress_bars.clear() - e.page.selected_files.controls.clear() + self.progress_bars.clear() + self.selected_files.controls.clear() e.page.close_uploads(e) - e.page.message('File upload(s) complete.') e.page.asset_manager.add_images_as_layers(file_picker.images) file_picker.images.clear() - e.page.refresh_gallery('uploads') - e.page.update() + e.page.message('File upload(s) complete.') def get_image_from_uploads(self, name): return flet_utils.get_image_from_uploads(name) def get_file_display(self, name, progress): - display = ft.Column( + display = ft.Row( controls = [ - ft.Row([ft.Text(name)]), - progress, + progress, + ft.Text(name), ], ) return display +class ImportWindow(ft.AlertDialog): + pass + + +selected_files = ft.Column( + scroll = 'auto', + tight = True, + controls = [], +); + +progress_bars: Dict[str, ft.ProgressBar] = {} + def upload_file(e): uploads.upload_file(e) @@ -47,7 +62,7 @@ def close_upload_window(e): uploads = UploadWindow( title = ft.Text("Confirm file upload(s)"), - content = None, + content = selected_files, actions_alignment = "center", actions = [ ft.ElevatedButton("UPLOAD", on_click = upload_file), @@ -55,8 +70,8 @@ uploads = UploadWindow( ], ) -class ImportWindow(ft.AlertDialog): - pass +uploads.selected_files = selected_files +uploads.progress_bars = progress_bars def import_file(e): e.page.close_imports(e) @@ -66,7 +81,7 @@ def close_import_window(e): imports = ImportWindow( title = ft.Text("Confirm file import(s)"), - content = None, + content = selected_files, actions_alignment = "center", actions = [ ft.ElevatedButton("IMPORT", on_click = import_file), @@ -74,24 +89,31 @@ imports = ImportWindow( ], ) +imports.selected_files = selected_files +imports.progress_bars = progress_bars + def pick_images(e: ft.FilePickerResultEvent): - e.page.progress_bars.clear() - e.page.selected_files.controls.clear() + progress_bars.clear() + selected_files.controls.clear() + file_picker.images.clear() # check to see if files or directory were chosen if e.files is not None and e.path is None: for f in e.files: - prog = ft.ProgressBar( + prog = ft.ProgressRing( + width = 12, + height = 12, + stroke_width = 2, value = 0, color = 'blue', ) - e.page.progress_bars[f.name] = prog - e.page.selected_files.controls.append(uploads.get_file_display(f.name,prog)) + progress_bars[f.name] = prog + selected_files.controls.append(uploads.get_file_display(f.name,prog)) file_picker.pending += 1 - # import if local, upload if remote - if not e.page.web: - e.page.open_imports(e) - else: + # upload if remote, import if local + if e.page.web: e.page.open_uploads(e) + else: + e.page.open_imports(e) def on_image_upload(e: ft.FilePickerUploadEvent): if e.error: @@ -99,14 +121,14 @@ def on_image_upload(e: ft.FilePickerUploadEvent): file_picker.pending -= 1 else: # update progress bars - e.page.progress_bars[e.file_name].value = e.progress - e.page.progress_bars[e.file_name].update() + progress_bars[e.file_name].value = e.progress + progress_bars[e.file_name].update() if e.progress >= 1: file_picker.pending -= 1 file_picker.images.append(uploads.get_image_from_uploads(e.file_name)) - if file_picker.pending <= 0: - file_picker.pending = 0 - uploads.upload_complete(e) + if file_picker.pending <= 0: + file_picker.pending = 0 + uploads.upload_complete(e) file_picker = ft.FilePicker( on_result = pick_images, diff --git a/webui/flet/webui_flet.py b/webui/flet/webui_flet.py index 36307d6..c59d3ae 100644 --- a/webui/flet/webui_flet.py +++ b/webui/flet/webui_flet.py @@ -5,6 +5,8 @@ import flet as ft from math import pi from typing import Optional from loguru import logger +import logging +#logging.basicConfig(level=logging.DEBUG) # utils imports from scripts import flet_utils @@ -66,13 +68,13 @@ def main(page: ft.Page): def change_theme_mode(e): page.theme_mode = "dark" if page.theme_mode == "light" else "light" - if "(Light theme)" in appbar.theme_switcher.tooltip: - appbar.theme_switcher.tooltip = appbar.theme_switcher.tooltip.replace("(Light theme)", '') + if "(Light theme)" in titlebar.theme_switcher.tooltip: + titlebar.theme_switcher.tooltip = titlebar.theme_switcher.tooltip.replace("(Light theme)", '') - if "(Dark theme)" in appbar.theme_switcher.tooltip: - appbar.theme_switcher.tooltip = appbar.theme_switcher.tooltip.replace("(Dark theme)", '') + if "(Dark theme)" in titlebar.theme_switcher.tooltip: + titlebar.theme_switcher.tooltip = titlebar.theme_switcher.tooltip.replace("(Dark theme)", '') - appbar.theme_switcher.tooltip += "(Light theme)" if page.theme_mode == "light" else "(Dark theme)" + titlebar.theme_switcher.tooltip += "(Light theme)" if page.theme_mode == "light" else "(Dark theme)" page.update() page.change_theme_mode = change_theme_mode @@ -199,7 +201,6 @@ def main(page: ft.Page): def open_upload_window(e): page.dialog = uploads - uploads.content = page.selected_files uploads.open = True page.update() @@ -213,19 +214,11 @@ def main(page: ft.Page): def open_import_window(e): page.dialog = imports - imports.content = page.selected_files imports.open = True page.update() page.open_imports = open_import_window - page.selected_files = ft.Column( - scroll = 'auto', - tight = True, - controls = [], - ); - - page.progress_bars: Dict[str, ft.ProgressBar] = {} page.uploads = uploads page.imports = imports page.file_picker = file_picker