Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CSS function completion provider #1976

Merged
merged 3 commits into from
Jan 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
97 changes: 97 additions & 0 deletions gaphor/ui/csscompletion.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,103 @@
from gaphor.core.styling import Style


class CssFunctionCompletionProvider(GObject.GObject, GtkSource.CompletionProvider):
FUNCTIONS = [
"attr",
"calc",
"conic-gradient",
"counter",
"cubic-bezier",
"hsl",
"hsla",
"lab",
"lch",
"linear-gradient",
"max",
"min",
"radial-gradient",
"repeating-conic-gradient",
"repeating-linear-gradient",
"repeating-radial-gradient",
"rgb",
"rgba",
"var",
]

def __init__(self):
super().__init__()
self._filter_data: FilterData = FilterData()

def do_activate(
self,
context: GtkSource.CompletionContext,
proposal: GtkSource.CompletionProposal,
) -> None:
buffer = context.get_buffer()
buffer.begin_user_action()
has_selection, begin, end = context.get_bounds()
if has_selection:
buffer.delete(begin, end)
buffer.insert(begin, proposal.text, len(proposal.text))
buffer.end_user_action()

def do_display(
self,
context: GtkSource.CompletionContext,
proposal: GtkSource.CompletionProposal,
cell: GtkSource.CompletionCell,
) -> None:
if cell.props.column == GtkSource.CompletionColumn.ICON:
pass
elif cell.props.column == GtkSource.CompletionColumn.TYPED_TEXT:
cell.set_text(proposal.text)

def do_get_priority(self, context: GtkSource.CompletionContext) -> int:
return 3

def do_get_title(self) -> str:
return "Functions"

def do_populate_async(self, context, cancellable, callback, user_data=None) -> None:
task = Gio.Task.new(self, cancellable, callback)
store = Gio.ListStore.new(CssFunctionProposal)
self._filter_data.word = context.get_word()

for function in self.FUNCTIONS:
proposal = CssFunctionProposal(function)
store.append(proposal)

def filter_fn(proposal, data):
return proposal.text.startswith(data.word)

store_filter = Gtk.CustomFilter.new(filter_fn, self._filter_data)
task.proposals = Gtk.FilterListModel.new(store, store_filter)
task.return_boolean(True)

def do_populate_finish(self, result: Gio.AsyncResult) -> Gio.ListModel:
if result.propagate_boolean():
return result.proposals

def do_refilter(
self, context: GtkSource.CompletionContext, model: Gio.ListModel
) -> None:
word = context.get_word()
change = Gtk.FilterChange.DIFFERENT
if old_word := self._filter_data.word:
if word.startswith(old_word):
change = Gtk.FilterChange.MORE_STRICT
elif old_word.startswith(word):
change = Gtk.FilterChange.LESS_STRICT
self._filter_data.word = word
model.get_filter().changed(change)


class CssFunctionProposal(GObject.Object, GtkSource.CompletionProposal):
def __init__(self, text: str):
super().__init__()
self.text: str = text


class CssPropertyCompletionProvider(GObject.GObject, GtkSource.CompletionProvider):
PROPERTIES = sorted(Style.__optional_keys__)

Expand Down
9 changes: 6 additions & 3 deletions gaphor/ui/elementeditor.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
)
from gaphor.diagram.propertypages import PropertyPages, new_resource_builder
from gaphor.ui.abc import UIComponent
from gaphor.ui.csscompletion import CssPropertyCompletionProvider
from gaphor.ui.csscompletion import (
CssFunctionCompletionProvider,
CssPropertyCompletionProvider,
)
from gaphor.ui.event import DiagramSelectionChanged

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -289,9 +292,9 @@ def open(self, builder):
)

if Gtk.get_major_version() == 4:
provider = CssPropertyCompletionProvider()
view_completion = self.style_sheet_view.get_completion()
view_completion.add_provider(provider)
view_completion.add_provider(CssFunctionCompletionProvider())
view_completion.add_provider(CssPropertyCompletionProvider())

self.event_manager.subscribe(self._model_ready)
self.event_manager.subscribe(self._style_sheet_created)
Expand Down