generated from itdominator/Python-With-Gtk-Template
More tab inferastructure setup
This commit is contained in:
parent
2dcfdabe37
commit
729b3850a0
@ -8,74 +8,8 @@ from gi.repository import Gtk
|
|||||||
# Application imports
|
# Application imports
|
||||||
from ..widgets.separator_widget import Separator
|
from ..widgets.separator_widget import Separator
|
||||||
from ..widgets.miniview_widget import MiniViewWidget
|
from ..widgets.miniview_widget import MiniViewWidget
|
||||||
from ..widgets.base.notebook.editor_notebook import EditorNotebook
|
from .editors_paned import EditorsPaned
|
||||||
|
|
||||||
from ..widgets.controls.tab_bar import TabBar
|
|
||||||
from .fixed_box import FixedBox
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class EditorsPaned(Gtk.Paned):
|
|
||||||
def __init__(self):
|
|
||||||
super(EditorsPaned, self).__init__()
|
|
||||||
|
|
||||||
self._setup_styling()
|
|
||||||
self._setup_signals()
|
|
||||||
self._subscribe_to_events()
|
|
||||||
self._load_widgets()
|
|
||||||
|
|
||||||
self.show()
|
|
||||||
|
|
||||||
|
|
||||||
def _setup_styling(self):
|
|
||||||
self.set_wide_handle(True)
|
|
||||||
|
|
||||||
def _setup_signals(self):
|
|
||||||
...
|
|
||||||
|
|
||||||
def _subscribe_to_events(self):
|
|
||||||
event_system.subscribe("update_paned_handle", self._update_paned_handle)
|
|
||||||
|
|
||||||
def _load_widgets(self):
|
|
||||||
left_view = Gtk.Box()
|
|
||||||
right_view = Gtk.Box()
|
|
||||||
|
|
||||||
left_view.add( TabBar() )
|
|
||||||
left_view.add( FixedBox() )
|
|
||||||
|
|
||||||
right_view.add( TabBar() )
|
|
||||||
right_view.add( FixedBox() )
|
|
||||||
|
|
||||||
left_view.set_orientation( Gtk.Orientation.VERTICAL )
|
|
||||||
right_view.set_orientation( Gtk.Orientation.VERTICAL )
|
|
||||||
|
|
||||||
left_view.show()
|
|
||||||
right_view.show()
|
|
||||||
|
|
||||||
self.add1(left_view)
|
|
||||||
self.add2(right_view)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# self.add1(FixedBox())
|
|
||||||
# self.add2(FixedBox())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# self.add1(EditorNotebook())
|
|
||||||
# self.add2(EditorNotebook())
|
|
||||||
|
|
||||||
def _update_paned_handle(self):
|
|
||||||
rect = self.get_allocation()
|
|
||||||
pos = -1
|
|
||||||
|
|
||||||
try:
|
|
||||||
size = rect.width / 2
|
|
||||||
pos = int(size)
|
|
||||||
except:
|
|
||||||
...
|
|
||||||
|
|
||||||
self.set_position(size)
|
|
||||||
|
|
||||||
|
|
||||||
class EditorsContainer(Gtk.Box):
|
class EditorsContainer(Gtk.Box):
|
||||||
|
52
src/core/containers/editors_paned.py
Normal file
52
src/core/containers/editors_paned.py
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class EditorsPaned(Gtk.Paned):
|
||||||
|
def __init__(self):
|
||||||
|
super(EditorsPaned, self).__init__()
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._subscribe_to_events()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
self.set_wide_handle(True)
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _subscribe_to_events(self):
|
||||||
|
event_system.subscribe("update_paned_handle", self._update_paned_handle)
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
self.add1( Editor() )
|
||||||
|
self.add2( Editor() )
|
||||||
|
|
||||||
|
# self.add1( EditorNotebook() )
|
||||||
|
# self.add2( EditorNotebook() )
|
||||||
|
|
||||||
|
def _update_paned_handle(self):
|
||||||
|
rect = self.get_allocation()
|
||||||
|
pos = -1
|
||||||
|
|
||||||
|
try:
|
||||||
|
size = rect.width / 2
|
||||||
|
pos = int(size)
|
||||||
|
except:
|
||||||
|
...
|
||||||
|
|
||||||
|
self.set_position(size)
|
@ -14,7 +14,6 @@ from ..mixins.signals_mixins import SignalsMixins
|
|||||||
from ..containers.core_widget import CoreWidget
|
from ..containers.core_widget import CoreWidget
|
||||||
from .base_controller_data import BaseControllerData
|
from .base_controller_data import BaseControllerData
|
||||||
from .bridge_controller import BridgeController
|
from .bridge_controller import BridgeController
|
||||||
from .files_controller import FilesController
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +58,6 @@ class BaseController(SignalsMixins, BaseControllerData):
|
|||||||
|
|
||||||
def _load_controllers(self):
|
def _load_controllers(self):
|
||||||
BridgeController()
|
BridgeController()
|
||||||
FilesController()
|
|
||||||
|
|
||||||
def load_glade_file(self):
|
def load_glade_file(self):
|
||||||
self.builder = Gtk.Builder()
|
self.builder = Gtk.Builder()
|
||||||
|
@ -26,14 +26,17 @@ class BridgeController:
|
|||||||
def handle_bridge_event(self, event):
|
def handle_bridge_event(self, event):
|
||||||
match event.topic:
|
match event.topic:
|
||||||
case "save":
|
case "save":
|
||||||
event_system.emit("handle_file_event", (event,))
|
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||||
case "close":
|
case "close":
|
||||||
event_system.emit("handle_file_event", (event,))
|
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||||
|
case "load_buffer":
|
||||||
|
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||||
|
# case "add_tab":
|
||||||
|
# event_system.emit(f"add_tab_{event.originator}", (event,))
|
||||||
|
|
||||||
case "error":
|
case "error":
|
||||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||||
logger.info(content)
|
logger.info(content)
|
||||||
case _:
|
case _:
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -12,8 +12,9 @@ from gi.repository import Gtk
|
|||||||
|
|
||||||
|
|
||||||
class FilesController:
|
class FilesController:
|
||||||
def __init__(self):
|
def __init__(self, index):
|
||||||
|
|
||||||
|
self.INDEX = index
|
||||||
self.opened_files = {}
|
self.opened_files = {}
|
||||||
|
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
@ -24,8 +25,8 @@ class FilesController:
|
|||||||
...
|
...
|
||||||
|
|
||||||
def _subscribe_to_events(self):
|
def _subscribe_to_events(self):
|
||||||
event_system.subscribe("set_pre_drop_dnd", self.set_pre_drop_dnd)
|
event_system.subscribe(f"set_pre_drop_dnd_{self.INDEX}", self.set_pre_drop_dnd)
|
||||||
event_system.subscribe("handle_file_event", self.handle_file_event)
|
event_system.subscribe(f"handle_file_event_{self.INDEX}", self.handle_file_event)
|
||||||
|
|
||||||
def set_pre_drop_dnd(self, gfiles):
|
def set_pre_drop_dnd(self, gfiles):
|
||||||
keys = self.opened_files.keys()
|
keys = self.opened_files.keys()
|
||||||
@ -46,37 +47,38 @@ class FilesController:
|
|||||||
def handle_file_event(self, event):
|
def handle_file_event(self, event):
|
||||||
match event.topic:
|
match event.topic:
|
||||||
case "save":
|
case "save":
|
||||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||||
self.save_session(event.target, content)
|
basename = self.save_session(event.target, content)
|
||||||
|
|
||||||
|
if basename:
|
||||||
|
event_system.emit(f"updated_tab_{event.originator}", (event.target, basename,))
|
||||||
case "close":
|
case "close":
|
||||||
self.close_session(event.target)
|
self.close_session(event.target)
|
||||||
|
case "load_buffer":
|
||||||
|
self.load_buffer(event.target)
|
||||||
|
event_system.emit(f"add_tab_{event.originator}", (event.target, "buffer",))
|
||||||
case _:
|
case _:
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def load_buffer(self, fhash):
|
||||||
|
self.opened_files[fhash] = {"file": None, "ftype": "buffer"}
|
||||||
|
|
||||||
def save_session(self, fhash, content):
|
def save_session(self, fhash, content):
|
||||||
keys = self.opened_files.keys()
|
ftype = self.opened_files[fhash]["ftype"]
|
||||||
gfile = event_system.emit_and_await(
|
gfile = event_system.emit_and_await(
|
||||||
"save_file_dialog", ("", None)
|
"save_file_dialog", ("", None)
|
||||||
) if not fhash in keys else self.opened_files[fhash]["file"]
|
) if fhash == "buffer" else self.opened_files[fhash]["file"]
|
||||||
|
|
||||||
if not gfile: return
|
|
||||||
|
|
||||||
file_written = self.write_to_file(fhash, gfile, content)
|
file_written = self.write_to_file(fhash, gfile, content)
|
||||||
if not fhash in keys and file_written:
|
if fhash == "buffer" and file_written:
|
||||||
self.insert_to_sessions(fhash, gfile)
|
self.update_session(fhash, gfile)
|
||||||
event_system.emit(
|
return gfile.get_basename()
|
||||||
"updated_tab",
|
|
||||||
(
|
|
||||||
self.opened_files[fhash]["ftype"],
|
|
||||||
gfile.get_basename(),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def close_session(self, target):
|
def close_session(self, target):
|
||||||
del self.opened_files[target]
|
del self.opened_files[target]
|
||||||
|
|
||||||
def insert_to_sessions(self, fhash, gfile):
|
def update_session(self, fhash, gfile):
|
||||||
info = gfile.query_info("standard::*", 0, cancellable = None)
|
info = gfile.query_info("standard::*", 0, cancellable = None)
|
||||||
ftype = info.get_content_type().replace("x-", "").split("/")[1]
|
ftype = info.get_content_type().replace("x-", "").split("/")[1]
|
||||||
|
|
||||||
|
@ -15,10 +15,11 @@ from libs.data_types import Event
|
|||||||
|
|
||||||
|
|
||||||
class AceEditor(WebKit2.WebView):
|
class AceEditor(WebKit2.WebView):
|
||||||
def __init__(self):
|
def __init__(self, index):
|
||||||
super(AceEditor, self).__init__()
|
super(AceEditor, self).__init__()
|
||||||
|
|
||||||
# self.get_context().set_sandbox_enabled(False)
|
# self.get_context().set_sandbox_enabled(False)
|
||||||
|
self.INDEX = index
|
||||||
|
|
||||||
self._load_settings()
|
self._load_settings()
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
@ -42,11 +43,11 @@ class AceEditor(WebKit2.WebView):
|
|||||||
...
|
...
|
||||||
|
|
||||||
def _subscribe_to_events(self):
|
def _subscribe_to_events(self):
|
||||||
event_system.subscribe("load_file", self.load_file)
|
event_system.subscribe(f"load_file_{self.INDEX}", self.load_file)
|
||||||
|
event_system.subscribe(f"new_session_{self.INDEX}", self.new_session)
|
||||||
event_system.subscribe("updated_tab", self.updated_tab)
|
event_system.subscribe(f"switch_session_{self.INDEX}", self.switch_session)
|
||||||
event_system.subscribe("ui_message", self.ui_message)
|
event_system.subscribe(f"close_session_{self.INDEX}", self.close_session)
|
||||||
|
event_system.subscribe(f"ui_message_{self.INDEX}", self.ui_message)
|
||||||
|
|
||||||
def _load_settings(self):
|
def _load_settings(self):
|
||||||
self.set_settings( WebkitUISettings() )
|
self.set_settings( WebkitUISettings() )
|
||||||
@ -72,6 +73,7 @@ class AceEditor(WebKit2.WebView):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
event = Event( **json.loads(message) )
|
event = Event( **json.loads(message) )
|
||||||
|
event.originator = self.INDEX
|
||||||
event_system.emit("handle_bridge_event", (event,))
|
event_system.emit("handle_bridge_event", (event,))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.info(e)
|
logger.info(e)
|
||||||
@ -80,8 +82,16 @@ class AceEditor(WebKit2.WebView):
|
|||||||
command = f"loadFile('{ftype}', '{fhash}', '{file}', '{content}')"
|
command = f"loadFile('{ftype}', '{fhash}', '{file}', '{content}')"
|
||||||
self.run_javascript(command, None, None)
|
self.run_javascript(command, None, None)
|
||||||
|
|
||||||
def updated_tab(self, ftype, fname):
|
def new_session(self):
|
||||||
command = f"updatedTab('{ftype}', '{fname}')"
|
command = f"newSession()"
|
||||||
|
self.run_javascript(command, None, None)
|
||||||
|
|
||||||
|
def switch_session(self, fhash):
|
||||||
|
command = f"switchSession('{fhash}')"
|
||||||
|
self.run_javascript(command, None, None)
|
||||||
|
|
||||||
|
def close_session(self, fhash):
|
||||||
|
command = f"closeSession('{fhash}')"
|
||||||
self.run_javascript(command, None, None)
|
self.run_javascript(command, None, None)
|
||||||
|
|
||||||
def ui_message(self, message, mtype):
|
def ui_message(self, message, mtype):
|
||||||
|
48
src/core/widgets/base/webkit/editor.py
Normal file
48
src/core/widgets/base/webkit/editor.py
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
# Python imports
|
||||||
|
|
||||||
|
# Lib imports
|
||||||
|
import gi
|
||||||
|
gi.require_version('Gtk', '3.0')
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
# Application imports
|
||||||
|
from ....controllers.files_controller import FilesController
|
||||||
|
from ...controls.tab_bar import TabBar
|
||||||
|
from .fixed_box import FixedBox
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Editor(Gtk.Box):
|
||||||
|
ccount = 0
|
||||||
|
|
||||||
|
def __new__(cls, *args, **kwargs):
|
||||||
|
obj = super(Editor, cls).__new__(cls)
|
||||||
|
cls.ccount += 1
|
||||||
|
|
||||||
|
return obj
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(Editor, self).__init__()
|
||||||
|
|
||||||
|
self.INDEX = self.ccount
|
||||||
|
|
||||||
|
self._setup_styling()
|
||||||
|
self._setup_signals()
|
||||||
|
self._subscribe_to_events()
|
||||||
|
self._load_widgets()
|
||||||
|
|
||||||
|
self.show()
|
||||||
|
|
||||||
|
|
||||||
|
def _setup_styling(self):
|
||||||
|
self.set_orientation( Gtk.Orientation.VERTICAL )
|
||||||
|
|
||||||
|
def _setup_signals(self):
|
||||||
|
...
|
||||||
|
|
||||||
|
def _subscribe_to_events(self):
|
||||||
|
FilesController(self.INDEX)
|
||||||
|
|
||||||
|
def _load_widgets(self):
|
||||||
|
self.add( TabBar(self.INDEX) )
|
||||||
|
self.add( FixedBox(self.INDEX) )
|
@ -6,8 +6,8 @@ gi.require_version('Gtk', '3.0')
|
|||||||
from gi.repository import Gtk
|
from gi.repository import Gtk
|
||||||
|
|
||||||
# Application imports
|
# Application imports
|
||||||
from ..widgets.base.webkit.dnd_box import DnDBox
|
from .dnd_box import DnDBox
|
||||||
from ..widgets.base.webkit.ace_editor import AceEditor
|
from .ace_editor import AceEditor
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -17,8 +17,10 @@ class FixedBox(Gtk.Fixed):
|
|||||||
(aka our DnDBox) above the Webkit2.Webview to intercept and proxy accordingly.
|
(aka our DnDBox) above the Webkit2.Webview to intercept and proxy accordingly.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, index):
|
||||||
super(FixedBox, self).__init__()
|
super(FixedBox, self).__init__()
|
||||||
|
|
||||||
|
self.INDEX = index
|
||||||
|
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
self._setup_signals()
|
self._setup_signals()
|
||||||
@ -39,7 +41,7 @@ class FixedBox(Gtk.Fixed):
|
|||||||
...
|
...
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
self.ace_editor = AceEditor()
|
self.ace_editor = AceEditor(self.INDEX)
|
||||||
self.dnd_box = DnDBox()
|
self.dnd_box = DnDBox()
|
||||||
|
|
||||||
self.add( self.ace_editor )
|
self.add( self.ace_editor )
|
@ -11,9 +11,11 @@ from ..tab_header_widget import TabHeaderWidget
|
|||||||
|
|
||||||
|
|
||||||
class TabBar(Gtk.Notebook):
|
class TabBar(Gtk.Notebook):
|
||||||
def __init__(self):
|
def __init__(self, index):
|
||||||
super(TabBar, self).__init__()
|
super(TabBar, self).__init__()
|
||||||
|
|
||||||
|
self.INDEX = index
|
||||||
|
|
||||||
self.set_group_name("editor_widget")
|
self.set_group_name("editor_widget")
|
||||||
|
|
||||||
self._setup_styling()
|
self._setup_styling()
|
||||||
@ -29,12 +31,10 @@ class TabBar(Gtk.Notebook):
|
|||||||
|
|
||||||
def _setup_signals(self):
|
def _setup_signals(self):
|
||||||
self.connect("switch-page", self._switch_page_update)
|
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):
|
def _subscribe_to_events(self):
|
||||||
...
|
event_system.subscribe(f"add_tab_{self.INDEX}", self.add_tab)
|
||||||
|
event_system.subscribe(f"update_tab_{self.INDEX}", self.update_tab)
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
start_box = Gtk.Box()
|
start_box = Gtk.Box()
|
||||||
@ -51,28 +51,50 @@ class TabBar(Gtk.Notebook):
|
|||||||
self.set_action_widget(start_box, 0)
|
self.set_action_widget(start_box, 0)
|
||||||
self.set_action_widget(end_box, 1)
|
self.set_action_widget(end_box, 1)
|
||||||
|
|
||||||
self.add_tab_click(None)
|
|
||||||
|
|
||||||
def _switch_page_update(self, notebook, page, page_num):
|
def _switch_page_update(self, notebook, page, page_num):
|
||||||
|
print(page_num)
|
||||||
...
|
...
|
||||||
|
|
||||||
def add_tab_click(self, widget):
|
def add_tab_click(self, widget):
|
||||||
container = Gtk.Box()
|
event_system.emit(f"new_session_{self.INDEX}")
|
||||||
page_num = self.append_page(container, TabHeaderWidget(container, self._close_tab))
|
|
||||||
|
|
||||||
|
def add_tab(self, fhash, title = "[BAD TITLE]"):
|
||||||
|
container = Gtk.EventBox()
|
||||||
|
header = TabHeaderWidget(container, self._close_tab)
|
||||||
|
page_num = self.append_page(container, header)
|
||||||
|
|
||||||
|
container.fhash = fhash
|
||||||
|
|
||||||
|
header.label.set_label(title)
|
||||||
self.set_tab_detachable(container, True)
|
self.set_tab_detachable(container, True)
|
||||||
self.set_tab_reorderable(container, True)
|
self.set_tab_reorderable(container, True)
|
||||||
|
|
||||||
self.show_all()
|
self.show_all()
|
||||||
self.set_current_page(page_num)
|
self.set_current_page(page_num)
|
||||||
|
|
||||||
|
def update_tab(self, fhash, title = "[BAD TITLE]"):
|
||||||
|
container = Gtk.EventBox()
|
||||||
|
header = TabHeaderWidget(container, self._close_tab)
|
||||||
|
page_num = self.append_page(container, header)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
# Note: Need to get parent instead given we pass the close_tab method
|
# Note: Need to get parent instead given we pass the close_tab method
|
||||||
# from a potentially former notebook.
|
# from a potentially former notebook.
|
||||||
def _close_tab(self, widget, container):
|
def _close_tab(self, widget, container):
|
||||||
notebook = container.get_parent()
|
notebook = container.get_parent()
|
||||||
page_num = notebook.page_num(container)
|
|
||||||
notebook.remove_page(page_num)
|
|
||||||
|
|
||||||
|
if notebook.get_n_pages() < 2: return
|
||||||
|
|
||||||
|
page_num = notebook.page_num(container)
|
||||||
|
|
||||||
|
event_system.emit(f"close_session_{self.INDEX}", (container.fhash))
|
||||||
|
notebook.remove_page(page_num)
|
||||||
|
|
||||||
|
|
||||||
# def close_tab(self, button, container, source_view, eve = None):
|
# def close_tab(self, button, container, source_view, eve = None):
|
||||||
@ -91,6 +113,4 @@ class TabBar(Gtk.Notebook):
|
|||||||
|
|
||||||
# if notebook.NAME == "notebook_2" and notebook.get_n_pages() == 0:
|
# if notebook.NAME == "notebook_2" and notebook.get_n_pages() == 0:
|
||||||
# notebook.hide()
|
# notebook.hide()
|
||||||
# event_system.emit("focused_target_changed", ("notebook_1",))
|
# event_system.emit("focused_target_changed", ("notebook_1",))
|
||||||
|
|
||||||
|
|
@ -37,20 +37,20 @@ class TabHeaderWidget(Gtk.Box):
|
|||||||
...
|
...
|
||||||
|
|
||||||
def _load_widgets(self):
|
def _load_widgets(self):
|
||||||
label = Gtk.Label(label = "buffer")
|
self.label = Gtk.Label(label = "buffer")
|
||||||
close = Gtk.Button()
|
close = Gtk.Button()
|
||||||
icon = Gtk.Image(stock = Gtk.STOCK_CLOSE)
|
icon = Gtk.Image(stock = Gtk.STOCK_CLOSE)
|
||||||
|
|
||||||
# TODO: Setup with settings and from file
|
# TODO: Setup with settings and from file
|
||||||
label.set_xalign(0.0)
|
self.label.set_xalign(0.0)
|
||||||
label.set_margin_left(25)
|
self.label.set_margin_left(25)
|
||||||
label.set_margin_right(25)
|
self.label.set_margin_right(25)
|
||||||
label.set_hexpand(True)
|
self.label.set_hexpand(True)
|
||||||
|
|
||||||
close.set_always_show_image(True)
|
close.set_always_show_image(True)
|
||||||
close.set_hexpand(False)
|
close.set_hexpand(False)
|
||||||
close.set_image( Gtk.Image.new_from_icon_name("gtk-close", 4) )
|
close.set_image( Gtk.Image.new_from_icon_name("gtk-close", 4) )
|
||||||
close.connect("released", self.close_tab, *(self.content,))
|
close.connect("released", self.close_tab, *(self.content,))
|
||||||
|
|
||||||
self.add(label)
|
self.add(self.label)
|
||||||
self.add(close)
|
self.add(close)
|
@ -13,3 +13,4 @@ class Event:
|
|||||||
topic: str
|
topic: str
|
||||||
target: str
|
target: str
|
||||||
content: str
|
content: str
|
||||||
|
originator: int = -1
|
@ -14,27 +14,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<div id="page-alert-zone" class="col">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="container editor-container">
|
<div class="container editor-container">
|
||||||
<div class="row">
|
|
||||||
<div class="col col-md-10 scroller">
|
|
||||||
<ul class="nav nav-tabs">
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
<div class="col col-auto align-self-end">
|
|
||||||
<ul>
|
|
||||||
<li id="add-tab-icon" class="add-session-bottom" role="presentation" onclick="newSession(this)">
|
|
||||||
<a href="#">
|
|
||||||
<i class="bi bi-plus-square" aria-hidden="true"></i>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<pre id="editor">
|
<pre id="editor">
|
||||||
@ -43,12 +23,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
|
||||||
<div id="status-bar">Status Bar: ...</div>
|
|
||||||
</p>
|
|
||||||
|
|
||||||
|
|
||||||
<!-- For internal scripts... -->
|
<!-- For internal scripts... -->
|
||||||
<!-- <script src="js/libs/jquery-3.7.1.min.js"></script> -->
|
<!-- <script src="js/libs/jquery-3.7.1.min.js"></script> -->
|
||||||
|
|
||||||
@ -64,14 +38,13 @@
|
|||||||
<script src="resources/js/libs/ace_editor/ext-settings_menu.js"></script>
|
<script src="resources/js/libs/ace_editor/ext-settings_menu.js"></script>
|
||||||
<script src="resources/js/libs/ace_editor/ace-linters.js"></script>
|
<script src="resources/js/libs/ace_editor/ace-linters.js"></script>
|
||||||
|
|
||||||
|
|
||||||
<!-- For Application... -->
|
<!-- For Application... -->
|
||||||
<!-- <script src="resources/js/newton/ajax.js"></script> -->
|
<!-- <script src="resources/js/newton/ajax.js"></script> -->
|
||||||
<!-- <script src="resources/js/newton/post-ajax.js"></script> -->
|
<!-- <script src="resources/js/newton/post-ajax.js"></script> -->
|
||||||
|
|
||||||
<script src="resources/js/newton/dnd-sort.js"></script>
|
<script src="resources/js/newton/globals.js"></script>
|
||||||
<script src="resources/js/newton/keybinding-newton.js"></script>
|
|
||||||
<script src="resources/js/newton/utils.js"></script>
|
<script src="resources/js/newton/utils.js"></script>
|
||||||
|
<script src="resources/js/newton/keybinding-newton.js"></script>
|
||||||
<script src="resources/js/newton/ui-logic.js"></script>
|
<script src="resources/js/newton/ui-logic.js"></script>
|
||||||
<script src="resources/js/newton/events.js"></script>
|
<script src="resources/js/newton/events.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
// Taken from: https://stackoverflow.com/questions/10588607/tutorial-for-html5-dragdrop-sortable-list
|
|
||||||
|
|
||||||
let dndSelected = null
|
|
||||||
|
|
||||||
function dragOver(e) {
|
|
||||||
if (isBefore(dndSelected, e.target)) {
|
|
||||||
e.target.parentNode.insertBefore(dndSelected, e.target);
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
e.target.parentNode.insertBefore(dndSelected, e.target.nextSibling);
|
|
||||||
} catch(e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragEnd() {
|
|
||||||
dndSelected = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function dragStart(e) {
|
|
||||||
e.dataTransfer.effectAllowed = 'move';
|
|
||||||
e.dataTransfer.setData('text/plain', null);
|
|
||||||
dndSelected = e.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isBefore(el1, el2) {
|
|
||||||
let cur;
|
|
||||||
if (el2.parentNode === el1.parentNode) {
|
|
||||||
for (cur = el1.previousSibling; cur; cur = cur.previousSibling) {
|
|
||||||
if (cur === el2) return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
@ -1,17 +1,11 @@
|
|||||||
const messenger = (window.webkit) ? window.webkit.messageHandlers : (message) => {
|
|
||||||
console.log("Message: " + message);
|
|
||||||
};
|
|
||||||
|
|
||||||
let aceSessions = {};
|
|
||||||
let currentSession = null;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
window.onload = (eve) => {
|
window.onload = (eve) => {
|
||||||
console.log("Loaded...");
|
loadEditor();
|
||||||
loadInitialSessions();
|
loadInitialSessionTab();
|
||||||
|
|
||||||
|
console.log("Window Loaded...");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
window.onerror = function(msg, url, line, col, error) {
|
window.onerror = function(msg, url, line, col, error) {
|
||||||
// Note that col & error are new to the HTML 5 spec and may not be supported in every browser.
|
// Note that col & error are new to the HTML 5 spec and may not be supported in every browser.
|
||||||
const suppressErrorAlert = false;
|
const suppressErrorAlert = false;
|
||||||
@ -23,35 +17,4 @@ window.onerror = function(msg, url, line, col, error) {
|
|||||||
|
|
||||||
// If you return true, then error alerts (like in older versions of Internet Explorer) will be suppressed.
|
// If you return true, then error alerts (like in older versions of Internet Explorer) will be suppressed.
|
||||||
return suppressErrorAlert;
|
return suppressErrorAlert;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ace.require("ace/ext/language_tools");
|
|
||||||
let StatusBar = ace.require('ace/ext/statusbar').StatusBar;
|
|
||||||
|
|
||||||
|
|
||||||
let editor = ace.edit("editor");
|
|
||||||
// Note: https://github.com/ajaxorg/ace/wiki/Configuring-Ace
|
|
||||||
editor.setOptions({
|
|
||||||
printMarginColumn: 80,
|
|
||||||
enableBasicAutocompletion: true,
|
|
||||||
enableInlineAutocompletion: true,
|
|
||||||
enableSnippets: true,
|
|
||||||
enableLiveAutocompletion: true,
|
|
||||||
highlightActiveLine: true,
|
|
||||||
useSoftTabs: true,
|
|
||||||
tabSize: 4,
|
|
||||||
tooltipFollowsMouse: true,
|
|
||||||
useWrapMode: false,
|
|
||||||
scrollPastEnd: 0.5,
|
|
||||||
mergeUndoDeltas: false
|
|
||||||
});
|
|
||||||
|
|
||||||
// Note: https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts
|
|
||||||
editor.commands.addCommands(editorCommands);
|
|
||||||
|
|
||||||
editor.setTheme("ace/theme/one_dark");
|
|
||||||
const statusBar = new StatusBar(editor, document.getElementById('status-bar'));
|
|
@ -0,0 +1,7 @@
|
|||||||
|
const messenger = (window.webkit) ? window.webkit.messageHandlers : (message) => {
|
||||||
|
console.log("Message: " + message);
|
||||||
|
};
|
||||||
|
|
||||||
|
let editor = null;
|
||||||
|
let aceSessions = {};
|
||||||
|
let currentSession = null;
|
@ -1,87 +1,62 @@
|
|||||||
const loadFile = (ftype, fhash, file, content) => {
|
const loadEditor = () => {
|
||||||
session = ace.createEditSession( atob(content) );
|
ace.require("ace/ext/language_tools");
|
||||||
aceSessions[fhash] = {"ftype": ftype, "file": file, "session": session};
|
|
||||||
|
|
||||||
let tab = `
|
editor = ace.edit("editor");
|
||||||
<li class='tab active-tab' role="presentation" fhash='${fhash}' ftype='${ftype}' draggable="true"
|
// Note: https://github.com/ajaxorg/ace/wiki/Configuring-Ace
|
||||||
ondragend="dragEnd()" ondragover="dragOver(event)" ondragstart="dragStart(event)"
|
editor.setOptions({
|
||||||
>
|
printMarginColumn: 80,
|
||||||
<span class='file-name' onclick='switchSession(this)'>${file}</span>
|
enableBasicAutocompletion: true,
|
||||||
<span class='close-button' onclick='closeSession(this)'>
|
enableInlineAutocompletion: true,
|
||||||
<i class="bi bi-x-square" aria-hidden="true"></i>
|
enableSnippets: true,
|
||||||
</span>
|
enableLiveAutocompletion: true,
|
||||||
</li>
|
highlightActiveLine: true,
|
||||||
`;
|
useSoftTabs: true,
|
||||||
|
tabSize: 4,
|
||||||
|
tooltipFollowsMouse: true,
|
||||||
|
useWrapMode: false,
|
||||||
|
scrollPastEnd: 0.5,
|
||||||
|
mergeUndoDeltas: false
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: Need to account for given editor we have focused when implimented...
|
// Note: https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts
|
||||||
document.getElementsByClassName("nav-tabs")[0]
|
editor.commands.addCommands(editorCommands);
|
||||||
.insertAdjacentHTML('beforeend', tab);
|
|
||||||
|
editor.setTheme("ace/theme/one_dark");
|
||||||
|
}
|
||||||
|
|
||||||
|
const loadInitialSessionTab = async () => {
|
||||||
|
newSession(null, editor.getSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
const newSession = async (elm = null, session = null) => {
|
||||||
|
let ftype = "buffer";
|
||||||
|
let fhash = await getSHA256Hash( new Date().toString() );
|
||||||
|
session = ( isNotNullOrUndefined(session) ) ? session : ace.createEditSession("");
|
||||||
|
|
||||||
|
aceSessions[fhash] = {"ftype": ftype, "file": "", "session": session};
|
||||||
|
|
||||||
|
setSession(ftype, fhash, session);
|
||||||
|
sendMessage("load_buffer", fhash, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
const switchSession = (fhash) => {
|
||||||
|
ftype = aceSessions[fhash]["ftype"];
|
||||||
|
session = aceSessions[fhash]["session"];
|
||||||
|
|
||||||
setSession(ftype, fhash, session);
|
setSession(ftype, fhash, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
const updatedTab = (ftype, fname) => {
|
|
||||||
let elm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
|
||||||
let tabTitleElm = elm.children[0];
|
|
||||||
|
|
||||||
aceSessions[currentSession]["ftype"] = ftype;
|
const closeSession = (fhash) => {
|
||||||
aceSessions[currentSession]["file"] = fname;
|
delete aceSessions[fhash];
|
||||||
|
|
||||||
elm.setAttribute("ftype", ftype);
|
keys = Object.keys(aceSessions);
|
||||||
tabTitleElm.textContent = fname;
|
console.log(keys.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const loadInitialSessions = () => {
|
|
||||||
let elms = document.getElementsByClassName("add-session-bottom");
|
|
||||||
for (let i = 0; i < elms.length; i++) {
|
|
||||||
elms[i].click();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const newSession = async (elm) => {
|
|
||||||
let ftype = "buffer";
|
|
||||||
let fhash = await getSHA256Hash( new Date().toString() );
|
|
||||||
let session = ace.createEditSession("");
|
|
||||||
|
|
||||||
let tab = `
|
|
||||||
<li class='tab active-tab' role="presentation" fhash='${fhash}' ftype='${ftype}' draggable="true"
|
|
||||||
ondragend="dragEnd()" ondragover="dragOver(event)" ondragstart="dragStart(event)"
|
|
||||||
>
|
|
||||||
<span class='file-name' onclick='switchSession(this)'>buffer</span>
|
|
||||||
<span class='close-button' onclick='closeSession(this)'>
|
|
||||||
<i class="bi bi-x-square" aria-hidden="true"></i>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
`;
|
|
||||||
|
|
||||||
aceSessions[fhash] = {"ftype": "buffer", "file": "", "session": session};
|
|
||||||
let container = elm.parentElement.parentElement.parentElement;
|
|
||||||
let tabs = container.children[0].children[0];
|
|
||||||
|
|
||||||
tabs.insertAdjacentHTML('beforeend', tab);
|
|
||||||
setSession(ftype, fhash, session);
|
|
||||||
}
|
|
||||||
|
|
||||||
const saveSession = () => {
|
|
||||||
let fhash = currentSession;
|
|
||||||
let session = aceSessions[fhash]["session"];
|
|
||||||
let data = session.getValue();
|
|
||||||
|
|
||||||
sendMessage("save", fhash, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const setSession = (ftype, fhash, session) => {
|
const setSession = (ftype, fhash, session) => {
|
||||||
if (currentSession) {
|
|
||||||
let currentElm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
|
||||||
currentElm.classList.remove("active-tab");
|
|
||||||
}
|
|
||||||
|
|
||||||
currentSession = fhash;
|
currentSession = fhash;
|
||||||
let currentElm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
|
||||||
|
|
||||||
currentElm.classList.add("active-tab");
|
|
||||||
editor.setSession(session);
|
editor.setSession(session);
|
||||||
|
|
||||||
if (ftype !== "buffer") {
|
if (ftype !== "buffer") {
|
||||||
@ -89,39 +64,71 @@ const setSession = (ftype, fhash, session) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const switchSession = (elm) => {
|
|
||||||
let parentElm = elm.parentElement;
|
|
||||||
let ftype = parentElm.getAttribute("ftype");
|
|
||||||
let fhash = parentElm.getAttribute("fhash");
|
|
||||||
let session = aceSessions[fhash]["session"];
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const loadFile = (ftype, fhash, file, content) => {
|
||||||
|
session = ace.createEditSession( atob(content) );
|
||||||
|
aceSessions[fhash] = {"ftype": ftype, "file": file, "session": session};
|
||||||
|
|
||||||
|
// let tab = `
|
||||||
|
// <li class='tab active-tab' role="presentation" fhash='${fhash}' ftype='${ftype}' draggable="true"
|
||||||
|
// ondragend="dragEnd()" ondragover="dragOver(event)" ondragstart="dragStart(event)"
|
||||||
|
// >
|
||||||
|
// <span class='file-name' onclick='switchSession(this)'>${file}</span>
|
||||||
|
// <span class='close-button' onclick='closeSession(this)'>
|
||||||
|
// <i class="bi bi-x-square" aria-hidden="true"></i>
|
||||||
|
// </span>
|
||||||
|
// </li>
|
||||||
|
// `;
|
||||||
|
|
||||||
|
// TODO: Need to account for given editor we have focused when implimented...
|
||||||
|
// document.getElementsByClassName("nav-tabs")[0]
|
||||||
|
// .insertAdjacentHTML('beforeend', tab);
|
||||||
|
|
||||||
setSession(ftype, fhash, session);
|
setSession(ftype, fhash, session);
|
||||||
}
|
}
|
||||||
|
|
||||||
const closeSession = (elm) => {
|
const updatedTab = (ftype, fname) => {
|
||||||
let keys = Object.keys(aceSessions);
|
// let elm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
||||||
if (keys.length < 2) return
|
// let tabTitleElm = elm.children[0];
|
||||||
|
|
||||||
let parentElm = elm.parentElement;
|
aceSessions[currentSession]["ftype"] = ftype;
|
||||||
let ftype = parentElm.getAttribute("ftype");
|
aceSessions[currentSession]["file"] = fname;
|
||||||
let fhash = parentElm.getAttribute("fhash");
|
|
||||||
|
|
||||||
if (ftype !== "buffer") {
|
// elm.setAttribute("ftype", ftype);
|
||||||
sendMessage("close", fhash, "");
|
// tabTitleElm.textContent = fname;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fhash === currentSession) {
|
|
||||||
let siblingElm = getSiblingElm(parentElm);
|
|
||||||
|
|
||||||
if ( isNotNullOrUndefined(siblingElm) ) {
|
|
||||||
let sftype = siblingElm.getAttribute("ftype");
|
|
||||||
let sfhash = siblingElm.getAttribute("fhash");
|
|
||||||
|
|
||||||
setSession(sftype, sfhash, aceSessions[sfhash]["session"]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
parentElm.remove();
|
const saveSession = () => {
|
||||||
delete aceSessions[fhash];
|
let fhash = currentSession;
|
||||||
|
let session = aceSessions[fhash]["session"];
|
||||||
|
let data = session.getValue();
|
||||||
|
|
||||||
|
sendMessage("save", fhash, data);
|
||||||
}
|
}
|
@ -41,11 +41,11 @@ const getSHA256Hash = async (input) => {
|
|||||||
let textAsBuffer = new TextEncoder().encode(input);
|
let textAsBuffer = new TextEncoder().encode(input);
|
||||||
let hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
|
let hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
|
||||||
let hashArray = Array.from( new Uint8Array(hashBuffer) );
|
let hashArray = Array.from( new Uint8Array(hashBuffer) );
|
||||||
let hash = hashArray.map(
|
let fhash = hashArray.map(
|
||||||
(item) => item.toString(16).padStart(2, "0")
|
(item) => item.toString(16).padStart(2, "0")
|
||||||
).join("");
|
).join("");
|
||||||
|
|
||||||
return hash;
|
return fhash;
|
||||||
};
|
};
|
||||||
|
|
||||||
const clearChildNodes = (parent) => {
|
const clearChildNodes = (parent) => {
|
||||||
|
Loading…
Reference in New Issue
Block a user