Remove tabs UI from code editor and move to plugin. Enhance plugin system.
- Remove tabs controller, tab widget, and tabs widget files and move to plugin - Delete plugins/README.txt - Add register_controller method to controller system for plugin use - Add error handling for plugin crashes via futures callback
This commit is contained in:
@@ -8,7 +8,6 @@ from plugins import plugins_controller
|
||||
from libs.controllers.controller_manager import ControllerManager
|
||||
|
||||
from .controllers.files_controller import FilesController
|
||||
from .controllers.tabs_controller import TabsController
|
||||
from .controllers.commands_controller import CommandsController
|
||||
from .controllers.completion_controller import CompletionController
|
||||
from .controllers.views.source_views_controller import SourceViewsController
|
||||
@@ -31,23 +30,18 @@ class CodeBase:
|
||||
|
||||
def _load_controllers(self):
|
||||
files_controller = FilesController()
|
||||
tabs_controller = TabsController()
|
||||
commands_controller = CommandsController()
|
||||
completion_controller = CompletionController()
|
||||
source_views_controller = SourceViewsController()
|
||||
|
||||
# self.controller_manager.register_controller("base", self)
|
||||
self.controller_manager.register_controller("files", files_controller)
|
||||
self.controller_manager.register_controller("tabs", tabs_controller)
|
||||
self.controller_manager.register_controller("commands", commands_controller)
|
||||
self.controller_manager.register_controller("completion", completion_controller)
|
||||
self.controller_manager.register_controller("source_views", source_views_controller)
|
||||
self.controller_manager.register_controller("plugins", plugins_controller)
|
||||
self.controller_manager.register_controller("widgets", widget_registery)
|
||||
|
||||
def get_tabs_widget(self):
|
||||
return self.controller_manager["tabs"].get_tabs_widget()
|
||||
|
||||
def create_source_view(self):
|
||||
source_view = self.controller_manager["source_views"].create_source_view()
|
||||
self.controller_manager["completion"].register_completer(
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from libs.controllers.controller_base import ControllerBase
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from ..tabs_widget import TabsWidget
|
||||
from ..tab_widget import TabWidget
|
||||
|
||||
from ..source_view import SourceView
|
||||
|
||||
|
||||
|
||||
class TabsController(ControllerBase):
|
||||
def __init__(self):
|
||||
super(TabsController, self).__init__()
|
||||
|
||||
self.tabs_widget: TabsWidget = TabsWidget()
|
||||
self.tabs_widget.message = self.message
|
||||
|
||||
|
||||
def _controller_message(self, event: Code_Event_Types.CodeEvent):
|
||||
if isinstance(event, Code_Event_Types.FocusedViewEvent):
|
||||
self.tabs_widget.view_changed( event.view.get_buffer() )
|
||||
elif isinstance(event, Code_Event_Types.FilePathSetEvent):
|
||||
self.update_tab_label(event)
|
||||
elif isinstance(event, Code_Event_Types.ModifiedChangedEvent):
|
||||
self.tabs_widget.modified_changed( event.buffer )
|
||||
elif isinstance(event, Code_Event_Types.FileExternallyDeletedEvent):
|
||||
self.tabs_widget.externally_deleted( event.buffer )
|
||||
elif isinstance(event, Code_Event_Types.AddedNewFileEvent):
|
||||
self.add_tab(event)
|
||||
elif isinstance(event, Code_Event_Types.PoppedFileEvent):
|
||||
...
|
||||
elif isinstance(event, Code_Event_Types.RemovedFileEvent):
|
||||
self.remove_tab(event)
|
||||
|
||||
def get_tabs_widget(self):
|
||||
return self.tabs_widget
|
||||
|
||||
def update_tab_label(self, event: Code_Event_Types.FilePathSetEvent):
|
||||
for page_widget in self.tabs_widget.get_children():
|
||||
tab = self.tabs_widget.get_tab_label(page_widget)
|
||||
if not event.file == tab.file: continue
|
||||
|
||||
tab.label.set_label(event.file.fname)
|
||||
|
||||
break
|
||||
|
||||
def add_tab(self, event: Code_Event_Types.AddedNewFileEvent):
|
||||
tab = TabWidget()
|
||||
tab.file = event.file
|
||||
|
||||
tab.label.set_label(event.file.fname)
|
||||
|
||||
self.tabs_widget.append_page(Gtk.Separator(), tab)
|
||||
tab.show_all()
|
||||
|
||||
def remove_tab(self, event: Code_Event_Types.RemovedFileEvent):
|
||||
for page_widget in self.tabs_widget.get_children():
|
||||
tab = self.tabs_widget.get_tab_label(page_widget)
|
||||
if not event.file == tab.file: continue
|
||||
|
||||
tab.clear_signals_and_data()
|
||||
self.tabs_widget.remove_page(
|
||||
self.tabs_widget.page_num(page_widget)
|
||||
)
|
||||
|
||||
break
|
||||
@@ -1,79 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class TabWidget(Gtk.Box):
|
||||
"""docstring for TabWidget"""
|
||||
|
||||
def __init__(self):
|
||||
super(TabWidget, self).__init__()
|
||||
|
||||
self.file = None
|
||||
|
||||
self._handler_id = None
|
||||
self._eve_handler_id = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("tab-widget")
|
||||
|
||||
self.set_orientation(0)
|
||||
self.set_hexpand(False)
|
||||
self.set_vexpand(False)
|
||||
self.set_size_request(-1, 12)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.event_box = Gtk.EventBox()
|
||||
self.label = Gtk.Label()
|
||||
self.close_bttn = Gtk.Button()
|
||||
icon = Gtk.Image(stock = Gtk.STOCK_CLOSE)
|
||||
|
||||
self.event_box.set_above_child(True)
|
||||
ctx = self.label.get_style_context()
|
||||
ctx.add_class("tab-label")
|
||||
ctx = self.close_bttn.get_style_context()
|
||||
ctx.add_class("tab-close-bttn")
|
||||
|
||||
self.label.set_xalign(0.0)
|
||||
self.label.set_margin_left(25)
|
||||
self.label.set_margin_right(25)
|
||||
self.label.set_hexpand(True)
|
||||
|
||||
self.close_bttn.add(icon)
|
||||
self.event_box.add(self.label)
|
||||
self.add(self.event_box)
|
||||
self.add(self.close_bttn)
|
||||
|
||||
self.show_all()
|
||||
|
||||
def clear_signals_and_data(self):
|
||||
self.close_bttn.disconnect(self._handler_id)
|
||||
self.event_box.disconnect(self._eve_handler_id)
|
||||
self._handler_id = None
|
||||
|
||||
for child in self.get_children():
|
||||
child.unparent()
|
||||
child.run_dispose()
|
||||
child.destroy()
|
||||
|
||||
def set_close_signal(self, callback):
|
||||
self._handler_id = self.close_bttn.connect(
|
||||
'clicked',
|
||||
callback,
|
||||
self.file
|
||||
)
|
||||
@@ -1,177 +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
|
||||
|
||||
# Application imports
|
||||
from libs.event_factory import Event_Factory, Code_Event_Types
|
||||
|
||||
from .tab_widget import TabWidget
|
||||
|
||||
|
||||
|
||||
class TabsWidget(Gtk.Notebook):
|
||||
def __init__(self):
|
||||
super(TabsWidget, self).__init__()
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
self._load_widgets()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
self.set_scrollable(True)
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("page-added", self._page_added)
|
||||
self.switch_page_id = \
|
||||
self.connect_after("switch-page", self._switch_page)
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
...
|
||||
|
||||
def _page_added(self, notebook, page_widget, page_num):
|
||||
tab = self.get_tab_label(page_widget)
|
||||
tab.set_close_signal(self._close_tab)
|
||||
|
||||
self._bind_tab_menu(tab, page_widget)
|
||||
|
||||
page_widget.show()
|
||||
self.set_tab_detachable(page_widget, True)
|
||||
self.set_tab_reorderable(page_widget, True)
|
||||
|
||||
def _close_tab(self, button, file):
|
||||
event = Event_Factory.create_event(
|
||||
"remove_file",
|
||||
buffer = file.buffer
|
||||
)
|
||||
|
||||
self.message(event)
|
||||
|
||||
def _switch_page(self, notebook, page_widget, page_num):
|
||||
tab = self.get_tab_label(page_widget)
|
||||
event = Event_Factory.create_event(
|
||||
"set_active_file",
|
||||
buffer = tab.file.buffer
|
||||
)
|
||||
|
||||
self.message(event)
|
||||
|
||||
def _bind_tab_menu(self, tab, page_widget):
|
||||
def do_context_menu(tab, eve, page_widget):
|
||||
if eve.type == Gdk.EventType.BUTTON_RELEASE and eve.button == 3: # r-click
|
||||
menu = self.create_menu(page_widget)
|
||||
menu.popup_at_pointer(eve)
|
||||
|
||||
tab._eve_handler_id = \
|
||||
tab.event_box.connect(
|
||||
"button-release-event",
|
||||
do_context_menu,
|
||||
page_widget
|
||||
)
|
||||
|
||||
def create_menu(self, page_widget) -> Gtk.Menu:
|
||||
context_menu = Gtk.Menu()
|
||||
|
||||
close_item = Gtk.MenuItem(label = "Close Tab")
|
||||
close_left_item = Gtk.MenuItem(label = "Close Tabs Left")
|
||||
close_right_item = Gtk.MenuItem(label = "Close Tabs Right")
|
||||
close_other_item = Gtk.MenuItem(label = "Close Other Tabs")
|
||||
close_all_item = Gtk.MenuItem(label = "Close All Tabs")
|
||||
|
||||
close_item.connect("activate", self.close_item, page_widget)
|
||||
close_left_item.connect("activate", self.close_left_items, page_widget)
|
||||
close_right_item.connect("activate", self.close_right_items, page_widget)
|
||||
close_other_item.connect("activate", self.close_other_items, page_widget)
|
||||
close_all_item.connect("activate", self.close_all_items, page_widget)
|
||||
|
||||
context_menu.append(close_item)
|
||||
context_menu.append(close_left_item)
|
||||
context_menu.append(close_right_item)
|
||||
context_menu.append(close_other_item)
|
||||
context_menu.append(close_all_item)
|
||||
|
||||
context_menu.show_all()
|
||||
|
||||
return context_menu
|
||||
|
||||
def view_changed(self, buffer):
|
||||
for page_widget in self.get_children():
|
||||
tab = self.get_tab_label(page_widget)
|
||||
if not buffer == tab.file.buffer: continue
|
||||
|
||||
self.handler_block(self.switch_page_id)
|
||||
|
||||
self.set_current_page(
|
||||
self.page_num(page_widget)
|
||||
)
|
||||
|
||||
self.handler_unblock(self.switch_page_id)
|
||||
|
||||
break
|
||||
|
||||
def modified_changed(self, buffer):
|
||||
for page_widget in self.get_children():
|
||||
tab = self.get_tab_label(page_widget)
|
||||
if not buffer == tab.file.buffer: continue
|
||||
|
||||
ctx = tab.label.get_style_context()
|
||||
ctx.remove_class("file-deleted")
|
||||
if buffer.get_modified():
|
||||
ctx.add_class("file-changed")
|
||||
else:
|
||||
ctx.remove_class("file-changed")
|
||||
|
||||
break
|
||||
|
||||
def externally_deleted(self, buffer):
|
||||
for page_widget in self.get_children():
|
||||
tab = self.get_tab_label(page_widget)
|
||||
if not buffer == tab.file.buffer: continue
|
||||
ctx = tab.label.get_style_context()
|
||||
ctx.add_class("file-deleted")
|
||||
break
|
||||
|
||||
|
||||
def close_item(self, menu_item, page_widget):
|
||||
tab = self.get_tab_label(page_widget)
|
||||
tab.close_bttn.clicked()
|
||||
|
||||
def close_left_items(self, menu_item, page_widget):
|
||||
children = self.get_children()
|
||||
i = children.index(page_widget)
|
||||
|
||||
if i == 0: return
|
||||
|
||||
for widget in children[ : i]:
|
||||
tab = self.get_tab_label(widget)
|
||||
tab.close_bttn.clicked()
|
||||
|
||||
def close_right_items(self, menu_item, page_widget):
|
||||
children = self.get_children()
|
||||
i = children.index(page_widget) + 1
|
||||
|
||||
if i == len(children): return
|
||||
|
||||
for widget in children[i : ]:
|
||||
tab = self.get_tab_label(widget)
|
||||
tab.close_bttn.clicked()
|
||||
|
||||
def close_other_items(self, menu_item, page_widget):
|
||||
self.close_left_items(menu_item, page_widget)
|
||||
self.close_right_items(menu_item, page_widget)
|
||||
|
||||
def close_all_items(self, menu_item, page_widget):
|
||||
children = self.get_children()
|
||||
|
||||
for widget in children[ : ]:
|
||||
tab = self.get_tab_label(widget)
|
||||
tab.close_bttn.clicked()
|
||||
Reference in New Issue
Block a user