summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2017-02-22 12:21:03 +0000
committertavmjong-free <tavmjong@free.fr>2017-02-22 12:21:03 +0000
commit1510fb894b45a78aaa2ac9f1dca81357c010544a (patch)
tree1fa9948a88985204aa9250cdcdd747dd472ef173 /src
parentFinish partially completed "cr_selector_parse_from_buf" and make it publicly ... (diff)
downloadinkscape-1510fb894b45a78aaa2ac9f1dca81357c010544a.tar.gz
inkscape-1510fb894b45a78aaa2ac9f1dca81357c010544a.zip
Allow any valid CSS selector.
(bzr r15539)
Diffstat (limited to 'src')
-rw-r--r--src/document.cpp49
-rw-r--r--src/document.h3
-rw-r--r--src/ui/dialog/styledialog.cpp43
3 files changed, 58 insertions, 37 deletions
diff --git a/src/document.cpp b/src/document.cpp
index b1f16fece..c7115f906 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -62,6 +62,11 @@
#include "sp-symbol.h"
#include "xml/rebase-hrefs.h"
+#include "libcroco/cr-sel-eng.h"
+#include "libcroco/cr-selector.h"
+#include "libcroco/cr-parser.h"
+#include "src/xml/croco-node-iface.h"
+
using Inkscape::DocumentUndo;
using Inkscape::Util::unit_table;
@@ -1119,6 +1124,50 @@ std::vector<SPObject *> SPDocument::getObjectsByElement(Glib::ustring const &ele
return objects;
}
+void _getObjectsBySelectorRecursive(SPObject *parent,
+ CRSelEng *sel_eng, CRSimpleSel *simple_sel,
+ std::vector<SPObject *> &objects)
+{
+ if (parent) {
+ gboolean result = false;
+ cr_sel_eng_matches_node( sel_eng, simple_sel, parent->getRepr(), &result );
+ if (result) {
+ objects.push_back(parent);
+ }
+
+ // Check children
+ for (auto& child : parent->children) {
+ _getObjectsBySelectorRecursive(&child, sel_eng, simple_sel, objects);
+ }
+ }
+}
+
+std::vector<SPObject *> SPDocument::getObjectsBySelector(Glib::ustring const &selector) const
+{
+ // std::cout << "\nSPDocument::getObjectsBySelector: " << selector << std::endl;
+
+ std::vector<SPObject *> objects;
+ g_return_val_if_fail(!selector.empty(), objects);
+
+ static CRSelEng *sel_eng = NULL;
+ if (!sel_eng) {
+ sel_eng = cr_sel_eng_new();
+ cr_sel_eng_set_node_iface(sel_eng, &Inkscape::XML::croco_node_iface);
+ }
+
+ Glib::ustring my_selector = selector + " {"; // Parsing fails sometimes without '{'. Fix me
+ CRSelector *cr_selector = cr_selector_parse_from_buf ((guchar*)my_selector.c_str(), CR_UTF_8);
+ // char * cr_string = (char*)cr_selector_to_string( cr_selector );
+ // std::cout << " selector: |" << (cr_string?cr_string:"Empty") << "|" << std::endl;
+ CRSelector const *cur = NULL;
+ for (cur = cr_selector; cur; cur = cur->next) {
+ if (cur->simple_sel ) {
+ _getObjectsBySelectorRecursive(root, sel_eng, cur->simple_sel, objects);
+ }
+ }
+ return objects;
+}
+
void SPDocument::bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object)
{
if (object) {
diff --git a/src/document.h b/src/document.h
index 142eb5000..db50f1717 100644
--- a/src/document.h
+++ b/src/document.h
@@ -199,7 +199,8 @@ public:
std::vector<SPObject *> getObjectsByClass(Glib::ustring const &klass) const;
std::vector<SPObject *> getObjectsByElement(Glib::ustring const &element) const;
-
+ std::vector<SPObject *> getObjectsBySelector(Glib::ustring const &selector) const;
+
void bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object);
SPObject *getObjectByRepr(Inkscape::XML::Node *repr) const;
diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp
index 9916551d8..67b56c259 100644
--- a/src/ui/dialog/styledialog.cpp
+++ b/src/ui/dialog/styledialog.cpp
@@ -628,42 +628,13 @@ Glib::ustring StyleDialog::_getIdList(std::vector<SPObject*> sel)
/**
* @brief StyleDialog::_getObjVec
- * @return objVec
- * Return a vector of all objects that selector matches. This only handles simple id, class, and
- * element selectors. Expanding this would take integrating a true CSS parser.
+ * @param selector: a valid CSS selector string.
+ * @return objVec: a vector of pointers to SPObject's the selector matches.
+ * Return a vector of all objects that selector matches.
*/
std::vector<SPObject *> StyleDialog::_getObjVec(Glib::ustring selector) {
- // Split selector string into individual selectors (which are comma separated).
- std::vector<Glib::ustring> tokens = Glib::Regex::split_simple("\\s*,\\s*", selector );
-
- std::vector<SPObject *> objVec;
-
- for (auto& token: tokens) {
-
- // Find objects that match class selector
- if (token[0] == '.') {
- token.erase(0,1);
- std::vector<SPObject *> objects = _document->getObjectsByClass( token );
- objVec.insert(objVec.end(), objects.begin(), objects.end());
- }
-
- // Find objects that match id selector
- else if (token[0] == '#') {
- token.erase(0,1);
- SPObject * object = _document->getObjectById( token );
- if (object) {
- objVec.push_back(object);
- }
- }
-
- // Find objects that match element selector
- else {
- std::vector<SPObject *> objects = _document->getObjectsByElement( token );
- objVec.insert(objVec.end(), objects.begin(), objects.end());
- }
-
- }
+ std::vector<SPObject *> objVec = _document->getObjectsBySelector( selector );
#ifdef DEBUG_STYLEDIALOG
std::cout << "StyleDialog::_getObjVec: |" << selector << "|" << std::endl;
@@ -792,8 +763,6 @@ void StyleDialog::_addSelector()
textDialogPtr->get_preferred_size(sreq1, sreq2);
int minWidth = 200;
int minHeight = 100;
- std::cout << " preferred: " << sreq2.width << "x" << sreq2.height << std::endl;
- std::cout << " minimum: " << minWidth << "x" << minHeight << std::endl;
minWidth = (sreq2.width > minWidth ? sreq2.width : minWidth );
minHeight = (sreq2.height > minHeight ? sreq2.height : minHeight);
textDialogPtr->set_size_request(minWidth, minHeight);
@@ -820,12 +789,14 @@ void StyleDialog::_addSelector()
* set to ".Class1"
*/
selectorValue = textEditPtr->get_text();
+ Glib::ustring firstWord = selectorValue.substr(0, selectorValue.find(" "));
del->set_sensitive(true);
if (selectorValue[0] == '.' ||
selectorValue[0] == '#' ||
- SPAttributeRelSVG::isSVGElement( selectorValue ) ) {
+ selectorValue[0] == '*' ||
+ SPAttributeRelSVG::isSVGElement( firstWord ) ) {
invalid = false;
} else {
textLabelPtr->show();