diff --git a/src/core/widgets/base/notebook/editor_controller.py b/src/core/widgets/base/notebook/editor_controller.py index c5e678c..8ada7a0 100644 --- a/src/core/widgets/base/notebook/editor_controller.py +++ b/src/core/widgets/base/notebook/editor_controller.py @@ -3,10 +3,12 @@ # Lib imports # Application imports +from .key_input_controller import KeyInputController +from .editor_events import EditorEventsMixin -class EditorControllerMixin: +class EditorControllerMixin(KeyInputController, EditorEventsMixin): def get_active_view(self): page_num = self.get_current_page() container = self.get_nth_page( page_num ) @@ -19,47 +21,13 @@ class EditorControllerMixin: return page_num, container, source_view = self.get_active_view() - if action == "close_tab": - self.close_tab(None, container, source_view) - if action == "keyboard_prev_tab": - self.keyboard_prev_tab(page_num) - if action == "keyboard_next_tab": - self.keyboard_next_tab(page_num) - if action == "keyboard_move_tab_left": - self.keyboard_move_tab_left(page_num) - if action == "keyboard_move_tab_right": - self.keyboard_move_tab_right(page_num) - if action == "keyboard_move_tab_to_1": - self.keyboard_move_tab_to_1(page_num) - if action == "keyboard_move_tab_to_2": - self.keyboard_move_tab_to_2(page_num) - # NOTE: These feel bad being here man... if action == "scale_up_text": self.scale_up_text(source_view) - if action == "keyboard_undo": - self.keyboard_undo(source_view) - if action == "keyboard_redo": - self.keyboard_redo(source_view) if action == "scale_down_text": self.scale_down_text(source_view) - if action == "toggle_highlight_line": - self.toggle_highlight_line(source_view) - if action == "keyboard_insert_mark": - self.keyboard_insert_mark(source_view) - if action == "keyboard_clear_marks": - self.keyboard_clear_marks(source_view) - if action == "keyboard_move_lines_up": - self.keyboard_move_lines_up(source_view) - if action == "keyboard_move_lines_down": - self.keyboard_move_lines_down(source_view) if action == "set_buffer_language": self.set_buffer_language(source_view, query) if action == "set_buffer_style": - self.set_buffer_style(source_view, query) - if action == "save_file": - return source_view.save_file() - if action == "save_file_as": - return source_view.save_file_as() - + self.set_buffer_style(source_view, query) \ No newline at end of file diff --git a/src/core/widgets/base/notebook/editor_events.py b/src/core/widgets/base/notebook/editor_events.py index c0a37a0..207fa2d 100644 --- a/src/core/widgets/base/notebook/editor_events.py +++ b/src/core/widgets/base/notebook/editor_events.py @@ -101,36 +101,17 @@ class EditorEventsMixin: # NOTE: These feel bad being here man... - def keyboard_undo(self, source_view): - source_view.keyboard_undo() - - def keyboard_redo(self, source_view): - source_view.keyboard_redo() - def scale_up_text(self, source_view): source_view.scale_up_text() def scale_down_text(self, source_view): source_view.scale_down_text() - def toggle_highlight_line(self, source_view): - source_view.toggle_highlight_line() - - def keyboard_insert_mark(self, source_view): - source_view.keyboard_insert_mark() - - def keyboard_clear_marks(self, source_view): - source_view.keyboard_clear_marks() - - def keyboard_move_lines_up(self, source_view): - source_view.keyboard_move_lines_up() - - def keyboard_move_lines_down(self, source_view): - source_view.keyboard_move_lines_down() - def set_buffer_language(self, source_view, language = "python3"): source_view.set_buffer_language(language) def set_buffer_style(self, source_view, style = settings.theming.syntax_theme): buffer = source_view.get_buffer() - source_view.set_buffer_style(buffer, style) \ No newline at end of file + source_view.set_buffer_style(buffer, style) + + diff --git a/src/core/widgets/base/notebook/editor_notebook.py b/src/core/widgets/base/notebook/editor_notebook.py index 1ec22b2..d792a68 100644 --- a/src/core/widgets/base/notebook/editor_notebook.py +++ b/src/core/widgets/base/notebook/editor_notebook.py @@ -10,13 +10,11 @@ from gi.repository import Gio # Application imports from .editor_controller import EditorControllerMixin -from .editor_events import EditorEventsMixin # NOTE: https://github.com/Axel-Erfurt/TextEdit/tree/b65f09be945196eb05bef83d81a6abcd129b4eb0 - -class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): +class EditorNotebook(EditorControllerMixin, Gtk.Notebook): ccount = 0 def __new__(cls, *args, **kwargs): @@ -35,7 +33,6 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): self.set_group_name("editor_widget") self.builder.expose_object(self.NAME, self) - self._add_action_widgets() self._setup_styling() self._setup_signals() self._subscribe_to_events() @@ -57,35 +54,30 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): def _setup_signals(self): self.connect("switch-page", self._switch_page_update) + self.connect("key-press-event", self._key_press_event) + self.connect("key-release-event", self._key_release_event) def _subscribe_to_events(self): event_system.subscribe("create_view", self._create_view) event_system.subscribe("set_buffer_style", self.action_controller) event_system.subscribe("set_buffer_language", self.action_controller) - event_system.subscribe("focused_target_changed", self._focused_target_changed) - event_system.subscribe("keyboard_create_tab", self._keyboard_create_tab) - event_system.subscribe("keyboard_open_file", self._keyboard_open_file) - event_system.subscribe("keyboard_close_tab", self._keyboard_close_tab) - event_system.subscribe("keyboard_prev_tab", self._keyboard_prev_tab) - event_system.subscribe("keyboard_next_tab", self._keyboard_next_tab) - event_system.subscribe("keyboard_move_tab_left", self._keyboard_move_tab_left) - event_system.subscribe("keyboard_move_tab_right", self._keyboard_move_tab_right) - event_system.subscribe("keyboard_move_tab_to_1", self._keyboard_move_tab_to_1) - event_system.subscribe("keyboard_move_tab_to_2", self._keyboard_move_tab_to_2) - event_system.subscribe("toggle_highlight_line", self._toggle_highlight_line) - event_system.subscribe("keyboard_move_lines_up", self._keyboard_move_lines_up) - event_system.subscribe("keyboard_move_lines_down", self._keyboard_move_lines_down) - event_system.subscribe("keyboard_undo", self._keyboard_undo) - event_system.subscribe("keyboard_redo", self._keyboard_redo) - event_system.subscribe("keyboard_insert_mark", self._keyboard_insert_mark) - event_system.subscribe("keyboard_clear_marks", self._keyboard_clear_marks) + event_system.subscribe("keyboard_open_file", self._keyboard_open_file) event_system.subscribe("keyboard_scale_up_text", self._keyboard_scale_up_text) event_system.subscribe("keyboard_scale_down_text", self._keyboard_scale_down_text) - event_system.subscribe("keyboard_save_file", self._keyboard_save_file) - event_system.subscribe("keyboard_save_file_as", self._keyboard_save_file_as) + # event_system.subscribe("keyboard_save_file_as", self._keyboard_save_file_as) + + + def _load_widgets(self): + self._add_action_widgets() + if self.NAME == "notebook_1" and not settings_manager.is_starting_with_file(): + self.create_view() + + def _dbl_click_create_view(self, notebook, eve): + if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS and eve.button == 1: # l-click + ... def _focused_target_changed(self, target): self.is_editor_focused = True if target == self.NAME else False @@ -108,14 +100,6 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): self.set_action_widget(start_box, 0) self.set_action_widget(end_box, 1) - def _load_widgets(self): - if self.NAME == "notebook_1" and not settings_manager.is_starting_with_file(): - self.create_view() - - def _dbl_click_create_view(self, notebook, eve): - if eve.type == Gdk.EventType.DOUBLE_BUTTON_PRESS and eve.button == 1: # l-click - ... - def _switch_page_update(self, notebook, page, page_num): source_view = page.get_source_view() gfile = source_view.get_current_file() @@ -150,66 +134,8 @@ class EditorNotebook(EditorEventsMixin, EditorControllerMixin, Gtk.Notebook): self.open_file(gfile) - def _keyboard_create_tab(self, _gfile = None): - if not self.is_editor_focused: # TODO: Find way to converge this - return - - self.create_view(gfile = _gfile) - - - def _keyboard_close_tab(self): - self.action_controller("close_tab") - - def _keyboard_move_tab_right(self): - self.action_controller("keyboard_move_tab_right") - - def _keyboard_move_tab_left(self): - self.action_controller("keyboard_move_tab_left") - - def _keyboard_move_tab_to_1(self): - self.action_controller("keyboard_move_tab_to_1") - - def _keyboard_move_tab_to_2(self): - self.action_controller("keyboard_move_tab_to_2") - - def _keyboard_prev_tab(self): - self.action_controller("keyboard_prev_tab") - - def _keyboard_next_tab(self): - self.action_controller("keyboard_next_tab") - - - # NOTE: These feel bad being here man... - def _keyboard_undo(self): - self.action_controller("keyboard_undo") - - def _keyboard_redo(self): - self.action_controller("keyboard_redo") - - def _toggle_highlight_line(self): - self.action_controller("toggle_highlight_line") - - - def _keyboard_insert_mark(self): - self.action_controller("keyboard_insert_mark") - - def _keyboard_move_lines_up(self): - self.action_controller("keyboard_move_lines_up") - - def _keyboard_move_lines_down(self): - self.action_controller("keyboard_move_lines_down") - - def _keyboard_clear_marks(self): - self.action_controller("keyboard_clear_marks") - def _keyboard_scale_up_text(self): self.action_controller("scale_up_text") def _keyboard_scale_down_text(self): - self.action_controller("scale_down_text") - - def _keyboard_save_file(self): - self.action_controller("save_file") - - def _keyboard_save_file_as(self): - self.action_controller("save_file_as") \ No newline at end of file + self.action_controller("scale_down_text") \ No newline at end of file diff --git a/src/core/widgets/base/notebook/key_input_controller.py b/src/core/widgets/base/notebook/key_input_controller.py new file mode 100644 index 0000000..b9140cc --- /dev/null +++ b/src/core/widgets/base/notebook/key_input_controller.py @@ -0,0 +1,68 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gdk', '3.0') +from gi.repository import Gdk + +# Application imports + + + +class KeyInputController: + def _key_press_event(self, widget, eve): + keyname = Gdk.keyval_name(eve.keyval) + modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK) + is_control = True if modifiers & Gdk.ModifierType.CONTROL_MASK else False + is_shift = True if modifiers & Gdk.ModifierType.SHIFT_MASK else False + + try: + is_alt = True if modifiers & Gdk.ModifierType.ALT_MASK else False + except Exception: + is_alt = True if modifiers & Gdk.ModifierType.MOD1_MASK else False + + + def _key_release_event(self, widget, eve): + keyname = Gdk.keyval_name(eve.keyval) + modifiers = Gdk.ModifierType(eve.get_state() & ~Gdk.ModifierType.LOCK_MASK) + is_control = True if modifiers & Gdk.ModifierType.CONTROL_MASK else False + is_shift = True if modifiers & Gdk.ModifierType.SHIFT_MASK else False + + try: + is_alt = True if modifiers & Gdk.ModifierType.ALT_MASK else False + except Exception: + is_alt = True if modifiers & Gdk.ModifierType.MOD1_MASK else False + + page_num, container, source_view = self.get_active_view() + if is_control: + if is_shift: + if keyname in ["Up", "Down"]: + if keyname == "Up": + self.keyboard_move_tab_to_1(page_num) + if keyname == "Down": + self.keyboard_move_tab_to_2(page_num) + + return True + + if keyname in ["w", "t", "o"]: + if keyname == "w": + self.close_tab(None, container, source_view) + if keyname == "t": + self._create_view() + if keyname == "o": + event_system.emit("open_files") + + return True + + if is_alt: + if keyname in ["Up", "Down", "Left", "Right"]: + if keyname == "Up": + self.keyboard_prev_tab(page_num) + if keyname == "Down": + self.keyboard_next_tab(page_num) + if keyname == "Left": + self.keyboard_move_tab_left(page_num) + if keyname == "Right": + self.keyboard_move_tab_right(page_num) + + return True diff --git a/src/core/widgets/base/sourceview/auto_indenter.py b/src/core/widgets/base/sourceview/auto_indenter.py deleted file mode 100644 index ead9ac7..0000000 --- a/src/core/widgets/base/sourceview/auto_indenter.py +++ /dev/null @@ -1,23 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('GtkSource', '4') -from gi.repository import GtkSource - -# Application imports - - - -# NOTE: GtkSource 5 allows for smart indent action by allowing us to override the default auto indent logic... -# In the long run this will be better because we can check not only for :, ;, { or other things but apply per language such as bash where -# there isn't a special char but words... -# class AutoIndenter(GtkSource.Indenter): -# def __init__(self): -# ... -# -# def indent(self, view, iter): -# ... -# -# def is_trigger(self, view, iter, modifier, keyval): -# print(iter.get_char()) diff --git a/src/core/widgets/base/sourceview/key_input_controller.py b/src/core/widgets/base/sourceview/key_input_controller.py index b182cca..866f43f 100644 --- a/src/core/widgets/base/sourceview/key_input_controller.py +++ b/src/core/widgets/base/sourceview/key_input_controller.py @@ -27,14 +27,10 @@ class KeyInputController: if is_control: if is_shift: - if keyname in [ "z", "Up", "Down", "Left", "Right" ]: - # NOTE: For now do like so for completion sake above. - if keyname in ["Left", "Right"]: - return False - + if keyname in [ "Up", "Down" ]: return True - if keyname in [ "slash", "Up", "Down", "z" ]: + if keyname in [ "slash", "Up", "Down", "m", "z", "y" ]: return True if is_alt: @@ -52,10 +48,12 @@ class KeyInputController: self.end_user_action(buffer) return True - + # NOTE: if a plugin recieves the call and handles, it will be the final decider for propigation return event_system.emit_and_await("autopairs", (keyname, is_control, is_alt, is_shift)) + + def _key_release_event(self, widget, eve): if self.freeze_multi_line_insert: return @@ -65,6 +63,57 @@ class KeyInputController: is_shift = True if modifiers & Gdk.ModifierType.SHIFT_MASK else False buffer = self.get_buffer() + try: + is_alt = True if modifiers & Gdk.ModifierType.ALT_MASK else False + except Exception: + is_alt = True if modifiers & Gdk.ModifierType.MOD1_MASK else False + + can_continue = self.can_proceed(keyname, is_control, is_shift, is_alt) + if not can_continue: + return can_continue + + + if is_control: + if is_shift: + if keyname in ["S"]: + if keyname == "S": + self.save_file_as() + + return True + + if keyname in ["z", "y", "m", "s", "h", "equal", "minus", "Up", "Down"]: + if keyname == "z": + self.keyboard_undo() + if keyname == "y": + self.keyboard_redo() + if keyname == "m": + self.keyboard_insert_mark() + if keyname == "s": + self.save_file() + if keyname == "h": + self.toggle_highlight_line() + + if keyname == "equal": + self.scale_up_text() + if keyname == "minus": + self.scale_down_text() + + if keyname == "Up": + self.keyboard_move_lines_up() + if keyname == "Down": + self.keyboard_move_lines_down() + + return True + + # Note: Sink these requets + if keyname in ["Slash"]: + return True + + if is_alt: + if keyname == "m": + self.keyboard_clear_marks() + + if keyname in {"Return", "Enter"}: if len(self._multi_insert_marks) > 0: self.begin_user_action(buffer) @@ -75,4 +124,20 @@ class KeyInputController: has_selection = buffer.get_has_selection() if not has_selection: - return self.insert_indent_handler(buffer) \ No newline at end of file + return self.insert_indent_handler(buffer) + + + def can_proceed(self, keyname, is_control, is_shift, is_alt): + if is_control: + if is_shift: + if keyname in ["Up", "Down"]: + return False + + if keyname in ["w", "t", "o"]: + return False + + if is_alt: + if keyname in ["Up", "Down", "Left", "Right"]: + return False + + return True \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/mixins/__init__.py b/src/core/widgets/base/sourceview/mixins/__init__.py new file mode 100644 index 0000000..c418b14 --- /dev/null +++ b/src/core/widgets/base/sourceview/mixins/__init__.py @@ -0,0 +1,3 @@ +""" + SourceView Mixins Module +""" \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/source_file_events_mixin.py b/src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py similarity index 85% rename from src/core/widgets/base/sourceview/source_file_events_mixin.py rename to src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py index e0c4881..92cb12d 100644 --- a/src/core/widgets/base/sourceview/source_file_events_mixin.py +++ b/src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py @@ -130,3 +130,34 @@ class FileEventsMixin: buffer.set_modified(False) return gfile + + + def _document_loaded(self, line: int = 0): + for provider in self._completion.get_providers(): + self._completion.remove_provider(provider) + + file = self._current_file.get_path() + buffer = self.get_buffer() + + word_completion = GtkSource.CompletionWords.new("word_completion") + word_completion.register(buffer) + self._completion.add_provider(word_completion) + + # TODO: actually load a meaningful provider based on file type... + # example_completion_provider = ExampleCompletionProvider() + # self._completion.add_provider(example_completion_provider) + + # py_completion_provider = PythonCompletionProvider(file) + # self._completion.add_provider(py_completion_provider) + self.got_to_line(buffer, line) + + + + + + + + + + + diff --git a/src/core/widgets/base/sourceview/source_mark_events_mixin.py b/src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py similarity index 98% rename from src/core/widgets/base/sourceview/source_mark_events_mixin.py rename to src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py index 46ef5a3..d5be743 100644 --- a/src/core/widgets/base/sourceview/source_mark_events_mixin.py +++ b/src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py @@ -11,7 +11,7 @@ from gi.repository import Gtk class MarkEventsMixin: - + def keyboard_insert_mark(self, target_iter = None, is_keyboard_insert = True): buffer = self.get_buffer() diff --git a/src/core/widgets/base/sourceview/source_view_dnd_mixin.py b/src/core/widgets/base/sourceview/mixins/source_view_dnd_mixin.py similarity index 100% rename from src/core/widgets/base/sourceview/source_view_dnd_mixin.py rename to src/core/widgets/base/sourceview/mixins/source_view_dnd_mixin.py diff --git a/src/core/widgets/base/sourceview/source_view.py b/src/core/widgets/base/sourceview/source_view.py index c4ca364..53c6c0e 100644 --- a/src/core/widgets/base/sourceview/source_view.py +++ b/src/core/widgets/base/sourceview/source_view.py @@ -12,15 +12,14 @@ from gi.repository import Gio from gi.repository import GtkSource # Application imports -# from .auto_indenter import AutoIndenter -from .key_input_controller import KeyInputController -from .source_view_events import SourceViewEventsMixin +from .source_view_controller import SourceViewControllerMixin + from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider from .custom_completion_providers.python_completion_provider import PythonCompletionProvider -class SourceView(KeyInputController, SourceViewEventsMixin, GtkSource.View): +class SourceView(SourceViewControllerMixin, GtkSource.View): def __init__(self): super(SourceView, self).__init__() @@ -46,7 +45,6 @@ class SourceView(KeyInputController, SourceViewEventsMixin, GtkSource.View): self._setup_styling() self._setup_signals() - self._set_up_dnd() self._subscribe_to_events() self._load_widgets() @@ -99,109 +97,4 @@ class SourceView(KeyInputController, SourceViewEventsMixin, GtkSource.View): ... def _load_widgets(self): - ... - - - def _document_loaded(self, line: int = 0): - for provider in self._completion.get_providers(): - self._completion.remove_provider(provider) - - file = self._current_file.get_path() - buffer = self.get_buffer() - - word_completion = GtkSource.CompletionWords.new("word_completion") - word_completion.register(buffer) - self._completion.add_provider(word_completion) - - # TODO: actually load a meaningful provider based on file type... - # example_completion_provider = ExampleCompletionProvider() - # self._completion.add_provider(example_completion_provider) - - # py_completion_provider = PythonCompletionProvider(file) - # self._completion.add_provider(py_completion_provider) - self.got_to_line(buffer, line) - - - def _create_default_tag(self, buffer): - general_style_tag = buffer.create_tag('general_style') - general_style_tag.set_property('size', 100) - general_style_tag.set_property('scale', 100) - - def _is_modified(self, *args): - buffer = self.get_buffer() - - if not self._loading_file: - event_system.emit("buffer_changed", (buffer, )) - else: - event_system.emit("buffer_changed_first_load", (buffer, )) - - self.update_cursor_position(buffer) - - def _insert_text(self, buffer, location_itr, text_str, len_int): - if self.freeze_multi_line_insert: return - - self.begin_user_action(buffer) - with buffer.freeze_notify(): - GLib.idle_add(self._update_multi_line_markers, *(buffer, text_str,)) - - def _buffer_modified_changed(self, buffer): - tab_widget = self.get_parent().get_tab_widget() - tab_widget.set_status(changed = True if buffer.get_modified() else False) - - - def _button_press_event(self, widget = None, eve = None, user_data = None): - if eve.type == Gdk.EventType.BUTTON_PRESS and eve.button == 1 : # l-click - if eve.state & Gdk.ModifierType.CONTROL_MASK: - self.button_press_insert_mark(eve) - return True - else: - self.keyboard_clear_marks() - elif eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 3: # r-click - ... - - def _scroll_event(self, widget, eve): - accel_mask = Gtk.accelerator_get_default_mod_mask() - x, y, z = eve.get_scroll_deltas() - if eve.state & accel_mask == Gdk.ModifierType.CONTROL_MASK: - buffer = self.get_buffer() - if z > 0: - self.scale_down_text(buffer) - else: - self.scale_up_text(buffer) - - return True - - if eve.state & accel_mask == Gdk.ModifierType.SHIFT_MASK: - adjustment = self.get_hadjustment() - current_val = adjustment.get_value() - step_val = adjustment.get_step_increment() - - if z > 0: # NOTE: scroll left - adjustment.set_value(current_val - step_val * 2) - else: # NOTE: scroll right - adjustment.set_value(current_val + step_val * 2) - - return True - - def _focus_in_event(self, widget, eve = None): - event_system.emit("set_active_src_view", (self,)) - self.get_parent().get_parent().is_editor_focused = True - - def _on_widget_focus(self, widget, eve = None): - tab_view = self.get_parent().get_parent() - path = self._current_file if self._current_file else "" - - event_system.emit('focused_target_changed', (tab_view.NAME,)) - event_system.emit("set_path_label", (path,)) - event_system.emit("set_encoding_label") - event_system.emit("set_file_type_label", (self._current_filetype,)) - - return False - - def _on_cursor_move(self, buffer, cursor_iter, mark, user_data = None): - if mark != buffer.get_insert(): return - - self.update_cursor_position(buffer) - - # NOTE: Not sure but this might not be efficient if the map reloads the same view... - event_system.emit(f"set_source_view", (self,)) \ No newline at end of file + self._set_up_dnd() diff --git a/src/core/widgets/base/sourceview/source_view_controller.py b/src/core/widgets/base/sourceview/source_view_controller.py new file mode 100644 index 0000000..0429782 --- /dev/null +++ b/src/core/widgets/base/sourceview/source_view_controller.py @@ -0,0 +1,129 @@ +# Python imports + +# Lib imports +import gi +gi.require_version('Gtk', '3.0') +from gi.repository import Gtk + +# Application imports +from .key_input_controller import KeyInputController +from .source_view_events import SourceViewEvents + + + +class SourceViewControllerMixin(KeyInputController, SourceViewEvents): + def get_current_filepath(self): + return self._current_file + + def get_filetype(self): + return self._current_filetype + + def set_buffer_language(self, buffer, language = "python3"): + buffer.set_language( self._language_manager.get_language(language) ) + + def set_buffer_style(self, buffer, style = settings.theming.syntax_theme): + buffer.set_style_scheme( self._style_scheme_manager.get_scheme(style) ) + + + def update_cursor_position(self, buffer = None): + buffer = self.get_buffer() if not buffer else buffer + iter = buffer.get_iter_at_mark( buffer.get_insert() ) + chars = iter.get_offset() + row = iter.get_line() + 1 + col = self.get_visual_column(iter) + 1 + + event_system.emit("set_line_char_label", (f"{row}:{col}",)) + + def update_labels(self, gfile = None): + if not gfile: return + + tab_widget = self.get_parent().get_tab_widget() + tab_widget.set_tab_label(self._current_filename) + self.set_bottom_labels(gfile) + + def set_bottom_labels(self, gfile = None): + if not gfile: return + + event_system.emit("set_bottom_labels", (gfile, None, self._current_filetype, None)) + self.update_cursor_position() + + def got_to_line(self, buffer = None, line: int = 0): + buffer = self.get_buffer() if not buffer else buffer + line_itr = buffer.get_iter_at_line(line) + char_iter = buffer.get_iter_at_line_offset(line, line_itr.get_bytes_in_line()) + + buffer.place_cursor(char_iter) + if not buffer.get_mark("starting_cursor"): + buffer.create_mark("starting_cursor", char_iter, True) + self.scroll_to_mark( buffer.get_mark("starting_cursor"), 0.0, True, 0.0, 0.0 ) + + def toggle_highlight_line(self, widget = None, eve = None): + self.set_highlight_current_line( not self.get_highlight_current_line() ) + + def scale_up_text(self, buffer = None, scale_step = 10): + if not buffer: + buffer = self.get_buffer() + + ctx = self.get_style_context() + + if self._px_value < 99: + self._px_value += 1 + ctx.add_class(f"px{self._px_value}") + + # NOTE: Hope to bring this or similar back after we decouple scaling issues coupled with the miniview. + # tag_table = buffer.get_tag_table() + # start_itr = buffer.get_start_iter() + # end_itr = buffer.get_end_iter() + # tag = tag_table.lookup('general_style') + # + # tag.set_property('scale', tag.get_property('scale') + scale_step) + # buffer.apply_tag(tag, start_itr, end_itr) + + def scale_down_text(self, buffer = None, scale_step = 10): + if not buffer: + buffer = self.get_buffer() + + ctx = self.get_style_context() + + if self._px_value > 1: + ctx.remove_class(f"px{self._px_value}") + self._px_value -= 1 + ctx.add_class(f"px{self._px_value}") + + # NOTE: Hope to bring this or similar back after we decouple scaling issues coupled with the miniview. + # tag_table = buffer.get_tag_table() + # start_itr = buffer.get_start_iter() + # end_itr = buffer.get_end_iter() + # tag = tag_table.lookup('general_style') + # + # tag.set_property('scale', tag.get_property('scale') - scale_step) + # buffer.apply_tag(tag, start_itr, end_itr) + + def keyboard_undo(self): + buffer = self.get_buffer() + buffer.undo() + + def keyboard_redo(self): + buffer = self.get_buffer() + buffer.redo() + + def keyboard_move_lines_up(self): + buffer = self.get_buffer() + + self.begin_user_action(buffer) + + self.emit("move-lines", *(False,)) + # unindent_lines + # self.emit("move-words", *(self, 4,)) + + self.end_user_action(buffer) + + def keyboard_move_lines_down(self): + buffer = self.get_buffer() + + self.begin_user_action(buffer) + + self.emit("move-lines", *(True,)) + # self.emit("move-words", *(self, -4,)) + + self.end_user_action(buffer) \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/source_view_events.py b/src/core/widgets/base/sourceview/source_view_events.py index 61de5f9..6ea87bd 100644 --- a/src/core/widgets/base/sourceview/source_view_events.py +++ b/src/core/widgets/base/sourceview/source_view_events.py @@ -3,121 +3,98 @@ # Lib imports import gi gi.require_version('Gtk', '3.0') +gi.require_version('Gdk', '3.0') from gi.repository import Gtk +from gi.repository import Gdk +from gi.repository import GLib # Application imports -from .source_view_dnd_mixin import SourceViewDnDMixin -from .source_file_events_mixin import FileEventsMixin -from .source_mark_events_mixin import MarkEventsMixin +from .mixins.source_view_dnd_mixin import SourceViewDnDMixin +from .mixins.source_file_events_mixin import FileEventsMixin +from .mixins.source_mark_events_mixin import MarkEventsMixin +class SourceViewEvents(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin): + def _create_default_tag(self, buffer): + general_style_tag = buffer.create_tag('general_style') + general_style_tag.set_property('size', 100) + general_style_tag.set_property('scale', 100) -class SourceViewEventsMixin(SourceViewDnDMixin, MarkEventsMixin, FileEventsMixin): - def get_current_filepath(self): - return self._current_file - - def get_filetype(self): - return self._current_filetype - - def set_buffer_language(self, buffer, language = "python3"): - buffer.set_language( self._language_manager.get_language(language) ) - - def set_buffer_style(self, buffer, style = settings.theming.syntax_theme): - buffer.set_style_scheme( self._style_scheme_manager.get_scheme(style) ) - - def toggle_highlight_line(self, widget = None, eve = None): - self.set_highlight_current_line( not self.get_highlight_current_line() ) - - def scale_up_text(self, buffer, scale_step = 10): - ctx = self.get_style_context() - - if self._px_value < 99: - self._px_value += 1 - ctx.add_class(f"px{self._px_value}") - - # NOTE: Hope to bring this or similar back after we decouple scaling issues coupled with the miniview. - # tag_table = buffer.get_tag_table() - # start_itr = buffer.get_start_iter() - # end_itr = buffer.get_end_iter() - # tag = tag_table.lookup('general_style') - # - # tag.set_property('scale', tag.get_property('scale') + scale_step) - # buffer.apply_tag(tag, start_itr, end_itr) - - def scale_down_text(self, buffer, scale_step = 10): - ctx = self.get_style_context() - - if self._px_value > 1: - ctx.remove_class(f"px{self._px_value}") - self._px_value -= 1 - ctx.add_class(f"px{self._px_value}") - - # NOTE: Hope to bring this or similar back after we decouple scaling issues coupled with the miniview. - # tag_table = buffer.get_tag_table() - # start_itr = buffer.get_start_iter() - # end_itr = buffer.get_end_iter() - # tag = tag_table.lookup('general_style') - # - # tag.set_property('scale', tag.get_property('scale') - scale_step) - # buffer.apply_tag(tag, start_itr, end_itr) - - def update_cursor_position(self, buffer = None): - buffer = self.get_buffer() if not buffer else buffer - iter = buffer.get_iter_at_mark( buffer.get_insert() ) - chars = iter.get_offset() - row = iter.get_line() + 1 - col = self.get_visual_column(iter) + 1 - - event_system.emit("set_line_char_label", (f"{row}:{col}",)) - - def got_to_line(self, buffer = None, line: int = 0): - buffer = self.get_buffer() if not buffer else buffer - line_itr = buffer.get_iter_at_line(line) - char_iter = buffer.get_iter_at_line_offset(line, line_itr.get_bytes_in_line()) - - buffer.place_cursor(char_iter) - if not buffer.get_mark("starting_cursor"): - buffer.create_mark("starting_cursor", char_iter, True) - self.scroll_to_mark( buffer.get_mark("starting_cursor"), 0.0, True, 0.0, 0.0 ) - - def keyboard_undo(self): + def _is_modified(self, *args): buffer = self.get_buffer() - buffer.undo() - def keyboard_redo(self): - buffer = self.get_buffer() - buffer.redo() + if not self._loading_file: + event_system.emit("buffer_changed", (buffer, )) + else: + event_system.emit("buffer_changed_first_load", (buffer, )) - def keyboard_move_lines_up(self): - buffer = self.get_buffer() + self.update_cursor_position(buffer) + + def _insert_text(self, buffer, location_itr, text_str, len_int): + if self.freeze_multi_line_insert: return self.begin_user_action(buffer) + with buffer.freeze_notify(): + GLib.idle_add(self._update_multi_line_markers, *(buffer, text_str,)) - self.emit("move-lines", *(False,)) - # unindent_lines - # self.emit("move-words", *(self, 4,)) - - self.end_user_action(buffer) - - def keyboard_move_lines_down(self): - buffer = self.get_buffer() - - self.begin_user_action(buffer) - - self.emit("move-lines", *(True,)) - # self.emit("move-words", *(self, -4,)) - - self.end_user_action(buffer) - - def update_labels(self, gfile = None): - if not gfile: return - + def _buffer_modified_changed(self, buffer): tab_widget = self.get_parent().get_tab_widget() - tab_widget.set_tab_label(self._current_filename) - self.set_bottom_labels(gfile) + tab_widget.set_status(changed = True if buffer.get_modified() else False) - def set_bottom_labels(self, gfile = None): - if not gfile: return - event_system.emit("set_bottom_labels", (gfile, None, self._current_filetype, None)) - self.update_cursor_position() \ No newline at end of file + def _button_press_event(self, widget = None, eve = None, user_data = None): + if eve.type == Gdk.EventType.BUTTON_PRESS and eve.button == 1 : # l-click + if eve.state & Gdk.ModifierType.CONTROL_MASK: + self.button_press_insert_mark(eve) + return True + else: + self.keyboard_clear_marks() + elif eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 3: # r-click + ... + + def _scroll_event(self, widget, eve): + accel_mask = Gtk.accelerator_get_default_mod_mask() + x, y, z = eve.get_scroll_deltas() + if eve.state & accel_mask == Gdk.ModifierType.CONTROL_MASK: + buffer = self.get_buffer() + if z > 0: + self.scale_down_text(buffer) + else: + self.scale_up_text(buffer) + + return True + + if eve.state & accel_mask == Gdk.ModifierType.SHIFT_MASK: + adjustment = self.get_hadjustment() + current_val = adjustment.get_value() + step_val = adjustment.get_step_increment() + + if z > 0: # NOTE: scroll left + adjustment.set_value(current_val - step_val * 2) + else: # NOTE: scroll right + adjustment.set_value(current_val + step_val * 2) + + return True + + def _focus_in_event(self, widget, eve = None): + event_system.emit("set_active_src_view", (self,)) + self.get_parent().get_parent().is_editor_focused = True + + def _on_widget_focus(self, widget, eve = None): + tab_view = self.get_parent().get_parent() + path = self._current_file if self._current_file else "" + + event_system.emit('focused_target_changed', (tab_view.NAME,)) + event_system.emit("set_path_label", (path,)) + event_system.emit("set_encoding_label") + event_system.emit("set_file_type_label", (self._current_filetype,)) + + return False + + def _on_cursor_move(self, buffer, cursor_iter, mark, user_data = None): + if mark != buffer.get_insert(): return + + self.update_cursor_position(buffer) + + # NOTE: Not sure but this might not be efficient if the map reloads the same view... + event_system.emit(f"set_source_view", (self,)) \ No newline at end of file