19#include <glibmm/i18n.h>
20#include <glibmm/regex.h>
21#include <gtkmm/adjustment.h>
22#include <gtkmm/dialog.h>
23#include <gtkmm/entry.h>
24#include <gtkmm/gestureclick.h>
25#include <gtkmm/label.h>
26#include <gtkmm/togglebutton.h>
27#include <gtkmm/treemodelfilter.h>
63 : _selectorsdialog(selectorsdialog)
65 g_debug(
"SelectorsDialog::NodeObserver: Constructor");
79 g_debug(
"SelectorsDialog::NodeObserver::notifyContentChanged");
80 _selectorsdialog->_scrollock =
true;
81 _selectorsdialog->_updating =
false;
82 _selectorsdialog->_readStyleElement();
83 _selectorsdialog->_selectRow();
92 : _selectorsdialog(selectorsdialog)
94 g_debug(
"SelectorsDialog::NodeWatcher: Constructor");
101 _selectorsdialog->_nodeAdded(
child);
108 _selectorsdialog->_nodeRemoved(
child);
116 static GQuark const CODE_id = g_quark_from_static_string(
"id");
117 static GQuark const CODE_class = g_quark_from_static_string(
"class");
119 if (qname == CODE_id || qname == CODE_class) {
120 _selectorsdialog->_nodeChanged(
node);
130auto extract_label(CSS::RuleStatement
const &rule)
132 return rule.selectors;
134auto extract_label(CSS::BlockAtStatement
const &block_at)
136 return block_at.at_statement;
165 g_debug(
"SelectorsDialog::NodeChanged");
180 g_debug(
"SelectorsDialog::TreeStore::row_draggable_vfunc");
183 const_iterator iter = unconstThis->get_iter(path);
185 auto const &row = *iter;
189 return Gtk::TreeStore::row_draggable_vfunc(path);
196 const Glib::ValueBase &)
const
198 g_debug(
"SelectorsDialog::TreeStore::row_drop_possible_vfunc");
200 Gtk::TreeModel::Path dest_parent = dest;
202 return dest_parent.empty();
208 if (_selectorsdialog->_updating)
211 g_debug(
"on_row_deleted");
212 _selectorsdialog->_writeStyleElement();
213 _selectorsdialog->_readStyleElement();
218 g_debug(
"SelectorsDialog::TreeStore::create");
221 store->_selectorsdialog = selectorsdialog;
222 store->set_column_types(
store->_selectorsdialog->_mColumns);
223 return Glib::RefPtr<SelectorsDialog::TreeStore>(
store);
233 :
DialogBase(
"/dialogs/selectors",
"Selectors")
235 g_debug(
"SelectorsDialog::SelectorsDialog");
244 auto const addRenderer = Gtk::make_managed<UI::Widget::IconRenderer>();
245 addRenderer->add_icon(
"edit-delete");
246 addRenderer->add_icon(
"list-add");
247 addRenderer->add_icon(
"empty-icon");
248 addRenderer->signal_activated().connect([
this](Glib::ustring
const &path) {
250 Gtk::TreeModel::iterator iter =
_store->get_iter(path);
251 Gtk::TreeModel::Row row = *iter;
259 _del.set_visible(
true);
265 _treeView.get_selection()->set_mode(Gtk::SelectionMode::SINGLE);
269 _treeView.enable_model_drag_dest( Gdk::DragAction::MOVE );
270 int addCol =
_treeView.append_column(
"", *addRenderer) - 1;
271 Gtk::TreeViewColumn *col =
_treeView.get_column(addCol);
276 auto const label = Gtk::make_managed<Gtk::CellRendererText>();
305 g_debug(
"SelectorsDialog::_showWidgets");
308 bool dir = prefs->
getBool(
"/dialogs/selectors/vertical",
true);
310 _paned.set_orientation(dir ? Gtk::Orientation::VERTICAL : Gtk::Orientation::HORIZONTAL);
330 auto const _horizontal = Gtk::make_managed<Gtk::ToggleButton>();
331 auto const _vertical = Gtk::make_managed<Gtk::ToggleButton>();
332 _horizontal->set_image_from_icon_name(INKSCAPE_ICON(
"horizontal"));
333 _vertical->set_image_from_icon_name(INKSCAPE_ICON(
"vertical"));
334 _vertical->set_group(*_horizontal);
335 _vertical->set_active(dir);
336 _vertical->signal_toggled().connect(
342 _del.set_visible(
false);
348 _paned.set_shrink_start_child();
350 _paned.set_shrink_end_child();
351 _paned.set_resize_end_child();
352 _paned.set_wide_handle(
true);
353 _paned.set_size_request(320, -1);
355 auto const contents = Gtk::make_managed<Gtk::Box>(Gtk::Orientation::VERTICAL);
358 contents->set_valign(Gtk::Align::FILL);
362 _paned.property_position() = 200;
365 set_name(
"SelectorsAndStyleDialog");
370 g_debug(
"SelectorsDialog::_toggleDirection");
372 bool dir = vertical->get_active();
373 prefs->
setBool(
"/dialogs/selectors/vertical", dir);
374 _paned.set_orientation(dir ? Gtk::Orientation::VERTICAL : Gtk::Orientation::HORIZONTAL);
376 int widthpos =
_paned.property_max_position() -
_paned.property_min_position();
377 prefs->
setInt(
"/dialogs/selectors/panedpos", widthpos / 2);
378 _paned.property_position() = widthpos / 2;
388 g_debug(
"SelectorsDialog::_getStyleTextNode");
418 Gtk::TreeIter<Gtk::TreeRow> where)
430 auto const id = obj->getId();
434 auto childrow = *
_store->append(row.children());
458 Gtk::TreeIter<Gtk::TreeRow> where)
468 block_at.
block_content->for_each([
this, expand, subtree = row.children()](
auto const &element) {
469 _insertSyntacticElement(element, expand, _store->append(subtree));
497 g_debug(
"SelectorsDialog::_readStyleElement(): updating %s", (
_updating ?
"true" :
"false"));
505 std::string
const content = (textNode && textNode->content()) ? textNode->content() :
"";
508 if (syntactic_decomposition.empty()) {
515 std::map<std::string, bool> expanded_status;
517 syntactic_decomposition.
for_each([&, rows =
_store->children(),
this](
auto const &element) {
518 auto const label = extract_label(element);
519 auto const row_with_matching_label = std::find_if(rows.begin(), rows.end(), [&
label,
this](
auto const &row) {
520 return label == Glib::ustring{row[_mColumns._colSelector]}.raw();
522 if (row_with_matching_label != rows.end()) {
530 syntactic_decomposition.for_each([&,
this](
auto const &element) {
531 _insertSyntacticElement(element, expanded_status[extract_label(element)], _store->append());
536 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
540void SelectorsDialog::_rowExpand(
const Gtk::TreeModel::iterator &iter,
const Gtk::TreeModel::Path &path)
542 g_debug(
"SelectorsDialog::_row_expand()");
543 Gtk::TreeModel::Row row = *iter;
544 row[_mColumns._colExpand] =
true;
547void SelectorsDialog::_rowCollapse(
const Gtk::TreeModel::iterator &iter,
const Gtk::TreeModel::Path &path)
549 g_debug(
"SelectorsDialog::_row_collapse()");
550 Gtk::TreeModel::Row row = *iter;
551 row[_mColumns._colExpand] =
false;
555Glib::ustring SelectorsDialog::_formatRowAsCSS(Gtk::TreeConstRow
const &row)
const
557 if (row[_mColumns._colType] == SELECTOR) {
558 return row[_mColumns._colSelector] +
" { " + row[_mColumns._colProperties] +
" }\n";
559 }
else if (row[_mColumns._colType] == OTHER) {
560 Glib::ustring
result = row[_mColumns._colSelector];
562 if (!row.children().empty()) {
564 for (
auto const &
child : row.children()) {
577void SelectorsDialog::_writeStyleElement()
585 Glib::ustring style_content;
586 for (
auto const &row : _store->children()) {
587 style_content += _formatRowAsCSS(row);
593 DocumentUndo::done(SP_ACTIVE_DOCUMENT, _(
"Edited style element."), INKSCAPE_ICON(
"dialog-selectors"));
597 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
598 g_debug(
"SelectorsDialog::_writeStyleElement(): | %s |", style_content.c_str());
601Glib::ustring SelectorsDialog::_getSelectorClasses(Glib::ustring selector)
603 g_debug(
"SelectorsDialog::_getSelectorClasses");
605 if (std::vector<Glib::ustring> tokensplus = Glib::Regex::split_simple(
"[ ]+", selector);
608 selector = std::move(tokensplus.back());
610 g_assert(!tokensplus.empty());
615 Glib::ustring toparse = Glib::ustring(selector);
616 selector = Glib::ustring(
"");
617 auto i = toparse.find(
".");
618 if (i == std::string::npos) {
621 if (toparse[0] !=
'.' && toparse[0] !=
'#') {
622 i = std::min(toparse.find(
"#"), toparse.find(
"."));
623 Glib::ustring tag = toparse.substr(0, i);
627 if (i != std::string::npos) {
632 i = toparse.find(
"#");
633 if (i != std::string::npos) {
637 auto j = toparse.find(
"#");
638 if (j != std::string::npos) {
642 if (i != std::string::npos) {
643 toparse.insert(i,
"#");
645 Glib::ustring post = toparse.substr(0, i);
646 Glib::ustring pre = toparse.substr(i, toparse.size() - i);
647 toparse = pre + post;
650 auto k = toparse.find(
".");
651 if (k != std::string::npos) {
652 toparse = toparse.substr(k, toparse.size() - k);
659std::vector<SPObject *> SelectorsDialog::getSelectedObjects()
661 auto const objects = getDesktop()->getSelection()->objects();
662 return std::vector<SPObject *>(objects.begin(), objects.end());
669void SelectorsDialog::_addToSelector(Gtk::TreeModel::Row row)
671 g_debug(
"SelectorsDialog::_addToSelector: Entrance");
677 if (row[_mColumns._colType] == OTHER) {
681 auto const toAddObjVec = getSelectedObjects();
683 Glib::ustring multiselector = row[_mColumns._colSelector];
684 row[_mColumns._colExpand] =
true;
686 std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(
"[,]+", multiselector);
688 for (
auto const &obj : toAddObjVec) {
689 auto const id = obj->getId();
693 for (
auto const &tok : tokens) {
694 Glib::ustring clases = _getSelectorClasses(tok);
695 if (!clases.empty()) {
696 _insertClass(obj, clases);
698 std::vector<SPObject *> currentobjs = _getObjVec(multiselector);
699 bool removeclass =
true;
700 for (
auto currentobj : currentobjs) {
701 if (g_strcmp0(currentobj->getId(),
id) == 0) {
706 _removeClass(obj, clases);
711 std::vector<SPObject *> currentobjs = _getObjVec(multiselector);
713 bool insertid =
true;
714 for (
auto currentobj : currentobjs) {
715 if (g_strcmp0(currentobj->getId(),
id) == 0) {
720 multiselector = multiselector +
",#" + id;
723 auto childrow = *_store->prepend(row.children());
724 childrow[_mColumns._colSelector] =
"#" + Glib::ustring(
id);
725 childrow[_mColumns._colExpand] =
false;
726 childrow[_mColumns._colType] = OBJECT;
727 childrow[_mColumns._colObj] = obj;
731 row[_mColumns._colSelector] = multiselector;
735 for (
auto const &obj : toAddObjVec) {
741 Glib::ustring selprops = row[_mColumns._colProperties];
746 auto const key = g_quark_to_string(iter.key);
747 css->removeAttribute(
key);
750 Glib::ustring css_str;
756 obj->getRepr()->setAttribute(
"style", css_str);
757 obj->style->readFromObject(obj);
758 obj->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
761 _writeStyleElement();
768void SelectorsDialog::_removeFromSelector(Gtk::TreeModel::Row row)
770 g_debug(
"SelectorsDialog::_removeFromSelector: Entrance");
777 Glib::ustring objectLabel = row[_mColumns._colSelector];
779 if (
auto const iter = row.parent()) {
780 Gtk::TreeModel::Row
parent = *iter;
781 Glib::ustring multiselector =
parent[_mColumns._colSelector];
784 obj = _getObjVec(objectLabel)[0];
785 Glib::ustring selector;
787 for (
auto const &tok : Glib::Regex::split_simple(
"[,]+", multiselector)) {
793 Glib::ustring clases = _getSelectorClasses(tok);
794 if (!clases.empty()) {
795 _removeClass(obj, tok,
true);
798 auto i = tok.find(row[_mColumns._colSelector]);
799 if (i == std::string::npos) {
800 selector = selector.empty() ? tok : selector +
"," + tok;
806 if (selector.empty()) {
807 _store->erase(
parent.get_iter());
809 _store->erase(row.get_iter());
810 parent[_mColumns._colSelector] = selector;
811 parent[_mColumns._colExpand] =
true;
812 parent[_mColumns._colObj] =
nullptr;
819 _writeStyleElement();
823 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
831Glib::ustring SelectorsDialog::_getIdList(std::vector<SPObject *> sel)
833 g_debug(
"SelectorsDialog::_getIdList");
836 for (
auto const &obj: sel) {
837 if (
auto const id = obj->getId()) {
841 str.append(
"#").append(
id);
852std::vector<SPObject *> SelectorsDialog::_getObjVec(Glib::ustring
const &selector)
854 g_debug(
"SelectorsDialog::_getObjVec: | %s |", selector.c_str());
856 g_assert(selector.find(
";") == Glib::ustring::npos);
858 return getDesktop()->getDocument()->getObjectsBySelector(selector);
866void SelectorsDialog::_insertClass(
const std::vector<SPObject *> &objVec,
const Glib::ustring &className)
868 g_debug(
"SelectorsDialog::_insertClass");
870 for (
auto const &obj: objVec) {
871 _insertClass(obj, className);
875template <
typename T,
typename U>
878 auto const end = haystack.end();
879 return std::find(haystack.begin(),
end, needle) !=
end;
887void SelectorsDialog::_insertClass(
SPObject *obj,
const Glib::ustring &className)
889 g_debug(
"SelectorsDialog::_insertClass");
891 Glib::ustring classAttr;
896 std::vector<Glib::ustring> tokens = Glib::Regex::split_simple(
"[.]+", className);
897 std::sort(tokens.begin(), tokens.end());
898 tokens.erase(std::unique(tokens.begin(), tokens.end()), tokens.end());
900 std::vector<Glib::ustring>
const tokensplus = Glib::Regex::split_simple(
"[\\s]+", classAttr);
901 for (
auto const &tok : tokens) {
904 classAttr = classAttr.empty() ? tok : classAttr +
" " + tok;
916void SelectorsDialog::_removeClass(
const std::vector<SPObject *> &objVec,
const Glib::ustring &className,
bool all)
918 g_debug(
"SelectorsDialog::_removeClass");
920 for (
auto const &obj : objVec) {
921 _removeClass(obj, className, all);
930void SelectorsDialog::_removeClass(
SPObject *obj,
const Glib::ustring &className,
bool all)
932 g_debug(
"SelectorsDialog::_removeClass");
936 Glib::ustring classAttrRestore = classAttr;
937 bool notfound =
false;
939 for (
auto const &tok : Glib::Regex::split_simple(
"[.]+", className)) {
940 auto i = classAttr.find(tok);
941 if (i != std::string::npos) {
942 classAttr.erase(i, tok.length());
948 if (all && notfound) {
949 classAttr = classAttrRestore;
954 if (classAttr.empty()) {
967void SelectorsDialog::_addSelector()
969 g_debug(
"SelectorsDialog::_addSelector: Entrance");
973 auto const objVec = getSelectedObjects();
976 auto textDialogPtr = std::make_unique<Gtk::Dialog>();
977 textDialogPtr->property_modal() =
true;
978 textDialogPtr->property_title() = _(
"CSS selector");
979 textDialogPtr->add_button(_(
"Cancel"), Gtk::ResponseType::CANCEL);
980 textDialogPtr->add_button(_(
"Add"), Gtk::ResponseType::OK);
982 auto const textEditPtr = Gtk::make_managed<Gtk::Entry>();
983 textEditPtr->signal_activate().connect(
984 sigc::bind(sigc::mem_fun(*
this, &SelectorsDialog::_closeDialog), textDialogPtr.get()));
987 auto const textLabelPtr = Gtk::make_managed<Gtk::Label>(_(
"Invalid CSS selector."));
995 if (getDesktop()->getSelection()->isEmpty()) {
996 textEditPtr->set_text(
".Class1");
998 textEditPtr->set_text(_getIdList(objVec));
1001 Gtk::Requisition sreq1, sreq2;
1002 textDialogPtr->get_preferred_size(sreq1, sreq2);
1003 int const minWidth = std::max(200, sreq2.get_width());
1004 int const minHeight = std::max(100, sreq2.get_height());
1005 textDialogPtr->set_size_request(minWidth, minHeight);
1007 textEditPtr->set_visible(
true);
1008 textLabelPtr->set_visible(
false);
1009 textDialogPtr->set_visible(
true);
1013 bool invalid =
true;
1014 Glib::ustring selectorValue;
1015 Glib::ustring originalValue;
1018 if (
result != Gtk::ResponseType::OK) {
1027 originalValue = textEditPtr->get_text();
1037 _del.set_visible(
true);
1038 if (originalValue.find(
"@import ") == std::string::npos && selectorValue.empty()) {
1039 textLabelPtr->set_visible(
true);
1048 if (originalValue.find(
"@import ") != std::string::npos) {
1049 Gtk::TreeModel::Row row = *_store->prepend();
1050 row[_mColumns._colSelector] = originalValue;
1051 row[_mColumns._colExpand] =
false;
1052 row[_mColumns._colType] = OTHER;
1053 row[_mColumns._colObj] =
nullptr;
1056 auto const tokens = Glib::Regex::split_simple(
"[,]+", selectorValue);
1057 for (
auto const &obj : objVec) {
1058 for (
auto const &tok : tokens) {
1059 Glib::ustring clases = _getSelectorClasses(tok);
1060 if (clases.empty()) {
1064 _insertClass(obj, clases);
1066 auto const currentobjs = _getObjVec(selectorValue);
1069 _removeClass(obj, clases);
1074 Gtk::TreeModel::Row row = *(_store->prepend());
1075 row[_mColumns._colExpand] =
true;
1076 row[_mColumns._colType] = SELECTOR;
1077 row[_mColumns._colSelector] = selectorValue;
1078 row[_mColumns._colObj] =
nullptr;
1081 for (
auto const &obj : _getObjVec(selectorValue)) {
1082 auto const id = obj->getId();
1086 auto childrow = *(_store->prepend(row.children()));
1087 childrow[_mColumns._colSelector] =
"#" + Glib::ustring(
id);
1088 childrow[_mColumns._colExpand] =
false;
1089 childrow[_mColumns._colType] = OBJECT;
1090 childrow[_mColumns._colObj] = obj;
1096 _writeStyleElement();
1098 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
1101void SelectorsDialog::_closeDialog(Gtk::Dialog *textDialogPtr) { textDialogPtr->response(Gtk::ResponseType::OK); }
1107void SelectorsDialog::_delSelector()
1109 g_debug(
"SelectorsDialog::_delSelector");
1112 Glib::RefPtr<Gtk::TreeSelection> refTreeSelection = _treeView.get_selection();
1113 Gtk::TreeModel::iterator iter = refTreeSelection->get_selected();
1118 if (iter->children().size() > 2) {
1123 _store->erase(iter);
1125 _writeStyleElement();
1126 _del.set_visible(
false);
1128 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
1136 PropertyData() =
default;;
1137 PropertyData(Glib::ustring
name) : _name(
std::move(
name)) {};
1139 void _setSheetValue(Glib::ustring value) { _sheetValue = value; };
1140 void _setAttrValue(Glib::ustring value) { _attrValue = value; };
1141 Glib::ustring _getName() {
return _name; };
1142 Glib::ustring _getSheetValue() {
return _sheetValue; };
1143 Glib::ustring _getAttrValue() {
return _attrValue; };
1146 Glib::ustring _name;
1147 Glib::ustring _sheetValue;
1148 Glib::ustring _attrValue;
1153SelectorsDialog::~SelectorsDialog()
1156 _style_dialog->setDesktop(
nullptr);
1159void SelectorsDialog::update()
1161 _style_dialog->update();
1164void SelectorsDialog::desktopReplaced()
1166 _style_dialog->setDesktop(getDesktop());
1169void SelectorsDialog::removeObservers()
1172 _textNode->removeObserver(*m_styletextwatcher);
1173 _textNode =
nullptr;
1176 m_root->removeSubtreeObserver(*m_nodewatcher);
1181void SelectorsDialog::documentReplaced()
1184 if (
auto document = getDocument()) {
1185 m_root = document->getReprRoot();
1186 m_root->addSubtreeObserver(*m_nodewatcher);
1188 selectionChanged(getSelection());
1194 _readStyleElement();
1202void SelectorsDialog::_selectRow()
1204 g_debug(
"SelectorsDialog::_selectRow: updating: %s", (_updating ?
"true" :
"false"));
1208 _del.set_visible(
false);
1210 std::vector<Gtk::TreeModel::Path> selectedrows = _treeView.get_selection()->get_selected_rows();
1211 if (selectedrows.size() == 1) {
1212 Gtk::TreeModel::Row row = *_store->get_iter(selectedrows[0]);
1213 if (!row.parent() && row.children().size() < 2) {
1214 _del.set_visible(
true);
1217 _style_dialog->setCurrentSelector(row[_mColumns._colSelector]);
1219 }
else if (selectedrows.size() == 0) {
1220 _del.set_visible(
true);
1223 if (_updating || !getDesktop())
return;
1225 Gtk::TreeModel::Children children = _store->children();
1229 _style_dialog->setCurrentSelector(
"");
1232 for (
auto &&row : children) {
1234 for (
auto &&subrow : row.children()) {
1240 auto selected_objs = getSelectedObjects();
1241 std::sort(selected_objs.begin(), selected_objs.end());
1243 for (
auto &&row : children) {
1244 if (row[_mColumns._colType] != SELECTOR) {
1248 auto row_children = _getObjVec(row[_mColumns._colSelector]);
1249 std::sort(row_children.begin(), row_children.end());
1252 if (row_children == selected_objs) {
1256 for (
auto &&subrow : row.children()) {
1257 if (subrow[_mColumns._colObj] && selection->
includes(subrow[_mColumns._colObj])) {
1262 if (row[_mColumns._colExpand]) {
1263 _treeView.expand_to_path(_treeView.get_model()->get_path(row.get_iter()));
1267 _vadj->set_value(std::min(_scrollpos, _vadj->get_upper()));
1276void SelectorsDialog::_styleButton(Gtk::Button &btn,
char const *iconName,
char const *tooltip)
1278 g_debug(
"SelectorsDialog::_styleButton");
1280 btn.set_image_from_icon_name(iconName, Gtk::IconSize::NORMAL);
1281 btn.set_has_frame(
false);
1282 btn.set_tooltip_text (tooltip);
TODO: insert short description here.
TODO: insert short description here.
A partial syntactic decomposition of a CSS stylesheet into syntactic elements.
void for_each(SyntacticElementHandler auto &&handler) const
Execute an operation for each syntactic element, in the order of their occurrence.
static void done(SPDocument *document, Glib::ustring const &event_description, Glib::ustring const &undo_icon, unsigned int object_modified_tag=0)
bool isEmpty()
Returns true if no items are selected.
Preference storage class.
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
static Preferences * get()
Access the singleton Preferences object.
void setInt(Glib::ustring const &pref_path, int value)
Set an integer value.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
The set of selected SPObjects for a given document and layer model.
bool includes(XML::Node *repr, bool anyAncestor=false)
Returns true if the given item is selected.
DialogBase is the base class for the dialog system.
Gtk::TreeModelColumn< Glib::ustring > _colSelector
Gtk::TreeModelColumn< SPObject * > _colObj
Gtk::TreeModelColumn< bool > _colExpand
Gtk::TreeModelColumn< gint > _fontWeight
Gtk::TreeModelColumn< gint > _colType
Gtk::TreeModelColumn< Glib::ustring > _colProperties
void on_row_deleted(const TreeModel::Path &path) final
bool row_drop_possible_vfunc(const Gtk::TreeModel::Path &path, const Glib::ValueBase &selection_data) const final
Allow dropping only in between other selectors.
SelectorsDialog * _selectorsdialog
bool row_draggable_vfunc(const Gtk::TreeModel::Path &path) const final
Allow dragging only selectors.
static Glib::RefPtr< SelectorsDialog::TreeStore > create(SelectorsDialog *styledialog)
The SelectorsDialog class A list of CSS selectors will show up in this dialog.
void _readStyleElement()
Fill the internal Gtk::TreeStore from the svg:style element.
SelectorsDialog()
Constructor A treeview and a set of two buttons are added to the dialog.
Inkscape::XML::Node * _getStyleTextNode(bool create_if_missing=false)
void _selectRow()
This function selects the row in treeview corresponding to an object selected in the drawing.
void _insertSyntacticElement(CSS::RuleStatement const &rule, bool expand, Gtk::TreeIter< Gtk::TreeRow > where)
Populate a tree row with a representation of a CSS rule statement.
void _styleButton(Gtk::Button &btn, char const *iconName, char const *tooltip)
void _addToSelector(Gtk::TreeModel::Row row)
Glib::RefPtr< Gtk::Adjustment > _vadj
Gtk::ScrolledWindow _scrolled_window_selectors
void _nodeChanged(Inkscape::XML::Node &repr)
void _rowExpand(const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path)
Inkscape::XML::Node * _textNode
void _rowCollapse(const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path)
Inkscape::XML::Node * m_root
StyleDialog * _style_dialog
void _nodeAdded(Inkscape::XML::Node &repr)
void _removeFromSelector(Gtk::TreeModel::Row row)
void _addSelector()
This function opens a dialog to add a selector.
void _nodeRemoved(Inkscape::XML::Node &repr)
std::unique_ptr< Inkscape::XML::NodeObserver > m_styletextwatcher
std::vector< SPObject * > _getObjVec(Glib::ustring const &selector)
Glib::RefPtr< TreeStore > _store
void _delSelector()
This function deletes selector when '-' at the bottom is clicked.
void _toggleDirection(Gtk::ToggleButton *vertical)
std::unique_ptr< Inkscape::XML::NodeObserver > m_nodewatcher
Interface for XML node observers.
Interface for refcounted XML nodes.
virtual const AttributeVector & attributeList() const =0
Get a list of the node's attributes.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute 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 void addObserver(NodeObserver &observer)=0
Add an object that will be notified of the changes to this node.
virtual void removeObserver(NodeObserver &observer)=0
Remove an object from the list of observers.
static bool isSVGElement(Glib::ustring const &element)
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.
typedefG_BEGIN_DECLS struct _CRSelector CRSelector
CRSelector * cr_selector_parse_from_buf(const guchar *a_char_buf, enum CREncoding a_enc)
void cr_selector_destroy(CRSelector *a_this)
std::shared_ptr< Css const > css
Editable view implementation.
static char const *const parent
TODO: insert short description here.
Macro for icon names used in Inkscape.
Inkscape::XML::Node * node
std::string OtherStatement
Another CSS statement, currently not handled in a special way; for example @charset.
std::string selector_to_validated_string(CRSelector const &croco_selector)
Convert a CSS selector to a string, performing a fix-up if needed.
bool vector_contains(std::vector< T > const &haystack, U const &needle)
XML::Node * get_first_style_text_node(XML::Node *root, bool create_if_missing)
Get the first <style> element's first text node.
void pack_end(Gtk::Box &box, Gtk::Widget &child, bool const expand, bool const fill, unsigned const padding)
Adds child to box, packed with reference to the end of box.
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.
int dialog_run(Gtk::Dialog &dialog)
This is a GTK4 porting aid meant to replace the removal of the Gtk::Dialog synchronous API.
void trim(Glib::ustring &input, Glib::ustring const &also_remove="")
Modifies a string in place, removing leading and trailing whitespace characters.
static cairo_user_data_key_t key
Helpers for using Gtk::Boxes, encapsulating large changes between GTK3 & GTK4.
Singleton class to access the preferences file in a convenient way.
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_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
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.
A dialog for CSS selectors.
SPCSSAttr - interface for CSS Attributes.
A decomposed block -statement, consisting of the statement and the contents of the associated block.
std::unique_ptr< SyntacticDecomposition > block_content
A decomposed CSS rule statement, consisting of a selector (which can be complex), and the associated ...
std::string selectors
Selectors for a rule set statement.
std::string rules
Semicolon-separated rules.
SPStyle - a style object for SPItem objects.
A dialog for CSS selectors.
Parsing utils capable of producing a rudimentary syntactic decomposition of a CSS stylesheet.
Inkscape::Util::trim - trim whitespace and other characters.