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
|
||||
from ..widgets.separator_widget import Separator
|
||||
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):
|
||||
|
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 .base_controller_data import BaseControllerData
|
||||
from .bridge_controller import BridgeController
|
||||
from .files_controller import FilesController
|
||||
|
||||
|
||||
|
||||
@ -59,7 +58,6 @@ class BaseController(SignalsMixins, BaseControllerData):
|
||||
|
||||
def _load_controllers(self):
|
||||
BridgeController()
|
||||
FilesController()
|
||||
|
||||
def load_glade_file(self):
|
||||
self.builder = Gtk.Builder()
|
||||
|
@ -26,14 +26,17 @@ class BridgeController:
|
||||
def handle_bridge_event(self, event):
|
||||
match event.topic:
|
||||
case "save":
|
||||
event_system.emit("handle_file_event", (event,))
|
||||
event_system.emit(f"handle_file_event_{event.originator}", (event,))
|
||||
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":
|
||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||
logger.info(content)
|
||||
case _:
|
||||
...
|
||||
|
||||
|
||||
|
||||
|
@ -12,8 +12,9 @@ from gi.repository import Gtk
|
||||
|
||||
|
||||
class FilesController:
|
||||
def __init__(self):
|
||||
def __init__(self, index):
|
||||
|
||||
self.INDEX = index
|
||||
self.opened_files = {}
|
||||
|
||||
self._setup_signals()
|
||||
@ -24,8 +25,8 @@ class FilesController:
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("set_pre_drop_dnd", self.set_pre_drop_dnd)
|
||||
event_system.subscribe("handle_file_event", self.handle_file_event)
|
||||
event_system.subscribe(f"set_pre_drop_dnd_{self.INDEX}", self.set_pre_drop_dnd)
|
||||
event_system.subscribe(f"handle_file_event_{self.INDEX}", self.handle_file_event)
|
||||
|
||||
def set_pre_drop_dnd(self, gfiles):
|
||||
keys = self.opened_files.keys()
|
||||
@ -46,37 +47,38 @@ class FilesController:
|
||||
def handle_file_event(self, event):
|
||||
match event.topic:
|
||||
case "save":
|
||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||
self.save_session(event.target, content)
|
||||
content = base64.b64decode( event.content.encode() ).decode("utf-8")
|
||||
basename = self.save_session(event.target, content)
|
||||
|
||||
if basename:
|
||||
event_system.emit(f"updated_tab_{event.originator}", (event.target, basename,))
|
||||
case "close":
|
||||
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 _:
|
||||
return
|
||||
|
||||
def load_buffer(self, fhash):
|
||||
self.opened_files[fhash] = {"file": None, "ftype": "buffer"}
|
||||
|
||||
def save_session(self, fhash, content):
|
||||
keys = self.opened_files.keys()
|
||||
ftype = self.opened_files[fhash]["ftype"]
|
||||
gfile = event_system.emit_and_await(
|
||||
"save_file_dialog", ("", None)
|
||||
) if not fhash in keys else self.opened_files[fhash]["file"]
|
||||
|
||||
if not gfile: return
|
||||
) if fhash == "buffer" else self.opened_files[fhash]["file"]
|
||||
|
||||
file_written = self.write_to_file(fhash, gfile, content)
|
||||
if not fhash in keys and file_written:
|
||||
self.insert_to_sessions(fhash, gfile)
|
||||
event_system.emit(
|
||||
"updated_tab",
|
||||
(
|
||||
self.opened_files[fhash]["ftype"],
|
||||
gfile.get_basename(),
|
||||
)
|
||||
)
|
||||
if fhash == "buffer" and file_written:
|
||||
self.update_session(fhash, gfile)
|
||||
return gfile.get_basename()
|
||||
|
||||
|
||||
def close_session(self, 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)
|
||||
ftype = info.get_content_type().replace("x-", "").split("/")[1]
|
||||
|
||||
|
@ -15,10 +15,11 @@ from libs.data_types import Event
|
||||
|
||||
|
||||
class AceEditor(WebKit2.WebView):
|
||||
def __init__(self):
|
||||
def __init__(self, index):
|
||||
super(AceEditor, self).__init__()
|
||||
|
||||
# self.get_context().set_sandbox_enabled(False)
|
||||
self.INDEX = index
|
||||
|
||||
self._load_settings()
|
||||
self._setup_styling()
|
||||
@ -42,11 +43,11 @@ class AceEditor(WebKit2.WebView):
|
||||
...
|
||||
|
||||
def _subscribe_to_events(self):
|
||||
event_system.subscribe("load_file", self.load_file)
|
||||
|
||||
event_system.subscribe("updated_tab", self.updated_tab)
|
||||
event_system.subscribe("ui_message", self.ui_message)
|
||||
|
||||
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(f"switch_session_{self.INDEX}", self.switch_session)
|
||||
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):
|
||||
self.set_settings( WebkitUISettings() )
|
||||
@ -72,6 +73,7 @@ class AceEditor(WebKit2.WebView):
|
||||
|
||||
try:
|
||||
event = Event( **json.loads(message) )
|
||||
event.originator = self.INDEX
|
||||
event_system.emit("handle_bridge_event", (event,))
|
||||
except Exception as e:
|
||||
logger.info(e)
|
||||
@ -80,8 +82,16 @@ class AceEditor(WebKit2.WebView):
|
||||
command = f"loadFile('{ftype}', '{fhash}', '{file}', '{content}')"
|
||||
self.run_javascript(command, None, None)
|
||||
|
||||
def updated_tab(self, ftype, fname):
|
||||
command = f"updatedTab('{ftype}', '{fname}')"
|
||||
def new_session(self):
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
# Application imports
|
||||
from ..widgets.base.webkit.dnd_box import DnDBox
|
||||
from ..widgets.base.webkit.ace_editor import AceEditor
|
||||
from .dnd_box import DnDBox
|
||||
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.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
def __init__(self, index):
|
||||
super(FixedBox, self).__init__()
|
||||
|
||||
self.INDEX = index
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
@ -39,7 +41,7 @@ class FixedBox(Gtk.Fixed):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
self.ace_editor = AceEditor()
|
||||
self.ace_editor = AceEditor(self.INDEX)
|
||||
self.dnd_box = DnDBox()
|
||||
|
||||
self.add( self.ace_editor )
|
@ -11,9 +11,11 @@ from ..tab_header_widget import TabHeaderWidget
|
||||
|
||||
|
||||
class TabBar(Gtk.Notebook):
|
||||
def __init__(self):
|
||||
def __init__(self, index):
|
||||
super(TabBar, self).__init__()
|
||||
|
||||
self.INDEX = index
|
||||
|
||||
self.set_group_name("editor_widget")
|
||||
|
||||
self._setup_styling()
|
||||
@ -29,12 +31,10 @@ class TabBar(Gtk.Notebook):
|
||||
|
||||
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(f"add_tab_{self.INDEX}", self.add_tab)
|
||||
event_system.subscribe(f"update_tab_{self.INDEX}", self.update_tab)
|
||||
|
||||
def _load_widgets(self):
|
||||
start_box = Gtk.Box()
|
||||
@ -51,28 +51,50 @@ class TabBar(Gtk.Notebook):
|
||||
self.set_action_widget(start_box, 0)
|
||||
self.set_action_widget(end_box, 1)
|
||||
|
||||
self.add_tab_click(None)
|
||||
|
||||
def _switch_page_update(self, notebook, page, page_num):
|
||||
print(page_num)
|
||||
...
|
||||
|
||||
def add_tab_click(self, widget):
|
||||
container = Gtk.Box()
|
||||
page_num = self.append_page(container, TabHeaderWidget(container, self._close_tab))
|
||||
event_system.emit(f"new_session_{self.INDEX}")
|
||||
|
||||
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_reorderable(container, True)
|
||||
|
||||
self.show_all()
|
||||
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
|
||||
# from a potentially former notebook.
|
||||
def _close_tab(self, widget, container):
|
||||
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):
|
||||
@ -91,6 +113,4 @@ class TabBar(Gtk.Notebook):
|
||||
|
||||
# if notebook.NAME == "notebook_2" and notebook.get_n_pages() == 0:
|
||||
# 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):
|
||||
label = Gtk.Label(label = "buffer")
|
||||
self.label = Gtk.Label(label = "buffer")
|
||||
close = Gtk.Button()
|
||||
icon = Gtk.Image(stock = Gtk.STOCK_CLOSE)
|
||||
|
||||
# TODO: Setup with settings and from file
|
||||
label.set_xalign(0.0)
|
||||
label.set_margin_left(25)
|
||||
label.set_margin_right(25)
|
||||
label.set_hexpand(True)
|
||||
self.label.set_xalign(0.0)
|
||||
self.label.set_margin_left(25)
|
||||
self.label.set_margin_right(25)
|
||||
self.label.set_hexpand(True)
|
||||
|
||||
close.set_always_show_image(True)
|
||||
close.set_hexpand(False)
|
||||
close.set_image( Gtk.Image.new_from_icon_name("gtk-close", 4) )
|
||||
close.connect("released", self.close_tab, *(self.content,))
|
||||
|
||||
self.add(label)
|
||||
self.add(close)
|
||||
self.add(self.label)
|
||||
self.add(close)
|
@ -13,3 +13,4 @@ class Event:
|
||||
topic: str
|
||||
target: str
|
||||
content: str
|
||||
originator: int = -1
|
@ -14,27 +14,7 @@
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="row">
|
||||
<div id="page-alert-zone" class="col">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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="col">
|
||||
<pre id="editor">
|
||||
@ -43,12 +23,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<p>
|
||||
<div id="status-bar">Status Bar: ...</div>
|
||||
</p>
|
||||
|
||||
|
||||
<!-- For internal scripts... -->
|
||||
<!-- <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/ace-linters.js"></script>
|
||||
|
||||
|
||||
<!-- For Application... -->
|
||||
<!-- <script src="resources/js/newton/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/keybinding-newton.js"></script>
|
||||
<script src="resources/js/newton/globals.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/events.js"></script>
|
||||
</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) => {
|
||||
console.log("Loaded...");
|
||||
loadInitialSessions();
|
||||
loadEditor();
|
||||
loadInitialSessionTab();
|
||||
|
||||
console.log("Window Loaded...");
|
||||
}
|
||||
|
||||
|
||||
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.
|
||||
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.
|
||||
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) => {
|
||||
session = ace.createEditSession( atob(content) );
|
||||
aceSessions[fhash] = {"ftype": ftype, "file": file, "session": session};
|
||||
const loadEditor = () => {
|
||||
ace.require("ace/ext/language_tools");
|
||||
|
||||
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>
|
||||
`;
|
||||
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
|
||||
});
|
||||
|
||||
// TODO: Need to account for given editor we have focused when implimented...
|
||||
document.getElementsByClassName("nav-tabs")[0]
|
||||
.insertAdjacentHTML('beforeend', tab);
|
||||
// Note: https://github.com/ajaxorg/ace/wiki/Default-Keyboard-Shortcuts
|
||||
editor.commands.addCommands(editorCommands);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const updatedTab = (ftype, fname) => {
|
||||
let elm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
||||
let tabTitleElm = elm.children[0];
|
||||
|
||||
aceSessions[currentSession]["ftype"] = ftype;
|
||||
aceSessions[currentSession]["file"] = fname;
|
||||
|
||||
elm.setAttribute("ftype", ftype);
|
||||
tabTitleElm.textContent = fname;
|
||||
const closeSession = (fhash) => {
|
||||
delete aceSessions[fhash];
|
||||
|
||||
keys = Object.keys(aceSessions);
|
||||
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) => {
|
||||
if (currentSession) {
|
||||
let currentElm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
||||
currentElm.classList.remove("active-tab");
|
||||
}
|
||||
|
||||
currentSession = fhash;
|
||||
let currentElm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
||||
|
||||
currentElm.classList.add("active-tab");
|
||||
editor.setSession(session);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const closeSession = (elm) => {
|
||||
let keys = Object.keys(aceSessions);
|
||||
if (keys.length < 2) return
|
||||
const updatedTab = (ftype, fname) => {
|
||||
// let elm = document.querySelectorAll(`[fhash="${currentSession}"]`)[0];
|
||||
// let tabTitleElm = elm.children[0];
|
||||
|
||||
let parentElm = elm.parentElement;
|
||||
let ftype = parentElm.getAttribute("ftype");
|
||||
let fhash = parentElm.getAttribute("fhash");
|
||||
aceSessions[currentSession]["ftype"] = ftype;
|
||||
aceSessions[currentSession]["file"] = fname;
|
||||
|
||||
if (ftype !== "buffer") {
|
||||
sendMessage("close", fhash, "");
|
||||
}
|
||||
// elm.setAttribute("ftype", ftype);
|
||||
// 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();
|
||||
delete aceSessions[fhash];
|
||||
const saveSession = () => {
|
||||
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 hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
|
||||
let hashArray = Array.from( new Uint8Array(hashBuffer) );
|
||||
let hash = hashArray.map(
|
||||
let fhash = hashArray.map(
|
||||
(item) => item.toString(16).padStart(2, "0")
|
||||
).join("");
|
||||
|
||||
return hash;
|
||||
return fhash;
|
||||
};
|
||||
|
||||
const clearChildNodes = (parent) => {
|
||||
|
Loading…
Reference in New Issue
Block a user