From 9ac55934fa18748f84dd69e980cc370291a1976b Mon Sep 17 00:00:00 2001 From: Kaalleen <36401965+kaalleen@users.noreply.github.com> Date: Wed, 12 Feb 2025 16:58:26 +0100 Subject: [PATCH] Edit-json: add kerning filter (#3499) * edit-json: add kerning filter * fix missing kerning pairs --- lib/gui/edit_json/combo_prompt.py | 49 +++++++++++++++++++++++++++++ lib/gui/edit_json/main_panel.py | 22 ++++++++++--- lib/gui/edit_json/settings_panel.py | 14 +++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 lib/gui/edit_json/combo_prompt.py diff --git a/lib/gui/edit_json/combo_prompt.py b/lib/gui/edit_json/combo_prompt.py new file mode 100644 index 000000000..bebb1947f --- /dev/null +++ b/lib/gui/edit_json/combo_prompt.py @@ -0,0 +1,49 @@ +import wx + + +class PromptingComboBox(wx.ComboBox): + def __init__(self, parent, choices=[], style=0, **kwargs): + if choices is None: + choices = [] + wx.ComboBox.__init__(self, parent, wx.ID_ANY, style=style, choices=choices, **kwargs) + self.choices = choices + self.Bind(wx.EVT_KEY_DOWN, self.on_button_down) + self.Bind(wx.EVT_TEXT, self.on_text_edit) + self.Bind(wx.EVT_TEXT_ENTER, self.on_text_edit) + self.ignore_text_event = False + self.delete_key = False + self.found_choice = False + self.parent = parent + + def update_choices(self, choices): + self.choices = choices + + def on_button_down(self, event): + if event.GetKeyCode() == 8: + self.delete_key = True + event.Skip() + + def on_text_edit(self, event): + current_text = event.GetString() + if len(current_text) == 0 or current_text == " ": + self.delete_key = False + self.parent.on_combobox_change(event) + return + if self.ignore_text_event: + self.ignore_text_event = False + return + if self.delete_key: + self.delete_key = False + if self.found_choice: + current_text = current_text[:-1] + + self.found_choice = False + for i, choice in enumerate(self.choices): + if choice.startswith(current_text.strip()): + self.ignore_text_event = True + self.SetValue(choice) + self.SetInsertionPoint(len(current_text)) + self.SetTextSelection(len(current_text), len(choice)) + self.found_choice = True + self.parent.on_combobox_change(event) + break diff --git a/lib/gui/edit_json/main_panel.py b/lib/gui/edit_json/main_panel.py index 8b8966290..895baef4e 100644 --- a/lib/gui/edit_json/main_panel.py +++ b/lib/gui/edit_json/main_panel.py @@ -1,6 +1,6 @@ # Authors: see git history # -# Copyright (c) 2023 Authors +# Copyright (c) 2025 Authors # Licensed under the GNU GPL version 3.0 or later. See the file LICENSE for details. import json @@ -41,7 +41,7 @@ class LetteringEditJsonPanel(wx.Panel): self.font = None self.default_variant = None self.font_meta = defaultdict(list) - self.glyphs = None + self.glyphs = [] self.kerning_pairs = None self.kerning_combinations = [] self.horiz_adv_x = {} @@ -240,14 +240,17 @@ class LetteringEditJsonPanel(wx.Panel): self.horiz_adv_x = self.font.horiz_adv_x kerning_combinations = combinations_with_replacement(self.glyphs, 2) - self.kerning_combinations = [' '.join(combination) for combination in kerning_combinations] - self.kerning_combinations.extend([f'{combination[1]} {combination[0]}' for combination in kerning_combinations]) + self.kerning_combinations = [] + for combination in kerning_combinations: + self.kerning_combinations.append(f'{combination[0]} {combination[1]}') + self.kerning_combinations.append(f'{combination[1]} {combination[0]}') self.kerning_combinations = list(set(self.kerning_combinations)) self.kerning_combinations.sort() self.update_legacy_kerning_pairs() self.update_settings() self.update_kerning_list() + self.update_filter_list() self.update_glyph_list() self.update_preview() @@ -314,7 +317,14 @@ class LetteringEditJsonPanel(wx.Panel): self.settings_panel.font_kerning.horiz_adv_x_default.SetValue(self.font.horiz_adv_x_default) self.settings_panel.font_kerning.horiz_adv_x_space.SetValue(self.font.word_spacing) - def update_kerning_list(self): + def update_filter_list(self): + # Update filter list + self.settings_panel.kerning_filter.Clear() + choices = [' '] + self.glyphs + self.settings_panel.kerning_filter.AppendItems(choices) + self.settings_panel.kerning_filter.update_choices(choices) + + def update_kerning_list(self, filter_value=None): kerning_list = self.settings_panel.kerning_list # Add the rows kerning_list.ClearAll() @@ -323,6 +333,8 @@ class LetteringEditJsonPanel(wx.Panel): kerning_list.AppendColumn("Current kerning", width=wx.LIST_AUTOSIZE_USEHEADER) kerning_list.AppendColumn("New kerning", width=wx.LIST_AUTOSIZE_USEHEADER) for kerning_pair in self.kerning_combinations: + if filter_value is not None and filter_value.strip() not in kerning_pair: + continue if self.font_meta['text_direction'] == 'rtl': pair = kerning_pair.split() kerning_pair = ' '.join(pair[::-1]) diff --git a/lib/gui/edit_json/settings_panel.py b/lib/gui/edit_json/settings_panel.py index 8c51a3d08..b4fd51d98 100644 --- a/lib/gui/edit_json/settings_panel.py +++ b/lib/gui/edit_json/settings_panel.py @@ -7,6 +7,7 @@ import wx from ...i18n import _ from ...lettering.categories import FONT_CATEGORIES +from .combo_prompt import PromptingComboBox from .editable_list import EditableListCtrl @@ -56,6 +57,7 @@ class SettingsPanel(wx.Panel): kerning_pairs = KerningPairs(self.notebook) self.notebook.AddPage(kerning_pairs, _("Kerning pairs")) self.kerning_list = kerning_pairs.kerning_list + self.kerning_filter = kerning_pairs.filter_kerning apply_sizer = wx.BoxSizer(wx.HORIZONTAL) self.cancel_button = wx.Button(self, label=_("Cancel")) @@ -285,9 +287,21 @@ class KerningPairs(wx.Panel): sizer = wx.BoxSizer(wx.VERTICAL) + choices = [' '] + self.parent.glyphs + self.filter_kerning = PromptingComboBox(self, choices=choices, style=wx.TE_PROCESS_ENTER) + sizer.Add(self.filter_kerning, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5) + self.kerning_list = EditableListCtrl(self, style=wx.LC_REPORT | wx.SUNKEN_BORDER) self.kerning_list.Bind(wx.EVT_LIST_ITEM_SELECTED, self.parent.on_kerning_list_select) self.kerning_list.Bind(wx.EVT_LIST_END_LABEL_EDIT, self.parent.on_kerning_update) sizer.Add(self.kerning_list, 1, wx.EXPAND, 0) self.SetSizer(sizer) + + def on_combobox_change(self, event): + combobox = event.GetEventObject() + value = combobox.GetValue().strip() + if value and value != " ": + self.parent.update_kerning_list(value) + else: + self.parent.update_kerning_list()