Wired tabs close and selection; improved files manager next index checking; code event focus ignore attrib added

This commit is contained in:
2025-12-28 22:44:44 -06:00
parent e18be655e8
commit 3fc39042f1
10 changed files with 133 additions and 76 deletions

View File

@@ -17,10 +17,10 @@ def execute(
logger.debug("Close File Command") logger.debug("Close File Command")
buffer = view.get_buffer() buffer = view.get_buffer()
sibling_file = view.files_manager.remove_file(buffer) next_file = view.files_manager.remove_file(buffer)
if not sibling_file: if not next_file:
view.command.exec("new_file") view.command.exec("new_file")
else: else:
view.set_buffer(sibling_file.buffer) view.set_buffer(next_file.buffer)
view.command.exec("update_info_bar") view.command.exec("update_info_bar")

View File

@@ -18,16 +18,15 @@ def execute(
if not view.sibling_left: return if not view.sibling_left: return
buffer = view.get_buffer() buffer = view.get_buffer()
popped_file, sibling_file = view.files_manager.swap_file(buffer) popped_file, next_file = view.files_manager.swap_file(buffer)
if sibling_file:
sibling_file.add_observer(view)
view.set_buffer(sibling_file.buffer)
else:
sibling_file = view.command.exec("new_file")
popped_file.remove_observer(view) popped_file.remove_observer(view)
popped_file.add_observer(view.sibling_left) popped_file.add_observer(view.sibling_left)
view.sibling_left.set_buffer(buffer) view.sibling_left.set_buffer(buffer)
view.sibling_left.grab_focus() view.sibling_left.grab_focus()
if next_file:
next_file.add_observer(view)
view.set_buffer(next_file.buffer)
else:
view.command.exec("new_file")

View File

@@ -18,17 +18,15 @@ def execute(
if not view.sibling_right: return if not view.sibling_right: return
buffer = view.get_buffer() buffer = view.get_buffer()
popped_file, sibling_file = view.files_manager.swap_file(buffer) popped_file, next_file = view.files_manager.swap_file(buffer)
if sibling_file:
sibling_file.add_observer(view)
view.set_buffer(sibling_file.buffer)
else:
sibling_file = view.command.exec("new_file")
popped_file.remove_observer(view) popped_file.remove_observer(view)
popped_file.add_observer(view.sibling_right) popped_file.add_observer(view.sibling_right)
view.sibling_right.set_buffer(buffer) view.sibling_right.set_buffer(buffer)
view.sibling_right.grab_focus() view.sibling_right.grab_focus()
if next_file:
next_file.add_observer(view)
view.set_buffer(next_file.buffer)
else:
view.command.exec("new_file")

View File

@@ -0,0 +1,36 @@
# Python imports
# Lib imports
import gi
gi.require_version('GtkSource', '4')
from gi.repository import GtkSource
# Application imports
from ..source_file import SourceFile
def execute(
view: GtkSource.View,
file: SourceFile
):
logger.debug("Set Buffer Command")
buffer = view.get_buffer()
_file = view.files_manager.get_file(buffer)
_file.remove_observer(view)
if not file:
view.command.exec("new_file")
return
view.set_buffer(file.buffer)
file.add_observer(view)
has_focus = view.command.exec("has_focus")
if has_focus:
view.command.exec("update_info_bar")

View File

@@ -37,11 +37,17 @@ class SourceViewEventsMixin:
return True return True
def notification(self, event: CodeEvent): def notification(self, event: CodeEvent):
has_focus = self.command.exec("has_focus") if not hasattr(self, "command"): return
if not has_focus: return
has_focus = self.command.exec("has_focus")
if not has_focus and not event.ignore_focus: return
self.command.exec("update_info_bar")
match event.etype: match event.etype:
case "removed_file":
logger.debug("SourceFileManager.remove_file")
if not event.file.buffer == self.get_buffer(): return
self.command.exec_with_args("set_buffer", (self, event.next_file))
return
case "changed": case "changed":
logger.debug("SourceFile._changed") logger.debug("SourceFile._changed")
case "modified_changed": case "modified_changed":
@@ -54,3 +60,4 @@ class SourceViewEventsMixin:
case _: case _:
... ...
self.command.exec("update_info_bar")

View File

@@ -29,8 +29,8 @@ class SourceFilesManager(Singleton, list, ObservableMixin):
super().append(file) super().append(file)
event = CodeEvent() event = CodeEvent()
event.file = file
event.etype = "appended_file" event.etype = "appended_file"
event.file = file
self.notify_observers(event) self.notify_observers(event)
@@ -47,23 +47,17 @@ class SourceFilesManager(Singleton, list, ObservableMixin):
for i, file in enumerate(self): for i, file in enumerate(self):
if not buffer == file.buffer: continue if not buffer == file.buffer: continue
popped_file = self.pop(i) j = self.next_index(i)
sibling_file = None next_file = self[j] if not j == -1 else None
size = len(self) popped_file = self.pop(i)
event = CodeEvent()
if size == 0: event.etype = "popped_file"
return popped_file, sibling_file event.file = popped_file
event.next_file = next_file
j = 0 if size == 1 else i - 1 if i > 1 else i + 1
sibling_file = self[j]
event = CodeEvent()
event.file = popped_file
event.etype = "popped_file"
self.notify_observers(event) self.notify_observers(event)
return popped_file, sibling_file return popped_file, next_file
def swap_file(self, buffer: SourceBuffer): def swap_file(self, buffer: SourceBuffer):
if not buffer: return if not buffer: return
@@ -71,38 +65,42 @@ class SourceFilesManager(Singleton, list, ObservableMixin):
for i, file in enumerate(self): for i, file in enumerate(self):
if not buffer == file.buffer: continue if not buffer == file.buffer: continue
swapped_file = self[i] j = self.next_index(i)
sibling_file = None next_file = self[j]
size = len(self) swapped_file = self[j] if not j == -1 else None
if size == 0: return swapped_file, next_file
return swapped_file, sibling_file
j = 0 if size == 1 else i - 1 if i > 1 else i + 1
sibling_file = self[j]
return swapped_file, sibling_file
def remove_file(self, buffer: SourceBuffer): def remove_file(self, buffer: SourceBuffer):
if not buffer: return if not buffer: return
for i, file in enumerate(self): for i, file in enumerate(self):
if not buffer == file.buffer: continue if not buffer == file.buffer: continue
self.remove(file)
event = CodeEvent()
event.file = file
event.etype = "removed_file"
j = self.next_index(i)
next_file = self[j] if not j == -1 else None
event = CodeEvent()
event.etype = "removed_file"
event.ignore_focus = True
event.file = file
event.next_file = next_file
self.notify_observers(event) self.notify_observers(event)
size = len(self) self.remove(file)
if size == 0:
return None
j = 0 if size == 1 else i - 1 if i > 1 else i + 1
sibling_file = self[j]
file.close() file.close()
return sibling_file return next_file
def next_index(self, i):
size = len(self)
if (i == 0) & (size >= 2):
j = i + 1
elif (i == (size - 1)) & (size >= 2):
j = i - 1
elif (size - 1) == 0:
j = -1
else:
j = i + 1
return j

View File

@@ -13,7 +13,8 @@ class TabWidget(Gtk.Box):
def __init__(self): def __init__(self):
super(TabWidget, self).__init__() super(TabWidget, self).__init__()
self.file = None self._handler_ids: list = []
self.file = None
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
@@ -34,8 +35,9 @@ class TabWidget(Gtk.Box):
... ...
def _load_widgets(self): def _load_widgets(self):
self.label = Gtk.Label(label="") self._label_eve_box = Gtk.EventBox()
self.close_btn = Gtk.Button(label="X") self.label = Gtk.Label(label = "")
self.close_btn = Gtk.Button(label = "X")
ctx = self.label.get_style_context() ctx = self.label.get_style_context()
ctx.add_class("tab-label") ctx.add_class("tab-label")
@@ -44,10 +46,19 @@ class TabWidget(Gtk.Box):
self.label.set_hexpand(True) self.label.set_hexpand(True)
self.add(self.label) self._label_eve_box.add(self.label)
self.add(self._label_eve_box)
self.add(self.close_btn) self.add(self.close_btn)
def __del__(self): def __del__(self):
# for handle_id in self._handler_ids: for handle_id in self._handler_ids:
# self.disconnect(handle_id) self.disconnect(handle_id)
... del self.file
def set_select_signal(self, callback):
_id = self._label_eve_box.connect('button-release-event', callback, self.file)
self._handler_ids.append(_id)
def set_close_signal(self, callback):
_id = self.close_btn.connect('button-release-event', callback, self.file)
self._handler_ids.append(_id)

View File

@@ -20,7 +20,7 @@ class TabsWidget(Gtk.ScrolledWindow):
def __init__(self): def __init__(self):
super(TabsWidget, self).__init__() super(TabsWidget, self).__init__()
self.active_view: SourceView = None self.active_view: SourceView = None
self._setup_styling() self._setup_styling()
self._setup_signals() self._setup_signals()
@@ -77,8 +77,16 @@ class TabsWidget(Gtk.ScrolledWindow):
tab.label.set_label(event.file.fname) tab.label.set_label(event.file.fname)
event.file.add_observer(self) event.file.add_observer(self)
def select_signal(widget, eve, file):
self.active_view.command.exec_with_args("set_buffer", (self.active_view, file))
def close_signal(widget, eve, file):
self.files_manager.remove_file(file.buffer)
tab.set_select_signal(select_signal)
tab.set_close_signal(close_signal)
self.tabs.add(tab) self.tabs.add(tab)
tab.show()
def remove_tab(self, event: CodeEvent): def remove_tab(self, event: CodeEvent):
for child in self.tabs.get_children(): for child in self.tabs.get_children():
@@ -86,8 +94,6 @@ class TabsWidget(Gtk.ScrolledWindow):
child.file.remove_observer(self) child.file.remove_observer(self)
self.tabs.remove(child) self.tabs.remove(child)
del child.file
del child del child
return return

View File

@@ -110,4 +110,4 @@ class SourceView(GtkSource.View, ObservableMixin, SourceViewEventsMixin, SourceV
def set_files_manager(self, files_manager: SourceFilesManager): def set_files_manager(self, files_manager: SourceFilesManager):
self.files_manager = files_manager self.files_manager = files_manager
# self.files_manager.add_observer(self) self.files_manager.add_observer(self)

View File

@@ -10,7 +10,9 @@ from .observable_event import ObservableEvent
@dataclass @dataclass
class CodeEvent(ObservableEvent): class CodeEvent(ObservableEvent):
etype: str = "" etype: str = ""
view: any = None ignore_focus: bool = False
file: any = None view: any = None
buffer: any = None file: any = None
next_file: any = None
buffer: any = None