Inkscape
Vector Graphics Editor
font-selector-toolbar.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
17/*
18 * Author:
19 * Tavmjong Bah <tavmjong@free.fr>
20 *
21 * Copyright (C) 2018 Tavmong Bah
22 *
23 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
24 */
25
27
28#include <iostream>
29#include <sigc++/functors/mem_fun.h>
30#include <glibmm/i18n.h>
31#include <glibmm/regex.h>
32#include <gdkmm/display.h>
35
36#include "inkscape.h"
37#include "desktop.h"
38#include "object/sp-text.h"
39#include "ui/controller.h"
40#include "ui/icon-names.h"
41// TEMP TEMP TEMP
43
44/* To do:
45 * Fix altx. The setToolboxFocusTo method now just searches for a named widget.
46 * We just need to do the following:
47 * * Set the name of the family_combo child widget
48 * * Change the setToolboxFocusTo() argument in tools/text-tool to point to that widget name
49 */
50
51static void family_cell_data_func(Gtk::TreeModel::const_iterator const iter,
52 Gtk::CellRendererText* const cell)
53{
55 Glib::ustring markup = font_lister->get_font_family_markup(iter);
56 cell->set_property ("markup", markup);
57}
58
59namespace Inkscape::UI::Widget {
60
62 : Gtk::Grid ()
63 , family_combo (true) // true => with text entry.
64 , style_combo (true)
65 , signal_block (false)
66{
68
69 // Font family
70 family_combo.set_model (font_lister->get_font_list());
71 family_combo.set_entry_text_column (0);
72 family_combo.set_name ("FontSelectorToolBar: Family");
73 family_combo.set_row_separator_func (&font_lister_separator_func);
74
75 family_combo.clear(); // Clears all CellRenderer mappings.
76 family_combo.set_cell_data_func (family_cell,
77 sigc::bind(sigc::ptr_fun(family_cell_data_func), &family_cell));
78 family_combo.pack_start (family_cell);
79
80 Gtk::Entry* entry = family_combo.get_entry();
81 entry->signal_icon_press().connect(sigc::mem_fun(*this, &FontSelectorToolbar::on_icon_pressed));
82 Controller::add_key<&FontSelectorToolbar::on_key_pressed>(*entry, *this);
83
84 Glib::RefPtr<Gtk::EntryCompletion> completion = Gtk::EntryCompletion::create();
85 completion->set_model (font_lister->get_font_list());
86 completion->set_text_column (0);
87 completion->set_popup_completion ();
88 completion->set_inline_completion (false);
89 completion->set_inline_selection ();
90 entry->set_completion (completion);
91
92 // Style
93 style_combo.set_model (font_lister->get_style_list());
94 style_combo.set_name ("FontSelectorToolbar: Style");
95
96 // Grid
97 set_name ("FontSelectorToolbar: Grid");
98 attach (family_combo, 0, 0, 1, 1);
99 attach (style_combo, 1, 0, 1, 1);
100
101 // Add signals
102 family_combo.signal_changed().connect ([=](){ on_family_changed(); });
103 style_combo.signal_changed().connect ([=](){ on_style_changed(); });
104
105 // Initialize font family lists. (May already be done.) Should be done on document change.
106 font_lister->update_font_list(SP_ACTIVE_DESKTOP->getDocument());
107
108 // When FontLister is changed, update family and style shown in GUI.
109 font_lister->connectUpdate([=](){ update_font(); });
110}
111
112// Update GUI based on font-selector values.
113void
115{
116 if (signal_block) return;
117
118 signal_block = true;
119
121 Gtk::TreeModel::Row row;
122
123 // Set font family.
124 try {
125 row = font_lister->get_row_for_font();
126 family_combo.set_active(row.get_iter());
127 } catch (FontLister::Exception) {
128 std::cerr << "FontSelectorToolbar::update_font: Couldn't find row for family: "
129 << font_lister->get_font_family().raw() << std::endl;
130 }
131
132 // Set style.
133 try {
134 row = font_lister->get_row_for_style();
135 style_combo.set_active(row.get_iter());
136 } catch (FontLister::Exception) {
137 std::cerr << "FontSelectorToolbar::update_font: Couldn't find row for style: "
138 << font_lister->get_font_style().raw() << std::endl;
139 }
140
141 // Check for missing fonts.
142 Glib::ustring missing_fonts = get_missing_fonts();
143
144 // Add an icon to end of entry.
145 Gtk::Entry* entry = family_combo.get_entry();
146 if (missing_fonts.empty()) {
147 // If no missing fonts, add icon for selecting all objects with this font-family.
148 entry->set_icon_from_icon_name(INKSCAPE_ICON("edit-select-all"), Gtk::Entry::IconPosition::SECONDARY);
149 entry->set_icon_tooltip_text(_("Select all text with this text family"), Gtk::Entry::IconPosition::SECONDARY);
150 } else {
151 // If missing fonts, add warning icon.
152 Glib::ustring warning = _("Font not found on system: ") + missing_fonts;
153 entry->set_icon_from_icon_name(INKSCAPE_ICON("dialog-warning"), Gtk::Entry::IconPosition::SECONDARY);
154 entry->set_icon_tooltip_text(warning, Gtk::Entry::IconPosition::SECONDARY);
155 }
156
157 signal_block = false;
158}
159
160// Get comma separated list of fonts in font-family that are not on system.
161// To do, move to font-lister.
162Glib::ustring
164{
165 // Get font list in text entry which may be a font stack (with fallbacks).
166 Glib::ustring font_list = family_combo.get_entry_text();
167 Glib::ustring missing_font_list;
169
170 std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", font_list);
171
172 for (auto token: tokens) {
173 bool found = false;
174 Gtk::TreeModel::Children children = font_lister->get_font_list()->children();
175 for (auto row2 : children) {
176 Glib::ustring family2 = row2[font_lister->font_list.family];
177 bool onSystem2 = row2[font_lister->font_list.onSystem];
178 // CSS dictates that font family names are case insensitive.
179 // This should really implement full Unicode case unfolding.
180 if (onSystem2 && token.casefold().compare(family2.casefold()) == 0) {
181 found = true;
182 break;
183 }
184 }
185
186 if (!found) {
187 missing_font_list += token;
188 missing_font_list += ", ";
189 }
190 }
191
192 // Remove extra comma and space from end.
193 if (missing_font_list.size() >= 2) {
194 missing_font_list.resize(missing_font_list.size() - 2);
195 }
196
197 return missing_font_list;
198}
199
200// Callbacks
201
202// Need to update style list
203void
205
206 if (signal_block) return;
207 signal_block = true;
208
209 Glib::ustring family = family_combo.get_entry_text();
210
212 fontlister->set_font_family (family);
213
214 signal_block = false;
215
216 // Let world know
217 changed_emit();
218}
219
220void
222
223 if (signal_block) return;
224 signal_block = true;
225
226 Glib::ustring style = style_combo.get_entry_text();
227
229 fontlister->set_font_style (style);
230
231 signal_block = false;
232
233 // Let world know
234 changed_emit();
235}
236
237void FontSelectorToolbar::on_icon_pressed(Gtk::Entry::IconPosition icon_position)
238{
239 std::cerr << "FontSelectorToolbar::on_entry_icon_pressed" << std::endl;
240 std::cerr << " .... Should select all items with same font-family. FIXME" << std::endl;
241 // Call equivalent of sp_text_toolbox_select_cb() in text-toolbar.cpp
242 // Should be action! (Maybe: select_all_fontfamily( Glib::ustring font_family );).
243 // Check how Find dialog works.
244}
245
246// Return focus to canvas.
247bool
248FontSelectorToolbar::on_key_pressed(GtkEventControllerKey const * /*controller*/,
249 unsigned /*keyval*/, unsigned const keycode,
250 GdkModifierType const state)
251{
252 unsigned int key = 0;
253 gdk_display_translate_key(gdk_display_get_default(),
254 keycode,
255 state,
256 0,
257 &key,
258 nullptr,
259 nullptr,
260 nullptr);
261 switch ( key ) {
262 case GDK_KEY_Escape:
263 case GDK_KEY_Return:
264 case GDK_KEY_KP_Enter:
265 // Defocus
266 std::cerr << "FontSelectorToolbar::on_key_pressed: Defocus: FIXME" << std::endl;
267 return true;
268 }
269
270 return false;
271}
272
273void
275 signal_block = true;
276 changed_signal.emit ();
277 signal_block = false;
278}
279
280} // namespace Inkscape::UI::Widget
281
282/*
283 Local Variables:
284 mode:c++
285 c-file-style:"stroustrup"
286 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
287 indent-tabs-mode:nil
288 fill-column:99
289 End:
290*/
291// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8 :
This class enumerates fonts using libnrtype into reusable data stores and allows for random access to...
Definition: font-lister.h:84
Glib::ustring get_font_family_markup(Gtk::TreeModel::const_iterator const &iter) const
Get markup for font-family.
Gtk::TreeModel::Row get_row_for_style()
Definition: font-lister.h:292
void set_font_style(Glib::ustring style, bool emit=true)
Sets style.
Glib::RefPtr< Gtk::ListStore > const & get_style_list() const
Definition: font-lister.h:162
void update_font_list(SPDocument *document)
Updates font list to include fonts in document.
Gtk::TreeModel::Row get_row_for_font()
Definition: font-lister.h:284
Glib::ustring const & get_font_style() const
Definition: font-lister.h:272
static Inkscape::FontLister * get_instance()
Glib::RefPtr< Gtk::ListStore > const & get_font_list() const
Definition: font-lister.h:157
std::pair< Glib::ustring, Glib::ustring > set_font_family(Glib::ustring const &family, bool check_style=true, bool emit=true)
Sets font-family, updating style list and attempting to find closest style to old current_style.
sigc::connection connectUpdate(sigc::slot< void()> slot)
Let users of FontLister know to update GUI.
Definition: font-lister.h:321
FontListClass font_list
Definition: font-lister.h:126
Glib::ustring const & get_font_family() const
Definition: font-lister.h:252
bool on_key_pressed(GtkEventControllerKey const *controller, unsigned keyval, unsigned keycode, GdkModifierType state)
void on_icon_pressed(Gtk::Entry::IconPosition icon_position)
void update_font()
Update GUI based on font-selector values.
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
Editable view implementation.
The data describing a single loaded font.
bool font_lister_separator_func(Glib::RefPtr< Gtk::TreeModel > const &, Gtk::TreeModel::const_iterator const &iter)
Font selection widgets.
static void family_cell_data_func(Gtk::TreeModel::const_iterator const iter, Gtk::CellRendererText *const cell)
The routines here create and manage a font selector widget with two parts, one each for font-family a...
Macro for icon names used in Inkscape.
Definition: desktop.h:51
Custom widgets.
Definition: desktop.h:127
static cairo_user_data_key_t key
Definition: nr-svgfonts.cpp:46
Gtk::TreeModelColumn< Glib::ustring > family
Family name.
Definition: font-lister.h:100
Gtk::TreeModelColumn< bool > onSystem
Whether font is on system.
Definition: font-lister.h:106
Text aux toolbar.
std::unique_ptr< Toolbar >(* create)(SPDesktop *desktop)
Definition: toolbars.cpp:63