diff options
| author | Tavmjong Bah, Kamalpreet Grewal <> | 2016-07-25 13:40:59 +0000 |
|---|---|---|
| committer | kamalpreetgrewal <grewalkamal005@gmail.com> | 2016-07-25 13:40:59 +0000 |
| commit | 6641c2e8c586612aad47e1296584ca6447e11b15 (patch) | |
| tree | c4a59dec5624aebab6aee2f0b6f3902a9168a7da /src | |
| parent | Merge changes from trunk (diff) | |
| download | inkscape-6641c2e8c586612aad47e1296584ca6447e11b15.tar.gz inkscape-6641c2e8c586612aad47e1296584ca6447e11b15.zip | |
Add robust implementation of _getSelectorVec()
(bzr r14949.1.60)
Diffstat (limited to 'src')
| -rw-r--r-- | src/document.cpp | 54 | ||||
| -rw-r--r-- | src/document.h | 3 | ||||
| -rw-r--r-- | src/ui/dialog/styledialog.cpp | 141 |
3 files changed, 124 insertions, 74 deletions
diff --git a/src/document.cpp b/src/document.cpp index 9f408788b..834d54132 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1053,6 +1053,60 @@ sigc::connection SPDocument::connectIdChanged(gchar const *id, return priv->id_changed_signals[g_quark_from_string(id)].connect(slot); } +void _getObjectsByClassRecursive(Glib::ustring const &klass, SPObject *parent, std::vector<SPObject *> &objects) +{ + if (parent) { + Glib::ustring class_attribute; + char const *temp = parent->getAttribute("class"); + if (temp) { + class_attribute = temp; + } + + if (class_attribute.find( klass ) != std::string::npos) { + objects.push_back( parent ); + } + + // Check children + for (SPObject *child = parent->children; child; child = child->next) { + _getObjectsByClassRecursive( klass, child, objects ); + } + } +} + +std::vector<SPObject *> SPDocument::getObjectsByClass(Glib::ustring const &klass) const +{ + std::vector<SPObject *> objects; + g_return_val_if_fail(!klass.empty(), objects); + + _getObjectsByClassRecursive(klass, root, objects); + return objects; +} + +void _getObjectsByElementRecursive(Glib::ustring const &element, SPObject *parent, + std::vector<SPObject *> &objects) +{ + if (parent) { + Glib::ustring prefixed = "svg:" + element; + if (parent->getRepr()->name() == prefixed) { + objects.push_back(parent); + } + + // Check children + for (SPObject *child = parent->children; child; child = child->next) { + _getObjectsByElementRecursive(element, child, objects); + } + } +} + +std::vector<SPObject *> SPDocument::getObjectsByElement(Glib::ustring const &element) const +{ + std::vector<SPObject *> objects; + g_return_val_if_fail(!element.empty(), objects); + + _getObjectsByElementRecursive(element, root, 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 813d4ae49..49bde1897 100644 --- a/src/document.h +++ b/src/document.h @@ -179,6 +179,9 @@ public: SPObject *getObjectById(char const *id) const; sigc::connection connectIdChanged(const char *id, IDChangedSignal::slot_type slot); + std::vector<SPObject *> getObjectsByClass(Glib::ustring const &klass) const; + std::vector<SPObject *> getObjectsByElement(Glib::ustring const &element) 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 1004fa151..259f326e4 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -425,95 +425,88 @@ std::string StyleDialog::_setClassAttribute(std::vector<SPObject*> sel) */ std::vector<StyleDialog::InkSelector> StyleDialog::_getSelectorVec() { - std::string key, value, selId; for (unsigned i = 0; i < _document->getReprRoot()->childCount(); ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { _styleExists = true; _newDrawing = false; _styleChild = _document->getReprRoot()->nthChild(i); - std::stringstream str; - str << _document->getReprRoot()->nthChild(i)->firstChild()->content(); - std::string sel; - /** - * If a selector without any style attribute content is added, the - * value is set to empty so that its corresponding XML repr is added. - */ - while(std::getline(str, sel, '\n')) { + // Get content from first style element. + std::string content = _styleChild->firstChild()->content(); + + // Remove end-of-lines (check it works on Windoze). + content.erase(std::remove(content.begin(), content.end(), '\n'), content.end()); + + // First split into selector/value chunks. + // An attempt to use Glib::Regex failed. A C++11 version worked but + // reportedly has problems on Windows. Using split_simple() is simpler + // and probably faster. + // + // Glib::RefPtr<Glib::Regex> regex1 = + // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}"); + // + // Glib::MatchInfo minfo; + // regex1->match(content, minfo); + + // Split on curly brackets. Even tokens are selectors, odd are values. + std::vector<std::string> tokens = Glib::Regex::split_simple("[}{]", content); + + for (unsigned i = 0; i < tokens.size()-1; i += 2) { + std::string selectors = tokens[i]; + REMOVE_SPACES(selectors); // Remove leading/trailing spaces + + /** Make a list of all objects that selector matches. This is + * currently limited to simple id, class, and element selectors. + * Expanding this would take integrating a true CSS parser. + */ std::vector<SPObject *>objVec; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - _selectorName = key; - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - std::stringstream ss(key); - std::string token; - std::size_t found = key.find(","); - if (found!=std::string::npos) { - while(std::getline(ss, token, ',')) { - REMOVE_SPACES(token); + // Split selector string into individual selectors (which are comma separated). + std::vector<std::string> tokens2 = Glib::Regex::split_simple + ("\\s*,\\s*", selectors ); - if (token[0] == '.') { - token.erase(0, token.find_first_not_of('.')); - for (unsigned i = 0; i < _document->getReprRoot() - ->childCount(); ++i) { - if (_document->getReprRoot()-> - nthChild(i)->attribute("class") && - _document->getReprRoot()->nthChild(i) - ->attribute("class") == token) { - selId = _document->getReprRoot()->nthChild(i) - ->attribute("id"); - objVec.push_back( _document->getObjectById(selId)); - } - } - } - else if (token[0] == '#') { - token.erase(0, token.find_first_not_of('#')); - selId = token; - objVec.push_back(_document->getObjectById(selId)); - } - else { - std::cout << "simple text" << std::endl; - } + for(unsigned i = 0; i < tokens2.size(); ++i) { + std::string token2 = tokens2[i]; + + // Find objects that match class selector + if (token2[0] == '.') { + token2.erase(0,1); + std::vector<SPObject *> objects = _document + ->getObjectsByClass(token2); + objVec.insert(objVec.end(), objects.begin(), objects.end()); + } + + // Find objects that match id selector + else if (token2[0] == '#') { + token2.erase(0,1); + SPObject * object = _document->getObjectById(token2); + if (object) { + objVec.push_back(object); } } + + // Find objects that match element selector else { - REMOVE_SPACES(key); - std::string tkn = key; - if (tkn[0] == '.') { - tkn.erase(0, tkn.find_first_not_of('.')); - for (unsigned i = 0; i < _document->getReprRoot() - ->childCount(); ++i) { - if (_document->getReprRoot()-> - nthChild(i)->attribute("class") && - _document->getReprRoot()->nthChild(i) - ->attribute("class") == tkn) { - selId = _document->getReprRoot()->nthChild(i) - ->attribute("id"); - objVec.push_back(_document->getObjectById(selId)); - } - } - } - else if (tkn[0] == '#') { - tkn.erase(0, key.find_first_not_of('#')); - selId = tkn; - objVec.push_back(_document->getObjectById(selId)); - } - else { - std::cout << "simple text" << std::endl; - } + std::vector<SPObject *> objects = _document-> + getObjectsByElement(token2); + objVec.insert(objVec.end(), objects.begin(), objects.end()); } - _selectorValue = _selectorName + "{" + value + "}\n"; + } - inkSelector._selector = key; - inkSelector._matchingObjs = objVec; - inkSelector._xmlContent = _selectorValue; - _selectorVec.push_back(inkSelector); + std::string values; + // Check to make sure we do have a value to match selector. + if ((i+1) < tokens.size()) { + values = tokens[i+1]; + } else { + std::cerr << "StyleDialog::_getSelectorVec: Missing values " + "for last selector!" << std::endl; } + + _selectorValue = selectors + "{" + values + "}\n"; + inkSelector._selector = selectors; + inkSelector._matchingObjs = objVec; + inkSelector._xmlContent = _selectorValue; + _selectorVec.push_back(inkSelector); } } } |
