generated from itdominator/Python-With-Gtk-Template
Implementing own completion UI logic
This commit is contained in:
parent
dc387d1d4c
commit
3d37a2335a
@ -11,6 +11,7 @@ from gi.repository import GtkSource
|
||||
from libs.dto.lsp_message_structs import LSPResponseTypes, LSPResponseRequest, LSPResponseNotification
|
||||
from .key_input_controller import KeyInputController
|
||||
from .editor_events import EditorEventsMixin
|
||||
from ...completion_item import CompletionItem
|
||||
|
||||
|
||||
|
||||
@ -44,7 +45,7 @@ class EditorControllerMixin(KeyInputController, EditorEventsMixin):
|
||||
page_num = None
|
||||
container = None
|
||||
|
||||
logger.debug( repr(message) )
|
||||
logger.debug( f"\n\n{repr(message)}\n\n" )
|
||||
|
||||
if isinstance(message, dict):
|
||||
...
|
||||
@ -53,14 +54,30 @@ class EditorControllerMixin(KeyInputController, EditorEventsMixin):
|
||||
if type(message.result) is dict:
|
||||
keys = message.result.keys()
|
||||
|
||||
if "items" in keys: # completion
|
||||
completion = source_view.get_completion()
|
||||
providers = completion.get_providers()
|
||||
if "items" in keys: # completion
|
||||
if source_view.completion_view.get_parent():
|
||||
source_view.remove(source_view.completion_view)
|
||||
|
||||
source_view.completion_view.clear_items()
|
||||
x, y = self._get_insert_line_xy(source_view)
|
||||
source_view.add_child_in_window(source_view.completion_view, Gtk.TextWindowType.WIDGET, x, y)
|
||||
|
||||
for item in message.result["items"]:
|
||||
ci = CompletionItem()
|
||||
ci.populate_completion_item(item)
|
||||
source_view.completion_view.add_completion_item(ci)
|
||||
|
||||
source_view.completion_view.show_all()
|
||||
|
||||
|
||||
# completion = source_view.get_completion()
|
||||
# providers = completion.get_providers()
|
||||
|
||||
# for provider in providers:
|
||||
# if provider.__class__.__name__ == 'LSPCompletionProvider':
|
||||
# source_view.completion_items = message.result["items"]
|
||||
# source_view.emit("show-completion")
|
||||
|
||||
for provider in providers:
|
||||
if provider.__class__.__name__ == 'LSPCompletionProvider':
|
||||
source_view.completion_items = message.result["items"]
|
||||
source_view.emit("show-completion")
|
||||
|
||||
if "result" in keys:
|
||||
...
|
||||
@ -77,4 +94,23 @@ class EditorControllerMixin(KeyInputController, EditorEventsMixin):
|
||||
if message.method == "textDocument/publshDiagnostics":
|
||||
...
|
||||
|
||||
source_view = None
|
||||
source_view = None
|
||||
|
||||
|
||||
|
||||
# Gotten logic from:
|
||||
# https://stackoverflow.com/questions/7139645/find-the-cursor-position-on-a-gtksourceview-window
|
||||
def _get_insert_line_xy(self, source_view):
|
||||
buffer = source_view.get_buffer()
|
||||
iter = buffer.get_iter_at_mark( buffer.get_insert() )
|
||||
iter_loc = source_view.get_iter_location(iter)
|
||||
|
||||
win_loc = source_view.buffer_to_window_coords(Gtk.TextWindowType.WIDGET, iter_loc.x, iter_loc.y)
|
||||
|
||||
win = source_view.get_window( Gtk.TextWindowType.WIDGET )
|
||||
view_pos = win.get_position()
|
||||
|
||||
xx = win_loc[0] + view_pos[0]
|
||||
yy = win_loc[1] + view_pos[1] + iter_loc.height
|
||||
|
||||
return xx, yy
|
@ -73,6 +73,9 @@ class LSPCompletionProvider(GObject.Object, GtkSource.CompletionProvider):
|
||||
if "insertText" in keys:
|
||||
comp_item.set_text(item["insertText"])
|
||||
|
||||
if "additionalTextEdits" in keys:
|
||||
comp_item.additionalTextEdits = item["additionalTextEdits"]
|
||||
|
||||
return comp_item
|
||||
|
||||
|
||||
|
@ -47,6 +47,10 @@ class KeyInputController:
|
||||
if keyname in [ "Up", "Down", "Left", "Right" ]:
|
||||
return True
|
||||
|
||||
if keyname in [ "Return", "Enter", "Up", "Down" ]:
|
||||
if self.completion_view.get_parent() and self.completion_view.is_visible():
|
||||
return True
|
||||
|
||||
|
||||
if len(self._multi_insert_marks) > 0:
|
||||
if keyname == "BackSpace":
|
||||
@ -125,6 +129,22 @@ class KeyInputController:
|
||||
self.keyboard_clear_marks()
|
||||
|
||||
|
||||
if keyname in [ "Return", "Enter", "Up", "Down", "Left", "Right" ]:
|
||||
if self.completion_view.get_parent() and self.completion_view.is_visible():
|
||||
if keyname in {"Return", "Enter"}:
|
||||
self.completion_view.activate_completion()
|
||||
if keyname == "UP":
|
||||
self.completion_view.move_selection_up()
|
||||
if keyname == "Down":
|
||||
self.completion_view.move_selection_down()
|
||||
if keyname == "Left":
|
||||
self.remove( self.completion_view )
|
||||
if keyname == "Right":
|
||||
self.remove( self.completion_view )
|
||||
|
||||
return True
|
||||
|
||||
|
||||
if keyname in {"Return", "Enter"}:
|
||||
if len(self._multi_insert_marks) > 0:
|
||||
self.begin_user_action(buffer)
|
||||
|
@ -149,12 +149,12 @@ class FileEventsMixin:
|
||||
|
||||
event_system.emit("textDocument/didOpen", (self._current_filetype, uri, self.get_text()))
|
||||
|
||||
word_completion = GtkSource.CompletionWords.new("word_completion")
|
||||
word_completion.register(buffer)
|
||||
self._completion.add_provider(word_completion)
|
||||
# word_completion = GtkSource.CompletionWords.new("word_completion")
|
||||
# word_completion.register(buffer)
|
||||
# self._completion.add_provider(word_completion)
|
||||
|
||||
lsp_completion_provider = LSPCompletionProvider(self)
|
||||
self._completion.add_provider(lsp_completion_provider)
|
||||
# lsp_completion_provider = LSPCompletionProvider(self)
|
||||
# self._completion.add_provider(lsp_completion_provider)
|
||||
|
||||
self.got_to_line(buffer, line)
|
||||
event_system.emit("buffer_changed_first_load", (buffer, ))
|
@ -17,6 +17,7 @@ from .source_view_controller import SourceViewControllerMixin
|
||||
|
||||
# from .custom_completion_providers.example_completion_provider import ExampleCompletionProvider
|
||||
# from .custom_completion_providers.python_completion_provider import PythonCompletionProvider
|
||||
from ...completion_view import CompletionView
|
||||
|
||||
|
||||
|
||||
@ -46,9 +47,11 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
self._px_value = settings.theming.default_zoom
|
||||
|
||||
self._multi_insert_marks = []
|
||||
self.completion_items = []
|
||||
self.freeze_multi_line_insert = False
|
||||
|
||||
self.completion_view = CompletionView()
|
||||
# self.completion_items = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._subscribe_to_events()
|
||||
@ -117,4 +120,4 @@ class SourceView(SourceViewControllerMixin, GtkSource.View):
|
||||
self._timer.start()
|
||||
|
||||
def _clear_cut_buffer(self):
|
||||
self._cut_buffer = ""
|
||||
self._cut_buffer = ""
|
||||
|
44
src/core/widgets/completion_item.py
Normal file
44
src/core/widgets/completion_item.py
Normal file
@ -0,0 +1,44 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
|
||||
|
||||
|
||||
class CompletionItem(Gtk.Button):
|
||||
def __init__(self):
|
||||
super(CompletionItem, self).__init__()
|
||||
|
||||
self.insertText: str = ""
|
||||
self.additionalTextEdits: [] = []
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
|
||||
self.show()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("completion-item")
|
||||
|
||||
def _setup_signals(self):
|
||||
self.connect("clicked", self._do_completion)
|
||||
|
||||
|
||||
def populate_completion_item(self, item):
|
||||
keys = item.keys()
|
||||
self.set_label(item["label"])
|
||||
|
||||
if "insertText" in keys:
|
||||
self.insertText = item["insertText"]
|
||||
|
||||
if "additionalTextEdits" in keys:
|
||||
self.additionalTextEdits = item["additionalTextEdits"]
|
||||
|
||||
def _do_completion(self, button):
|
||||
...
|
59
src/core/widgets/completion_view.py
Normal file
59
src/core/widgets/completion_view.py
Normal file
@ -0,0 +1,59 @@
|
||||
# Python imports
|
||||
|
||||
# Lib imports
|
||||
import gi
|
||||
gi.require_version('Gtk', '3.0')
|
||||
from gi.repository import Gtk
|
||||
|
||||
# Application imports
|
||||
from .completion_item import CompletionItem
|
||||
|
||||
|
||||
|
||||
class CompletionView(Gtk.ScrolledWindow):
|
||||
def __init__(self):
|
||||
super(CompletionView, self).__init__()
|
||||
|
||||
self.button_box = None
|
||||
|
||||
self._setup_styling()
|
||||
self._setup_signals()
|
||||
self._load_widgets()
|
||||
|
||||
self.show_all()
|
||||
|
||||
|
||||
def _setup_styling(self):
|
||||
ctx = self.get_style_context()
|
||||
ctx.add_class("completion-view")
|
||||
self.set_size_request(320, 320)
|
||||
|
||||
def _setup_signals(self):
|
||||
...
|
||||
|
||||
def _load_widgets(self):
|
||||
viewport = Gtk.Viewport()
|
||||
self.button_box = Gtk.Box()
|
||||
|
||||
self.button_box.set_orientation( Gtk.Orientation.VERTICAL )
|
||||
self.button_box.set_hexpand( True )
|
||||
|
||||
viewport.add(self.button_box)
|
||||
self.add(viewport)
|
||||
|
||||
def add_completion_item(self, item: CompletionItem):
|
||||
self.button_box.add(item)
|
||||
|
||||
def clear_items(self):
|
||||
for child in self.button_box.get_children():
|
||||
self.button_box.remove(child)
|
||||
|
||||
def activate_completion(self):
|
||||
...
|
||||
|
||||
def move_selection_up(self):
|
||||
...
|
||||
|
||||
def move_selection_down(self):
|
||||
...
|
||||
|
Loading…
Reference in New Issue
Block a user