Refactor controller architecture and multi-insert state
- Rename ControllerContext to ControllerMessageBus for clarity - Switch ControllerBase to use SingletonRaised - Replace MarkEventsMixin with MarkerManager for multi-cursor editing - Add populate_popup event support for source view context menus - Remove unused swap file events - Moved JSON prettify feature to plugin - Fix event name: "removed_file" -> "remove_file"
This commit is contained in:
@@ -3,12 +3,12 @@
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from ..singleton import Singleton
|
||||
from ..singleton_raised import SingletonRaised
|
||||
|
||||
from ..dto.base_event import BaseEvent
|
||||
|
||||
from .emit_dispatcher import EmitDispatcher
|
||||
from .controller_context import ControllerContext
|
||||
from .controller_message_bus import ControllerMessageBus
|
||||
|
||||
|
||||
|
||||
@@ -17,28 +17,28 @@ class ControllerBaseException(Exception):
|
||||
|
||||
|
||||
|
||||
class ControllerBase(Singleton, EmitDispatcher):
|
||||
class ControllerBase(SingletonRaised, EmitDispatcher):
|
||||
def __init__(self):
|
||||
super(ControllerBase, self).__init__()
|
||||
|
||||
self.controller_context: ControllerContext = None
|
||||
self.controller_message_bus: ControllerMessageBus = None
|
||||
|
||||
|
||||
def _controller_message(self, event: BaseEvent):
|
||||
raise ControllerBaseException("Controller Base '_controller_message' must be overridden...")
|
||||
|
||||
def set_controller_context(self, controller_context: ControllerContext):
|
||||
self.controller_context = controller_context
|
||||
def set_controller_message_bus(self, controller_message_bus: ControllerMessageBus):
|
||||
self.controller_message_bus = controller_message_bus
|
||||
|
||||
def message(self, event: BaseEvent):
|
||||
return self.controller_context.message(event)
|
||||
return self.controller_message_bus.message(event)
|
||||
|
||||
def message_to(self, name: str, event: BaseEvent):
|
||||
return self.controller_context.message_to(name, event)
|
||||
return self.controller_message_bus.message_to(name, event)
|
||||
|
||||
def message_to_selected(self, names: list[str], event: BaseEvent):
|
||||
for name in names:
|
||||
self.controller_context.message_to_selected(name, event)
|
||||
self.controller_message_bus.message_to_selected(name, event)
|
||||
|
||||
def register_controller(self, name: str, controller):
|
||||
self.controller_context.register_controller(name, controller)
|
||||
self.controller_message_bus.register_controller(name, controller)
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from ..dto.base_event import BaseEvent
|
||||
|
||||
|
||||
|
||||
class ControllerContextException(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
class ControllerContext:
|
||||
def __init__(self):
|
||||
super(ControllerContext, self).__init__()
|
||||
|
||||
|
||||
def message(self, event: BaseEvent):
|
||||
raise ControllerContextException("Controller Context 'message' must be overriden by Controller Manager...")
|
||||
|
||||
def message_to(self, name: str, event: BaseEvent):
|
||||
raise ControllerContextException("Controller Context 'message_to' must be overriden by Controller Manager...")
|
||||
|
||||
def message_to_selected(self, name: list, event: BaseEvent):
|
||||
raise ControllerContextException("Controller Context 'message_to_selected' must be overriden by Controller Manager...")
|
||||
|
||||
def register_controller(self, name: str, controller):
|
||||
raise ControllerContextException("Controller Context 'register_controller' must be overriden by Controller Manager...")
|
||||
@@ -7,7 +7,7 @@ from ..singleton import Singleton
|
||||
from ..event_factory import Code_Event_Types
|
||||
|
||||
from .controller_base import ControllerBase
|
||||
from .controller_context import ControllerContext
|
||||
from .controller_message_bus import ControllerMessageBus
|
||||
|
||||
|
||||
|
||||
@@ -17,17 +17,26 @@ class ControllerManagerException(Exception):
|
||||
|
||||
|
||||
class ControllerManager(Singleton, dict):
|
||||
"""
|
||||
ControllerManager registers controllers by key/value pair.
|
||||
It binds the message bus methods methods each controller has
|
||||
due to extending ControllerBase.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(ControllerManager, self).__init__()
|
||||
|
||||
self.message_bus: ControllerMessageBus \
|
||||
= self._crete_controller_message_bus()
|
||||
|
||||
def _crete_controller_context(self) -> ControllerContext:
|
||||
controller_context = ControllerContext()
|
||||
controller_context.message_to = self.message_to
|
||||
controller_context.message = self.message
|
||||
controller_context.register_controller = self.register_controller
|
||||
|
||||
return controller_context
|
||||
def _crete_controller_message_bus(self) -> ControllerMessageBus:
|
||||
controller_message_bus = ControllerMessageBus()
|
||||
controller_message_bus.message_to = self.message_to
|
||||
controller_message_bus.message = self.message
|
||||
controller_message_bus.register_controller = self.register_controller
|
||||
|
||||
return controller_message_bus
|
||||
|
||||
def register_controller(self, name: str, controller: ControllerBase):
|
||||
if not name or controller == None:
|
||||
@@ -38,7 +47,7 @@ class ControllerManager(Singleton, dict):
|
||||
f"Can't bind controller to existing registered name of '{name}'..."
|
||||
)
|
||||
|
||||
controller.set_controller_context( self._crete_controller_context() )
|
||||
controller.set_controller_message_bus( self.message_bus )
|
||||
|
||||
self[name] = controller
|
||||
|
||||
|
||||
30
src/libs/controllers/controller_message_bus.py
Normal file
30
src/libs/controllers/controller_message_bus.py
Normal file
@@ -0,0 +1,30 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from ..dto.base_event import BaseEvent
|
||||
|
||||
|
||||
|
||||
class ControllerMessageBusException(Exception):
|
||||
...
|
||||
|
||||
|
||||
|
||||
class ControllerMessageBus:
|
||||
def __init__(self):
|
||||
super(ControllerMessageBus, self).__init__()
|
||||
|
||||
|
||||
def message(self, event: BaseEvent):
|
||||
raise ControllerMessageBusException("Controller Message Bus 'message' must be overriden by Controller Manager...")
|
||||
|
||||
def message_to(self, name: str, event: BaseEvent):
|
||||
raise ControllerMessageBusException("Controller Message Bus 'message_to' must be overriden by Controller Manager...")
|
||||
|
||||
def message_to_selected(self, name: list, event: BaseEvent):
|
||||
raise ControllerMessageBusException("Controller Message Bus 'message_to_selected' must be overriden by Controller Manager...")
|
||||
|
||||
def register_controller(self, name: str, controller):
|
||||
raise ControllerMessageBusException("Controller Message Bus 'register_controller' must be overriden by Controller Manager...")
|
||||
@@ -8,6 +8,13 @@ from ..dto.base_event import BaseEvent
|
||||
|
||||
|
||||
class EmitDispatcher:
|
||||
"""
|
||||
EmitDispatcher is used for allowing controllers to pass/hook in
|
||||
their message system to children that need to signal events.
|
||||
Note how we are not handling return info from the 'message' methods
|
||||
whereas a controller would or could do so.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super(EmitDispatcher, self).__init__()
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ from dataclasses import dataclass, field
|
||||
|
||||
@dataclass(slots = True)
|
||||
class BaseEvent:
|
||||
topic: str = None
|
||||
content: any = None
|
||||
raw_content: any = None
|
||||
topic: str = None
|
||||
content: any = None
|
||||
raw_content: any = None
|
||||
success: callable = None
|
||||
fail: callable = None
|
||||
|
||||
@@ -9,6 +9,7 @@ from .register_command_event import RegisterCommandEvent
|
||||
from .file_externally_modified_event import FileExternallyModifiedEvent
|
||||
from .file_externally_deleted_event import FileExternallyDeletedEvent
|
||||
from .set_info_labels_event import SetInfoLabelsEvent
|
||||
from .populate_source_view_popup_event import PopulateSourceViewPopupEvent
|
||||
|
||||
from .get_new_command_system_event import GetNewCommandSystemEvent
|
||||
from .request_completion_event import RequestCompletionEvent
|
||||
@@ -21,7 +22,6 @@ from .set_active_file_event import SetActiveFileEvent
|
||||
|
||||
from .file_path_set_event import FilePathSetEvent
|
||||
from .added_new_file_event import AddedNewFileEvent
|
||||
from .swapped_file_event import SwappedFileEvent
|
||||
from .popped_file_event import PoppedFileEvent
|
||||
from .removed_file_event import RemovedFileEvent
|
||||
from .saved_file_event import SavedFileEvent
|
||||
@@ -29,6 +29,5 @@ from .saved_file_event import SavedFileEvent
|
||||
from .get_file_event import GetFileEvent
|
||||
from .get_swap_file_event import GetSwapFileEvent
|
||||
from .add_new_file_event import AddNewFileEvent
|
||||
from .swap_file_event import SwapFileEvent
|
||||
from .pop_file_event import PopFileEvent
|
||||
from .remove_file_event import RemoveFileEvent
|
||||
|
||||
18
src/libs/dto/code/populate_source_view_popup_event.py
Normal file
18
src/libs/dto/code/populate_source_view_popup_event.py
Normal file
@@ -0,0 +1,18 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
|
||||
gi.require_version('Gtk', '3.0')
|
||||
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from .code_event import CodeEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class PopulateSourceViewPopupEvent(CodeEvent):
|
||||
menu: Gtk.Widget = None
|
||||
@@ -1,13 +0,0 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .code_event import CodeEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class SwapFileEvent(CodeEvent):
|
||||
...
|
||||
@@ -1,13 +0,0 @@
|
||||
# Python imports
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
from .code_event import CodeEvent
|
||||
|
||||
|
||||
|
||||
@dataclass
|
||||
class SwappedFileEvent(CodeEvent):
|
||||
...
|
||||
@@ -4,4 +4,3 @@
|
||||
|
||||
from .source_view_states import SourceViewStates
|
||||
from .cursor_action import CursorAction
|
||||
from .move_direction import MoveDirection
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
# Python imports
|
||||
from enum import Enum
|
||||
|
||||
# Lib imports
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class MoveDirection(Enum):
|
||||
NONE = 0
|
||||
UP = 1
|
||||
DOWN = 2
|
||||
LEFT = 3
|
||||
RIGHT = 4
|
||||
@@ -15,18 +15,18 @@ class SingletonError(Exception):
|
||||
T = TypeVar('T', bound='Singleton')
|
||||
|
||||
class Singleton:
|
||||
_instance = None
|
||||
__instance = None
|
||||
|
||||
def __new__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
||||
if cls._instance is not None:
|
||||
if cls.__instance is not None:
|
||||
logger.debug(f"'{cls.__name__}' is a Singleton. Returning instance...")
|
||||
return cls._instance
|
||||
return cls.__instance
|
||||
|
||||
cls._instance = super(Singleton, cls).__new__(cls)
|
||||
return cls._instance
|
||||
cls.__instance = super(Singleton, cls).__new__(cls)
|
||||
return cls.__instance
|
||||
|
||||
def __init__(self) -> None:
|
||||
if self._instance is not None:
|
||||
if self.__instance is not None:
|
||||
return
|
||||
|
||||
super(Singleton, self).__init__()
|
||||
|
||||
@@ -15,15 +15,15 @@ class SingletonError(Exception):
|
||||
T = TypeVar('T', bound='SingletonRaised')
|
||||
|
||||
class SingletonRaised:
|
||||
_instance = None
|
||||
__instance = None
|
||||
|
||||
def __new__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
|
||||
if cls._instance is not None:
|
||||
if cls.__instance is not None:
|
||||
raise SingletonError(f"'{cls.__name__}' is a Singleton. Cannot create a new instance...")
|
||||
|
||||
cls._instance = super(SingletonRaised, cls).__new__(cls)
|
||||
return cls._instance
|
||||
cls.__instance = super(SingletonRaised, cls).__new__(cls)
|
||||
return cls.__instance
|
||||
|
||||
def __init__(self) -> None:
|
||||
if self._instance is not None:
|
||||
if self.__instance is not None:
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user