From c2060963cc53d02d5af197cf589b9b9d5bdc4cd7 Mon Sep 17 00:00:00 2001 From: itdominator <1itdominator@gmail.com> Date: Sun, 11 Jan 2026 17:48:35 -0600 Subject: [PATCH] Full 'code' widget refactor to utilize controllers and cross controller event signaling --- src/core/containers/code/code_container.py | 32 +++- src/core/containers/code/editors_container.py | 60 +++++-- .../code/paned_editors_container.py | 69 -------- src/core/widgets/code/code_base.py | 50 ++++++ src/core/widgets/code/command_system.py | 63 +++++++ src/core/widgets/code/commands/buffer_redo.py | 2 +- src/core/widgets/code/commands/buffer_undo.py | 2 +- src/core/widgets/code/commands/close_file.py | 11 +- .../code/commands/cut_to_temp_buffer.py | 2 +- .../code/commands/dnd_load_file_to_buffer.py | 8 +- .../widgets/code/commands/dnd_load_files.py | 2 +- .../widgets/code/commands/duplicate_line.py | 2 +- .../code/commands/focus_left_sibling.py | 2 +- .../code/commands/focus_right_sibling.py | 2 +- .../widgets/code/commands/get_current_file.py | 7 +- .../code/{ => commands}/get_filetype.py | 6 +- src/core/widgets/code/commands/get_text.py | 2 +- src/core/widgets/code/commands/go_to.py | 4 +- src/core/widgets/code/commands/has_focus.py | 2 +- src/core/widgets/code/commands/line_down.py | 2 +- src/core/widgets/code/commands/line_up.py | 2 +- src/core/widgets/code/commands/load_file.py | 4 +- .../widgets/code/commands/load_start_files.py | 6 +- .../code/commands/move_to_left_sibling.py | 7 +- .../code/commands/move_to_right_sibling.py | 7 +- src/core/widgets/code/commands/new_file.py | 8 +- src/core/widgets/code/commands/open_files.py | 20 +-- .../code/commands/paste_temp_buffer.py | 2 +- src/core/widgets/code/commands/save_file.py | 6 +- .../widgets/code/commands/save_file_as.py | 10 +- src/core/widgets/code/commands/set_buffer.py | 9 +- .../code/commands/set_buffer_language.py | 4 +- .../widgets/code/commands/set_buffer_style.py | 4 +- .../widgets/code/commands/set_focus_border.py | 2 +- .../widgets/code/commands/set_miniview.py | 9 +- .../widgets/code/commands/show_completion.py | 4 +- .../widgets/code/commands/update_info_bar.py | 6 +- src/core/widgets/code/commands/zoom_in.py | 2 +- src/core/widgets/code/commands/zoom_out.py | 2 +- src/core/widgets/code/completion_manager.py | 66 -------- src/core/widgets/code/controllers/__init__.py | 3 + .../code/controllers/commands_controller.py | 34 ++++ .../code/controllers/completion_controller.py | 111 +++++++++++++ .../code/controllers/controller_base.py | 38 +++++ .../code/controllers/controller_context.py | 24 +++ .../code/controllers/controller_manager.py | 48 ++++++ .../code/controllers/emit_dispatcher.py | 19 +++ .../code/controllers/files_controller.py | 156 ++++++++++++++++++ .../controllers/source_views_controller.py | 131 +++++++++++++++ .../code/controllers/tabs_controller.py | 90 ++++++++++ ...eral_info_widget.py => info_bar_widget.py} | 9 +- ...miniview_widget.py => mini_view_widget.py} | 3 +- .../code/mixins/source_view_events_mixin.py | 63 ------- src/core/widgets/code/source_file.py | 57 +++---- src/core/widgets/code/source_files_manager.py | 106 ------------ .../widgets/code/{view.py => source_view.py} | 54 +----- src/core/widgets/code/tabs_widget.py | 68 +++----- src/core/widgets/vte_widget.py | 19 ++- src/libs/dto/__init__.py | 2 +- src/libs/dto/code/__init__.py | 27 +++ src/libs/dto/code/add_new_file_event.py | 13 ++ src/libs/dto/code/added_new_file_event.py | 13 ++ src/libs/dto/{ => code}/code_event.py | 7 +- src/libs/dto/code/cursor_moved_event.py | 14 ++ src/libs/dto/code/file_path_set_event.py | 15 ++ src/libs/dto/code/focused_view_event.py | 14 ++ src/libs/dto/code/get_command_system_event.py | 13 ++ src/libs/dto/code/get_file_event.py | 13 ++ src/libs/dto/code/get_swap_file_event.py | 13 ++ src/libs/dto/code/modified_changed_event.py | 15 ++ src/libs/dto/code/pop_file_event.py | 13 ++ src/libs/dto/code/popped_file_event.py | 15 ++ src/libs/dto/code/remove_file_event.py | 13 ++ src/libs/dto/code/removed_file_event.py | 15 ++ src/libs/dto/code/request_completion_event.py | 13 ++ src/libs/dto/code/set_active_file_event.py | 13 ++ src/libs/dto/code/swap_file_event.py | 13 ++ src/libs/dto/code/swapped_file_event.py | 13 ++ src/libs/dto/code/text_changed_event.py | 18 ++ src/libs/dto/code/text_inserted_event.py | 15 ++ 80 files changed, 1282 insertions(+), 561 deletions(-) delete mode 100644 src/core/containers/code/paned_editors_container.py create mode 100644 src/core/widgets/code/code_base.py rename src/core/widgets/code/{ => commands}/get_filetype.py (63%) delete mode 100644 src/core/widgets/code/completion_manager.py create mode 100644 src/core/widgets/code/controllers/__init__.py create mode 100644 src/core/widgets/code/controllers/commands_controller.py create mode 100644 src/core/widgets/code/controllers/completion_controller.py create mode 100644 src/core/widgets/code/controllers/controller_base.py create mode 100644 src/core/widgets/code/controllers/controller_context.py create mode 100644 src/core/widgets/code/controllers/controller_manager.py create mode 100644 src/core/widgets/code/controllers/emit_dispatcher.py create mode 100644 src/core/widgets/code/controllers/files_controller.py create mode 100644 src/core/widgets/code/controllers/source_views_controller.py create mode 100644 src/core/widgets/code/controllers/tabs_controller.py rename src/core/widgets/code/{general_info_widget.py => info_bar_widget.py} (91%) rename src/core/widgets/code/{miniview_widget.py => mini_view_widget.py} (95%) delete mode 100644 src/core/widgets/code/mixins/source_view_events_mixin.py delete mode 100644 src/core/widgets/code/source_files_manager.py rename src/core/widgets/code/{view.py => source_view.py} (57%) create mode 100644 src/libs/dto/code/__init__.py create mode 100644 src/libs/dto/code/add_new_file_event.py create mode 100644 src/libs/dto/code/added_new_file_event.py rename src/libs/dto/{ => code}/code_event.py (62%) create mode 100644 src/libs/dto/code/cursor_moved_event.py create mode 100644 src/libs/dto/code/file_path_set_event.py create mode 100644 src/libs/dto/code/focused_view_event.py create mode 100644 src/libs/dto/code/get_command_system_event.py create mode 100644 src/libs/dto/code/get_file_event.py create mode 100644 src/libs/dto/code/get_swap_file_event.py create mode 100644 src/libs/dto/code/modified_changed_event.py create mode 100644 src/libs/dto/code/pop_file_event.py create mode 100644 src/libs/dto/code/popped_file_event.py create mode 100644 src/libs/dto/code/remove_file_event.py create mode 100644 src/libs/dto/code/removed_file_event.py create mode 100644 src/libs/dto/code/request_completion_event.py create mode 100644 src/libs/dto/code/set_active_file_event.py create mode 100644 src/libs/dto/code/swap_file_event.py create mode 100644 src/libs/dto/code/swapped_file_event.py create mode 100644 src/libs/dto/code/text_changed_event.py create mode 100644 src/libs/dto/code/text_inserted_event.py diff --git a/src/core/containers/code/code_container.py b/src/core/containers/code/code_container.py index 16771c8..f0ae232 100644 --- a/src/core/containers/code/code_container.py +++ b/src/core/containers/code/code_container.py @@ -6,7 +6,10 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from ...widgets.code.tabs_widget import TabsWidget +from ...widgets.code.code_base import CodeBase + +from ...widgets.separator_widget import Separator +from ...widgets.code.mini_view_widget import MiniViewWidget from .editors_container import EditorsContainer @@ -34,5 +37,28 @@ class CodeContainer(Gtk.Box): ... def _load_widgets(self): - self.add( TabsWidget() ) - self.add( EditorsContainer() ) + code_base = CodeBase() + + self.add( self._create_tabs_widgets(code_base) ) + self.add( self._create_editor_widget(code_base) ) + + def _create_tabs_widgets(self, code_base: CodeBase): + scrolled_window = Gtk.ScrolledWindow() + viewport = Gtk.Viewport() + + scrolled_window.set_overlay_scrolling(False) + + viewport.add( code_base.get_tabs_widget() ) + scrolled_window.add( viewport ) + + return scrolled_window + + def _create_editor_widget(self, code_base: CodeBase): + editors_container = Gtk.Box() + + editors_container.add( Separator("separator_left") ) + editors_container.add( EditorsContainer(code_base) ) + editors_container.add( Separator("separator_right") ) + editors_container.add( code_base.get_mini_view_widget() ) + + return editors_container diff --git a/src/core/containers/code/editors_container.py b/src/core/containers/code/editors_container.py index 55fe8f3..6b10c8b 100644 --- a/src/core/containers/code/editors_container.py +++ b/src/core/containers/code/editors_container.py @@ -4,18 +4,18 @@ import gi gi.require_version('Gtk', '3.0') from gi.repository import Gtk +from gi.repository import GLib # Application imports -from ...widgets.separator_widget import Separator -from ...widgets.code.miniview_widget import MiniViewWidget -from .paned_editors_container import PanedEditorsContainer -class EditorsContainer(Gtk.Box): - def __init__(self): +class EditorsContainer(Gtk.Paned): + def __init__(self, code_base: any): super(EditorsContainer, self).__init__() + self.code_base = code_base + self._setup_styling() self._setup_signals() self._subscribe_to_events() @@ -23,16 +23,54 @@ class EditorsContainer(Gtk.Box): def _setup_styling(self): - ... + self.ctx = self.get_style_context() + self.ctx.add_class("paned-editors-container") + + self.set_hexpand(True) + self.set_vexpand(True) + self.set_wide_handle(True) def _setup_signals(self): - ... + self.map_id = self.connect("map", self._init_map) + # self.map_id = self.connect("show", self._init_map) def _subscribe_to_events(self): ... def _load_widgets(self): - self.add( Separator("separator_left") ) - self.add( PanedEditorsContainer() ) - self.add( Separator("separator_right") ) - self.add( MiniViewWidget() ) \ No newline at end of file + self.scrolled_win1, \ + self.scrolled_win2 = self._create_views() + + self.add1(self.scrolled_win1) + self.add2(self.scrolled_win2) + + def _create_views(self): + scrolled_win1 = Gtk.ScrolledWindow() + scrolled_win2 = Gtk.ScrolledWindow() + + source_view1 = self.code_base.create_source_view() + source_view2 = self.code_base.create_source_view() + + source_view1.sibling_right = source_view2 + source_view2.sibling_left = source_view1 + + scrolled_win1.add( source_view1 ) + scrolled_win2.add( source_view2 ) + + return scrolled_win1, scrolled_win2 + + def _init_map(self, view): + def _first_show_init(): + self.disconnect(self.map_id) + del self.map_id + + self.set_position( + (self.get_allocated_width() / 2) + 250 + ) + + self.code_base.first_map_load() + + del self.code_base + return False + + GLib.timeout_add(225, _first_show_init) diff --git a/src/core/containers/code/paned_editors_container.py b/src/core/containers/code/paned_editors_container.py deleted file mode 100644 index 5beabad..0000000 --- a/src/core/containers/code/paned_editors_container.py +++ /dev/null @@ -1,69 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk -from gi.repository import GLib - -# Application imports -from ...widgets.code.view import SourceView - - - -class PanedEditorsContainer(Gtk.Paned): - def __init__(self): - super(PanedEditorsContainer, self).__init__() - - self._setup_styling() - self._setup_signals() - self._subscribe_to_events() - self._load_widgets() - - - def _setup_styling(self): - self.ctx = self.get_style_context() - self.ctx.add_class("paned-editors-container") - - self.set_hexpand(True) - self.set_vexpand(True) - # self.set_homogeneous(True) - self.set_wide_handle(True) - - def _setup_signals(self): - self.map_id = self.connect("map", self._init_map) - - def _subscribe_to_events(self): - ... - - def _load_widgets(self): - scrolled_win1 = Gtk.ScrolledWindow() - scrolled_win2 = Gtk.ScrolledWindow() - source_view1 = SourceView() - source_view2 = SourceView() - - source_view1.sibling_right = source_view2 - source_view2.sibling_left = source_view1 - - scrolled_win1.add( source_view1 ) - scrolled_win2.add( source_view2 ) - - self.add1(scrolled_win1) - self.add2(scrolled_win2) - - def _init_map(self, view): - def _first_show_init(): - self.disconnect(self.map_id) - del self.map_id - - self._handle_first_show() - - return False - - GLib.timeout_add(200, _first_show_init) - - def _handle_first_show(self): - self.set_position( - self.get_allocated_width() / 2 - ) - diff --git a/src/core/widgets/code/code_base.py b/src/core/widgets/code/code_base.py new file mode 100644 index 0000000..f784437 --- /dev/null +++ b/src/core/widgets/code/code_base.py @@ -0,0 +1,50 @@ +# Python imports + +# Lib imports + +# Application imports +from .controllers.controller_manager import ControllerManager +from .controllers.files_controller import FilesController +from .controllers.tabs_controller import TabsController +from .controllers.commands_controller import CommandsController +from .controllers.completion_controller import CompletionController +from .controllers.source_views_controller import SourceViewsController + +from .mini_view_widget import MiniViewWidget + + + +class CodeBase: + def __init__(self): + super(CodeBase, self).__init__() + + self.controller_manager: ControllerManager = ControllerManager() + self.miniview_widget: MiniViewWidget = MiniViewWidget() + + self._load_controllers() + + + def _load_controllers(self): + files_controller = FilesController() + tabs_controller = TabsController() + commands_controller = CommandsController() + completion_controller = CompletionController() + source_views_controller = SourceViewsController() + + self.controller_manager.register_controller("files", files_controller) + self.controller_manager.register_controller("tabs", tabs_controller) + self.controller_manager.register_controller("commands", commands_controller) + self.controller_manager.register_controller("completion", completion_controller) + self.controller_manager.register_controller("source_views", source_views_controller) + + def get_tabs_widget(self): + return self.controller_manager["tabs"].get_tabs_widget() + + def get_mini_view_widget(self): + return self.miniview_widget + + def create_source_view(self): + return self.controller_manager["source_views"].create_source_view() + + def first_map_load(self): + self.controller_manager["source_views"].first_map_load() diff --git a/src/core/widgets/code/command_system.py b/src/core/widgets/code/command_system.py index 3f234c9..4421d9f 100644 --- a/src/core/widgets/code/command_system.py +++ b/src/core/widgets/code/command_system.py @@ -3,8 +3,19 @@ # Lib imports # Application imports +from libs.dto.code import ( + CodeEvent, + RequestCompletionEvent, + GetFileEvent, + GetSwapFileEvent, + AddNewFileEvent, + RemoveFileEvent, +) + from . import commands +from .source_view import SourceView + class CommandSystem: @@ -32,3 +43,55 @@ class CommandSystem: method = getattr(commands, command) return method.execute(*args) + + + def emit(self, event: CodeEvent): + """ Monky patch 'emit' from command controller... """ + ... + + def emit_to(self, controller: str, event: CodeEvent): + """ Monky patch 'emit' from command controller... """ + ... + + + def get_file(self, view: SourceView): + event = GetFileEvent() + event.view = view + event.buffer = view.get_buffer() + + self.emit_to("files", event) + + return event.response + + def get_swap_file(self, view: SourceView): + event = GetSwapFileEvent() + event.view = self + event.buffer = view.get_buffer() + + self.emit_to("files", event) + + return event.response + + def new_file(self, view: SourceView): + event = AddNewFileEvent() + event.view = view + + self.emit_to("files", event) + + return event.response + + def remove_file(self, view: SourceView): + event = RemoveFileEvent() + event.view = view + event.buffer = view.get_buffer() + + self.emit_to("files", event) + + return event.response + + def request_completion(self, view: SourceView): + event = RequestCompletionEvent() + event.view = view + event.buffer = view.get_buffer() + + self.emit_to("completion", event) diff --git a/src/core/widgets/code/commands/buffer_redo.py b/src/core/widgets/code/commands/buffer_redo.py index b0c738f..9d4e3e5 100644 --- a/src/core/widgets/code/commands/buffer_redo.py +++ b/src/core/widgets/code/commands/buffer_redo.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Buffer Redo Command") + logger.debug("Command: Buffer Redo") buffer = view.get_buffer() undo_manager = buffer.get_undo_manager() diff --git a/src/core/widgets/code/commands/buffer_undo.py b/src/core/widgets/code/commands/buffer_undo.py index 87688e2..36d53b6 100644 --- a/src/core/widgets/code/commands/buffer_undo.py +++ b/src/core/widgets/code/commands/buffer_undo.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Buffer Undo Command") + logger.debug("Command: Buffer Undo") buffer = view.get_buffer() undo_manager = buffer.get_undo_manager() diff --git a/src/core/widgets/code/commands/close_file.py b/src/core/widgets/code/commands/close_file.py index 5af1140..c5876c3 100644 --- a/src/core/widgets/code/commands/close_file.py +++ b/src/core/widgets/code/commands/close_file.py @@ -14,13 +14,6 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Close File Command") - buffer = view.get_buffer() - - next_file = view.files_manager.remove_file(buffer) - if not next_file: - view.command.exec("new_file") - else: - view.set_buffer(next_file.buffer) - + logger.debug("Command: Close File") + view.command.remove_file() view.command.exec("update_info_bar") diff --git a/src/core/widgets/code/commands/cut_to_temp_buffer.py b/src/core/widgets/code/commands/cut_to_temp_buffer.py index 572e190..7215e20 100644 --- a/src/core/widgets/code/commands/cut_to_temp_buffer.py +++ b/src/core/widgets/code/commands/cut_to_temp_buffer.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Cut to Temp Buffer Command") + logger.debug("Command: Cut to Temp Buffer") view.clear_temp_cut_buffer_delayed() diff --git a/src/core/widgets/code/commands/dnd_load_file_to_buffer.py b/src/core/widgets/code/commands/dnd_load_file_to_buffer.py index cc7e537..da10e34 100644 --- a/src/core/widgets/code/commands/dnd_load_file_to_buffer.py +++ b/src/core/widgets/code/commands/dnd_load_file_to_buffer.py @@ -16,13 +16,13 @@ def execute( view: GtkSource.View, uri: str ): - logger.debug("DnD Load File To Buffer Command") + logger.debug("Command: DnD Load File To Buffer") - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + file = view.command.get_file(view) + buffer = file.buffer if not file.ftype == "buffer": - file = view.command.exec("new_file") + file = view.command.new_file(view) gfile = Gio.File.new_for_uri(uri) view.command.exec_with_args( diff --git a/src/core/widgets/code/commands/dnd_load_files.py b/src/core/widgets/code/commands/dnd_load_files.py index 0b063a7..c13042c 100644 --- a/src/core/widgets/code/commands/dnd_load_files.py +++ b/src/core/widgets/code/commands/dnd_load_files.py @@ -17,7 +17,7 @@ def execute( view: GtkSource.View, uris: list = [] ): - logger.debug("DnD Load Files Command") + logger.debug("Command: DnD Load Files") for uri in uris: try: gfile = Gio.File.new_for_uri(uri) diff --git a/src/core/widgets/code/commands/duplicate_line.py b/src/core/widgets/code/commands/duplicate_line.py index 10e89d9..bc4f65d 100644 --- a/src/core/widgets/code/commands/duplicate_line.py +++ b/src/core/widgets/code/commands/duplicate_line.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Duplicate Line Command") + logger.debug("Command: Duplicate Line") buffer = view.get_buffer() diff --git a/src/core/widgets/code/commands/focus_left_sibling.py b/src/core/widgets/code/commands/focus_left_sibling.py index 42790c4..d3eaed4 100644 --- a/src/core/widgets/code/commands/focus_left_sibling.py +++ b/src/core/widgets/code/commands/focus_left_sibling.py @@ -14,6 +14,6 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Focus Left Sibling Command") + logger.debug("Command: Focus Left Sibling") if not view.sibling_left: return view.sibling_left.grab_focus() diff --git a/src/core/widgets/code/commands/focus_right_sibling.py b/src/core/widgets/code/commands/focus_right_sibling.py index fbfbb48..8ed5e08 100644 --- a/src/core/widgets/code/commands/focus_right_sibling.py +++ b/src/core/widgets/code/commands/focus_right_sibling.py @@ -14,6 +14,6 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Focus Right Sibling Command") + logger.debug("Command: Focus Right Sibling") if not view.sibling_right: return view.sibling_right.grab_focus() diff --git a/src/core/widgets/code/commands/get_current_file.py b/src/core/widgets/code/commands/get_current_file.py index 6d28e2b..51f5a44 100644 --- a/src/core/widgets/code/commands/get_current_file.py +++ b/src/core/widgets/code/commands/get_current_file.py @@ -14,7 +14,8 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Get Current File Command") + logger.debug("Command: Get Current File") - buffer = view.get_buffer() - return view.files_manager.get_file(buffer) + file = view.command.get_file(view) + + return file diff --git a/src/core/widgets/code/get_filetype.py b/src/core/widgets/code/commands/get_filetype.py similarity index 63% rename from src/core/widgets/code/get_filetype.py rename to src/core/widgets/code/commands/get_filetype.py index f19fed0..ae98fcd 100644 --- a/src/core/widgets/code/get_filetype.py +++ b/src/core/widgets/code/commands/get_filetype.py @@ -14,8 +14,6 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Get File Type Command") - - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + logger.debug("Command: Get File Type") + file = view.command.get_file(view) return file.ftype diff --git a/src/core/widgets/code/commands/get_text.py b/src/core/widgets/code/commands/get_text.py index 4a35bd8..20876ab 100644 --- a/src/core/widgets/code/commands/get_text.py +++ b/src/core/widgets/code/commands/get_text.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Get Text Command") + logger.debug("Command: Get Text") buffer = view.get_buffer() start_itr, end_itr = buffer.get_bounds() diff --git a/src/core/widgets/code/commands/go_to.py b/src/core/widgets/code/commands/go_to.py index 81f9912..55d6efe 100644 --- a/src/core/widgets/code/commands/go_to.py +++ b/src/core/widgets/code/commands/go_to.py @@ -14,9 +14,9 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Go-To Command") + logger.debug("Command: Go-To") - file = view.command.exec("get_current_file") + file = view.command.get_file(view) gfile = file.get_location() uri = gfile.get_uri() diff --git a/src/core/widgets/code/commands/has_focus.py b/src/core/widgets/code/commands/has_focus.py index 53fb64e..3f87456 100644 --- a/src/core/widgets/code/commands/has_focus.py +++ b/src/core/widgets/code/commands/has_focus.py @@ -14,6 +14,6 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Has Focus Command") + logger.debug("Command: Has Focus") ctx = view.get_parent().get_style_context() return ctx.has_class("source-view-focused") diff --git a/src/core/widgets/code/commands/line_down.py b/src/core/widgets/code/commands/line_down.py index 01d5c37..5aa730c 100644 --- a/src/core/widgets/code/commands/line_down.py +++ b/src/core/widgets/code/commands/line_down.py @@ -14,5 +14,5 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Line Up Command") + logger.debug("Command: Line Down") view.emit("move-lines", True) diff --git a/src/core/widgets/code/commands/line_up.py b/src/core/widgets/code/commands/line_up.py index 0472f01..e10c15d 100644 --- a/src/core/widgets/code/commands/line_up.py +++ b/src/core/widgets/code/commands/line_up.py @@ -14,5 +14,5 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Line Up Command") + logger.debug("Command: Line Up") view.emit("move-lines", False) diff --git a/src/core/widgets/code/commands/load_file.py b/src/core/widgets/code/commands/load_file.py index 58677ea..2532061 100644 --- a/src/core/widgets/code/commands/load_file.py +++ b/src/core/widgets/code/commands/load_file.py @@ -18,9 +18,9 @@ def execute( gfile: Gio.File, file: SourceFile = None, ): - logger.debug("Load File Command") + logger.debug("Command: Load File") if not file: - file = view.files_manager.new() + file = view.command.new_file(view) file.load_path(gfile) diff --git a/src/core/widgets/code/commands/load_start_files.py b/src/core/widgets/code/commands/load_start_files.py index 6802699..3af2186 100644 --- a/src/core/widgets/code/commands/load_start_files.py +++ b/src/core/widgets/code/commands/load_start_files.py @@ -9,14 +9,13 @@ from gi.repository import GtkSource from gi.repository import Gio # Application imports -from ..source_file import SourceFile def execute( view: GtkSource.View, ): - logger.debug("Load Start File(s) Command") + logger.debug("Command: Load Start File(s)") starting_files = settings_manager.get_starting_files() @@ -25,8 +24,7 @@ def execute( file = starting_files.pop() file = file.replace("FILE|", "") gfile = Gio.File.new_for_path(file) - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + file = view.command.get_file(view) view.command.exec_with_args( "load_file", diff --git a/src/core/widgets/code/commands/move_to_left_sibling.py b/src/core/widgets/code/commands/move_to_left_sibling.py index 5edf5bc..ea6b83b 100644 --- a/src/core/widgets/code/commands/move_to_left_sibling.py +++ b/src/core/widgets/code/commands/move_to_left_sibling.py @@ -14,19 +14,16 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Move To Left Sibling Command") + logger.debug("Command: Move To Left Sibling") if not view.sibling_left: return buffer = view.get_buffer() - popped_file, next_file = view.files_manager.swap_file(buffer) + popped_file, next_file = view.command.get_swap_file(view) - popped_file.remove_observer(view) - popped_file.add_observer(view.sibling_left) view.sibling_left.set_buffer(buffer) view.sibling_left.grab_focus() if next_file: - next_file.add_observer(view) view.set_buffer(next_file.buffer) else: view.command.exec("new_file") diff --git a/src/core/widgets/code/commands/move_to_right_sibling.py b/src/core/widgets/code/commands/move_to_right_sibling.py index 806f7c5..71f150e 100644 --- a/src/core/widgets/code/commands/move_to_right_sibling.py +++ b/src/core/widgets/code/commands/move_to_right_sibling.py @@ -14,19 +14,16 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Move To Right Sibling Command") + logger.debug("Command: Move To Right Sibling") if not view.sibling_right: return buffer = view.get_buffer() - popped_file, next_file = view.files_manager.swap_file(buffer) + popped_file, next_file = view.command.get_swap_file(view) - popped_file.remove_observer(view) - popped_file.add_observer(view.sibling_right) view.sibling_right.set_buffer(buffer) view.sibling_right.grab_focus() if next_file: - next_file.add_observer(view) view.set_buffer(next_file.buffer) else: view.command.exec("new_file") diff --git a/src/core/widgets/code/commands/new_file.py b/src/core/widgets/code/commands/new_file.py index 85eb07a..c7e85e5 100644 --- a/src/core/widgets/code/commands/new_file.py +++ b/src/core/widgets/code/commands/new_file.py @@ -15,16 +15,16 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("New File Command") - file = view.files_manager.new() + logger.debug("Command: New File") + + file = view.command.new_file(view) language = view.language_manager \ - .guess_language("file.txt", None) + .guess_language("file.txt", None) file.buffer.set_language(language) file.buffer.set_style_scheme(view.syntax_theme) view.set_buffer(file.buffer) - file.add_observer(view) has_focus = view.command.exec("has_focus") if not has_focus: return file diff --git a/src/core/widgets/code/commands/open_files.py b/src/core/widgets/code/commands/open_files.py index 82dd055..e890116 100644 --- a/src/core/widgets/code/commands/open_files.py +++ b/src/core/widgets/code/commands/open_files.py @@ -14,20 +14,16 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Open File(s) Command") + logger.debug("Command: Open File(s)") gfiles = event_system.emit_and_await("open-files") if not gfiles: return - size = len(gfiles) - for i, gfile in enumerate(gfiles): - file = view.files_manager.new() + file = view.command.get_file(view) + if file.ftype == "buffer": + gfile = gfiles.pop() view.command.exec_with_args("load_file", (view, gfile, file)) + view.set_buffer(file.buffer) + view.command.exec("update_info_bar") - if i == (size - 1): - buffer = view.get_buffer() - _file = view.files_manager.get_file(buffer) - _file.remove_observer(view) - - view.set_buffer(file.buffer) - file.add_observer(view) - view.command.exec("update_info_bar") + for i, gfile in enumerate(gfiles): + view.command.exec_with_args("load_file", (view, gfile)) diff --git a/src/core/widgets/code/commands/paste_temp_buffer.py b/src/core/widgets/code/commands/paste_temp_buffer.py index 30d28ed..12640c6 100644 --- a/src/core/widgets/code/commands/paste_temp_buffer.py +++ b/src/core/widgets/code/commands/paste_temp_buffer.py @@ -15,7 +15,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Paste Temp Buffer Command") + logger.debug("Command: Paste Temp Buffer") view.clear_temp_cut_buffer_delayed() diff --git a/src/core/widgets/code/commands/save_file.py b/src/core/widgets/code/commands/save_file.py index f63dd5a..22f4795 100644 --- a/src/core/widgets/code/commands/save_file.py +++ b/src/core/widgets/code/commands/save_file.py @@ -14,9 +14,9 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Save File Command") - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + logger.debug("Command: Save File") + file = view.command.get_file(view) + buffer = file.buffer if file.ftype == "buffer": file.save_as() diff --git a/src/core/widgets/code/commands/save_file_as.py b/src/core/widgets/code/commands/save_file_as.py index 6e1568d..88bbe1e 100644 --- a/src/core/widgets/code/commands/save_file_as.py +++ b/src/core/widgets/code/commands/save_file_as.py @@ -14,9 +14,9 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.info("Save File As Command") - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + logger.info("Command: Save File As") + file = view.command.get_file(view) + buffer = file.buffer file.save_as() @@ -24,5 +24,5 @@ def execute( .guess_language(file.fname, None) file.ftype = language file.buffer.set_language(language) - file.add_observer(view) - view.exec_command("update_info_bar") + + view.command.exec("update_info_bar") diff --git a/src/core/widgets/code/commands/set_buffer.py b/src/core/widgets/code/commands/set_buffer.py index a03e120..6e75b25 100644 --- a/src/core/widgets/code/commands/set_buffer.py +++ b/src/core/widgets/code/commands/set_buffer.py @@ -17,18 +17,13 @@ def execute( view: GtkSource.View, file: SourceFile ): - logger.debug("Set Buffer Command") - - buffer = view.get_buffer() - _file = view.files_manager.get_file(buffer) - _file.remove_observer(view) + logger.debug("Command: Set Buffer") if not file: - view.command.exec("new_file") + view.command.new_file(view) return view.set_buffer(file.buffer) - file.add_observer(view) has_focus = view.command.exec("has_focus") if has_focus: diff --git a/src/core/widgets/code/commands/set_buffer_language.py b/src/core/widgets/code/commands/set_buffer_language.py index 299b23c..6268110 100644 --- a/src/core/widgets/code/commands/set_buffer_language.py +++ b/src/core/widgets/code/commands/set_buffer_language.py @@ -15,9 +15,9 @@ def execute( view: GtkSource.View, language: str ): - logger.debug("Set Buffer Language Command") + logger.debug("Command: Set Buffer Language") - buffer = editor.get_buffer() + buffer = view.get_buffer() buffer.set_language( view.language_manager.get_language(language) ) diff --git a/src/core/widgets/code/commands/set_buffer_style.py b/src/core/widgets/code/commands/set_buffer_style.py index e12a030..76a1d7a 100644 --- a/src/core/widgets/code/commands/set_buffer_style.py +++ b/src/core/widgets/code/commands/set_buffer_style.py @@ -15,9 +15,9 @@ def execute( view: GtkSource.View, style: str ): - logger.debug("Set Buffer Style Command") + logger.debug("Command: Set Buffer Style") - buffer = editor.get_buffer() + buffer = view.get_buffer() buffer.set_style_scheme( view.style_scheme_manager.get_scheme(style) ) diff --git a/src/core/widgets/code/commands/set_focus_border.py b/src/core/widgets/code/commands/set_focus_border.py index 4f6bf39..2f2cdaf 100644 --- a/src/core/widgets/code/commands/set_focus_border.py +++ b/src/core/widgets/code/commands/set_focus_border.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Set Focus Border Command") + logger.debug("Command: Set Focus Border") ctx = view.get_parent().get_style_context() ctx.add_class("source-view-focused") diff --git a/src/core/widgets/code/commands/set_miniview.py b/src/core/widgets/code/commands/set_miniview.py index 22b7161..553265a 100644 --- a/src/core/widgets/code/commands/set_miniview.py +++ b/src/core/widgets/code/commands/set_miniview.py @@ -9,7 +9,7 @@ from gi.repository import GtkSource from gi.repository import Gio # Application imports -from libs.dto.code_event import CodeEvent +from libs.dto.code import FocusedViewEvent from ..source_file import SourceFile @@ -18,10 +18,5 @@ from ..source_file import SourceFile def execute( view: GtkSource.View, ): - logger.debug("Set MiniView Command") + logger.debug("Command: Set MiniView") event_system.emit("set-mini-view", (view,)) - - event = CodeEvent() - event.etype = "focused_view_change" - event.view = view - view.notify_observers(event) diff --git a/src/core/widgets/code/commands/show_completion.py b/src/core/widgets/code/commands/show_completion.py index ba12082..dedb491 100644 --- a/src/core/widgets/code/commands/show_completion.py +++ b/src/core/widgets/code/commands/show_completion.py @@ -14,5 +14,5 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Show Completion Command") - view.completion.request_completion() + logger.debug("Command: Show Completion") + view.command.request_completion(view) diff --git a/src/core/widgets/code/commands/update_info_bar.py b/src/core/widgets/code/commands/update_info_bar.py index 73418a1..c499945 100644 --- a/src/core/widgets/code/commands/update_info_bar.py +++ b/src/core/widgets/code/commands/update_info_bar.py @@ -16,9 +16,9 @@ from ..source_file import SourceFile def execute( view: GtkSource.View, ): - logger.debug("Update Info Bar Command") - buffer = view.get_buffer() - file = view.files_manager.get_file(buffer) + logger.debug("Command: Update Info Bar") + file = view.command.get_file(view) + buffer = file.buffer if not file: return diff --git a/src/core/widgets/code/commands/zoom_in.py b/src/core/widgets/code/commands/zoom_in.py index 2590bd5..1151656 100644 --- a/src/core/widgets/code/commands/zoom_in.py +++ b/src/core/widgets/code/commands/zoom_in.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Zoom In Command") + logger.debug("Command: Zoom In") ctx = view.get_style_context() if view.zoom_level < 99: diff --git a/src/core/widgets/code/commands/zoom_out.py b/src/core/widgets/code/commands/zoom_out.py index 611905d..f03485f 100644 --- a/src/core/widgets/code/commands/zoom_out.py +++ b/src/core/widgets/code/commands/zoom_out.py @@ -14,7 +14,7 @@ from gi.repository import GtkSource def execute( view: GtkSource.View = None ): - logger.debug("Zoom Out Command") + logger.debug("Command: Zoom Out") ctx = view.get_style_context() if view.zoom_level > 1: diff --git a/src/core/widgets/code/completion_manager.py b/src/core/widgets/code/completion_manager.py deleted file mode 100644 index 7600fb8..0000000 --- a/src/core/widgets/code/completion_manager.py +++ /dev/null @@ -1,66 +0,0 @@ -# Python imports - -# Lib imports -import gi -from gi.repository import GLib - -# Application imports -from .completion_providers.example_completion_provider import ExampleCompletionProvider -from .completion_providers.lsp_completion_provider import LSPCompletionProvider - - - -class CompletionManager(): - def __init__(self): - super(CompletionManager, self).__init__() - - self._lsp_provider = LSPCompletionProvider() - self._timeout_id = None - - - def set_completer(self, completer): - self._completor = completer - - def request_completion(self): - if self._timeout_id: - GLib.source_remove(self._timeout_id) - - self._timeout_id = GLib.timeout_add( - 800, - self._process_request_completion - ) - - def _process_request_completion(self): - self._start_completion() - - self._timeout_id = None - return False - - def _do_completion(self): - if self._completor.get_providers(): - self._mach_completion() - else: - self._start_completion() - - def _mach_completion(self): - """ - Note: Use IF providers were added to completion... - """ - self._completion.match( - self._completion.create_context() - ) - - def _start_completion(self): - """ - Note: Use IF NO providers have been added to completion... - print("here") - """ - self._completor.start( - [ - ExampleCompletionProvider(), - self._lsp_provider - ], - self._completor.create_context() - ) - - \ No newline at end of file diff --git a/src/core/widgets/code/controllers/__init__.py b/src/core/widgets/code/controllers/__init__.py new file mode 100644 index 0000000..0f53a83 --- /dev/null +++ b/src/core/widgets/code/controllers/__init__.py @@ -0,0 +1,3 @@ +""" + Controllers Package +""" \ No newline at end of file diff --git a/src/core/widgets/code/controllers/commands_controller.py b/src/core/widgets/code/controllers/commands_controller.py new file mode 100644 index 0000000..9d41a6d --- /dev/null +++ b/src/core/widgets/code/controllers/commands_controller.py @@ -0,0 +1,34 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code import ( + CodeEvent, + GetCommandSystemEvent, + FocusedViewEvent +) + +from ..command_system import CommandSystem + +from .controller_base import ControllerBase + + + +class CommandsController(ControllerBase, list): + def __init__(self): + super(CommandsController, self).__init__() + + + def _controller_message(self, event: CodeEvent): + if isinstance(event, GetCommandSystemEvent): + event.response = self.get_command_system() + + def get_command_system(self): + command_system = CommandSystem() + command_system.emit = self.emit + command_system.emit_to = self.emit_to + + self.append(command_system) + + return command_system diff --git a/src/core/widgets/code/controllers/completion_controller.py b/src/core/widgets/code/controllers/completion_controller.py new file mode 100644 index 0000000..cd1722d --- /dev/null +++ b/src/core/widgets/code/controllers/completion_controller.py @@ -0,0 +1,111 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('GtkSource', '4') + +from gi.repository import GLib +from gi.repository import GtkSource + +# Application imports +from libs.dto.code import ( + CodeEvent, + FocusedViewEvent, + RequestCompletionEvent, + CursorMovedEvent, + TextChangedEvent, + TextInsertedEvent +) + +from ..completion_providers.example_completion_provider import ExampleCompletionProvider +from ..completion_providers.lsp_completion_provider import LSPCompletionProvider + +from .controller_base import ControllerBase + + + +class CompletionController(ControllerBase): + def __init__(self): + super(CompletionController, self).__init__() + + self._completor: GtkSource.Completion = None + self._timeout_id: int = None + self._lsp_provider: LSPCompletionProvider = LSPCompletionProvider() + + + def _controller_message(self, event: CodeEvent): + if isinstance(event, FocusedViewEvent): + self._completor = event.view.get_completion() + + if not self._timeout_id: return + + GLib.source_remove(self._timeout_id) + self._timeout_id = None + elif isinstance(event, RequestCompletionEvent): + self.request_completion() + # elif isinstance(event, TextInsertedEvent): + # self.request_completion() + + def _process_request_completion(self): + self._start_completion() + + self._timeout_id = None + return False + + def _do_completion(self): + if self._completor.get_providers(): + self._match_completion() + else: + self._start_completion() + + def _match_completion(self): + """ + Note: Use IF providers were added to completion... + """ + self._completion.match( + self._completion.create_context() + ) + + + def _start_completion(self): + """ + Note: Use IF NO providers have been added to completion... + """ + self._completor.start( + [ + ExampleCompletionProvider(), + self._lsp_provider + ], + self._completor.create_context() + ) + + + def set_completer(self, completer): + self._completor = completer + + def request_completion(self): + if self._timeout_id: + GLib.source_remove(self._timeout_id) + + self._timeout_id = GLib.timeout_add( + 800, + self._process_request_completion + ) + + def register_provider( + self, + provider_name: str, + provider: GtkSource.CompletionProvider, + priority: int = 0, + language_ids: list = None + ): + """Register completion providers with priority and language filtering""" + ... + + def unregister_provider(self, provider_name: str): + """Remove completion providers""" + ... + + def get_active_providers(self, language_id: str = None) -> list: + """Get providers filtered by language""" + ... diff --git a/src/core/widgets/code/controllers/controller_base.py b/src/core/widgets/code/controllers/controller_base.py new file mode 100644 index 0000000..6f1cdc5 --- /dev/null +++ b/src/core/widgets/code/controllers/controller_base.py @@ -0,0 +1,38 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.singleton import Singleton + +from libs.dto.code.code_event import CodeEvent + +from .emit_dispatcher import EmitDispatcher +from .controller_context import ControllerContext + + + +class ControllerBaseException(Exception): + ... + + + +class ControllerBase(Singleton, EmitDispatcher): + def __init__(self): + super(ControllerBase, self).__init__() + + self.controller_context: ControllerContext = None + + + def _controller_message(self, event: CodeEvent): + raise ControllerBaseException("Controller Base must override '_controller_message'...") + + def set_controller_context(self, controller_context: ControllerContext): + self.controller_context = controller_context + + def message_to(self, name: str, event: CodeEvent): + return self.controller_context.message_to(name, event) + + def message_all(self, event: CodeEvent): + return self.controller_context.message_all(event) + diff --git a/src/core/widgets/code/controllers/controller_context.py b/src/core/widgets/code/controllers/controller_context.py new file mode 100644 index 0000000..0fd5672 --- /dev/null +++ b/src/core/widgets/code/controllers/controller_context.py @@ -0,0 +1,24 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code.code_event import CodeEvent + + + +class ControllerContextException(Exception): + ... + + + +class ControllerContext: + def __init__(self): + super(ControllerContext, self).__init__() + + + def message_to(self, name: str, event: CodeEvent): + raise ControllerContextException("Controller Context 'message_to' must be overriden by Controller Manager...") + + def message_all(self, event: CodeEvent): + raise ControllerContextException("Controller Context 'message_all' must be overriden by Controller Manager...") diff --git a/src/core/widgets/code/controllers/controller_manager.py b/src/core/widgets/code/controllers/controller_manager.py new file mode 100644 index 0000000..c87a01d --- /dev/null +++ b/src/core/widgets/code/controllers/controller_manager.py @@ -0,0 +1,48 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.singleton import Singleton + +from libs.dto.code.code_event import CodeEvent + +from .controller_base import ControllerBase +from .controller_context import ControllerContext + + + +class ControllerManagerException(Exception): + ... + + + +class ControllerManager(Singleton, dict): + def __init__(self): + super(ControllerManager, self).__init__() + + + def _crete_controller_context(self) -> ControllerContext: + controller_context = ControllerContext() + controller_context.message_to = self.message_to + controller_context.message_all = self.message_all + + return controller_context + + def register_controller(self, name: str, controller: ControllerBase): + if not name or controller == None: + raise ControllerManagerException("Must pass in a 'name' and 'controller'...") + + controller.set_controller_context( + self._crete_controller_context() + ) + + self[name] = controller + + + def message_to(self, name: str, event: CodeEvent): + self[name]._controller_message(event) + + def message_all(self, event: CodeEvent): + for key in self.keys(): + self[key]._controller_message(event) diff --git a/src/core/widgets/code/controllers/emit_dispatcher.py b/src/core/widgets/code/controllers/emit_dispatcher.py new file mode 100644 index 0000000..79bf70a --- /dev/null +++ b/src/core/widgets/code/controllers/emit_dispatcher.py @@ -0,0 +1,19 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code.code_event import CodeEvent + + + +class EmitDispatcher: + def __init__(self): + super(EmitDispatcher, self).__init__() + + + def emit(self, event: CodeEvent): + self.message_all(event) + + def emit_to(self, controller: str, event: CodeEvent): + self.message_to(controller, event) diff --git a/src/core/widgets/code/controllers/files_controller.py b/src/core/widgets/code/controllers/files_controller.py new file mode 100644 index 0000000..078eef1 --- /dev/null +++ b/src/core/widgets/code/controllers/files_controller.py @@ -0,0 +1,156 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code import ( + CodeEvent, + FilePathSetEvent, + GetSwapFileEvent, + GetFileEvent, + AddNewFileEvent, + PopFileEvent, + SwapFileEvent, + RemoveFileEvent, + AddedNewFileEvent, + SwappedFileEvent, + PoppedFileEvent, + RemovedFileEvent +) + +from ..source_file import SourceFile +from ..source_buffer import SourceBuffer + +from .controller_base import ControllerBase + + + +class FilesController(ControllerBase, list): + def __init__(self): + super(FilesController, self).__init__() + + + def _controller_message(self, event: CodeEvent): + if isinstance(event, AddNewFileEvent): + self.new_file(event) + elif isinstance(event, SwapFileEvent): + self.swap_file(event) + elif isinstance(event, PopFileEvent): + self.pop_file(event) + elif isinstance(event, RemoveFileEvent): + self.remove_file(event) + elif isinstance(event, GetFileEvent): + self.get_file(event) + elif isinstance(event, GetSwapFileEvent): + self.get_swap_file(event) + + def get_file(self, event: GetFileEvent): + if not event.buffer: return + + for file in self: + if not event.buffer == file.buffer: continue + + event.response = file + + return file + + def get_swap_file(self, event: GetSwapFileEvent): + if not event.buffer: return + + for i, file in enumerate(self): + if not event.buffer == file.buffer: continue + + j = self.next_index(i) + next_file = self[j] + swapped_file = self[j] if not j == -1 else None + + event.response = [swapped_file, next_file] + + return swapped_file, next_file + + def new_file(self, event: AddNewFileEvent): + file = SourceFile() + file.emit = self.emit + file.emit_to = self.emit_to + + event.response = file + + eve = AddedNewFileEvent() + eve.view = event.view + eve.file = file + self.message_all(eve) + + self.append(file) + + return file + + def swap_file(self, event: GetSwapFileEvent): + if not event.buffer: return + + for i, file in enumerate(self): + if not event.buffer == file.buffer: continue + + j = self.next_index(i) + next_file = self[j] + swapped_file = self[j] if not j == -1 else None + + event.response = [swapped_file, next_file] + + return swapped_file, next_file + + def pop_file(self, event: PopFileEvent): + if not event.buffer: return + + for i, file in enumerate(self): + if not event.buffer == file.buffer: continue + + j = self.next_index(i) + next_file = self[j] if not j == -1 else None + popped_file = self.pop(i) + + event.response = [popped_file, next_file] + + eve = PoppedFileEvent() + eve.view = view + eve.file = popped_file + eve.next_file = next_file + self.message_all(eve) + + return popped_file, next_file + + def remove_file(self, event: RemoveFileEvent): + if not event.buffer: return + + for i, file in enumerate(self): + if not event.buffer == file.buffer: continue + + j = self.next_index(i) + next_file = self[j] if not j == -1 else None + + event.response = next_file + + eve = RemovedFileEvent() + eve.view = event.view + eve.ignore_focus = True + eve.file = file + eve.next_file = next_file + self.message_all(eve) + + self.remove(file) + file.close() + + return next_file + + def next_index(self, i): + size = len(self) + + if (i == 0) & (size >= 2): + j = i + 1 + elif (i == (size - 1)) & (size >= 2): + j = i - 1 + elif (size - 1) == 0: + j = -1 + else: + j = i + 1 + + return j diff --git a/src/core/widgets/code/controllers/source_views_controller.py b/src/core/widgets/code/controllers/source_views_controller.py new file mode 100644 index 0000000..3fd9209 --- /dev/null +++ b/src/core/widgets/code/controllers/source_views_controller.py @@ -0,0 +1,131 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code import ( + CodeEvent, + GetCommandSystemEvent, + CursorMovedEvent, + TextChangedEvent, + FocusedViewEvent, + SetActiveFileEvent, + RemoveFileEvent, + RemovedFileEvent +) + +from ..command_system import CommandSystem +from ..key_mapper import KeyMapper + +from ..source_view import SourceView + +from .controller_base import ControllerBase + + + +class SourceViewsController(ControllerBase, list): + def __init__(self): + super(SourceViewsController, self).__init__() + + self.key_mapper: KeyMapper = KeyMapper() + self.active_view: SourceView = None + + + def get_command_system(self): + event = GetCommandSystemEvent() + self.message_to("commands", event) + command = event.response + + del event + return command + + def create_source_view(self): + source_view: SourceView = SourceView() + source_view.command = self.get_command_system() + source_view.command.set_data(source_view) + + self._map_signals(source_view) + + self.append(source_view) + return source_view + + def _controller_message(self, event: CodeEvent): + if isinstance(event, RemovedFileEvent): + self._remove_file(event) + if isinstance(event, TextChangedEvent): + self.active_view.command.exec("update_info_bar") + + def _map_signals(self, source_view: SourceView): + source_view.connect("focus-in-event", self._focus_in_event) + source_view.connect("move-cursor", self._move_cursor) + source_view.connect("key-press-event", self._key_press_event) + source_view.connect("key-release-event", self._key_release_event) + source_view.connect("button-press-event", self._button_press_event) + source_view.connect("button-release-event", self._button_release_event) + + def _focus_in_event(self, view, eve): + self.active_view = view + + view.command.exec("set_miniview") + view.command.exec("set_focus_border") + view.command.exec("update_info_bar") + + event = FocusedViewEvent() + event.view = view + self.emit(event) + + def _move_cursor(self, view, step, count, extend_selection): + event = CursorMovedEvent() + buffer = view.get_buffer() + iter = buffer.get_iter_at_mark( buffer.get_insert() ) + line = iter.get_line() + char = iter.get_line_offset() + + event.view = view + event.buffer = buffer + event.line = line + event.char = char + + self.emit(event) + + view.command.exec("update_info_bar") + + def _button_press_event(self, view, eve): + self.active_view.command.exec("update_info_bar") + + def _button_release_event(self, view, eve): + self.active_view.command.exec("update_info_bar") + + def _key_press_event(self, view, eve): + command = self.key_mapper._key_press_event(eve) + if not command: return False + + view.command.exec(command) + + return False + + def _key_release_event(self, view, eve): + command = self.key_mapper._key_release_event(eve) + if not command: return False + + view.command.exec(command) + + return False + + def _remove_file(self, event: RemovedFileEvent): + for view in self: + if not event.file.buffer == view.get_buffer(): continue + if not event.next_file: + view.command.exec("new_file") + continue + + view.set_buffer(event.next_file.buffer) + + def first_map_load(self): + for view in self: + view.command.exec("new_file") + + view = self[0] + view.grab_focus() + view.command.exec("load_start_files") + diff --git a/src/core/widgets/code/controllers/tabs_controller.py b/src/core/widgets/code/controllers/tabs_controller.py new file mode 100644 index 0000000..cd5abf8 --- /dev/null +++ b/src/core/widgets/code/controllers/tabs_controller.py @@ -0,0 +1,90 @@ +# Python imports + +# Lib imports + +# Application imports +from libs.dto.code import ( + CodeEvent, + FocusedViewEvent, + FilePathSetEvent, + RemoveFileEvent, + SetActiveFileEvent, + AddedNewFileEvent, + PoppedFileEvent, + RemovedFileEvent +) + +from ..tabs_widget import TabsWidget +from ..tab_widget import TabWidget + +from ..source_view import SourceView + +from .controller_base import ControllerBase + + + +class TabsController(ControllerBase): + def __init__(self): + super(TabsController, self).__init__() + + self.active_view: SourceView = None + self.tabs_widget: TabsWidget = TabsWidget() + + + def _controller_message(self, event: CodeEvent): + if isinstance(event, FocusedViewEvent): + self.active_view = event.view + elif isinstance(event, FilePathSetEvent): + self.update_tab_label(event) + elif isinstance(event, AddedNewFileEvent): + self.add_tab(event) + elif isinstance(event, PoppedFileEvent): + ... + elif isinstance(event, RemovedFileEvent): + self.remove_tab(event) + + def get_tabs_widget(self): + return self.tabs_widget + + def update_tab_label(self, event: FilePathSetEvent): + for tab in self.tabs_widget.get_children(): + if not event.file == tab.file: continue + tab.label.set_label(event.file.fname) + break + + def add_tab(self, event: AddedNewFileEvent): + def set_active_tab(tab, eve, file): + event = SetActiveFileEvent() + event.buffer = tab.get_parent().file.buffer + + self.active_view.set_buffer( + tab.get_parent().file.buffer + ) + + self.message_all(event) + + def close_tab(tab, eve, file): + event = RemoveFileEvent() + event.buffer = tab.get_parent().file.buffer + + self.message_all(event) + + tab = TabWidget() + tab.file = event.file + tab.label.set_label(event.file.fname) + tab.set_select_signal(set_active_tab) + tab.set_close_signal(close_tab) + + self.tabs_widget.add(tab) + tab.show() + + def remove_tab(self, event: RemovedFileEvent): + for tab in self.tabs_widget.get_children(): + if not event.file == tab.file: continue + + tab.clear_signals_and_data() + tab.run_dispose() + tab.destroy() + + del tab + break diff --git a/src/core/widgets/code/general_info_widget.py b/src/core/widgets/code/info_bar_widget.py similarity index 91% rename from src/core/widgets/code/general_info_widget.py rename to src/core/widgets/code/info_bar_widget.py index a9c47b6..a4da54c 100644 --- a/src/core/widgets/code/general_info_widget.py +++ b/src/core/widgets/code/info_bar_widget.py @@ -11,11 +11,11 @@ from gi.repository import Gio -class GeneralInfoWidget(Gtk.Box): - """ docstring for StatusInfoWidget. """ +class InfoBarWidget(Gtk.Box): + """ docstring for InfoBarWidget. """ def __init__(self): - super(GeneralInfoWidget, self).__init__() + super(InfoBarWidget, self).__init__() self._setup_styling() self._setup_signals() @@ -76,9 +76,6 @@ class GeneralInfoWidget(Gtk.Box): gfile = "" if not gfile else gfile if isinstance(gfile, str): - # path = gfile - # path = "..." + path[-120: -1] if len(path) >= 123 else path - # self.path_label.set_text( path ) self.path_label.set_text( gfile ) self.path_label.set_tooltip_text( gfile ) else: diff --git a/src/core/widgets/code/miniview_widget.py b/src/core/widgets/code/mini_view_widget.py similarity index 95% rename from src/core/widgets/code/miniview_widget.py rename to src/core/widgets/code/mini_view_widget.py index ba5c758..789f475 100644 --- a/src/core/widgets/code/miniview_widget.py +++ b/src/core/widgets/code/mini_view_widget.py @@ -21,10 +21,11 @@ class MiniViewWidget(Map): def _setup_styling(self): - self.set_hexpand(False) ctx = self.get_style_context() ctx.add_class("mini-view") + self.set_hexpand(False) + def _setup_signals(self): ... diff --git a/src/core/widgets/code/mixins/source_view_events_mixin.py b/src/core/widgets/code/mixins/source_view_events_mixin.py deleted file mode 100644 index 5e070e0..0000000 --- a/src/core/widgets/code/mixins/source_view_events_mixin.py +++ /dev/null @@ -1,63 +0,0 @@ -# Python imports - -# Lib imports - -# Application imports -from libs.dto.code_event import CodeEvent - - - -class SourceViewEventsMixin: - def _focus_in_event(self, view, eve): - self.command.exec("set_miniview") - self.command.exec("set_focus_border") - self.command.exec("update_info_bar") - - def _move_cursor(self, view, step, count, extend_selection): - self.command.exec("update_info_bar") - - def _button_press_event(self, view, eve): - self.command.exec("update_info_bar") - - def _button_release_event(self, view, eve): - self.command.exec("update_info_bar") - - def _key_press_event(self, view, eve): - command = self.key_mapper._key_press_event(eve) - if not command: return False - - self.command.exec(command) - return True - - def _key_release_event(self, view, eve): - command = self.key_mapper._key_release_event(eve) - if not command: return False - - self.command.exec(command) - return True - - def notification(self, event: CodeEvent): - if not hasattr(self, "command"): return - - has_focus = self.command.exec("has_focus") - if not has_focus and not event.ignore_focus: return - - match event.etype: - case "removed_file": - logger.debug("SourceFileManager.remove_file") - if not event.file.buffer == self.get_buffer(): return - self.command.exec_with_args("set_buffer", (self, event.next_file)) - return - case "changed": - logger.debug("SourceFile._changed") - case "modified_changed": - logger.debug("SourceFile._modified_changed") - case "insert_text": - logger.debug("SourceFile._insert_text") - case "mark_set": - # logger.debug("SourceFile._mark_set") - ... - case _: - ... - - self.command.exec("update_info_bar") diff --git a/src/core/widgets/code/source_file.py b/src/core/widgets/code/source_file.py index 2304202..063a67a 100644 --- a/src/core/widgets/code/source_file.py +++ b/src/core/widgets/code/source_file.py @@ -12,19 +12,22 @@ from gi.repository import GtkSource from gi.repository import Gio # Application imports -from libs.mixins.observable_mixin import ObservableMixin -from libs.dto.code_event import CodeEvent +from libs.dto.code import ( + CodeEvent, + TextChangedEvent, + TextInsertedEvent, + FilePathSetEvent, + ModifiedChangedEvent +) from .source_buffer import SourceBuffer -class SourceFile(GtkSource.File, ObservableMixin): +class SourceFile(GtkSource.File): def __init__(self): super(SourceFile, self).__init__() - self.observers = [] - self.encoding: str = "UTF-8" self.fname: str = "buffer" self.fpath: str = "buffer" @@ -43,24 +46,21 @@ class SourceFile(GtkSource.File, ObservableMixin): self._modified_changed ) + def _changed(self, buffer: SourceBuffer): + event = TextChangedEvent() + event.file = self + event.buffer = buffer + + self.emit(event) def _insert_text(self, buffer: SourceBuffer, location: Gtk.TextIter, text: str, length: int ): - event = CodeEvent() - event.etype = "insert_text" + event = TextInsertedEvent() event.file = self event.buffer = buffer - self.notify_observers(event) - - def _changed(self, buffer: SourceBuffer): - event = CodeEvent() - event.etype = "changed" - event.file = self - event.buffer = buffer - - self.notify_observers(event) + self.emit(event) def _mark_set(self, buffer: SourceBuffer, location: Gtk.TextIter, mark: Gtk.TextMark @@ -70,16 +70,15 @@ class SourceFile(GtkSource.File, ObservableMixin): # event.file = self # event.buffer = buffer - # self.notify_observers(event) + # self.emit(event) ... def _modified_changed(self, buffer: SourceBuffer): - event = CodeEvent() - event.etype = "modified_changed" + event = ModifiedChangedEvent() event.file = self event.buffer = buffer - self.notify_observers(event) + self.emit(event) def _write_file(self, gfile: Gio.File): @@ -109,14 +108,13 @@ class SourceFile(GtkSource.File, ObservableMixin): if not gfile: return self.set_location(gfile) - self.fpath = gfile.get_path() - self.fname = gfile.get_basename() + self.fpath = gfile.get_path() + self.fname = gfile.get_basename() - event = CodeEvent() - event.etype = "set_path" + event = FilePathSetEvent() event.file = self - self.notify_observers(event) + self.emit(event) def save(self): self._write_file( self.get_location() ) @@ -131,7 +129,10 @@ class SourceFile(GtkSource.File, ObservableMixin): return file def close(self): - self.observers.clear() + del self.buffer - del self.observers - del self.buffer \ No newline at end of file + def emit(self, event: CodeEvent): + ... + + def emit_to(self, controller: str, event: CodeEvent): + ... \ No newline at end of file diff --git a/src/core/widgets/code/source_files_manager.py b/src/core/widgets/code/source_files_manager.py deleted file mode 100644 index 0e9c9f0..0000000 --- a/src/core/widgets/code/source_files_manager.py +++ /dev/null @@ -1,106 +0,0 @@ -# Python imports - -# Lib imports - -# Application imports -from libs.mixins.observable_mixin import ObservableMixin -from libs.singleton import Singleton -from libs.dto.code_event import CodeEvent - -from .source_file import SourceFile -from .source_buffer import SourceBuffer - - - -class SourceFilesManager(Singleton, list, ObservableMixin): - def __init__(self): - super(SourceFilesManager, self).__init__() - - self.observers = [] - - - def new(self): - file = SourceFile() - self.append(file) - return file - - def append(self, file: SourceFile): - if not file: return - super().append(file) - - event = CodeEvent() - event.etype = "appended_file" - event.file = file - - self.notify_observers(event) - - def get_file(self, buffer: SourceBuffer): - if not buffer: return - - for file in self: - if not buffer == file.buffer: continue - return file - - def pop_file(self, buffer: SourceBuffer): - if not buffer: return - - for i, file in enumerate(self): - if not buffer == file.buffer: continue - - j = self.next_index(i) - next_file = self[j] if not j == -1 else None - popped_file = self.pop(i) - event = CodeEvent() - event.etype = "popped_file" - event.file = popped_file - event.next_file = next_file - - self.notify_observers(event) - - return popped_file, next_file - - def swap_file(self, buffer: SourceBuffer): - if not buffer: return - - for i, file in enumerate(self): - if not buffer == file.buffer: continue - - j = self.next_index(i) - next_file = self[j] - swapped_file = self[j] if not j == -1 else None - - return swapped_file, next_file - - def remove_file(self, buffer: SourceBuffer): - if not buffer: return - - for i, file in enumerate(self): - if not buffer == file.buffer: continue - - j = self.next_index(i) - next_file = self[j] if not j == -1 else None - event = CodeEvent() - event.etype = "removed_file" - event.ignore_focus = True - event.file = file - event.next_file = next_file - self.notify_observers(event) - - self.remove(file) - file.close() - - return next_file - - def next_index(self, i): - size = len(self) - - if (i == 0) & (size >= 2): - j = i + 1 - elif (i == (size - 1)) & (size >= 2): - j = i - 1 - elif (size - 1) == 0: - j = -1 - else: - j = i + 1 - - return j \ No newline at end of file diff --git a/src/core/widgets/code/view.py b/src/core/widgets/code/source_view.py similarity index 57% rename from src/core/widgets/code/view.py rename to src/core/widgets/code/source_view.py index 44be6f9..e6cc897 100644 --- a/src/core/widgets/code/view.py +++ b/src/core/widgets/code/source_view.py @@ -9,29 +9,19 @@ from gi.repository import Gtk from gi.repository import GLib from gi.repository import GtkSource -# Application imports -from libs.mixins.observable_mixin import ObservableMixin - -from .mixins.source_view_events_mixin import SourceViewEventsMixin from .mixins.source_view_dnd_mixin import SourceViewDnDMixin -from .source_files_manager import SourceFilesManager -from .completion_manager import CompletionManager -from .command_system import CommandSystem -from .key_mapper import KeyMapper - -class SourceView(GtkSource.View, ObservableMixin, SourceViewEventsMixin, SourceViewDnDMixin): +class SourceView(GtkSource.View, SourceViewDnDMixin): def __init__(self): super(SourceView, self).__init__() - self.observers = [] self._cut_temp_timeout_id = None self._cut_buffer = "" - self.sibling_right = None - self.sibling_left = None + self.sibling_right = None + self.sibling_left = None self._setup_styles() self._setup_signals() @@ -63,40 +53,15 @@ class SourceView(GtkSource.View, ObservableMixin, SourceViewEventsMixin, SourceV self.set_highlight_current_line(True) def _setup_signals(self): - self.map_id = self.connect("map", self._init_map) - - self.connect("focus-in-event", self._focus_in_event) self.connect("drag-data-received", self._on_drag_data_received) - self.connect("move-cursor", self._move_cursor) - self.connect("key-press-event", self._key_press_event) - self.connect("key-release-event", self._key_release_event) - self.connect("button-press-event", self._button_press_event) - self.connect("button-release-event", self._button_release_event) def _subscribe_to_events(self): ... def _load_widgets(self): - self._set_up_dnd() - event_system.emit("register-view-to-tabs-widget", (self,)) - - def _init_map(self, view): - self.disconnect(self.map_id) - del self.map_id - - GLib.idle_add(self._init_show) - - def _init_show(self): self.language_manager = GtkSource.LanguageManager() self.style_scheme_manager = GtkSource.StyleSchemeManager() - self.key_mapper = KeyMapper() - self.command = CommandSystem() - self.completion = CompletionManager() - - self.command.set_data(self) - self.completion.set_completer( self.get_completion() ) - self.style_scheme_manager.append_search_path( f"{settings_manager.path_manager.get_home_config_path()}/code_styles" ) @@ -104,18 +69,7 @@ class SourceView(GtkSource.View, ObservableMixin, SourceViewEventsMixin, SourceV f"{settings_manager.settings.theming.syntax_theme}" ) - self.command.exec("new_file") - - if not self.sibling_right: return - - self.grab_focus() - self.command.exec("load_start_files") - - return False - - def set_files_manager(self, files_manager: SourceFilesManager): - self.files_manager = files_manager - self.files_manager.add_observer(self) + self._set_up_dnd() def clear_temp_cut_buffer_delayed(self): if self._cut_temp_timeout_id: diff --git a/src/core/widgets/code/tabs_widget.py b/src/core/widgets/code/tabs_widget.py index 208f44a..f9225da 100644 --- a/src/core/widgets/code/tabs_widget.py +++ b/src/core/widgets/code/tabs_widget.py @@ -6,22 +6,19 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from libs.dto.code_event import CodeEvent +from libs.dto.code.code_event import CodeEvent -from .view import SourceView -from .source_files_manager import SourceFilesManager +from .source_view import SourceView from .source_file import SourceFile from .tab_widget import TabWidget -class TabsWidget(Gtk.ScrolledWindow): +class TabsWidget(Gtk.ButtonBox): def __init__(self): super(TabsWidget, self).__init__() - self.active_view: SourceView = None - self._setup_styling() self._setup_signals() self._subscribe_to_events() @@ -29,59 +26,35 @@ class TabsWidget(Gtk.ScrolledWindow): def _setup_styling(self): - self.set_overlay_scrolling(False) + self.set_layout(Gtk.ButtonBoxStyle.CENTER) def _setup_signals(self): - event_system.subscribe("register-view-to-tabs-widget", self._register_view_to_tabs_widget) + ... def _subscribe_to_events(self): - self.files_manager: SourceFilesManager = SourceFilesManager() - self.files_manager.add_observer(self) + ... def _load_widgets(self): - self.viewport = Gtk.Viewport() - self.tabs = Gtk.ButtonBox() - - self.tabs.set_layout(Gtk.ButtonBoxStyle.CENTER) - - self.viewport.add(self.tabs) - self.add(self.viewport) - - def _register_view_to_tabs_widget(self, view: SourceView): - view.add_observer(self) - view.set_files_manager(self.files_manager) - - def notification(self, event: CodeEvent): - match event.etype: - case "focused_view_change": - logger.debug("SourceView.focused_view_change") - self.active_view = event.view - case "appended_file": - logger.debug("SourceFilesManager.appended") - self.add_tab(event) - case "popped_file": - logger.debug("SourceFilesManager.pop_file") - case "removed_file": - logger.debug("SourceFilesManager.remove_file") - self.remove_tab(event) - case "set_path": - logger.debug("SourceFile.set_path") - self.update_tab_label(event) - case _: - ... + ... def add_tab(self, event: CodeEvent): + """Add a tab widget for the given file event.""" + if not hasattr(self, 'tabs'): + return + tab = TabWidget() tab.file = event.file tab.label.set_label(event.file.fname) - event.file.add_observer(self) def select_signal(widget, eve, file): - self.active_view.command.exec_with_args("set_buffer", (self.active_view, file)) + self.code_base.active_view.command.exec_with_args( + "set_buffer", + (self.code_base.active_view, file) + ) def close_signal(widget, eve, file): - self.files_manager.remove_file(file.buffer) + self.code_base.files_controller.remove_file(file.buffer) tab.set_select_signal(select_signal) tab.set_close_signal(close_signal) @@ -89,10 +62,13 @@ class TabsWidget(Gtk.ScrolledWindow): self.tabs.add(tab) def remove_tab(self, event: CodeEvent): + """Remove a tab widget for the given file event.""" + if not hasattr(self, 'tabs'): + return + for child in self.tabs.get_children(): if not child.file == event.file: continue - child.file.remove_observer(self) self.tabs.remove(child) child.clear_signals_and_data() del child @@ -100,6 +76,10 @@ class TabsWidget(Gtk.ScrolledWindow): return def update_tab_label(self, event: CodeEvent): + """Update tab label for the given file event.""" + if not hasattr(self, 'tabs'): + return + for tab in self.tabs.get_children(): if not tab.file == event.file: continue tab.label.set_label(event.file.fname) diff --git a/src/core/widgets/vte_widget.py b/src/core/widgets/vte_widget.py index d80bea2..421962c 100644 --- a/src/core/widgets/vte_widget.py +++ b/src/core/widgets/vte_widget.py @@ -70,16 +70,17 @@ class VteWidget(Vte.Terminal): # Note: '-->:' is used as a delimiter to split on to get command actual. # !!! DO NOT REMOVE UNLESS CODE UPDATED ACCORDINGLY !!! + # Also, KEEP the prefix in commands to keep from inserting to bash history. startup_cmds = [ - "env -i /bin/bash --noprofile --norc\n", - "export TERM='xterm-256color'\n", - "export LC_ALL=C\n", - "export XDG_RUNTIME_DIR='/run/user/1000'\n", - "export DISPLAY=:0\n", - f"export XAUTHORITY='{settings_manager.path_manager.get_home_path()}/.Xauthority'\n", - f"\nexport HOME='{settings_manager.path_manager.get_home_path()}'\n", - "export PS1='\\h@\\u \\W -->: '\n", - "clear\n" + " env -i /bin/bash --noprofile --norc\n", + " export TERM='xterm-256color'\n", + " export LC_ALL=C\n", + " export XDG_RUNTIME_DIR='/run/user/1000'\n", + " export DISPLAY=:0\n", + f" export XAUTHORITY='{settings_manager.path_manager.get_home_path()}/.Xauthority'\n", + f" \nexport HOME='{settings_manager.path_manager.get_home_path()}'\n", + " export PS1='\\h@\\u \\W -->: '\n", + " clear\n" ] for i in startup_cmds: diff --git a/src/libs/dto/__init__.py b/src/libs/dto/__init__.py index 8c55071..1763ba0 100644 --- a/src/libs/dto/__init__.py +++ b/src/libs/dto/__init__.py @@ -1,5 +1,5 @@ """ - Dasta Class Package + DTO Class Package """ from .event import Event \ No newline at end of file diff --git a/src/libs/dto/code/__init__.py b/src/libs/dto/code/__init__.py new file mode 100644 index 0000000..f65207c --- /dev/null +++ b/src/libs/dto/code/__init__.py @@ -0,0 +1,27 @@ +""" + Code DTO Class Package +""" + + +from .code_event import CodeEvent +from .get_command_system_event import GetCommandSystemEvent +from .request_completion_event import RequestCompletionEvent +from .cursor_moved_event import CursorMovedEvent +from .modified_changed_event import ModifiedChangedEvent +from .text_changed_event import TextChangedEvent +from .text_inserted_event import TextInsertedEvent +from .focused_view_event import FocusedViewEvent +from .set_active_file_event import SetActiveFileEvent + +from .file_path_set_event import FilePathSetEvent +from .added_new_file_event import AddedNewFileEvent +from .swapped_file_event import SwappedFileEvent +from .popped_file_event import PoppedFileEvent +from .removed_file_event import RemovedFileEvent + +from .get_file_event import GetFileEvent +from .get_swap_file_event import GetSwapFileEvent +from .add_new_file_event import AddNewFileEvent +from .swap_file_event import SwapFileEvent +from .pop_file_event import PopFileEvent +from .remove_file_event import RemoveFileEvent diff --git a/src/libs/dto/code/add_new_file_event.py b/src/libs/dto/code/add_new_file_event.py new file mode 100644 index 0000000..fa1235d --- /dev/null +++ b/src/libs/dto/code/add_new_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class AddNewFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/added_new_file_event.py b/src/libs/dto/code/added_new_file_event.py new file mode 100644 index 0000000..1add983 --- /dev/null +++ b/src/libs/dto/code/added_new_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class AddedNewFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code_event.py b/src/libs/dto/code/code_event.py similarity index 62% rename from src/libs/dto/code_event.py rename to src/libs/dto/code/code_event.py index 0e87976..e893333 100644 --- a/src/libs/dto/code_event.py +++ b/src/libs/dto/code/code_event.py @@ -4,15 +4,14 @@ from dataclasses import dataclass, field # Lib imports # Application imports -from .observable_event import ObservableEvent @dataclass -class CodeEvent(ObservableEvent): - etype: str = "" +class CodeEvent: ignore_focus: bool = False view: any = None file: any = None next_file: any = None - buffer: any = None \ No newline at end of file + buffer: any = None + response: any = None diff --git a/src/libs/dto/code/cursor_moved_event.py b/src/libs/dto/code/cursor_moved_event.py new file mode 100644 index 0000000..608e331 --- /dev/null +++ b/src/libs/dto/code/cursor_moved_event.py @@ -0,0 +1,14 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class CursorMovedEvent(CodeEvent): + line: int = 0 + char: int = 0 diff --git a/src/libs/dto/code/file_path_set_event.py b/src/libs/dto/code/file_path_set_event.py new file mode 100644 index 0000000..40415aa --- /dev/null +++ b/src/libs/dto/code/file_path_set_event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class FilePathSetEvent(CodeEvent): + fname: str = "" + fpath: str = "" + ftype: str = "" diff --git a/src/libs/dto/code/focused_view_event.py b/src/libs/dto/code/focused_view_event.py new file mode 100644 index 0000000..1064170 --- /dev/null +++ b/src/libs/dto/code/focused_view_event.py @@ -0,0 +1,14 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class FocusedViewEvent(CodeEvent): + left_view: any = False + right_view: any = False diff --git a/src/libs/dto/code/get_command_system_event.py b/src/libs/dto/code/get_command_system_event.py new file mode 100644 index 0000000..ae6b60e --- /dev/null +++ b/src/libs/dto/code/get_command_system_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class GetCommandSystemEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/get_file_event.py b/src/libs/dto/code/get_file_event.py new file mode 100644 index 0000000..4b92c72 --- /dev/null +++ b/src/libs/dto/code/get_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class GetFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/get_swap_file_event.py b/src/libs/dto/code/get_swap_file_event.py new file mode 100644 index 0000000..4144756 --- /dev/null +++ b/src/libs/dto/code/get_swap_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class GetSwapFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/modified_changed_event.py b/src/libs/dto/code/modified_changed_event.py new file mode 100644 index 0000000..95e3363 --- /dev/null +++ b/src/libs/dto/code/modified_changed_event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class ModifiedChangedEvent(CodeEvent): + line: int = 0 + char: int = 0 + value: str = "" diff --git a/src/libs/dto/code/pop_file_event.py b/src/libs/dto/code/pop_file_event.py new file mode 100644 index 0000000..702aa17 --- /dev/null +++ b/src/libs/dto/code/pop_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class PopFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/popped_file_event.py b/src/libs/dto/code/popped_file_event.py new file mode 100644 index 0000000..dc637e2 --- /dev/null +++ b/src/libs/dto/code/popped_file_event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class PoppedFileEvent(CodeEvent): + fname: str = "" + fpath: str = "" + ftype: str = "" diff --git a/src/libs/dto/code/remove_file_event.py b/src/libs/dto/code/remove_file_event.py new file mode 100644 index 0000000..c076bd6 --- /dev/null +++ b/src/libs/dto/code/remove_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class RemoveFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/removed_file_event.py b/src/libs/dto/code/removed_file_event.py new file mode 100644 index 0000000..129faa2 --- /dev/null +++ b/src/libs/dto/code/removed_file_event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class RemovedFileEvent(CodeEvent): + fname: str = "" + fpath: str = "" + ftype: str = "" diff --git a/src/libs/dto/code/request_completion_event.py b/src/libs/dto/code/request_completion_event.py new file mode 100644 index 0000000..ba9b01c --- /dev/null +++ b/src/libs/dto/code/request_completion_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class RequestCompletionEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/set_active_file_event.py b/src/libs/dto/code/set_active_file_event.py new file mode 100644 index 0000000..0f466d5 --- /dev/null +++ b/src/libs/dto/code/set_active_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class SetActiveFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/swap_file_event.py b/src/libs/dto/code/swap_file_event.py new file mode 100644 index 0000000..04c8a6c --- /dev/null +++ b/src/libs/dto/code/swap_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class SwapFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/swapped_file_event.py b/src/libs/dto/code/swapped_file_event.py new file mode 100644 index 0000000..33e5551 --- /dev/null +++ b/src/libs/dto/code/swapped_file_event.py @@ -0,0 +1,13 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class SwappedFileEvent(CodeEvent): + ... diff --git a/src/libs/dto/code/text_changed_event.py b/src/libs/dto/code/text_changed_event.py new file mode 100644 index 0000000..61b2317 --- /dev/null +++ b/src/libs/dto/code/text_changed_event.py @@ -0,0 +1,18 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class TextChangedEvent(CodeEvent): + has_selection: bool = False + start_range: int = 0 + end_range: int = 0 + line: int = 0 + char: int = 0 + value: str = "" diff --git a/src/libs/dto/code/text_inserted_event.py b/src/libs/dto/code/text_inserted_event.py new file mode 100644 index 0000000..30f5f2e --- /dev/null +++ b/src/libs/dto/code/text_inserted_event.py @@ -0,0 +1,15 @@ +# Python imports +from dataclasses import dataclass, field + +# Lib imports + +# Application imports +from .code_event import CodeEvent + + + +@dataclass +class TextInsertedEvent(CodeEvent): + line: int = 0 + char: int = 0 + value: str = ""