25#include <glibmm/i18n.h>
26#include <glibmm/regex.h>
27#include <gdk/gdkkeysyms.h>
28#include <gtkmm/adjustment.h>
30#include <gtkmm/button.h>
31#include <gtkmm/cellrenderertext.h>
32#include <gtkmm/cellrenderertoggle.h>
33#include <gtkmm/dialog.h>
34#include <gtkmm/entry.h>
35#include <gtkmm/eventcontrollerfocus.h>
36#include <gtkmm/eventcontrollerkey.h>
37#include <gtkmm/label.h>
38#include <gtkmm/liststore.h>
39#include <gtkmm/treemodel.h>
40#include <gtkmm/treestore.h>
41#include <gtkmm/treeviewcolumn.h>
42#include <gtkmm/treeview.h>
43#include <sigc++/adaptors/bind.h>
44#include <sigc++/functors/mem_fun.h>
88 static GQuark const CODE_svg_style = g_quark_from_static_string(
"svg:style");
89 static GQuark const CODE_svg_defs = g_quark_from_static_string(
"svg:defs");
101 if (textNode !=
nullptr) {
106 if (
node->
code() == CODE_svg_style) {
112 if (styleNode ==
nullptr) {
113 if (!create_if_missing)
128 if (textNode ==
nullptr) {
129 if (!create_if_missing)
144 : _styledialog(styledialog)
146 g_debug(
"StyleDialog::NodeObserver: Constructor");
161 g_debug(
"StyleDialog::NodeObserver::notifyContentChanged");
162 _styledialog->_updating =
false;
163 _styledialog->readStyleElement();
173 : _styledialog(styledialog)
175 g_debug(
"StyleDialog::NodeWatcher: Constructor");
181 _styledialog->_nodeAdded(
child);
187 _styledialog->_nodeRemoved(
child);
193 static GQuark const CODE_id = g_quark_from_static_string(
"id");
194 static GQuark const CODE_class = g_quark_from_static_string(
"class");
195 static GQuark const CODE_style = g_quark_from_static_string(
"style");
197 if (qname == CODE_id || qname == CODE_class || qname == CODE_style) {
198 _styledialog->_nodeChanged(
node);
228 g_debug(
"StyleDialog::_nodeChanged");
240 , m_nodewatcher {
std::make_unique<
StyleDialog::NodeWatcher >(this)}
241 , m_styletextwatcher{
std::make_unique<
StyleDialog::NodeObserver>(this)}
243 g_debug(
"StyleDialog::StyleDialog");
246 _scrolledWindow.set_policy(Gtk::PolicyType::AUTOMATIC, Gtk::PolicyType::AUTOMATIC);
249 _styleBox.set_orientation(Gtk::Orientation::VERTICAL);
257 _mainBox.set_orientation(Gtk::Orientation::VERTICAL);
286 g_debug(
"StyleDialog::_getStyleTextNoded");
307 g_debug(
"StyleDialog::setCurrentSelector");
321 return (g_ascii_strncasecmp(p,
"url(", 4) == 0);
329 g_debug(
"StyleDialog::readStyleElement");
339 std::string content = (textNode && textNode->
content()) ? textNode->
content() :
"";
342 content.erase(std::remove(content.begin(), content.end(),
'\n'), content.end());
346 bool breakme =
false;
347 size_t start = content.find(
"/*");
348 size_t open = content.find(
"{",
start + 1);
349 size_t close = content.find(
"}",
start + 1);
350 size_t end = content.find(
"*/", close + 1);
352 if (open == std::string::npos || close == std::string::npos ||
end == std::string::npos) {
356 while (open < close) {
357 open = content.find(
"{", close + 1);
358 close = content.find(
"}", close + 1);
359 end = content.find(
"*/", close + 1);
360 size_t reopen = content.find(
"{", close + 1);
361 if (open == std::string::npos ||
end == std::string::npos ||
end < reopen) {
371 open = content.find(
"{",
start + 1);
372 close = content.find(
"}",
start + 1);
373 end = content.find(
"*/", close + 1);
388 std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(
"[}{]", content.c_str());
409 auto css_selector_container = &get_widget<Gtk::Box> (
builder,
"CSSSelectorContainer");
410 auto css_selector = &get_widget<Gtk::Label> (
builder,
"CSSSelector");
411 auto css_tree = &get_widget<Gtk::TreeView>(
builder,
"CSSTree");
412 auto css_button = &get_widget<Gtk::Button> (
builder,
"CSSSelectorAddButton");
414 css_selector->set_text(
"element");
416 css_tree->add_css_class(
"style_element");
417 Glib::RefPtr<Gtk::TreeStore>
store = Gtk::TreeStore::create(
_mColumns);
418 css_tree->set_model(
store);
421 unsigned selectorpos = 0;
422 css_button->signal_clicked().connect(
426 auto const addRenderer = Gtk::make_managed<UI::Widget::IconRenderer>();
427 addRenderer->add_icon(
"edit-delete");
428 int addCol = css_tree->append_column(
" ", *addRenderer) - 1;
429 Gtk::TreeViewColumn *col = css_tree->get_column(addCol);
431 addRenderer->signal_activated().connect(
435 auto const label = Gtk::make_managed<Gtk::CellRendererText>();
436 label->property_placeholder_text() = _(
"property");
437 label->property_editable() =
true;
438 label->signal_edited().connect(sigc::bind(
441 addCol = css_tree->append_column(
" ", *
label) - 1;
442 col = css_tree->get_column(addCol);
444 col->set_resizable(
true);
448 auto const value = Gtk::make_managed<Gtk::CellRendererText>();
449 value->property_placeholder_text() = _(
"value");
450 value->property_editable() =
true;
451 value->signal_edited().connect(
453 value->signal_editing_started().connect(
455 addCol = css_tree->append_column(
" ", *value) - 1;
456 col = css_tree->get_column(addCol);
459 col->set_expand(
true);
463 auto const urlRenderer = Gtk::make_managed<UI::Widget::IconRenderer>();
464 urlRenderer->add_icon(
"empty-icon");
465 urlRenderer->add_icon(
"edit-redo");
467 int urlCol = css_tree->append_column(
" ", *urlRenderer) - 1;
468 Gtk::TreeViewColumn *urlcol = css_tree->get_column(urlCol);
470 urlcol->set_min_width(40);
471 urlcol->set_max_width(40);
477 Gtk::TreeModel::Path path;
484 auto const &
name = iter->name();
485 auto const found = attr_prop.find(
name);
486 if (found == attr_prop.end())
continue;
488 auto const &value = found->second;
490 Gtk::TreeModel::Row row = *(
store->prepend());
500 if (
is_url(value.c_str())) {
501 auto id = value.substr(5, value.size() - 6);
515 css_tree->set_visible(
false);
522 if (tokens.size() == 0) {
528 for (
size_t i = 0; i < tokens.size() - 1; i += 2) {
529 auto selector = std::move(tokens[i]);
532 std::vector<Glib::ustring> selectordata = Glib::Regex::split_simple(
";", selector);
533 Glib::ustring selector_orig = selector;
534 if (!selectordata.empty()) {
535 selector = selectordata.back();
537 std::vector<SPObject *> objVec =
_getObjVec(selector);
540 for (
auto objel : objVec) {
557 bool present =
false;
558 for (
auto objv : objVec) {
560 if (objv == objsel) {
576 Glib::ustring properties;
578 if ((i + 1) < tokens.size()) {
579 properties = std::move(tokens[i + 1]);
581 std::cerr <<
"StyleDialog::readStyleElement: Missing values "
588 auto css_selector_container = &get_widget<Gtk::Box> (
builder,
"CSSSelectorContainer");
589 auto css_selector = &get_widget<Gtk::Label> (
builder,
"CSSSelector");
590 auto css_tree = &get_widget<Gtk::TreeView>(
builder,
"CSSTree");
591 auto css_button = &get_widget<Gtk::Button> (
builder,
"CSSSelectorAddButton");
593 css_selector->set_text(selector);
595 css_tree->add_css_class(
"style_sheet");
596 Glib::RefPtr<Gtk::TreeStore>
store = Gtk::TreeStore::create(
_mColumns);
597 css_tree->set_model(
store);
600 css_button->signal_clicked().connect(
604 auto const addRenderer = Gtk::make_managed<UI::Widget::IconRenderer>();
605 addRenderer->add_icon(
"edit-delete");
606 int addCol = css_tree->append_column(
" ", *addRenderer) - 1;
607 Gtk::TreeViewColumn *col = css_tree->get_column(addCol);
609 addRenderer->signal_activated().connect(
613 auto const isactive = Gtk::make_managed<Gtk::CellRendererToggle>();
614 isactive->property_activatable() =
true;
615 addCol = css_tree->append_column(
" ", *isactive) - 1;
616 col = css_tree->get_column(addCol);
619 isactive->signal_toggled().connect(
623 auto const label = Gtk::make_managed<Gtk::CellRendererText>();
624 label->property_placeholder_text() = _(
"property");
625 label->property_editable() =
true;
626 label->signal_edited().connect(sigc::bind(
629 addCol = css_tree->append_column(
" ", *
label) - 1;
630 col = css_tree->get_column(addCol);
632 col->set_resizable(
true);
636 auto const value = Gtk::make_managed<Gtk::CellRendererText>();
637 value->property_editable() =
true;
638 value->property_placeholder_text() = _(
"value");
639 value->signal_edited().connect(
641 value->signal_editing_started().connect(
643 addCol = css_tree->append_column(
" ", *value) - 1;
644 col = css_tree->get_column(addCol);
650 Glib::ustring comments;
651 for (
size_t beg = 0,
end = 0;
652 (beg = properties.find(
"/*", beg )) != properties.npos &&
653 (
end = properties.find(
"*/", beg + 2)) != properties.npos;)
655 comments.append(properties, beg + 2,
end - beg - 2);
656 properties.erase(beg,
end - beg + 2);
659 std::map<Glib::ustring, std::pair<Glib::ustring, bool>> result_props;
660 auto const move_to_result = [&](
AttrProp &&src_props,
bool const active)
662 while (!src_props.empty()) {
663 auto &&
node = src_props.extract(src_props.begin());
664 result_props[std::move(
node.key())] = {std::move(
node.mapped()), active};
667 move_to_result(
parseStyle(std::move(properties)),
true );
668 move_to_result(
parseStyle(std::move(comments )),
false);
669 empty = result_props.empty();
672 for (
auto const &[
name, pair] : result_props) {
673 auto const &[value, active] = pair;
675 Gtk::TreeModel::iterator iterstore = obj ?
store->append() :
store->prepend();
676 Gtk::TreeModel::Row row = *(iterstore);
694 auto val = Glib::ustring{};
697 val = iterprop->get_value();
702 auto r1 = Colors::Color::parse(value);
703 auto r2 = Colors::Color::parse(val);
704 if (((!r1 || *r1 != *r2) && value != val) || attr_prop.count(
name)) {
714 css_tree->set_visible(
false);
725 css_selector_container = &get_widget<Gtk::Box> (
builder,
"CSSSelectorContainer");
726 css_selector = &get_widget<Gtk::Label> (
builder,
"CSSSelector");
727 css_tree = &get_widget<Gtk::TreeView>(
builder,
"CSSTree");
728 css_button = &get_widget<Gtk::Button> (
builder,
"CSSSelectorAddButton");
730 css_selector->set_text(
"element.attributes");
732 css_tree->add_css_class(
"style_attribute");
734 css_tree->set_model(
store);
737 css_button->signal_clicked().connect(
741 bool hasattributes =
false;
746 auto key = iter->id();
750 if (!hasattributes) {
751 auto const addRenderer = Gtk::make_managed<UI::Widget::IconRenderer>();
752 addRenderer->add_icon(
"edit-delete");
753 int addCol = css_tree->append_column(
" ", *addRenderer) - 1;
754 Gtk::TreeViewColumn *col = css_tree->get_column(addCol);
756 addRenderer->signal_activated().connect(sigc::bind(
760 auto const label = Gtk::make_managed<Gtk::CellRendererText>();
761 label->property_placeholder_text() = _(
"property");
762 label->property_editable() =
true;
763 label->signal_edited().connect(sigc::bind(
766 addCol = css_tree->append_column(
" ", *
label) - 1;
767 col = css_tree->get_column(addCol);
769 col->set_resizable(
true);
773 auto const value = Gtk::make_managed<Gtk::CellRendererText>();
774 value->property_placeholder_text() = _(
"value");
775 value->property_editable() =
true;
776 value->signal_edited().connect(sigc::bind(
778 value->signal_editing_started().connect(sigc::bind(
780 addCol = css_tree->append_column(
" ", *value) - 1;
781 col = css_tree->get_column(addCol);
789 Gtk::TreeModel::iterator iterstore =
store->prepend();
790 Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iterstore;
791 Gtk::TreeModel::Row row = *(iterstore);
805 hasattributes =
true;
812 css_tree->set_visible(
false);
815 if (!hasattributes) {
823 if (
auto const box =
dynamic_cast<Gtk::Box *
>(selector)) {
825 if (childs.size() > 1) {
826 if (
auto const css_tree =
dynamic_cast<Gtk::TreeView *
>(childs[1])) {
827 if (
auto const &model = css_tree->get_model()) {
845 g_debug(
"StyleDialog::_on_foreach_iter");
847 Gtk::TreeModel::Row row = *(iter);
849 if (!owner.empty())
return false;
864 g_debug(
"StyleDialog::_onLinkObj");
866 Gtk::TreeModel::Row row = *
store->get_iter(path);
886 g_debug(
"StyleDialog::_onPropDelete");
887 auto iter =
store->get_iter(path);
902 g_debug(
"StyleDialog::_addOwnerStyle");
918 g_debug(
"StyleDialog::parseStyle");
924 static auto const r_props = Glib::Regex::create(
"\\s*;\\s*");
925 std::vector<Glib::ustring>
props = r_props->split(style_string);
927 for (
auto &&token :
props) {
932 static auto const r_pair = Glib::Regex::create(
"\\s*:\\s*");
933 std::vector<Glib::ustring> pair = r_pair->split(token);
935 if (pair.size() > 1) {
936 ret[std::move(pair[0])] = std::move(pair[1]);
947 Glib::ustring selector, Glib::ustring
const &new_selector)
949 g_debug(
"StyleDialog::_writeStyleElemen");
967 std::string styleContent;
968 if (selector !=
"style_properties" && selector !=
"attributes") {
969 if (!new_selector.empty()) {
970 selector = new_selector;
972 std::vector<Glib::ustring> selectordata = Glib::Regex::split_simple(
";", selector);
973 for (
auto selectoritem : selectordata) {
974 if (selectordata[selectordata.size() - 1] == selectoritem) {
975 selector = selectoritem;
977 styleContent = styleContent + selectoritem +
";\n";
980 styleContent.append(
"\n").append(selector.raw()).
append(
" { \n");
983 for (
auto &row :
store->children()) {
986 const char *opencomment =
"";
987 const char *closecomment =
"";
988 if (selector !=
"style_properties" && selector !=
"attributes") {
994 if (!(
name.empty() && value.empty())) {
995 styleContent = styleContent + opencomment +
name.raw() +
":" + value.raw() +
";" + closecomment;
998 if (selector !=
"style_properties" && selector !=
"attributes") {
999 styleContent = styleContent +
"}";
1001 if (selector ==
"style_properties") {
1005 }
else if (selector ==
"attributes") {
1007 auto key = iter->id();
1017 for (
auto &row :
store->children()) {
1020 if (!(
name.empty() && value.empty())) {
1026 }
else if (!selector.empty()) {
1030 std::string pos = std::to_string(selectorpos);
1031 std::string selectormatch =
"(";
1032 for (; selectorpos > 1; selectorpos--) {
1033 selectormatch = selectormatch +
"[^\\}]*?\\}";
1035 selectormatch = selectormatch +
")([^\\}]*?\\})((.|\n)*)";
1038 std::regex e(selectormatch.c_str());
1039 std::string content = (textNode->
content() ? textNode->
content() :
"");
1041 std::regex_replace(std::back_inserter(
result), content.begin(), content.end(), e,
"$1" + styleContent +
"$3");
1045 result =
"* > .inkscapehacktmp{}";
1055 iter->style->readFromObject(iter);
1056 iter->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
1060 g_debug(
"StyleDialog::_writeStyleElement(): | %s |", styleContent.c_str());
1064 Glib::ustring
const &selector,
int const pos)
1066 g_debug(
"StyleDialog::_addRow");
1068 Gtk::TreeModel::iterator iter =
store->prepend();
1069 Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter;
1070 Gtk::TreeModel::Row row = *(iter);
1075 auto const col = pos < 1 ? 1 : 2;
1076 css_tree->set_visible(
true);
1077 css_tree->set_cursor(path, *(css_tree->get_column(col)),
true);
1083 g_debug(
"StyleDialog::_setAutocompletion");
1085 Glib::RefPtr<Gtk::ListStore> completionModel = Gtk::ListStore::create(
_mCSSData);
1086 Glib::RefPtr<Gtk::EntryCompletion> entry_completion = Gtk::EntryCompletion::create();
1087 entry_completion->set_model(completionModel);
1089 entry_completion->set_minimum_key_length(0);
1090 entry_completion->set_popup_completion(
true);
1094 Gtk::TreeModel::Row row = *(completionModel->prepend());
1099 entry->set_completion(entry_completion);
1105 g_debug(
"StyleDialog::_setAutocompletion");
1107 Glib::RefPtr<Gtk::ListStore> completionModel = Gtk::ListStore::create(
_mCSSData);
1108 Glib::RefPtr<Gtk::EntryCompletion> entry_completion = Gtk::EntryCompletion::create();
1109 entry_completion->set_model(completionModel);
1111 entry_completion->set_minimum_key_length(0);
1112 entry_completion->set_popup_completion(
true);
1113 if (
name ==
"paint-order") {
1114 Gtk::TreeModel::Row row = *(completionModel->append());
1116 row = *(completionModel->append());
1118 row = *(completionModel->append());
1120 row = *(completionModel->append());
1122 row = *(completionModel->append());
1124 row = *(completionModel->append());
1127 entry->set_completion(entry_completion);
1133 g_debug(
"StyleDialog::_startValueEdit");
1137 Gtk::TreeModel::Row row = *
store->get_iter(path);
1139 Gtk::Entry *entry =
dynamic_cast<Gtk::Entry *
>(cell);
1142 if (
name ==
"paint-order") {
1144 }
else if (
name ==
"fill-rule") {
1146 }
else if (
name ==
"stroke-linecap") {
1148 }
else if (
name ==
"stroke-linejoin") {
1150 }
else if (
name ==
"font-style") {
1152 }
else if (
name ==
"font-variant") {
1154 }
else if (
name ==
"font-weight") {
1156 }
else if (
name ==
"font-stretch") {
1158 }
else if (
name ==
"font-variant-position") {
1160 }
else if (
name ==
"text-align") {
1162 }
else if (
name ==
"text-transform") {
1164 }
else if (
name ==
"text-anchor") {
1166 }
else if (
name ==
"white-space") {
1168 }
else if (
name ==
"direction") {
1170 }
else if (
name ==
"baseline-shift") {
1172 }
else if (
name ==
"visibility") {
1174 }
else if (
name ==
"overflow") {
1176 }
else if (
name ==
"display") {
1178 }
else if (
name ==
"shape-rendering") {
1180 }
else if (
name ==
"color-rendering") {
1182 }
else if (
name ==
"clip-rule") {
1184 }
else if (
name ==
"color-interpolation") {
1194 g_debug(
"StyleDialog::_startNameEdit");
1198 Glib::RefPtr<Gtk::ListStore> completionModel = Gtk::ListStore::create(
_mCSSData);
1199 Glib::RefPtr<Gtk::EntryCompletion> entry_completion = Gtk::EntryCompletion::create();
1200 entry_completion->set_model(completionModel);
1202 entry_completion->set_minimum_key_length(1);
1203 entry_completion->set_popup_completion(
true);
1206 Gtk::TreeModel::Row row = *(completionModel->append());
1210 Gtk::Entry *entry =
dynamic_cast<Gtk::Entry *
>(cell);
1211 entry->set_completion(entry_completion);
1219 Gtk::TreeModel::iterator iter = selection->get_selected();
1223 Gtk::TreeModel::Path model = (Gtk::TreeModel::Path)iter;
1237 Gtk::TreeView *css_tree)
1239 g_debug(
"StyleDialog::_nameEdited");
1243 auto iter =
store->get_iter(path);
1251 Glib::ustring finalname =
name;
1252 auto i = finalname.find_first_of(
";:=");
1253 if (i != std::string::npos) {
1254 finalname.erase(i,
name.size() - i);
1263 bool is_attr = selector ==
"attributes";
1268 if (finalname.empty() && value.empty()) {
1273 auto const col = pos < 1 || is_attr ? 2 : 3;
1276 if (write && old_name !=
name) {
1291 Glib::RefPtr<Gtk::TreeStore>
store)
1293 g_debug(
"StyleDialog::_valueEdited");
1297 auto iter =
store->get_iter(path);
1300 Glib::ustring finalvalue = value;
1301 auto i = std::min(finalvalue.find(
";"), finalvalue.find(
":"));
1302 if (i != std::string::npos) {
1303 finalvalue.erase(i, finalvalue.size() - i);
1306 if (old_value == finalvalue) {
1312 if (
name.empty() && finalvalue.empty()) {
1317 if (selector !=
"style_properties" && selector !=
"attributes") {
1318 std::vector<SPObject *> objs =
_getObjVec(selector);
1319 for (
auto obj : objs) {
1320 auto css_str = Glib::ustring{};
1325 obj->getRepr()->setAttribute(
"style", css_str);
1326 obj->style->readFromObject(obj);
1327 obj->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
1335 g_debug(
"StyleDialog::_activeToggled");
1338 Gtk::TreeModel::Row row = *
store->get_iter(path);
1349 auto const key = Gtk::EventControllerKey::create();
1351 treeview.add_controller(
key);
1354 auto focus = Gtk::EventControllerFocus::create();
1355 focus->set_propagation_phase(Gtk::PropagationPhase::BUBBLE);
1356 treeview.add_controller(focus);
1365 g_debug(
"StyleDialog::_setEditingEntry: _editingEntry = %p",
static_cast<void *
>(entry));
1369 if (entry ==
nullptr)
return;
1372 entry->property_text().signal_changed().connect( [entry, endChars = std::move(endChars)]
1374 g_debug(
"StyleDialog::_setEditingEntry: Entry:text changed");
1376 auto text = entry->get_text();
1377 if (text.empty())
return;
1378 auto const endChar = text[text.size() - 1];
1379 if (endChars.find(endChar) == endChars.npos)
return;
1381 text.resize(text.size() - 1);
1382 entry->set_text(text);
1383 entry->editing_done();
1386 entry->signal_editing_done().connect([
this]{
_setEditingEntry(
nullptr, {}); });
1391 g_debug(
"StyleDialog::_onTreeViewKeyReleased");
1393 if (
_editingEntry !=
nullptr && (keyval == GDK_KEY_Tab or keyval == GDK_KEY_KP_Tab))
1395 g_debug(
"StyleDialog::_onTreeViewKeyReleased: _editingEntry != nullptr && Tab");
1403 g_debug(
"StyleDialog::_onTreeViewFocusLeave");
1406 g_debug(
"StyleDialog::_onTreeViewFocus: _editingEntry != nullptr");
1420 g_debug(
"StyleDialog::_getObjVec");
1422 g_assert(selector.find(
";") == Glib::ustring::npos);
1462 _vadj->set_value(0);
TODO: insert short description here.
TODO: insert short description here.
std::vector< Glib::ustring > sp_attribute_name_list(bool css_only)
Get sorted attribute name list.
static SPStyleProp const props[]
Lookup dictionary for attributes/properties.
Lookup dictionary for attributes/properties.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
void clear()
Unselects all selected objects.
SPObjectRange objects()
Returns the list of selected objects.
The set of selected SPObjects for a given document and layer model.
void set(XML::Node *repr)
Set the selection to an XML node's SPObject.
DialogBase is the base class for the dialog system.
Selection * getSelection() const
SPDocument * getDocument() const
SPDesktop * getDesktop() const
Gtk::TreeModelColumn< Glib::ustring > _colCSSData
Gtk::TreeModelColumn< bool > _colActive
Gtk::TreeModelColumn< SPObject * > _colHref
Gtk::TreeModelColumn< bool > _colStrike
Gtk::TreeModelColumn< Glib::ustring > _colOwner
Gtk::TreeModelColumn< int > _colSelectorPos
Gtk::TreeModelColumn< Glib::ustring > _colSelector
Gtk::TreeModelColumn< Glib::ustring > _colValue
Gtk::TreeModelColumn< Glib::ustring > _colName
Gtk::TreeModelColumn< bool > _colLinked
The StyleDialog class A list of CSS selectors will show up in this dialog.
Inkscape::XML::Node * _textNode
Gtk::TreeModel::Path _current_path
Inkscape::XML::Node * _getStyleTextNode(bool create_if_missing=false)
Glib::ustring _current_selector
void _startValueEdit(Gtk::CellEditable *cell, const Glib::ustring &path, Glib::RefPtr< Gtk::TreeStore > store)
Gtk::TreeView * _current_css_tree
void _startNameEdit(Gtk::CellEditable *cell, const Glib::ustring &path)
void _setEditingEntry(Gtk::Entry *entry, Glib::ustring endChars)
std::unique_ptr< XML::NodeObserver > const m_nodewatcher
void _onTreeViewKeyReleased(unsigned keyval, unsigned keycode, Gdk::ModifierType state)
void documentReplaced() final
Handle document replaced.
void _writeStyleElement(Glib::RefPtr< Gtk::TreeStore > const &store, Glib::ustring selector, Glib::ustring const &new_selector={})
Update the content of the style element as selectors (or objects) are added/removed.
void readStyleElement()
Fill the Gtk::TreeStore from the svg:style element.
void _activeToggled(const Glib::ustring &path, Glib::RefPtr< Gtk::TreeStore > const &store)
StyleDialog()
Constructor A treeview and a set of two buttons are added to the dialog.
void _nameEdited(const Glib::ustring &path, const Glib::ustring &name, Glib::RefPtr< Gtk::TreeStore > store, Gtk::TreeView *css_tree)
StyleDialog::nameEdited.
void _setAutocompletion(Gtk::Entry *entry, SPStyleEnum const cssenum[])
void _nodeChanged(Inkscape::XML::Node &repr)
AttrProp parseStyle(Glib::ustring style_string)
StyleDialog::parseStyle.
Inkscape::XML::Node * m_root
Glib::RefPtr< Gtk::Adjustment > _vadj
void _onPropDelete(Glib::ustring const &path, Glib::RefPtr< Gtk::TreeStore > const &store)
StyleDialog::_onPropDelete.
void _closeDialog(Gtk::Dialog *textDialogPtr)
void setCurrentSelector(Glib::ustring current_selector)
void selectionChanged(Selection *selection) final
std::map< Glib::ustring, Glib::ustring > AttrProp
std::vector< SPObject * > _getObjVec(Glib::ustring selector)
void _valueEdited(const Glib::ustring &path, const Glib::ustring &value, Glib::RefPtr< Gtk::TreeStore > store)
StyleDialog::valueEdited.
Gtk::TreeViewColumn * _current_value_col
std::unique_ptr< XML::NodeObserver > const m_styletextwatcher
Gtk::ScrolledWindow _scrolledWindow
void _nodeAdded(Inkscape::XML::Node &repr)
void _onLinkObj(Glib::ustring const &path, Glib::RefPtr< Gtk::TreeStore > const &store)
bool _on_foreach_iter(const Gtk::TreeModel::iterator &iter)
Gtk::Entry * _editingEntry
void _nodeRemoved(Inkscape::XML::Node &repr)
void _onTreeViewFocusLeave()
void _addRow(Glib::RefPtr< Gtk::TreeStore > const &store, Gtk::TreeView *css_tree, Glib::ustring const &selector, int pos)
void _addTreeViewHandlers(Gtk::TreeView &treeview)
void _addOwnerStyle(Glib::ustring name, Glib::ustring selector)
Interface for XML node observers.
Interface for refcounted XML nodes.
virtual Node * next()=0
Get the next sibling of this node.
virtual void addSubtreeObserver(NodeObserver &observer)=0
Add an object that will be notified of the changes to this node and its descendants.
virtual void addChild(Node *child, Node *after)=0
Insert another node as a child of this node.
virtual int code() const =0
Get the integer code corresponding to the node's name.
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
virtual void removeSubtreeObserver(NodeObserver &observer)=0
Remove an object from the subtree observers list.
virtual Node * firstChild()=0
Get the first child of this node.
virtual void setContent(char const *value)=0
Set the content of a text or comment node.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
void removeAttribute(Inkscape::Util::const_char_ptr key)
Remove an attribute of this node.
virtual char const * content() const =0
Get the content of a text or comment node.
virtual void addObserver(NodeObserver &observer)=0
Add an object that will be notified of the changes to this node.
virtual Document * document()=0
Get the node's associated document.
virtual NodeType type() const =0
Get the type of the node.
virtual void removeObserver(NodeObserver &observer)=0
Remove an object from the list of observers.
void setXMLDialogSelectedObject(SPObject *activexmltree)
SPObject * getObjectById(std::string const &id) const
Inkscape::XML::Node * getReprRoot()
SPObject * getXMLDialogSelectedObject()
std::vector< SPObject * > getObjectsBySelector(Glib::ustring const &selector) const
SPObject is an abstract base class of all of the document nodes at the SVG document level.
SPStyle * style
Represents the style properties, whether from presentation attributes, the style attribute,...
Inkscape::XML::Node * getRepr()
Returns the XML representation of tree.
void requestDisplayUpdate(unsigned int flags)
Queues an deferred update of this object's display.
void readFromObject(SPObject *object)
Read style properties from object's repr.
std::vector< SPIBase * > const & properties() const
Utilities to more easily use Gtk::EventController & subclasses like Gesture.
std::shared_ptr< Css const > css
TODO: insert short description here.
Inkscape::XML::Node * node
static R & release(R &r)
Decrements the reference count of a anchored object.
static bool is_url(char const *p)
gboolean sp_styledialog_store_move_to_next(gpointer data)
XML::Node * get_first_style_text_node(XML::Node *root, bool create_if_missing)
Get the first <style> element's first text node.
void remove_all_children(Widget &widget)
For each child in get_children(widget), call widget.remove(*child). May not cause delete child!
std::vector< Gtk::Widget * > get_children(Gtk::Widget &widget)
Get a vector of the widgetʼs children, from get_first_child() through each get_next_sibling().
void pack_start(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the start of box.
Glib::RefPtr< Gtk::Builder > create_builder(const char *filename)
void trim(Glib::ustring &input, Glib::ustring const &also_remove="")
Modifies a string in place, removing leading and trailing whitespace characters.
@ TEXT_NODE
Text node, e.g. "Some text" in <group>Some text</group> is represented by a text node.
static void append(std::vector< T > &target, std::vector< T > &&source)
Interface for XML node observers.
static cairo_user_data_key_t key
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
void sp_repr_css_write_string(SPCSSAttr *css, Glib::ustring &str)
Write a style attribute string from a list of properties stored in an SPCSAttr object.
void sp_repr_css_attr_add_from_string(SPCSSAttr *css, gchar const *p)
Use libcroco to parse a string for CSS properties and then merge them into an existing SPCSSAttr.
Inkscape::IO::Resource - simple resource API.
SPCSSAttr - interface for CSS Attributes.
virtual Node * createTextNode(char const *content)=0
virtual Node * createElement(char const *name)=0
SPStyle enums: named public enums that correspond to SVG property values.
static SPStyleEnum const enum_baseline_shift[]
static SPStyleEnum const enum_font_variant_position[]
static SPStyleEnum const enum_direction[]
static SPStyleEnum const enum_overflow[]
static SPStyleEnum const enum_shape_rendering[]
static SPStyleEnum const enum_color_rendering[]
static SPStyleEnum const enum_visibility[]
static SPStyleEnum const enum_stroke_linecap[]
static SPStyleEnum const enum_fill_rule[]
static SPStyleEnum const enum_white_space[]
static SPStyleEnum const enum_display[]
static SPStyleEnum const enum_stroke_linejoin[]
static SPStyleEnum const enum_clip_rule[]
static SPStyleEnum const enum_text_align[]
static SPStyleEnum const enum_font_style[]
static SPStyleEnum const enum_font_weight[]
static SPStyleEnum const enum_color_interpolation[]
static SPStyleEnum const enum_font_stretch[]
static SPStyleEnum const enum_text_anchor[]
static SPStyleEnum const enum_text_transform[]
static SPStyleEnum const enum_font_variant[]
SPStyle internal: classes that are internal to SPStyle.
SPStyle - a style object for SPItem objects.
A dialog for CSS selectors.
Glib::RefPtr< Gtk::Builder > builder
Inkscape::Util::trim - trim whitespace and other characters.