diff --git a/src/core/containers/editors_paned.py b/src/core/containers/editors_paned.py index da04f99..fa82071 100644 --- a/src/core/containers/editors_paned.py +++ b/src/core/containers/editors_paned.py @@ -6,7 +6,6 @@ gi.require_version('Gtk', '3.0') from gi.repository import Gtk # Application imports -from ..widgets.base.notebook.editor_notebook import EditorNotebook from ..widgets.base.webkit.editor import Editor @@ -34,10 +33,7 @@ class EditorsPaned(Gtk.Paned): def _load_widgets(self): self.add1( Editor() ) - self.add2( Editor() ) - - # self.add1( EditorNotebook() ) - # self.add2( EditorNotebook() ) + # self.add2( Editor() ) def _update_paned_handle(self): rect = self.get_allocation() @@ -49,4 +45,4 @@ class EditorsPaned(Gtk.Paned): except: ... - self.set_position(size) + self.set_position(size) \ No newline at end of file diff --git a/src/core/controllers/base_controller.py b/src/core/controllers/base_controller.py index 84e55ee..cf3afe5 100644 --- a/src/core/controllers/base_controller.py +++ b/src/core/controllers/base_controller.py @@ -10,17 +10,16 @@ from gi.repository import Gdk from gi.repository import GLib # Application imports -from ..mixins.signals_mixins import SignalsMixins +from libs.mixins.keyboard_signals_mixin import KeyboardSignalsMixin from ..containers.base_container import BaseContainer -# from ..containers.core_widget import CoreWidget from .base_controller_data import BaseControllerData from .bridge_controller import BridgeController -class BaseController(SignalsMixins, BaseControllerData): +class BaseController(KeyboardSignalsMixin, BaseControllerData): def __init__(self, args, unknownargs): messages = [] for arg in unknownargs + [args.new_tab,]: diff --git a/src/core/controllers/bridge_controller.py b/src/core/controllers/bridge_controller.py index 4affce8..6fc9fdd 100644 --- a/src/core/controllers/bridge_controller.py +++ b/src/core/controllers/bridge_controller.py @@ -11,6 +11,7 @@ class BridgeController: def __init__(self): self.opened_files = {} + self.originator = -1 self._setup_signals() self._subscribe_to_events() @@ -21,9 +22,27 @@ class BridgeController: def _subscribe_to_events(self): event_system.subscribe("handle_bridge_event", self.handle_bridge_event) + event_system.subscribe(f"keyboard_open_file", self.keyboard_open_file) + event_system.subscribe(f"keyboard_scale_up_text", self.keyboard_scale_up_text) + event_system.subscribe(f"keyboard_scale_down_text", self.keyboard_scale_down_text) + event_system.subscribe(f"toggle_highlight_line", self.toggle_highlight_line) + + def keyboard_open_file(self, gfiles): + event_system.emit(f"set_pre_drop_dnd_{self.originator}", (gfiles,)) + + def keyboard_scale_up_text(self): + event_system.emit(f"keyboard_scale_up_text_{self.originator}") + + def keyboard_scale_down_text(self): + event_system.emit(f"keyboard_scale_down_text_{self.originator}") + + def toggle_highlight_line(self): + event_system.emit(f"toggle_highlight_line_{self.originator}") def handle_bridge_event(self, event): + self.originator = event.originator + match event.topic: case "save": event_system.emit(f"handle_file_event_{event.originator}", (event,)) @@ -35,6 +54,15 @@ class BridgeController: event_system.emit(f"handle_file_event_{event.originator}", (event,)) case "open_file": event_system.emit(f"handle_file_event_{event.originator}", (event,)) + case "tggl_top_main_menubar": + event_system.emit("tggl_top_main_menubar") + case "set_info_labels": + content = base64.b64decode( event.content.encode() ).decode("utf-8") + path = event.fpath + line_char = content + file_type = event.ftype + encoding_type = "utf-8" + event_system.emit(f"set_info_labels", (path, line_char, file_type, encoding_type,)) case "error": content = base64.b64decode( event.content.encode() ).decode("utf-8") logger.info(content) diff --git a/src/core/mixins/__init__.py b/src/core/mixins/__init__.py deleted file mode 100644 index 636992f..0000000 --- a/src/core/mixins/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - Mixins module -""" diff --git a/src/core/mixins/signals/__init__.py b/src/core/mixins/signals/__init__.py deleted file mode 100644 index 03c3ec2..0000000 --- a/src/core/mixins/signals/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - Signals module -""" diff --git a/src/core/mixins/signals_mixins.py b/src/core/mixins/signals_mixins.py deleted file mode 100644 index 52e970e..0000000 --- a/src/core/mixins/signals_mixins.py +++ /dev/null @@ -1,12 +0,0 @@ -# Python imports - -# Lib imports -from .signals.keyboard_signals_mixin import KeyboardSignalsMixin - -# Application imports - - - - -class SignalsMixins(KeyboardSignalsMixin): - ... diff --git a/src/core/widgets/base/general_info_widget.py b/src/core/widgets/base/general_info_widget.py index f34ff9b..424c74a 100644 --- a/src/core/widgets/base/general_info_widget.py +++ b/src/core/widgets/base/general_info_widget.py @@ -35,7 +35,7 @@ class GeneralInfoWidget: ... def _subscribe_to_events(self): - event_system.subscribe("set_bottom_labels", self.set_bottom_labels) + event_system.subscribe("set_info_labels", self.set_info_labels) event_system.subscribe("set_path_label", self._set_path_label) event_system.subscribe("set_encoding_label", self._set_encoding_label) event_system.subscribe("set_line_char_label", self._set_line_char_label) @@ -63,7 +63,7 @@ class GeneralInfoWidget: builder.get_object("core_widget").add(self.bottom_status_info) - def set_bottom_labels(self, path = None, line_char = None, file_type = None, encoding_type = None): + def set_info_labels(self, path = None, line_char = None, file_type = None, encoding_type = None): self._set_path_label(path) self._set_line_char_label(line_char) self._set_file_type_label(file_type) diff --git a/src/core/widgets/base/notebook/__init__.py b/src/core/widgets/base/notebook/__init__.py deleted file mode 100644 index dc54ccc..0000000 --- a/src/core/widgets/base/notebook/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - Notebook Module -""" diff --git a/src/core/widgets/base/notebook/editor_controller.py b/src/core/widgets/base/notebook/editor_controller.py deleted file mode 100644 index 8ada7a0..0000000 --- a/src/core/widgets/base/notebook/editor_controller.py +++ /dev/null @@ -1,33 +0,0 @@ -# Python imports - -# Lib imports - -# Application imports -from .key_input_controller import KeyInputController -from .editor_events import EditorEventsMixin - - - -class EditorControllerMixin(KeyInputController, EditorEventsMixin): - def get_active_view(self): - page_num = self.get_current_page() - container = self.get_nth_page( page_num ) - source_view = container.get_source_view() - return page_num, container, source_view - - def action_controller(self, action = "", query = ""): - # NOTE: Not efficent here as multiple same calls - if not self.is_editor_focused: # TODO: Find way to converge this - return - - page_num, container, source_view = self.get_active_view() - - # NOTE: These feel bad being here man... - if action == "scale_up_text": - self.scale_up_text(source_view) - if action == "scale_down_text": - self.scale_down_text(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) \ 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 deleted file mode 100644 index 4e9a82c..0000000 --- a/src/core/widgets/base/notebook/editor_events.py +++ /dev/null @@ -1,160 +0,0 @@ -# Python imports - -# Lib imports - -# Application imports -from ..sourceview_container import SourceViewContainer - - - -class EditorEventsMixin: - def create_view(self, widget = None, eve = None, gfile = None, line: int = 0): - container = SourceViewContainer(self.close_tab) - page_num = self.append_page(container, container.get_tab_widget()) - - self.set_tab_detachable(container, True) - self.set_tab_reorderable(container, True) - - self.show_all() - self.set_current_page(page_num) - - if gfile: - source_view = container.get_source_view() - source_view.open_file(gfile, line) - source_view.grab_focus() - - def open_file(self, gfile): - page_num = self.get_current_page() - container = self.get_nth_page( page_num ) - source_view = container.get_source_view() - - if source_view._current_filename == "": - source_view.open_file(gfile) - else: - self.create_view(None, None, gfile) - - # Note: Need to get parent instead given we pass the close_tab method - # from a potentially former notebook. - def close_tab(self, button, container, source_view, eve = None): - notebook = container.get_parent() - if notebook.NAME == "notebook_1" and notebook.get_n_pages() == 1: - return - - file_type = source_view.get_filetype() - if not file_type == "buffer": - uri = source_view.get_current_file().get_uri() - event_system.emit("textDocument/didClose", (file_type, uri,)) - - page_num = notebook.page_num(container) - source_view._cancel_current_file_watchers() - notebook.remove_page(page_num) - - if notebook.NAME == "notebook_2" and notebook.get_n_pages() == 0: - notebook.hide() - event_system.emit("focused_target_changed", ("notebook_1",)) - - def keyboard_prev_tab(self, page_num): - page_num = self.get_n_pages() - 1 if page_num == 0 else page_num - 1 - self.set_current_page(page_num) - - def keyboard_next_tab(self, page_num): - page_num = 0 if self.get_n_pages() - 1 == page_num else page_num + 1 - self.set_current_page(page_num) - - def keyboard_focus_1st_pane(self): - if self.NAME == "notebook_1": - return - - notebook = self.builder.get_object("notebook_1") - i = notebook.get_current_page() - page = notebook.get_nth_page(i) - - self.set_page_focus(page, notebook, self) - - def keyboard_focus_2nd_pane(self): - if self.NAME == "notebook_2": - return - - notebook = self.builder.get_object("notebook_2") - if not notebook.is_visible(): - notebook.show() - notebook.create_view() - event_system.emit("update_paned_handle") - - i = notebook.get_current_page() - page = notebook.get_nth_page(i) - - self.set_page_focus(page, notebook, self) - - def keyboard_move_tab_to_1(self, page_num): - if self.NAME == "notebook_1": return - - notebook = self.builder.get_object("notebook_1") - page = self.get_nth_page(page_num) - tab = page.get_tab_widget() - - self.detach_tab(page) - notebook.show() - notebook.insert_page(page, tab, -1) - - if self.get_n_pages() == 0: - self.hide() - - self.set_page_focus(page, notebook, self) - - def keyboard_move_tab_to_2(self, page_num): - if self.NAME == "notebook_2": - return - - if self.NAME == "notebook_1" and self.get_n_pages() == 1: - return - - notebook = self.builder.get_object("notebook_2") - page = self.get_nth_page(page_num) - tab = page.get_tab_widget() - - self.detach_tab(page) - if not notebook.is_visible(): - notebook.show() - event_system.emit("update_paned_handle") - - notebook.insert_page(page, tab, -1) - - self.set_page_focus(page, notebook, self) - - def set_page_focus(self, page, notebook, old_notebook): - old_notebook.is_editor_focused = False - notebook.set_current_page(-1) - page.get_children()[0].grab_focus() - notebook.is_editor_focused = True - - ctx = old_notebook.get_style_context() - ctx.remove_class("notebook-selected-focus") - - ctx = notebook.get_style_context() - ctx.add_class("notebook-selected-focus") - - def keyboard_move_tab_left(self, page_num): - page = self.get_nth_page(page_num) - page_num = self.get_n_pages() - 1 if page_num == 0 else page_num - 1 - self.reorder_child(page, page_num) - - def keyboard_move_tab_right(self, page_num): - page = self.get_nth_page(page_num) - page_num = 0 if self.get_n_pages() - 1 == page_num else page_num + 1 - self.reorder_child(page, page_num) - - - # NOTE: These feel bad being here man... - 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 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 diff --git a/src/core/widgets/base/notebook/editor_notebook.py b/src/core/widgets/base/notebook/editor_notebook.py deleted file mode 100644 index afc3d95..0000000 --- a/src/core/widgets/base/notebook/editor_notebook.py +++ /dev/null @@ -1,142 +0,0 @@ -# Python imports - -# 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 Gio - -# Application imports -from .editor_controller import EditorControllerMixin - - - -# NOTE: https://github.com/Axel-Erfurt/TextEdit/tree/b65f09be945196eb05bef83d81a6abcd129b4eb0 -class EditorNotebook(EditorControllerMixin, Gtk.Notebook): - ccount = 0 - - def __new__(cls, *args, **kwargs): - obj = super(EditorNotebook, cls).__new__(cls) - cls.ccount += 1 - - return obj - - def __init__(self): - super(EditorNotebook, self).__init__() - - self.NAME = f"notebook_{self.ccount}" - self.builder = settings_manager.get_builder() - self.is_editor_focused = False - - self.set_group_name("editor_widget") - self.builder.expose_object(self.NAME, self) - - self._setup_styling() - self._setup_signals() - self._subscribe_to_events() - self._load_widgets() - - self.show_all() - - if self.NAME == "notebook_1": - self.is_editor_focused = True - - if self.NAME == "notebook_2": - self.hide() - - - def _setup_styling(self): - self.set_scrollable(True) - self.set_vexpand(True) - self.set_hexpand(True) - - 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_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_focus_1st_pane", self.keyboard_focus_1st_pane) - event_system.subscribe("keyboard_focus_2nd_pane", self.keyboard_focus_2nd_pane) - - 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 - if self.is_editor_focused: - self.grab_focus() - - def _add_action_widgets(self): - start_box = Gtk.Box() - end_box = Gtk.Box() - - add_btn = Gtk.Button() - add_btn.set_image( Gtk.Image.new_from_icon_name("add", 4) ) - add_btn.set_always_show_image(True) - add_btn.connect("released", self.create_view) - - end_box.add(add_btn) - - start_box.show_all() - end_box.show_all() - - # PACKTYPE: 0 Start, 1 = End - self.set_action_widget(start_box, 0) - self.set_action_widget(end_box, 1) - - def _switch_page_update(self, notebook, page, page_num): - source_view = page.get_source_view() - gfile = source_view.get_current_file() - - if not gfile: - event_system.emit("set_path_label", ("",)) - event_system.emit("set_file_type_label", (source_view._current_filetype,)) - else: - source_view.load_file_info(gfile) - source_view.update_cursor_position() - source_view.set_bottom_labels(gfile) - - event_system.emit(f"set_source_view", (source_view,)) - - def _create_view(self, gfile = None, line: int = 0): - if not self.is_editor_focused: # TODO: Find way to converge this - return - - if isinstance(gfile, str): - parts = gfile.split(":") - gfile = Gio.File.new_for_path(parts[0]) - try: - line = int(parts[1]) if len(parts) > 1 else 0 - except Exception: - ... - - self.create_view(None, None, gfile, line) - - def _keyboard_open_file(self, gfile): - if not self.is_editor_focused: # TODO: Find way to converge this - return - - self.open_file(gfile) - - def _keyboard_scale_up_text(self): - self.action_controller("scale_up_text") - - def _keyboard_scale_down_text(self): - 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 deleted file mode 100644 index 21f21be..0000000 --- a/src/core/widgets/base/notebook/key_input_controller.py +++ /dev/null @@ -1,69 +0,0 @@ -# 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": - page_num, container, source_view = self.get_active_view() - event_system.emit("open_files", (source_view,)) - - 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 \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/__init__.py b/src/core/widgets/base/sourceview/__init__.py deleted file mode 100644 index 619f9a0..0000000 --- a/src/core/widgets/base/sourceview/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - SourceView Module -""" diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/__init__.py b/src/core/widgets/base/sourceview/custom_completion_providers/__init__.py deleted file mode 100644 index fdff2e4..0000000 --- a/src/core/widgets/base/sourceview/custom_completion_providers/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - Custom Completion Providers Module -""" diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py b/src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py deleted file mode 100644 index a363516..0000000 --- a/src/core/widgets/base/sourceview/custom_completion_providers/example_completion_provider.py +++ /dev/null @@ -1,74 +0,0 @@ -# Python imports -import re - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('GtkSource', '4') - -from gi.repository import Gtk -from gi.repository import GtkSource -from gi.repository import GObject - -# Application imports - - - -class ExampleCompletionProvider(GObject.GObject, GtkSource.CompletionProvider): - """ - This is a custom Completion Example Provider. - # NOTE: used information from here --> https://warroom.rsmus.com/do-that-auto-complete/ - """ - __gtype_name__ = 'CustomProvider' - - def __init__(self): - GObject.Object.__init__(self) - - def do_get_name(self): - """ Returns: a new string containing the name of the provider. """ - return _('ExampleProvider') - - def do_match(self, context): - """ Get whether the provider match the context of completion detailed in context. """ - # NOTE: True for debugging but context needs to normally get checked for actual usage needs. - # TODO: Fix me - return True - - def do_populate(self, context): - """ - In this instance, it will do 2 things: - 1) always provide Hello World! (Not ideal but an option so its in the example) - 2) Utilizes the Gtk.TextIter from the TextBuffer to determine if there is a jinja - example of '{{ custom.' if so it will provide you with the options of foo and bar. - If selected it will insert foo }} or bar }}, completing your syntax... - - PLEASE NOTE the GtkTextIter Logic and regex are really rough and should be adjusted and tuned - """ - - proposals = [ - # GtkSource.CompletionItem(label='Hello World!', text = 'Hello World!', icon = None, info = None) # NOTE: Always proposed... - ] - - # Gtk Versions differ on get_iter responses... - end_iter = context.get_iter() - if not isinstance(end_iter, Gtk.TextIter): - _, end_iter = context.get_iter() - - if end_iter: - buf = end_iter.get_buffer() - mov_iter = end_iter.copy() - if mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY): - mov_iter, _ = mov_iter.backward_search('{{', Gtk.TextSearchFlags.VISIBLE_ONLY) - left_text = buf.get_text(mov_iter, end_iter, True) - else: - left_text = '' - - if re.match(r'.*\{\{\s*custom\.$', left_text): - proposals.append( - GtkSource.CompletionItem(label='foo', text='foo }}') # optionally proposed based on left search via regex - ) - proposals.append( - GtkSource.CompletionItem(label='bar', text='bar }}') # optionally proposed based on left search via regex - ) - - context.add_proposals(self, proposals, True) \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/lsp_completion_provider.py b/src/core/widgets/base/sourceview/custom_completion_providers/lsp_completion_provider.py deleted file mode 100644 index 652cdae..0000000 --- a/src/core/widgets/base/sourceview/custom_completion_providers/lsp_completion_provider.py +++ /dev/null @@ -1,91 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('GtkSource', '4') - -from gi.repository import Gtk -from gi.repository import GtkSource -from gi.repository import GObject - -# Application imports - - - -class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider): - """ - This code is an LSP code completion plugin for Newton. - # NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi - """ - __gtype_name__ = 'LSPProvider' - - def __init__(self, source_view): - GObject.Object.__init__(self) - - self._theme = Gtk.IconTheme.get_default() - self._source_view = source_view - - - def do_get_name(self): - return "LSP Code Completion" - - def get_iter_correctly(self, context): - return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter() - - def do_match(self, context): - iter = self.get_iter_correctly(context) - buffer = iter.get_buffer() - if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']: - return False - - event_system.emit("textDocument/completion", (self._source_view, context, self.do_populate)) - return True - - def do_get_priority(self): - return 1 - - def do_get_activation(self): - return GtkSource.CompletionActivation.INTERACTIVE - - def do_populate(self, context, result = None): - proposals = [] - if result: - if not result.items is None: - for item in result.items: - proposals.append( self.create_completion_item(item) ) - else: - proposals.append( self.create_completion_item(result) ) - - context.add_proposals(self, proposals, True) - - def get_icon_for_type(self, _type): - try: - return self._theme.load_icon(icon_names[_type.lower()], 16, 0) - except: - ... - - try: - return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0) - except: - ... - - return None - - def create_completion_item(self, item): - comp_item = GtkSource.CompletionItem.new() - comp_item.set_label(item.label) - - if item.textEdit: - if isinstance(item.textEdit, dict): - comp_item.set_text(item.textEdit["newText"]) - else: - comp_item.set_text(item.textEdit) - else: - comp_item.set_text(item.insertText) - - comp_item.set_icon( self.get_icon_for_type(item.kind) ) - comp_item.set_info(item.documentation) - - - return comp_item diff --git a/src/core/widgets/base/sourceview/custom_completion_providers/python_completion_provider.py b/src/core/widgets/base/sourceview/custom_completion_providers/python_completion_provider.py deleted file mode 100644 index d8268fe..0000000 --- a/src/core/widgets/base/sourceview/custom_completion_providers/python_completion_provider.py +++ /dev/null @@ -1,108 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('GtkSource', '4') - -from gi.repository import Gtk -from gi.repository import GtkSource -from gi.repository import GObject - -import jedi -from jedi.api import Script - -# Application imports - - - -# FIXME: Find real icon names... -icon_names = { - 'import': '', - 'module': '', - 'class': '', - 'function': '', - 'statement': '', - 'param': '' -} - - -class Jedi: - def get_script(file, doc_text): - return Script(code = doc_text, path = file) - - -class PythonCompletionProvider(GObject.Object, GtkSource.CompletionProvider): - """ - This code is A python code completion plugin for Newton. - # NOTE: Some code pulled/referenced from here --> https://github.com/isamert/gedi - """ - __gtype_name__ = 'PythonProvider' - - def __init__(self, file): - GObject.Object.__init__(self) - self._theme = Gtk.IconTheme.get_default() - self._file = file - - def do_get_name(self): - return "Python Code Completion" - - def get_iter_correctly(self, context): - return context.get_iter()[1] if isinstance(context.get_iter(), tuple) else context.get_iter() - - def do_match(self, context): - iter = self.get_iter_correctly(context) - iter.backward_char() - - buffer = iter.get_buffer() - if buffer.get_context_classes_at_iter(iter) != ['no-spell-check']: - return False - - ch = iter.get_char() - # NOTE: Look to re-add or apply supprting logic to use spaces - # As is it slows down the editor in certain contexts... - # if not (ch in ('_', '.', ' ') or ch.isalnum()): - if not (ch in ('_', '.') or ch.isalnum()): - return False - - return True - - def do_get_priority(self): - return 1 - - def do_get_activation(self): - return GtkSource.CompletionActivation.INTERACTIVE - - def do_populate(self, context): - # TODO: Maybe convert async? - it = self.get_iter_correctly(context) - buffer = it.get_buffer() - proposals = [] - - doc_text = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False) - iter_cursor = buffer.get_iter_at_mark(buffer.get_insert()) - linenum = iter_cursor.get_line() + 1 - charnum = iter_cursor.get_line_index() - - def create_generator(): - for completion in Jedi.get_script(self._file, doc_text).complete(line = linenum, column = None, fuzzy = False): - comp_item = GtkSource.CompletionItem.new() - comp_item.set_label(completion.name) - comp_item.set_text(completion.name) - comp_item.set_icon(self.get_icon_for_type(completion.type)) - comp_item.set_info(completion.docstring()) - yield comp_item - - for item in create_generator(): - proposals.append(item) - - context.add_proposals(self, proposals, True) - - def get_icon_for_type(self, _type): - try: - return self._theme.load_icon(icon_names[_type.lower()], 16, 0) - except: - try: - return self._theme.load_icon(Gtk.STOCK_ADD, 16, 0) - except: - return None \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/key_input_controller.py b/src/core/widgets/base/sourceview/key_input_controller.py deleted file mode 100644 index a9384a3..0000000 --- a/src/core/widgets/base/sourceview/key_input_controller.py +++ /dev/null @@ -1,145 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gdk', '3.0') -from gi.repository import Gdk -from gi.repository import GLib - -# Application imports - - - -class KeyInputController: - - # NOTE: Mostly sinking pre-bound keys here to let our keybinder control instead... - 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 - 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 - - if is_control: - if is_shift: - if keyname in [ "Up", "Down" ]: - return True - - if keyname in [ "slash", "Up", "Down", "m", "z", "y" ]: - return True - - if is_alt: - if keyname in [ "Up", "Down", "Left", "Right" ]: - return True - - - if len(self._multi_insert_marks) > 0: - if keyname == "BackSpace": - self.begin_user_action(buffer) - - with buffer.freeze_notify(): - GLib.idle_add(self._delete_on_multi_line_markers, *(buffer,)) - - 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 - - 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 - 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", "g", "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 == "g": - self.go_to_call() - - 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) - with buffer.freeze_notify(): - GLib.idle_add(self._new_line_on_multi_line_markers, *(buffer,)) - - return - - has_selection = buffer.get_has_selection() - if not has_selection: - 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 deleted file mode 100644 index c418b14..0000000 --- a/src/core/widgets/base/sourceview/mixins/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -""" - SourceView Mixins Module -""" \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py b/src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py deleted file mode 100644 index 1affe10..0000000 --- a/src/core/widgets/base/sourceview/mixins/source_file_events_mixin.py +++ /dev/null @@ -1,157 +0,0 @@ -# Python imports -import random - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('GtkSource', '4') -from gi.repository import Gtk -from gi.repository import Gio -from gi.repository import GtkSource - -# Application imports -from ..custom_completion_providers.lsp_completion_provider import LSPCompletionProvider - - - -class FileEventsMixin: - - def get_current_file(self): - return self._current_file - - def open_file(self, gfile, line: int = 0, *args): - self._current_file = gfile - self._loading_file = True - - self.load_file_info(gfile) - self.load_file_async(gfile, line) - self._create_file_watcher(gfile) - - def save_file(self): - self._skip_file_load = True - gfile = event_system.emit_and_await("save_file_dialog", (self._current_filename, self._current_file)) if not self._current_file else self._current_file - - if not gfile: - self._skip_file_load = False - return - - self.open_file( self._write_file(gfile) ) - self._skip_file_load = False - - def save_file_as(self): - gfile = event_system.emit_and_await("save_file_dialog", (self._current_filename, self._current_file)) - self._write_file(gfile, True) - if gfile: event_system.emit("create_view", (gfile,)) - - def load_file_info(self, gfile): - info = gfile.query_info("standard::*", 0, cancellable=None) - content_type = info.get_content_type() - display_name = info.get_display_name() - self._current_filename = display_name - - try: - lm = self._language_manager.guess_language(None, content_type) - self._current_filetype = lm.get_id() - self.set_buffer_language(self._current_filetype) - except Exception as e: - ... - - logger.debug(f"Detected Content Type: {content_type}") - if self._current_filetype == "buffer": - self._current_filetype = info.get_content_type() - - def load_file_async(self, gfile, line: int = 0): - if self._skip_file_load: - self.update_labels(gfile) - return - - file = GtkSource.File() - buffer = self.get_buffer() - file.set_location(gfile) - self._file_loader = GtkSource.FileLoader.new(buffer, file) - - event_system.emit("pause_event_processing") - def finish_load_callback(obj, res, user_data = None): - event_system.emit("resume_event_processing") - - self._file_loader.load_finish(res) - self._document_loaded(line) - self.update_labels(gfile) - self._loading_file = False - - self._file_loader.load_async(io_priority = 80, - cancellable = None, - progress_callback = None, - progress_callback_data = None, - callback = finish_load_callback, - user_data = (None)) - - def _create_file_watcher(self, gfile = None): - if not gfile: return - - self._cancel_current_file_watchers() - self._file_change_watcher = gfile.monitor(Gio.FileMonitorFlags.NONE, Gio.Cancellable()) - self._file_change_watcher.connect("changed", self._file_monitor) - - def _file_monitor(self, file_monitor, file, other_file = None, eve_type = None, data = None): - if not file.get_path() == self._current_file.get_path(): return - - if eve_type in [Gio.FileMonitorEvent.CREATED, - Gio.FileMonitorEvent.DELETED, - Gio.FileMonitorEvent.RENAMED, - Gio.FileMonitorEvent.MOVED_IN, - Gio.FileMonitorEvent.MOVED_OUT]: - buffer = self.get_buffer() - buffer.set_modified(True) - - if eve_type in [ Gio.FileMonitorEvent.CHANGES_DONE_HINT ]: - if self._ignore_internal_change: - self._ignore_internal_change = False - return - - # TODO: Any better way to load the difference?? - if self._current_file.query_exists(): - self.load_file_async(self._current_file) - - def _cancel_current_file_watchers(self): - if self._file_change_watcher: - self._file_change_watcher.cancel() - self._file_change_watcher = None - - def _write_file(self, gfile, save_as = False): - if not gfile: return - - buffer = self.get_buffer() - with open(gfile.get_path(), 'w') as f: - if not save_as: - self._ignore_internal_change = True - - start_itr = buffer.get_start_iter() - end_itr = buffer.get_end_iter() - text = buffer.get_text(start_itr, end_itr, True) - - f.write(text) - - 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) - - uri = self._current_file.get_uri() - buffer = self.get_buffer() - - event_system.emit("textDocument/didOpen", (self._current_filetype, uri,)) - - word_completion = GtkSource.CompletionWords.new("word_completion") - word_completion.register(buffer) - self._completion.add_provider(word_completion) - - lsp_completion_provider = LSPCompletionProvider(self) - self._completion.add_provider(lsp_completion_provider) - - self.got_to_line(buffer, line) - - diff --git a/src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py b/src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py deleted file mode 100644 index d5be743..0000000 --- a/src/core/widgets/base/sourceview/mixins/source_mark_events_mixin.py +++ /dev/null @@ -1,151 +0,0 @@ -# Python imports -import random - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk - -# Application imports - - - -class MarkEventsMixin: - - def keyboard_insert_mark(self, target_iter = None, is_keyboard_insert = True): - buffer = self.get_buffer() - - if not target_iter: - target_iter = buffer.get_iter_at_mark( buffer.get_insert() ) - - found_mark = self.check_for_insert_marks(target_iter, is_keyboard_insert) - if not found_mark: - random_bits = random.getrandbits(128) - hash = "%032x" % random_bits - mark = Gtk.TextMark.new(name = f"multi_insert_{hash}", left_gravity = False) - - buffer.add_mark(mark, target_iter) - self._multi_insert_marks.append(mark) - mark.set_visible(True) - - def button_press_insert_mark(self, eve): - data = self.window_to_buffer_coords(Gtk.TextWindowType.TEXT , eve.x, eve.y) - is_over_text, target_iter, is_trailing = self.get_iter_at_position(data.buffer_x, data.buffer_y) - - if not is_over_text: - # NOTE: Trying to put at very end of line if not over text (aka, clicking right of text) - target_iter.forward_visible_line() - target_iter.backward_char() - - self.keyboard_insert_mark(target_iter, is_keyboard_insert = False) - - def check_for_insert_marks(self, target_iter, is_keyboard_insert): - marks = target_iter.get_marks() - buffer = self.get_buffer() - found_mark = False - - for mark in marks: - for _mark in self._multi_insert_marks: - if _mark == mark: - mark.set_visible(False) - buffer.delete_mark(mark) - found_mark = True - break - - if found_mark: - self._multi_insert_marks.remove(mark) - break - - if not is_keyboard_insert: - for mark in marks: - if "insert" in mark.get_name(): - found_mark = True - - return found_mark - - def keyboard_clear_marks(self): - buffer = self.get_buffer() - - buffer.begin_user_action() - - for mark in self._multi_insert_marks: - mark.set_visible(False) - buffer.delete_mark(mark) - - self._multi_insert_marks.clear() - buffer.end_user_action() - - - def _update_multi_line_markers(self, buffer, text_str): - for mark in self._multi_insert_marks: - iter = buffer.get_iter_at_mark(mark) - buffer.insert(iter, text_str, -1) - - self.end_user_action(buffer) - - def _delete_on_multi_line_markers(self, buffer): - iter = buffer.get_iter_at_mark( buffer.get_insert() ) - buffer.backspace(iter, interactive = True, default_editable = True) - - for mark in self._multi_insert_marks: - iter = buffer.get_iter_at_mark(mark) - buffer.backspace(iter, interactive = True, default_editable = True) - - self.end_user_action(buffer) - - def _new_line_on_multi_line_markers(self, buffer): - iter = buffer.get_iter_at_mark( buffer.get_insert() ) - self._base_indent(buffer, iter) - self.insert_indent_handler(buffer, iter) - - for mark in self._multi_insert_marks: - iter = buffer.get_iter_at_mark(mark) - self._base_indent(buffer, iter) - self.insert_indent_handler(buffer, iter) - - def insert_indent_handler(self, buffer, iter = None): - if not iter: - iter = buffer.get_iter_at_mark( buffer.get_insert() ) - - iter_copy = iter.copy() - iter_copy.backward_sentence_start() - iter_copy.forward_sentence_end() - iter_copy.backward_char() - - # Note: Need to compare line nums too because backward_sentence_start - # and forward_sentence_end can go farther back if just spaces inbetween... - line_start = iter.get_line() - line_end = iter_copy.get_line() - - _char = iter_copy.get_char() - if _char in ["{", ":"] and (line_start - line_end) == 1: - self._indent_deeper(buffer, iter) - - def _base_indent(self, buffer, iter): - line_num = iter.get_line() - iter_copy = buffer.get_iter_at_line(line_num) - - spaces = "" - _char = iter_copy.get_char() - while _char == " ": - spaces += " " - iter_copy.forward_char() - _char = iter_copy.get_char() - - buffer.insert(iter, f"\n{spaces}") - - - def _indent_deeper(self, buffer, iter): - buffer.insert(iter, " ") - - - - def begin_user_action(self, buffer): - if len(self._multi_insert_marks) > 0: - buffer.begin_user_action() - self.freeze_multi_line_insert = True - - def end_user_action(self, buffer): - if len(self._multi_insert_marks) > 0: - buffer.end_user_action() - self.freeze_multi_line_insert = False \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/mixins/source_view_dnd_mixin.py b/src/core/widgets/base/sourceview/mixins/source_view_dnd_mixin.py deleted file mode 100644 index 6f23e4e..0000000 --- a/src/core/widgets/base/sourceview/mixins/source_view_dnd_mixin.py +++ /dev/null @@ -1,45 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk -from gi.repository import Gio - -# Application imports - - - -class SourceViewDnDMixin: - - def _set_up_dnd(self): - PLAIN_TEXT_TARGET_TYPE = 70 - URI_TARGET_TYPE = 80 - text_target = Gtk.TargetEntry.new('text/plain', Gtk.TargetFlags(0), PLAIN_TEXT_TARGET_TYPE) - uri_target = Gtk.TargetEntry.new('text/uri-list', Gtk.TargetFlags(0), URI_TARGET_TYPE) - targets = [ text_target, uri_target ] - self.drag_dest_set_target_list(targets) - - def _on_drag_data_received(self, widget, drag_context, x, y, data, info, time): - if info == 70: return - - if info == 80: - buffer = self.get_buffer() - uris = data.get_uris() - - if len(uris) == 0: - uris = data.get_text().split("\n") - - if not self._current_file and not buffer.get_modified(): - gfile = Gio.File.new_for_uri(uris[0]) - self.open_file(gfile) - uris.pop(0) - - for uri in uris: - gfile = None - try: - gfile = Gio.File.new_for_uri(uri) - except Exception as e: - gfile = Gio.File.new_for_path(uri) - - event_system.emit('create_view', (gfile,)) diff --git a/src/core/widgets/base/sourceview/source_view.py b/src/core/widgets/base/sourceview/source_view.py deleted file mode 100644 index f089bff..0000000 --- a/src/core/widgets/base/sourceview/source_view.py +++ /dev/null @@ -1,98 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -gi.require_version('GtkSource', '4') -gi.require_version('Gdk', '3.0') -from gi.repository import Gtk -from gi.repository import Gdk -from gi.repository import GLib -from gi.repository import Gio -from gi.repository import GtkSource - -# Application imports -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(SourceViewControllerMixin, GtkSource.View): - def __init__(self): - super(SourceView, self).__init__() - - self._language_manager = GtkSource.LanguageManager() - self._style_scheme_manager = GtkSource.StyleSchemeManager() - - self._file_loader = None - self._file_change_watcher = None - self._current_file: Gio.File = None - - self._current_filename: str = "" - self._current_filepath: str = None - self._current_filetype: str = "buffer" - - self._skip_file_load = False - self._ignore_internal_change = False - self._loading_file = False - self._completion = self.get_completion() - self._px_value = settings.theming.default_zoom - - self._multi_insert_marks = [] - self.freeze_multi_line_insert = False - - self._setup_styling() - self._setup_signals() - self._subscribe_to_events() - self._load_widgets() - - - def _setup_styling(self): - ctx = self.get_style_context() - ctx.add_class("source-view") - ctx.add_class(f"px{self._px_value}") - - self.set_vexpand(True) - - self.set_show_line_marks(True) - self.set_show_line_numbers(True) - self.set_smart_backspace(True) - self.set_indent_on_tab(True) - self.set_insert_spaces_instead_of_tabs(True) - self.set_auto_indent(True) - self.set_monospace(True) - self.set_tab_width(4) - self.set_show_right_margin(True) - self.set_right_margin_position(80) - self.set_background_pattern(0) # 0 = None, 1 = Grid - - buffer = self.get_buffer() - self._create_default_tag(buffer) - self.set_buffer_language(buffer) - self.set_buffer_style(buffer) - - - def _setup_signals(self): - self.connect("focus", self._on_widget_focus) - self.connect("focus-in-event", self._focus_in_event) - - self.connect("drag-data-received", self._on_drag_data_received) - 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("scroll-event", self._scroll_event) - - buffer = self.get_buffer() - buffer.connect('changed', self._is_modified) - buffer.connect("mark-set", self._on_cursor_move) - buffer.connect('insert-text', self._insert_text) - buffer.connect('modified-changed', self._buffer_modified_changed) - - - def _subscribe_to_events(self): - ... - - def _load_widgets(self): - self._set_up_dnd() \ No newline at end of file diff --git a/src/core/widgets/base/sourceview/source_view_controller.py b/src/core/widgets/base/sourceview/source_view_controller.py deleted file mode 100644 index a173524..0000000 --- a/src/core/widgets/base/sourceview/source_view_controller.py +++ /dev/null @@ -1,138 +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 .key_input_controller import KeyInputController -from .source_view_events import SourceViewEvents - - - -class SourceViewControllerMixin(KeyInputController, SourceViewEvents): - def get_current_file(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 go_to_call(self): - buffer = self.get_buffer() - iter = buffer.get_iter_at_mark( buffer.get_insert() ) - line = iter.get_line() - offset = iter.get_line_offset() - uri = self.get_current_file().get_uri() - - event_system.emit("textDocument/definition", (self.get_filetype(), uri, line, offset,)) - - - 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) - # Note: scroll_to_iter and scroll_to_mark depend on an idle recalculate of buffers after load to work - GLib.idle_add(self.scroll_to_mark, buffer.get_insert(), 0.1, True, 0.0, 0.1) - - 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 deleted file mode 100644 index acb7ace..0000000 --- a/src/core/widgets/base/sourceview/source_view_events.py +++ /dev/null @@ -1,102 +0,0 @@ -# Python imports - -# 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 .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) - - def _is_modified(self, *args): - buffer = self.get_buffer() - file_type = self.get_filetype() - - if not self._loading_file: - event_system.emit("buffer_changed", (buffer, )) - event_system.emit("textDocument/didChange", (file_type, 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 diff --git a/src/core/widgets/base/sourceview_container.py b/src/core/widgets/base/sourceview_container.py deleted file mode 100644 index ce40588..0000000 --- a/src/core/widgets/base/sourceview_container.py +++ /dev/null @@ -1,46 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk - -# Application imports -from ..tab_header_widget import TabHeaderWidget -from .sourceview.source_view import SourceView - - - -class SourceViewContainer(Gtk.ScrolledWindow): - def __init__(self, close_tab): - super(SourceViewContainer, self).__init__() - - self._close_tab: function = close_tab - self._source_view: SourceView = None - self._tab_widget: TabHeaderWidget = None - - self._setup_styling() - self._setup_signals() - self._subscribe_to_events() - self._load_widgets() - - - def _setup_styling(self): - ... - - def _setup_signals(self): - ... - - def _subscribe_to_events(self): - ... - - def _load_widgets(self): - self._source_view = SourceView() - self._tab_widget = TabHeaderWidget(self, self._source_view, self._close_tab) - self.add(self._source_view) - - def get_tab_widget(self): - return self._tab_widget - - def get_source_view(self): - return self._source_view \ No newline at end of file diff --git a/src/core/widgets/base/webkit/ace_editor.py b/src/core/widgets/base/webkit/ace_editor.py index 216d995..17f7101 100644 --- a/src/core/widgets/base/webkit/ace_editor.py +++ b/src/core/widgets/base/webkit/ace_editor.py @@ -49,6 +49,10 @@ class AceEditor(WebKit2.WebView): event_system.subscribe(f"updated_session_{self.INDEX}", self.updated_session) event_system.subscribe(f"close_session_{self.INDEX}", self.close_session) event_system.subscribe(f"remove_session_{self.INDEX}", self.remove_session) + event_system.subscribe(f"keyboard_scale_up_text_{self.INDEX}", self.keyboard_scale_up_text) + event_system.subscribe(f"keyboard_scale_down_text_{self.INDEX}", self.keyboard_scale_down_text) + event_system.subscribe(f"toggle_highlight_line_{self.INDEX}", self.toggle_highlight_line) + event_system.subscribe(f"ui_message_{self.INDEX}", self.ui_message) def _load_settings(self): @@ -104,6 +108,18 @@ class AceEditor(WebKit2.WebView): command = f"removeSession('{fhash}')" self.run_javascript(command, None, None) + def keyboard_scale_up_text(self): + command = "zoomIn()" + self.run_javascript(command, None, None) + + def keyboard_scale_down_text(self): + command = "zoomOut()" + self.run_javascript(command, None, None) + + def toggle_highlight_line(self): + command = "toggleLineHighlight()" + self.run_javascript(command, None, None) + def ui_message(self, message, mtype): command = f"displayMessage('{message}', '{mtype}', '3')" self.run_javascript(command, None, None) diff --git a/src/core/widgets/base/webkit/editor.py b/src/core/widgets/base/webkit/editor.py index 736dd4f..5e6c120 100644 --- a/src/core/widgets/base/webkit/editor.py +++ b/src/core/widgets/base/webkit/editor.py @@ -7,7 +7,6 @@ from gi.repository import Gtk # Application imports from ....controllers.files_controller import FilesController -# from ...controls.tab_bar import TabBar from .fixed_box import FixedBox @@ -44,5 +43,4 @@ class Editor(Gtk.Box): FilesController(self.INDEX) def _load_widgets(self): - # self.add( TabBar(self.INDEX) ) self.add( FixedBox(self.INDEX) ) \ No newline at end of file diff --git a/src/core/widgets/controls/save_as_button.py b/src/core/widgets/controls/save_as_button.py index 163131b..913138e 100644 --- a/src/core/widgets/controls/save_as_button.py +++ b/src/core/widgets/controls/save_as_button.py @@ -25,6 +25,7 @@ class SaveAsButton(Gtk.Button): self.set_always_show_image(True) self.set_image_position(1) # Left - 0, Right = 1 self.set_hexpand(False) + self.set_sensitive(False) def _setup_signals(self): self.connect("released", self._emit_save_as_eve) diff --git a/src/core/widgets/controls/scale_down_button.py b/src/core/widgets/controls/scale_down_button.py index 49399d5..9b42659 100644 --- a/src/core/widgets/controls/scale_down_button.py +++ b/src/core/widgets/controls/scale_down_button.py @@ -20,7 +20,7 @@ class ScaleDownButton(Gtk.Button): def _setup_styling(self): - self.set_label("Zoom") + self.set_label("Zoom Out") self.set_image( Gtk.Image.new_from_icon_name("gtk-zoom-out", 4) ) self.set_always_show_image(True) self.set_image_position(1) # Left - 0, Right = 1 diff --git a/src/core/widgets/controls/scale_up_button.py b/src/core/widgets/controls/scale_up_button.py index b090dfe..25f2215 100644 --- a/src/core/widgets/controls/scale_up_button.py +++ b/src/core/widgets/controls/scale_up_button.py @@ -20,7 +20,7 @@ class ScaleUpButton(Gtk.Button): def _setup_styling(self): - self.set_label("Zoom") + self.set_label("Zoom In") self.set_image( Gtk.Image.new_from_icon_name("gtk-zoom-in", 4) ) self.set_always_show_image(True) self.set_image_position(1) # Left - 0, Right = 1 diff --git a/src/core/widgets/controls/tab_bar.py b/src/core/widgets/controls/tab_bar.py deleted file mode 100644 index 2938bca..0000000 --- a/src/core/widgets/controls/tab_bar.py +++ /dev/null @@ -1,114 +0,0 @@ -# Python imports - -# Lib imports -import gi -gi.require_version('Gtk', '3.0') -from gi.repository import Gtk - -# Application imports -from ..tab_header_widget import TabHeaderWidget - - - -class TabBar(Gtk.Notebook): - def __init__(self, index): - super(TabBar, self).__init__() - - self.INDEX = index - self.added_tab = None - - self.set_group_name("editor_widget") - - self._setup_styling() - self._setup_signals() - self._subscribe_to_events() - self._load_widgets() - - self.show_all() - - - def _setup_styling(self): - ... - - def _setup_signals(self): - self.connect("switch-page", self._switch_page_update) - - def _subscribe_to_events(self): - event_system.subscribe(f"add_tab_{self.INDEX}", self.add_tab) - event_system.subscribe(f"add_tab_with_name_{self.INDEX}", self.add_tab) - event_system.subscribe(f"update_tab_{self.INDEX}", self.update_tab) - event_system.subscribe(f"close_tab_{self.INDEX}", self.close_tab) - - def _load_widgets(self): - start_box = Gtk.Box() - end_box = Gtk.Box() - - add_tab = Gtk.Button(label = "+") - add_tab.connect("released", self._button_add_tab) - - end_box.add(add_tab) - - start_box.show_all() - end_box.show_all() - - self.set_action_widget(start_box, 0) - self.set_action_widget(end_box, 1) - - def _button_add_tab(self, widget): - event_system.emit(f"new_session_{self.INDEX}") - - def _button_close_tab(self, widget, container): - self._close_tab(widget, container) - event_system.emit(f"remove_session_{self.INDEX}", (container.fhash)) - - # Note: Need to get parent instead given we pass the close_tab method - # from a potentially former notebook. - def _close_tab(self, widget, container): - notebook = container.get_parent() - - if notebook.get_n_pages() < 2: return - - page_num = notebook.page_num(container) - notebook.remove_page(page_num) - # container._cancel_current_file_watchers() - - def _switch_page_update(self, notebook, container, page_num): - if self.added_tab or self.added_tab == None: - self.added_tab = False - return - - event_system.emit(f"switch_session_{self.INDEX}", (container.fhash,)) - - - def add_tab(self, fhash, title = "[BAD TITLE]"): - container = Gtk.EventBox() - header = TabHeaderWidget(container, self._button_close_tab) - page_num = self.append_page(container, header) - - container.fhash = fhash - self.added_tab = True - - header.label.set_label(title) - self.set_tab_detachable(container, True) - self.set_tab_reorderable(container, True) - - self.show_all() - self.set_current_page(page_num) - - def update_tab(self, fhash, title = "[BAD TITLE]"): - for child in self.get_children(): - if child.fhash == fhash: - target = child - break - - label = self.get_tab_label(target).get_children()[0] - label.set_label(title) - - def close_tab(self, fhash): - target = None - for child in self.get_children(): - if child.fhash == fhash: - target = child - break - - self._close_tab(None, target) \ No newline at end of file diff --git a/src/core/widgets/controls/theme_button.py b/src/core/widgets/controls/theme_button.py index f166d2a..cb793d0 100644 --- a/src/core/widgets/controls/theme_button.py +++ b/src/core/widgets/controls/theme_button.py @@ -73,6 +73,7 @@ class ThemeButton(Gtk.Button): self.set_image_position(1) # Left - 0, Right = 1 self.set_margin_left(5) # self.set_margin_right(5) + self.set_sensitive(False) def _setup_signals(self): self.connect("clicked", self._show_popover) diff --git a/src/core/mixins/signals/keyboard_signals_mixin.py b/src/libs/mixins/keyboard_signals_mixin.py similarity index 100% rename from src/core/mixins/signals/keyboard_signals_mixin.py rename to src/libs/mixins/keyboard_signals_mixin.py diff --git a/user_config/usr/share/newton/context_path/index.html b/user_config/usr/share/newton/context_path/index.html index c557fb7..495a773 100644 --- a/user_config/usr/share/newton/context_path/index.html +++ b/user_config/usr/share/newton/context_path/index.html @@ -26,7 +26,7 @@
-