diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2017-02-22 12:21:03 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2017-02-22 12:21:03 +0000 |
| commit | 1510fb894b45a78aaa2ac9f1dca81357c010544a (patch) | |
| tree | 1fa9948a88985204aa9250cdcdd747dd472ef173 /src | |
| parent | Finish partially completed "cr_selector_parse_from_buf" and make it publicly ... (diff) | |
| download | inkscape-1510fb894b45a78aaa2ac9f1dca81357c010544a.tar.gz inkscape-1510fb894b45a78aaa2ac9f1dca81357c010544a.zip | |
Allow any valid CSS selector.
(bzr r15539)
Diffstat (limited to 'src')
| -rw-r--r-- | src/document.cpp | 49 | ||||
| -rw-r--r-- | src/document.h | 3 | ||||
| -rw-r--r-- | src/ui/dialog/styledialog.cpp | 43 |
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(); |
