From 46bff7b31a99784086c5f5589956e647c862e944 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sat, 4 Jun 2016 20:02:59 +0530 Subject: Register style dialog with support to add selector (bzr r14949.1.1) --- src/ui/dialog/styledialog.cpp | 113 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/ui/dialog/styledialog.cpp (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp new file mode 100644 index 000000000..7e555ddb2 --- /dev/null +++ b/src/ui/dialog/styledialog.cpp @@ -0,0 +1,113 @@ +#include "styledialog.h" +#include "widgets/icon.h" +#include "verbs.h" +#include "sp-object.h" +#include "selection.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, + char const* tooltip) +{ + GtkWidget *child = sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName); + gtk_widget_show(child); + btn.add(*manage(Glib::wrap(child))); + btn.set_relief(Gtk::RELIEF_NONE); + btn.set_tooltip_text (tooltip); +} + +/** + * Constructor + * A treeview and a set of two buttons are added to the dialog. _addSelector + * adds selectors to treeview. Currently, delete button is disabled. + */ +StyleDialog::StyleDialog() : + UI::Widget::Panel("", "/dialogs/style", SP_VERB_DIALOG_STYLE), + _desktop(0) +{ + set_size_request(200, 200); + add(_mainBox); + + _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); + _treeView.set_headers_visible(false); + _scrolledWindow.add(_treeView); + _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + _store = Gtk::ListStore::create(_mColumns); + _treeView.set_model(_store); + _treeView.append_column("Selector Number", _mColumns._selectorNumber); + _treeView.append_column("Selector Name", _mColumns._selectorLabel); + + Gtk::Button* create = manage( new Gtk::Button() ); + _styleButton(*create, "list-add", "Add a new CSS Selector"); + create->signal_clicked().connect(sigc::mem_fun(*this, + &StyleDialog::_addSelector)); + + Gtk::Button* del = manage( new Gtk::Button() ); + _styleButton(*del, "list-remove", "Remove a CSS Selector"); + del->set_sensitive(false); + + _mainBox.pack_start(_buttonBox, Gtk::PACK_SHRINK); + _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); + _buttonBox.pack_start(*del, Gtk::PACK_SHRINK); + + SPDesktop* targetDesktop = getDesktop(); + setDesktop(targetDesktop); +} + +StyleDialog::~StyleDialog() +{ + setDesktop(NULL); +} + +void StyleDialog::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + _desktop = Panel::getDesktop(); +} + +void StyleDialog::_addSelector() +{ + Gtk::TreeModel::Row row = *(_store->append()); + + /** + * On clicking '+' button, an entrybox with default text opens up. If an + * object is already selected, 'class' attribute with value in the entry + * is added to the selected object. + */ + Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); + Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); + textDialogPtr->add_button("Add", Gtk::RESPONSE_OK); + textDialogPtr->get_vbox()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); + textEditPtr->set_text("Class1"); + + textDialogPtr->set_size_request(200, 100); + textDialogPtr->show_all(); + int result = textDialogPtr->run(); + static int number = 1; + + switch (result) { + case Gtk::RESPONSE_OK: + textDialogPtr->hide(); + row[_mColumns._selectorNumber] = number; + row[_mColumns._selectorLabel] = textEditPtr->get_text(); + number++; + break; + default: + break; + } + + if (_desktop->selection) { + std::vector selected = _desktop->getSelection()->list(); + for (int i = 0; i < selected.size(); ++i ) { + SPObject *obj = selected.at(i); + obj->setAttribute("class", textEditPtr->get_text()); + } + } +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape -- cgit v1.2.3 From 8970301df8e29722a113e20295239c64e070d0d7 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Mon, 6 Jun 2016 22:50:06 +0530 Subject: Set class attribute values of selected objects using style dialog (bzr r14949.1.3) --- src/ui/dialog/styledialog.cpp | 71 +++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 7e555ddb2..6681a7c56 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -1,3 +1,14 @@ +/** @file + * @brief A dialog for CSS selectors + */ +/* Authors: + * Kamalpreet Kaur Grewal + * + * Copyright (C) Kamalpreet Kaur Grewal 2016 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + #include "styledialog.h" #include "widgets/icon.h" #include "verbs.h" @@ -8,6 +19,13 @@ namespace Inkscape { namespace UI { namespace Dialog { +/** + * @brief StyleDialog::_styleButton + * @param btn + * @param iconName + * @param tooltip + * This function sets the style of '+' and '-' buttons at the bottom of dialog. + */ void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip) { @@ -68,6 +86,11 @@ void StyleDialog::setDesktop( SPDesktop* desktop ) _desktop = Panel::getDesktop(); } +/** + * @brief StyleDialog::_addSelector + * This function is the slot to the signal emitted when '+' at the bottom of + * the dialog is clicked. + */ void StyleDialog::_addSelector() { Gtk::TreeModel::Row row = *(_store->append()); @@ -81,7 +104,18 @@ void StyleDialog::_addSelector() Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); textDialogPtr->add_button("Add", Gtk::RESPONSE_OK); textDialogPtr->get_vbox()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); - textEditPtr->set_text("Class1"); + + /** + * By default, the entrybox contains 'Class1' as text. However, if object(s) + * is(are) selected and user clicks '+' at the bottom of dialog, the + * entrybox will have the id(s) of the selected objects as text. + */ + if (_desktop->selection->isEmpty()) + textEditPtr->set_text("Class1"); + else { + std::vector selected = _desktop->getSelection()->list(); + textEditPtr->set_text(_setClassAttribute(selected)); + } textDialogPtr->set_size_request(200, 100); textDialogPtr->show_all(); @@ -99,15 +133,48 @@ void StyleDialog::_addSelector() break; } + /** + * The 'class' attribute of the selected objects is set to the text that + * the user sets in the entrybox. If the attribute does not exist, it is + * created. In case the attribute already has a value, the new value entered + * is appended to the values. + */ if (_desktop->selection) { std::vector selected = _desktop->getSelection()->list(); for (int i = 0; i < selected.size(); ++i ) { SPObject *obj = selected.at(i); - obj->setAttribute("class", textEditPtr->get_text()); + const char *classExists = obj->getAttribute("class"); + + if (classExists) { + if (strlen(classExists) == 0) + obj->setAttribute("class", textEditPtr->get_text()); + else + obj->setAttribute("class", std::string(classExists) + " " + + textEditPtr->get_text()); + } + else { + obj->setAttribute("class", textEditPtr->get_text()); + } } } } +/** + * @brief StyleDialog::_setClassAttribute + * @param sel + * @return This function returns the ids of objects selected which are passed + * to entrybox. + */ +std::string StyleDialog::_setClassAttribute(std::vector sel) +{ + std::string str = ""; + for (int i = 0; i < sel.size(); ++i ) { + SPObject *obj = sel.at(i); + str = str + " " + std::string(obj->getId()); + } + return str; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape -- cgit v1.2.3 From d05e7ac156a8dedc0e80390a80edaa90b6260a4c Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 10 Jun 2016 14:10:53 +0530 Subject: Add selector to style element (bzr r14949.1.5) --- src/ui/dialog/styledialog.cpp | 100 +++++++++++++++++++++++++++++++++--------- 1 file changed, 79 insertions(+), 21 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 6681a7c56..992e75285 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -14,6 +14,10 @@ #include "verbs.h" #include "sp-object.h" #include "selection.h" +#include "xml/attribute-record.h" + +using Inkscape::Util::List; +using Inkscape::XML::AttributeRecord; namespace Inkscape { namespace UI { @@ -97,8 +101,8 @@ void StyleDialog::_addSelector() /** * On clicking '+' button, an entrybox with default text opens up. If an - * object is already selected, 'class' attribute with value in the entry - * is added to the selected object. + * object is already selected, a selector with value in the entry + * is added to a new style element. */ Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); @@ -110,7 +114,7 @@ void StyleDialog::_addSelector() * is(are) selected and user clicks '+' at the bottom of dialog, the * entrybox will have the id(s) of the selected objects as text. */ - if (_desktop->selection->isEmpty()) + if ( _desktop->selection->isEmpty() ) textEditPtr->set_text("Class1"); else { std::vector selected = _desktop->getSelection()->list(); @@ -120,13 +124,28 @@ void StyleDialog::_addSelector() textDialogPtr->set_size_request(200, 100); textDialogPtr->show_all(); int result = textDialogPtr->run(); + + /** + * @brief selectorName + * This string stores selector name. If '#' or a '.' is present in the + * beginning of string, text from entrybox is saved directly as name for + * selector. If text like 'red' is written in entrybox, it is prefixed + * with a dot. + */ + std::string selectorName = ""; + if ( textEditPtr->get_text().at(0) == '#' || + textEditPtr->get_text().at(0) == '.' ) + selectorName = textEditPtr->get_text(); + else + selectorName = "." + textEditPtr->get_text(); + static int number = 1; switch (result) { case Gtk::RESPONSE_OK: textDialogPtr->hide(); row[_mColumns._selectorNumber] = number; - row[_mColumns._selectorLabel] = textEditPtr->get_text(); + row[_mColumns._selectorLabel] = selectorName; number++; break; default: @@ -134,27 +153,49 @@ void StyleDialog::_addSelector() } /** - * The 'class' attribute of the selected objects is set to the text that - * the user sets in the entrybox. If the attribute does not exist, it is + * The selector name objects is set to the text that the user sets in the + * entrybox. If the attribute does not exist, it is * created. In case the attribute already has a value, the new value entered * is appended to the values. */ - if (_desktop->selection) { + if ( _desktop->selection ) { std::vector selected = _desktop->getSelection()->list(); - for (int i = 0; i < selected.size(); ++i ) { + std::string selectorValue; + for ( unsigned i = 0; i < selected.size(); ++i ) { SPObject *obj = selected.at(i); - const char *classExists = obj->getAttribute("class"); - - if (classExists) { - if (strlen(classExists) == 0) - obj->setAttribute("class", textEditPtr->get_text()); - else - obj->setAttribute("class", std::string(classExists) + " " + - textEditPtr->get_text()); - } - else { - obj->setAttribute("class", textEditPtr->get_text()); + + std::string style = std::string(obj->getRepr()->attribute("style")); + style = row[_mColumns._selectorLabel] + ";" + style; + + for ( List iter = obj->getRepr()->attributeList() ; + iter ; ++iter ) { + gchar const * property = g_quark_to_string(iter->key); + gchar const * value = iter->value; + + if ( std::string(property) == "style" ) + { + selectorValue = row[_mColumns._selectorLabel] + "{" + + "\n" + std::string(value) + "\n" + "}"; + } } + + /** + * @brief root + * A new style element is added to the document with value obtained + * from selectorValue above. + */ + Inkscape::XML::Node *root = obj->getRepr()->document()->root(); + Inkscape::XML::Node *newChild = obj->getRepr()->document() + ->createElement("svg:style"); + + Inkscape::XML::Node *smallChildren = obj->getRepr()->document() + ->createTextNode(selectorValue.c_str()); + + newChild->appendChild(smallChildren); + Inkscape::GC::release(smallChildren); + + root->addChild(newChild, NULL); + Inkscape::GC::release(newChild); } } } @@ -168,13 +209,30 @@ void StyleDialog::_addSelector() std::string StyleDialog::_setClassAttribute(std::vector sel) { std::string str = ""; - for (int i = 0; i < sel.size(); ++i ) { + for (unsigned i = 0; i < sel.size(); ++i) { SPObject *obj = sel.at(i); - str = str + " " + std::string(obj->getId()); + str = str + "#" + std::string(obj->getId()) + " "; } return str; } +/** + * @brief StyleDialog::_populateTree + * @param _selMap + * This function will populate the treeview with selectors available in the + * stylesheet. Not used yet. + */ +void StyleDialog::_populateTree(std::map _selMap) +{ + std::map _selectMap = _selMap; + + for(std::map::iterator it = _selectMap.begin(); + it != _selectMap.end(); ++it) { + Gtk::TreeModel::Row row = *(_store->append()); + row[_mColumns._selectorLabel] = it->first; + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape -- cgit v1.2.3 From 0792b241079daea6c984d9fd6761b9bdfbe85455 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 10 Jun 2016 20:13:26 +0530 Subject: Populate style dialog with existing selectors in stylesheet (bzr r14949.1.7) --- src/ui/dialog/styledialog.cpp | 49 +++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 13 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 992e75285..7a3dfeaff 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -59,7 +59,6 @@ StyleDialog::StyleDialog() : _store = Gtk::ListStore::create(_mColumns); _treeView.set_model(_store); - _treeView.append_column("Selector Number", _mColumns._selectorNumber); _treeView.append_column("Selector Name", _mColumns._selectorLabel); Gtk::Button* create = manage( new Gtk::Button() ); @@ -77,6 +76,32 @@ StyleDialog::StyleDialog() : SPDesktop* targetDesktop = getDesktop(); setDesktop(targetDesktop); + + /** + * @brief document + * If an existing document is opened, its XML representation is obtained + * and if it contains any style element with a style selector, the selector + * name and its value is extracted and saved to a map. This map is then used + * to populate the treeview with the already existing selectors. + */ + SPDocument * document = targetDesktop->doc(); + unsigned num = document->getReprRoot()->childCount(); + + std::string key, value; + std::map selMap; + + for ( unsigned i = 0; i < num; ++i ) + { + if ( std::string(document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) + { + char *str = strdup(document->getReprRoot()->nthChild(i)->firstChild() + ->content()); + key = strtok(str, " "); + value = strtok(NULL, ""); + selMap[key] = value; + } + } + _populateTree(selMap); } StyleDialog::~StyleDialog() @@ -134,19 +159,15 @@ void StyleDialog::_addSelector() */ std::string selectorName = ""; if ( textEditPtr->get_text().at(0) == '#' || - textEditPtr->get_text().at(0) == '.' ) + textEditPtr->get_text().at(0) == '.' ) selectorName = textEditPtr->get_text(); else selectorName = "." + textEditPtr->get_text(); - static int number = 1; - switch (result) { case Gtk::RESPONSE_OK: textDialogPtr->hide(); - row[_mColumns._selectorNumber] = number; row[_mColumns._selectorLabel] = selectorName; - number++; break; default: break; @@ -167,8 +188,8 @@ void StyleDialog::_addSelector() std::string style = std::string(obj->getRepr()->attribute("style")); style = row[_mColumns._selectorLabel] + ";" + style; - for ( List iter = obj->getRepr()->attributeList() ; - iter ; ++iter ) { + for ( List iter = obj->getRepr()->attributeList(); + iter; ++iter ) { gchar const * property = g_quark_to_string(iter->key); gchar const * value = iter->value; @@ -196,6 +217,8 @@ void StyleDialog::_addSelector() root->addChild(newChild, NULL); Inkscape::GC::release(newChild); + + _selectorMap[selectorName] = selectorValue; } } } @@ -209,7 +232,7 @@ void StyleDialog::_addSelector() std::string StyleDialog::_setClassAttribute(std::vector sel) { std::string str = ""; - for (unsigned i = 0; i < sel.size(); ++i) { + for ( unsigned i = 0; i < sel.size(); ++i ) { SPObject *obj = sel.at(i); str = str + "#" + std::string(obj->getId()) + " "; } @@ -219,15 +242,15 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) /** * @brief StyleDialog::_populateTree * @param _selMap - * This function will populate the treeview with selectors available in the - * stylesheet. Not used yet. + * This function populates the treeview with selectors available in the + * stylesheet. */ void StyleDialog::_populateTree(std::map _selMap) { std::map _selectMap = _selMap; - for(std::map::iterator it = _selectMap.begin(); - it != _selectMap.end(); ++it) { + for( std::map::iterator it = _selectMap.begin(); + it != _selectMap.end(); ++it ) { Gtk::TreeModel::Row row = *(_store->append()); row[_mColumns._selectorLabel] = it->first; } -- cgit v1.2.3 From 2e2712f1a6f1b31b18b40f9cffc58c8ef7b9198e Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sat, 11 Jun 2016 23:46:45 +0530 Subject: Delete selector from style dialog (not from repr yet) (bzr r14949.1.12) --- src/ui/dialog/styledialog.cpp | 115 +++++++++++++++++++++++++++++++++--------- 1 file changed, 90 insertions(+), 25 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 7a3dfeaff..14213f97d 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -61,47 +61,31 @@ StyleDialog::StyleDialog() : _treeView.set_model(_store); _treeView.append_column("Selector Name", _mColumns._selectorLabel); - Gtk::Button* create = manage( new Gtk::Button() ); + create = manage( new Gtk::Button() ); _styleButton(*create, "list-add", "Add a new CSS Selector"); create->signal_clicked().connect(sigc::mem_fun(*this, &StyleDialog::_addSelector)); - Gtk::Button* del = manage( new Gtk::Button() ); + del = manage( new Gtk::Button() ); _styleButton(*del, "list-remove", "Remove a CSS Selector"); + del->signal_clicked().connect(sigc::mem_fun(*this, + &StyleDialog::_delSelector)); del->set_sensitive(false); _mainBox.pack_start(_buttonBox, Gtk::PACK_SHRINK); _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); _buttonBox.pack_start(*del, Gtk::PACK_SHRINK); - SPDesktop* targetDesktop = getDesktop(); - setDesktop(targetDesktop); + _targetDesktop = getDesktop(); + setDesktop(_targetDesktop); /** * @brief document * If an existing document is opened, its XML representation is obtained - * and if it contains any style element with a style selector, the selector - * name and its value is extracted and saved to a map. This map is then used - * to populate the treeview with the already existing selectors. + * and is then used to populate the treeview with the already existing + * selectors in the style element. */ - SPDocument * document = targetDesktop->doc(); - unsigned num = document->getReprRoot()->childCount(); - - std::string key, value; - std::map selMap; - - for ( unsigned i = 0; i < num; ++i ) - { - if ( std::string(document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) - { - char *str = strdup(document->getReprRoot()->nthChild(i)->firstChild() - ->content()); - key = strtok(str, " "); - value = strtok(NULL, ""); - selMap[key] = value; - } - } - _populateTree(selMap); + _populateTree(_getSelectorMap()); } StyleDialog::~StyleDialog() @@ -173,6 +157,8 @@ void StyleDialog::_addSelector() break; } + del->set_sensitive(true); + /** * The selector name objects is set to the text that the user sets in the * entrybox. If the attribute does not exist, it is @@ -223,6 +209,52 @@ void StyleDialog::_addSelector() } } +/** + * @brief StyleDialog::_delSelector + * This function deletes selector when '-' at the bottom is clicked. Currently + * selectors are deleted from StyleDialog and not from repr of the document. + */ +void StyleDialog::_delSelector() +{ + Glib::RefPtr refTreeSelection = _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); + std::mapselMap = _getSelectorMap(); + + if (iter) + { + Gtk::TreeModel::Row row = *iter; + for( unsigned it = 0; it < selMap.size(); ++it ) { + std::string key = strtok(strdup(_document->getReprRoot() + ->nthChild(it) + ->firstChild()->content()), " "); + + /** + * @brief toDeleteNode + * The node to be deleted is obtained using nthChild and the selector + * name and corresponding style node from the repr of document are + * saved to a map. Keys of this map and labels of selected rows of + * dialog are compared and deleted. + */ + Inkscape::XML::Node *toDeleteNode = _document->getReprRoot()->nthChild(it); + std::maptoDeleteMap; + toDeleteMap[key] = toDeleteNode; + + for( std::map::iterator i = + toDeleteMap.begin(); i != toDeleteMap.end(); ++i ) { + if( row[_mColumns._selectorLabel] == i->first) + { + std::cout << i->second->name() << std::endl; + /** + This should work but uncommenting it causes a crash currently. + */ + //_document->getReprRoot()->removeChild(toDeleteNode); + } + } + } + _store->erase(row); + } +} + /** * @brief StyleDialog::_setClassAttribute * @param sel @@ -239,6 +271,36 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) return str; } +/** + * @brief StyleDialog::_getSelectorMap + * @return selMap + * This function returns a map whose key is the style selector name and value is + * the style properties. All style selectors are extracted from svg:style + * element. + */ +std::mapStyleDialog::_getSelectorMap() +{ + _document = _targetDesktop->doc(); + unsigned num = _document->getReprRoot()->childCount(); + + std::string key, value; + std::map selMap; + + for ( unsigned i = 0; i < num; ++i ) + { + if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) + { + char *str = strdup(_document->getReprRoot()->nthChild(i)->firstChild() + ->content()); + key = strtok(str, " "); + value = strtok(NULL, ""); + selMap[key] = value; + } + } + + return selMap; +} + /** * @brief StyleDialog::_populateTree * @param _selMap @@ -254,6 +316,9 @@ void StyleDialog::_populateTree(std::map _selMap) Gtk::TreeModel::Row row = *(_store->append()); row[_mColumns._selectorLabel] = it->first; } + + if (_selectMap.size() > 0) + del->set_sensitive(true); } } // namespace Dialog -- cgit v1.2.3 From b9f56542de1f33e8ac45325653dcac11691e3e47 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Mon, 13 Jun 2016 12:27:11 +0530 Subject: Correct parsing of style element (bzr r14949.1.14) --- src/ui/dialog/styledialog.cpp | 67 ++++++++++++++++++++++++++----------------- 1 file changed, 40 insertions(+), 27 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 14213f97d..9abcc1562 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -19,6 +19,8 @@ using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; +#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end()); + namespace Inkscape { namespace UI { namespace Dialog { @@ -181,8 +183,8 @@ void StyleDialog::_addSelector() if ( std::string(property) == "style" ) { - selectorValue = row[_mColumns._selectorLabel] + "{" + - "\n" + std::string(value) + "\n" + "}"; + selectorValue = "\n" + row[_mColumns._selectorLabel] + "{" + + std::string(value) + "}"; } } @@ -223,10 +225,10 @@ void StyleDialog::_delSelector() if (iter) { Gtk::TreeModel::Row row = *iter; - for( unsigned it = 0; it < selMap.size(); ++it ) { - std::string key = strtok(strdup(_document->getReprRoot() - ->nthChild(it) - ->firstChild()->content()), " "); +// for( unsigned it = 0; it < selMap.size(); ++it ) { +// std::string key = strtok(strdup(_document->getReprRoot() +// ->nthChild(it) +// ->firstChild()->content()), "{"); /** * @brief toDeleteNode @@ -235,22 +237,22 @@ void StyleDialog::_delSelector() * saved to a map. Keys of this map and labels of selected rows of * dialog are compared and deleted. */ - Inkscape::XML::Node *toDeleteNode = _document->getReprRoot()->nthChild(it); - std::maptoDeleteMap; - toDeleteMap[key] = toDeleteNode; - - for( std::map::iterator i = - toDeleteMap.begin(); i != toDeleteMap.end(); ++i ) { - if( row[_mColumns._selectorLabel] == i->first) - { - std::cout << i->second->name() << std::endl; - /** - This should work but uncommenting it causes a crash currently. - */ - //_document->getReprRoot()->removeChild(toDeleteNode); - } - } - } +// Inkscape::XML::Node *toDeleteNode = _document->getReprRoot()->nthChild(it); +// std::maptoDeleteMap; +// toDeleteMap[key] = toDeleteNode; + +// for( std::map::iterator i = +// toDeleteMap.begin(); i != toDeleteMap.end(); ++i ) { +// if( row[_mColumns._selectorLabel] == i->first) +// { +// std::cout << i->second->name() << std::endl; +// /** +// This should work but uncommenting it causes a crash currently. +// */ +// //_document->getReprRoot()->removeChild(toDeleteNode); +// } +// } +// } _store->erase(row); } } @@ -290,11 +292,22 @@ std::mapStyleDialog::_getSelectorMap() { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) { - char *str = strdup(_document->getReprRoot()->nthChild(i)->firstChild() - ->content()); - key = strtok(str, " "); - value = strtok(NULL, ""); - selMap[key] = value; + std::stringstream str; + str << _document->getReprRoot()->nthChild(i)->firstChild()->content(); + std::string sel; + + while (str != NULL) + { + while(std::getline(str, sel, '\n')){ + REMOVE_SPACES(sel); + if (!sel.empty()) + { + key = strtok(strdup(sel.c_str()), "{"); + value = strtok(NULL, "}"); + selMap[key] = value; + } + } + } } } -- cgit v1.2.3 From d35fb3b6e570691908282543b97076591510c5f3 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Mon, 13 Jun 2016 13:31:06 +0530 Subject: Fix crash when object without style attribute is added to selector (bzr r14949.1.15) --- src/ui/dialog/styledialog.cpp | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 9abcc1562..997d8b230 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -173,21 +173,28 @@ void StyleDialog::_addSelector() for ( unsigned i = 0; i < selected.size(); ++i ) { SPObject *obj = selected.at(i); - std::string style = std::string(obj->getRepr()->attribute("style")); - style = row[_mColumns._selectorLabel] + ";" + style; - - for ( List iter = obj->getRepr()->attributeList(); - iter; ++iter ) { - gchar const * property = g_quark_to_string(iter->key); - gchar const * value = iter->value; - - if ( std::string(property) == "style" ) - { - selectorValue = "\n" + row[_mColumns._selectorLabel] + "{" - + std::string(value) + "}"; + if (obj->getRepr()->attribute("style")) + { + std::string style = std::string(obj->getRepr()->attribute("style")); + style = row[_mColumns._selectorLabel] + ";" + style; + + for ( List iter = obj->getRepr()->attributeList(); + iter; ++iter ) { + gchar const * property = g_quark_to_string(iter->key); + gchar const * value = iter->value; + + if ( std::string(property) == "style" ) + { + selectorValue = "\n" + row[_mColumns._selectorLabel] + "{" + + std::string(value) + "}"; + } } } + else + std::cout << "This object does not have a style attribute. Add " + "one first."; + /** * @brief root * A new style element is added to the document with value obtained -- cgit v1.2.3 From a2c9a2962f6b9d4419b689ed4924f2cae2485332 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Mon, 13 Jun 2016 18:43:40 +0530 Subject: Set style and class attribute of object approprialtely when adding new style selector (bzr r14949.1.16) --- src/ui/dialog/styledialog.cpp | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 997d8b230..15c870e5d 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -165,17 +165,20 @@ void StyleDialog::_addSelector() * The selector name objects is set to the text that the user sets in the * entrybox. If the attribute does not exist, it is * created. In case the attribute already has a value, the new value entered - * is appended to the values. + * is appended to the values. If a style attribute does not exist, it is + * created with an empty value. Also if a class selector is added, then + * class attribute for the selected object is set too. */ if ( _desktop->selection ) { std::vector selected = _desktop->getSelection()->list(); std::string selectorValue; for ( unsigned i = 0; i < selected.size(); ++i ) { SPObject *obj = selected.at(i); + std::string style; if (obj->getRepr()->attribute("style")) { - std::string style = std::string(obj->getRepr()->attribute("style")); + style = std::string(obj->getRepr()->attribute("style")); style = row[_mColumns._selectorLabel] + ";" + style; for ( List iter = obj->getRepr()->attributeList(); @@ -192,8 +195,23 @@ void StyleDialog::_addSelector() } else - std::cout << "This object does not have a style attribute. Add " - "one first."; + { + style = " "; + std::cout << "style" << style; + obj->getRepr()->setAttribute("style", style); + } + + if ( strcmp(selectorName.substr(0,1).c_str(), ".") == 0 ){ + if (!obj->getRepr()->attribute("class")) + obj->getRepr()->setAttribute("class", textEditPtr->get_text() + .erase(0,1)); + else + obj->getRepr()->setAttribute("class", std::string(obj-> + getRepr()-> + attribute("class")) + + " " + textEditPtr->get_text() + .erase(0,0)); + } /** * @brief root @@ -303,16 +321,13 @@ std::mapStyleDialog::_getSelectorMap() str << _document->getReprRoot()->nthChild(i)->firstChild()->content(); std::string sel; - while (str != NULL) - { - while(std::getline(str, sel, '\n')){ - REMOVE_SPACES(sel); - if (!sel.empty()) - { - key = strtok(strdup(sel.c_str()), "{"); - value = strtok(NULL, "}"); - selMap[key] = value; - } + while(std::getline(str, sel, '\n')){ + REMOVE_SPACES(sel); + if (!sel.empty()) + { + key = strtok(strdup(sel.c_str()), "{"); + value = strtok(NULL, "}"); + selMap[key] = value; } } } -- cgit v1.2.3 From cf648cc9b825188b3a790eeeb202b52b07ff6cef Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 15 Jun 2016 19:54:38 +0530 Subject: Add selector to single style element & replace storage map by a vector (bzr r14949.1.18) --- src/ui/dialog/styledialog.cpp | 106 +++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 37 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 15c870e5d..bab08390c 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -10,6 +10,7 @@ */ #include "styledialog.h" +#include "ui/widget/addtoicon.h" #include "widgets/icon.h" #include "verbs.h" #include "sp-object.h" @@ -61,6 +62,11 @@ StyleDialog::StyleDialog() : _store = Gtk::ListStore::create(_mColumns); _treeView.set_model(_store); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( + new Inkscape::UI::Widget::AddToIcon() ); + addRenderer->property_active() = true; + _treeView.append_column("type", *addRenderer); _treeView.append_column("Selector Name", _mColumns._selectorLabel); create = manage( new Gtk::Button() ); @@ -87,7 +93,8 @@ StyleDialog::StyleDialog() : * and is then used to populate the treeview with the already existing * selectors in the style element. */ - _populateTree(_getSelectorMap()); + _styleExists = false; + _sValue = _populateTree(_getSelectorVec()); } StyleDialog::~StyleDialog() @@ -178,9 +185,6 @@ void StyleDialog::_addSelector() if (obj->getRepr()->attribute("style")) { - style = std::string(obj->getRepr()->attribute("style")); - style = row[_mColumns._selectorLabel] + ";" + style; - for ( List iter = obj->getRepr()->attributeList(); iter; ++iter ) { gchar const * property = g_quark_to_string(iter->key); @@ -188,8 +192,8 @@ void StyleDialog::_addSelector() if ( std::string(property) == "style" ) { - selectorValue = "\n" + row[_mColumns._selectorLabel] + "{" - + std::string(value) + "}"; + selectorValue = row[_mColumns._selectorLabel] + "{" + + std::string(value) + "}" + "\n"; } } } @@ -197,7 +201,6 @@ void StyleDialog::_addSelector() else { style = " "; - std::cout << "style" << style; obj->getRepr()->setAttribute("style", style); } @@ -216,22 +219,45 @@ void StyleDialog::_addSelector() /** * @brief root * A new style element is added to the document with value obtained - * from selectorValue above. + * from selectorValue above. If style element already exists, then + * the new selector's content is appended to its previous content. */ - Inkscape::XML::Node *root = obj->getRepr()->document()->root(); - Inkscape::XML::Node *newChild = obj->getRepr()->document() - ->createElement("svg:style"); - - Inkscape::XML::Node *smallChildren = obj->getRepr()->document() - ->createTextNode(selectorValue.c_str()); - - newChild->appendChild(smallChildren); - Inkscape::GC::release(smallChildren); - - root->addChild(newChild, NULL); - Inkscape::GC::release(newChild); + unsigned num = _document->getReprRoot()->childCount(); + Inkscape::XML::Node *styleChild; + for ( unsigned i = 0; i < num; ++i ) + { + if ( std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style" ) + { + _styleExists = true; + styleChild = _document->getReprRoot()->nthChild(i); + break; + } + else + _styleExists = false; + } - _selectorMap[selectorName] = selectorValue; + if ( _styleExists ) + { + _sValue = _sValue + selectorValue; + styleChild->firstChild()->setContent(_sValue.c_str()); + } + else + { + _sValue = selectorValue; + Inkscape::XML::Node *root = obj->getRepr()->document()->root(); + Inkscape::XML::Node *newChild = obj->getRepr()->document() + ->createElement("svg:style"); + Inkscape::XML::Node *smallChildren = obj->getRepr()->document() + ->createTextNode(selectorValue.c_str()); + + newChild->appendChild(smallChildren); + Inkscape::GC::release(smallChildren); + + root->addChild(newChild, NULL); + Inkscape::GC::release(newChild); + } + _selectorVec.push_back(std::make_pair(selectorName, selectorValue)); } } } @@ -245,7 +271,7 @@ void StyleDialog::_delSelector() { Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); - std::mapselMap = _getSelectorMap(); + std::vector >selVec = _getSelectorVec(); if (iter) { @@ -299,19 +325,19 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) } /** - * @brief StyleDialog::_getSelectorMap - * @return selMap - * This function returns a map whose key is the style selector name and value is - * the style properties. All style selectors are extracted from svg:style + * @brief StyleDialog::_getSelectorVec + * @return selVec + * This function returns a vector whose key is the style selector name and value + * is the style properties. All style selectors are extracted from svg:style * element. */ -std::mapStyleDialog::_getSelectorMap() +std::vector >StyleDialog::_getSelectorVec() { _document = _targetDesktop->doc(); unsigned num = _document->getReprRoot()->childCount(); std::string key, value; - std::map selMap; + std::vector > selVec; for ( unsigned i = 0; i < num; ++i ) { @@ -327,33 +353,39 @@ std::mapStyleDialog::_getSelectorMap() { key = strtok(strdup(sel.c_str()), "{"); value = strtok(NULL, "}"); - selMap[key] = value; + selVec.push_back(std::make_pair(key, value)); } } } } - return selMap; + return selVec; } /** * @brief StyleDialog::_populateTree - * @param _selMap + * @param _selVec * This function populates the treeview with selectors available in the * stylesheet. */ -void StyleDialog::_populateTree(std::map _selMap) +std::string StyleDialog::_populateTree(std::vector > _selVec) { - std::map _selectMap = _selMap; + std::vector > _selectVec = _selVec; + std::string selectorValue; - for( std::map::iterator it = _selectMap.begin(); - it != _selectMap.end(); ++it ) { + for( unsigned it = 0; it < _selectVec.size(); ++it ) { Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._selectorLabel] = it->first; + row[_mColumns._selectorLabel] = _selectVec[it].first; + std::string selValue = _selectVec[it].first + " { " + + _selectVec[it].second + " }" + "\n"; + selectorValue.append(selValue.c_str()); } - if (_selectMap.size() > 0) + if (_selectVec.size() > 0) del->set_sensitive(true); + + return selectorValue; } } // namespace Dialog -- cgit v1.2.3 From c21fa260cf5dde3e3558414ad69b05e04f173a73 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Thu, 16 Jun 2016 00:14:01 +0530 Subject: Implement deletion of style selector both from repr and treeview (bzr r14949.1.19) --- src/ui/dialog/styledialog.cpp | 70 ++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 38 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index bab08390c..a56277054 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -94,6 +94,8 @@ StyleDialog::StyleDialog() : * selectors in the style element. */ _styleExists = false; + _document = _targetDesktop->doc(); + _num = _document->getReprRoot()->childCount(); _sValue = _populateTree(_getSelectorVec()); } @@ -222,15 +224,13 @@ void StyleDialog::_addSelector() * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - unsigned num = _document->getReprRoot()->childCount(); - Inkscape::XML::Node *styleChild; - for ( unsigned i = 0; i < num; ++i ) + for ( unsigned i = 0; i < _num; ++i ) { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) { _styleExists = true; - styleChild = _document->getReprRoot()->nthChild(i); + _styleChild = _document->getReprRoot()->nthChild(i); break; } else @@ -240,7 +240,7 @@ void StyleDialog::_addSelector() if ( _styleExists ) { _sValue = _sValue + selectorValue; - styleChild->firstChild()->setContent(_sValue.c_str()); + _styleChild->firstChild()->setContent(_sValue.c_str()); } else { @@ -264,46 +264,34 @@ void StyleDialog::_addSelector() /** * @brief StyleDialog::_delSelector - * This function deletes selector when '-' at the bottom is clicked. Currently - * selectors are deleted from StyleDialog and not from repr of the document. + * This function deletes selector when '-' at the bottom is clicked. The index + * of selected row is obtained and the corresponding selector and its values are + * deleted from the selector vector. Then _sValue's content is reset and contains + * only selectors remaining in the selVec (or treeview). */ void StyleDialog::_delSelector() { Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); std::vector >selVec = _getSelectorVec(); + Gtk::TreeModel::Path path; if (iter) { Gtk::TreeModel::Row row = *iter; -// for( unsigned it = 0; it < selMap.size(); ++it ) { -// std::string key = strtok(strdup(_document->getReprRoot() -// ->nthChild(it) -// ->firstChild()->content()), "{"); + path = _treeView.get_model()->get_path(iter); + int i = atoi(path.to_string().c_str()); + selVec.erase(selVec.begin()+i); + _sValue.clear(); - /** - * @brief toDeleteNode - * The node to be deleted is obtained using nthChild and the selector - * name and corresponding style node from the repr of document are - * saved to a map. Keys of this map and labels of selected rows of - * dialog are compared and deleted. - */ -// Inkscape::XML::Node *toDeleteNode = _document->getReprRoot()->nthChild(it); -// std::maptoDeleteMap; -// toDeleteMap[key] = toDeleteNode; - -// for( std::map::iterator i = -// toDeleteMap.begin(); i != toDeleteMap.end(); ++i ) { -// if( row[_mColumns._selectorLabel] == i->first) -// { -// std::cout << i->second->name() << std::endl; -// /** -// This should work but uncommenting it causes a crash currently. -// */ -// //_document->getReprRoot()->removeChild(toDeleteNode); -// } -// } -// } + for (unsigned i = 0; i < selVec.size(); ++i) + { + std::string selValue = (selVec[i].first + "{" + + selVec[i].second + " }\n"); + _sValue.append(selValue.c_str()); + } + + _styleChild->firstChild()->setContent(_sValue.c_str()); _store->erase(row); } } @@ -333,13 +321,10 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) */ std::vector >StyleDialog::_getSelectorVec() { - _document = _targetDesktop->doc(); - unsigned num = _document->getReprRoot()->childCount(); - std::string key, value; std::vector > selVec; - for ( unsigned i = 0; i < num; ++i ) + for ( unsigned i = 0; i < _num; ++i ) { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) { @@ -385,6 +370,15 @@ std::string StyleDialog::_populateTree(std::vector 0) del->set_sensitive(true); + for ( unsigned i = 0; i < _num; ++i ) + { + if ( std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style" ) + { + _styleChild = _document->getReprRoot()->nthChild(i); + } + } + return selectorValue; } -- cgit v1.2.3 From 736149f0b6b617c2cf6f6bef55b4606cd70e416b Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 17 Jun 2016 11:22:07 +0530 Subject: Remove unwanted empty space at top in style dialog (bzr r14949.1.21) --- src/ui/dialog/styledialog.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index a56277054..622bbcdb9 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -53,7 +53,6 @@ StyleDialog::StyleDialog() : _desktop(0) { set_size_request(200, 200); - add(_mainBox); _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); _treeView.set_headers_visible(false); @@ -80,10 +79,13 @@ StyleDialog::StyleDialog() : &StyleDialog::_delSelector)); del->set_sensitive(false); - _mainBox.pack_start(_buttonBox, Gtk::PACK_SHRINK); + _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); + _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); _buttonBox.pack_start(*del, Gtk::PACK_SHRINK); + _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); + _targetDesktop = getDesktop(); setDesktop(_targetDesktop); -- cgit v1.2.3 From 0ce1eb6fcfa054641be8225cf65ef7d01bf0a813 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 17 Jun 2016 14:49:21 +0530 Subject: Fix a crash while deleting when there was single selector in the style dialog (bzr r14949.1.23) --- src/ui/dialog/styledialog.cpp | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 622bbcdb9..f81faec97 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -283,17 +283,44 @@ void StyleDialog::_delSelector() Gtk::TreeModel::Row row = *iter; path = _treeView.get_model()->get_path(iter); int i = atoi(path.to_string().c_str()); - selVec.erase(selVec.begin()+i); - _sValue.clear(); - for (unsigned i = 0; i < selVec.size(); ++i) + if (selVec.size() != 0) { - std::string selValue = (selVec[i].first + "{" - + selVec[i].second + " }\n"); - _sValue.append(selValue.c_str()); - } + selVec.erase(selVec.begin()+i); + _sValue.clear(); + + if (selVec.size() != 0) + { + for (unsigned i = 0; i < selVec.size(); ++i) + { + std::string selValue = (selVec[i].first + "{" + + selVec[i].second + " }\n"); + _sValue.append(selValue.c_str()); + } - _styleChild->firstChild()->setContent(_sValue.c_str()); + } + + /** + * Only if a value exists in _sValue and there is a _styleChild + * which contains the style element, then the content in style + * element is updated else the _styleChild is set and its content + * is set to an empty string. + */ + if (!_sValue.empty() && _styleChild) + _styleChild->firstChild()->setContent(_sValue.c_str()); + else + { + for ( unsigned i = 0; i < _num; ++i ) + { + if ( std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style" ) + { + _styleChild = _document->getReprRoot()->nthChild(i); + } + } + _styleChild->firstChild()->setContent(""); + } + } _store->erase(row); } } -- cgit v1.2.3 From 71959483ca7952c2b90c9b04651c187b6e17a19b Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sun, 19 Jun 2016 16:29:01 +0530 Subject: Resolve crash when empty string was added via entrybox in style dialog (bzr r14949.1.24) --- src/ui/dialog/styledialog.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index f81faec97..a7a803edd 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -155,11 +155,16 @@ void StyleDialog::_addSelector() * with a dot. */ std::string selectorName = ""; - if ( textEditPtr->get_text().at(0) == '#' || - textEditPtr->get_text().at(0) == '.' ) - selectorName = textEditPtr->get_text(); - else - selectorName = "." + textEditPtr->get_text(); + if ( !textEditPtr->get_text().empty() ) { + if ( textEditPtr->get_text().at(0) == '#' || + textEditPtr->get_text().at(0) == '.' ) + selectorName = textEditPtr->get_text(); + else + selectorName = "." + textEditPtr->get_text(); + } + else { + selectorName = ".Class1"; + } switch (result) { case Gtk::RESPONSE_OK: -- cgit v1.2.3 From 47a71e1eb00db2a3b6030ff545f624283a95e174 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sun, 26 Jun 2016 09:24:02 +0530 Subject: Add/Remove objects to/from selector (bzr r14949.1.27) --- src/ui/dialog/styledialog.cpp | 252 ++++++++++++++++++++++++++++-------------- 1 file changed, 170 insertions(+), 82 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index a7a803edd..6cb970eae 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -59,13 +59,20 @@ StyleDialog::StyleDialog() : _scrolledWindow.add(_treeView); _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - _store = Gtk::ListStore::create(_mColumns); + _store = Gtk::TreeStore::create(_mColumns); _treeView.set_model(_store); Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon() ); addRenderer->property_active() = true; - _treeView.append_column("type", *addRenderer); + + int addCol = _treeView.append_column("type", *addRenderer) - 1; + + Gtk::TreeViewColumn *col = _treeView.get_column(addCol); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _mColumns._colAddRemove ); + } + _treeView.append_column("Selector Name", _mColumns._selectorLabel); create = manage( new Gtk::Button() ); @@ -99,6 +106,11 @@ StyleDialog::StyleDialog() : _document = _targetDesktop->doc(); _num = _document->getReprRoot()->childCount(); _sValue = _populateTree(_getSelectorVec()); + + _treeView.signal_button_press_event().connect(sigc::mem_fun(*this, + &StyleDialog:: + _handleButtonEvent), + false); } StyleDialog::~StyleDialog() @@ -119,7 +131,7 @@ void StyleDialog::setDesktop( SPDesktop* desktop ) */ void StyleDialog::_addSelector() { - Gtk::TreeModel::Row row = *(_store->append()); + _row = *(_store->append()); /** * On clicking '+' button, an entrybox with default text opens up. If an @@ -154,22 +166,22 @@ void StyleDialog::_addSelector() * selector. If text like 'red' is written in entrybox, it is prefixed * with a dot. */ - std::string selectorName = ""; if ( !textEditPtr->get_text().empty() ) { if ( textEditPtr->get_text().at(0) == '#' || textEditPtr->get_text().at(0) == '.' ) - selectorName = textEditPtr->get_text(); + _selectorName = textEditPtr->get_text(); else - selectorName = "." + textEditPtr->get_text(); + _selectorName = "." + textEditPtr->get_text(); } else { - selectorName = ".Class1"; + _selectorName = ".Class1"; } switch (result) { case Gtk::RESPONSE_OK: textDialogPtr->hide(); - row[_mColumns._selectorLabel] = selectorName; + _row[_mColumns._selectorLabel] = _selectorName; + _row[_mColumns._colAddRemove] = true; break; default: break; @@ -185,11 +197,11 @@ void StyleDialog::_addSelector() * created with an empty value. Also if a class selector is added, then * class attribute for the selected object is set too. */ - if ( _desktop->selection ) { + SPObject *obj; + if ( !_desktop->getSelection()->list().empty() ) { std::vector selected = _desktop->getSelection()->list(); - std::string selectorValue; for ( unsigned i = 0; i < selected.size(); ++i ) { - SPObject *obj = selected.at(i); + obj = selected.at(i); std::string style; if (obj->getRepr()->attribute("style")) @@ -201,7 +213,7 @@ void StyleDialog::_addSelector() if ( std::string(property) == "style" ) { - selectorValue = row[_mColumns._selectorLabel] + "{" + _selectorValue = _row[_mColumns._selectorLabel] + "{" + std::string(value) + "}" + "\n"; } } @@ -213,7 +225,7 @@ void StyleDialog::_addSelector() obj->getRepr()->setAttribute("style", style); } - if ( strcmp(selectorName.substr(0,1).c_str(), ".") == 0 ){ + if ( strcmp(_selectorName.substr(0,1).c_str(), ".") == 0 ){ if (!obj->getRepr()->attribute("class")) obj->getRepr()->setAttribute("class", textEditPtr->get_text() .erase(0,1)); @@ -224,49 +236,49 @@ void StyleDialog::_addSelector() + " " + textEditPtr->get_text() .erase(0,0)); } + } + } + else { + _selectorValue = _selectorName + "{" + "}" + "\n"; + } - /** - * @brief root - * A new style element is added to the document with value obtained - * from selectorValue above. If style element already exists, then - * the new selector's content is appended to its previous content. - */ - for ( unsigned i = 0; i < _num; ++i ) - { - if ( std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style" ) - { - _styleExists = true; - _styleChild = _document->getReprRoot()->nthChild(i); - break; - } - else - _styleExists = false; - } - - if ( _styleExists ) - { - _sValue = _sValue + selectorValue; - _styleChild->firstChild()->setContent(_sValue.c_str()); - } - else - { - _sValue = selectorValue; - Inkscape::XML::Node *root = obj->getRepr()->document()->root(); - Inkscape::XML::Node *newChild = obj->getRepr()->document() - ->createElement("svg:style"); - Inkscape::XML::Node *smallChildren = obj->getRepr()->document() - ->createTextNode(selectorValue.c_str()); - - newChild->appendChild(smallChildren); - Inkscape::GC::release(smallChildren); - - root->addChild(newChild, NULL); - Inkscape::GC::release(newChild); - } - _selectorVec.push_back(std::make_pair(selectorName, selectorValue)); + /** + * @brief root + * A new style element is added to the document with value obtained + * from selectorValue above. If style element already exists, then + * the new selector's content is appended to its previous content. + */ + for ( unsigned i = 0; i < _num; ++i ) { + if ( std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style" ) { + _styleExists = true; + _styleChild = _document->getReprRoot()->nthChild(i); + break; } + else { + _styleExists = false; + } + } + + if ( _styleExists ) { + _sValue = _sValue + _selectorValue; + _styleChild->firstChild()->setContent(_sValue.c_str()); + } + else { + _sValue = _selectorValue; + Inkscape::XML::Node *root = _document->getReprDoc()->root(); + Inkscape::XML::Node *newChild = _document->getReprDoc() + ->createElement("svg:style"); + Inkscape::XML::Node *smallChildren = _document->getReprDoc() + ->createTextNode(_selectorValue.c_str()); + + newChild->appendChild(smallChildren); + Inkscape::GC::release(smallChildren); + + root->addChild(newChild, NULL); + Inkscape::GC::release(newChild); } + _selectorVec.push_back(std::make_pair(_selectorName, _selectorValue)); } /** @@ -283,26 +295,19 @@ void StyleDialog::_delSelector() std::vector >selVec = _getSelectorVec(); Gtk::TreeModel::Path path; - if (iter) - { + if (iter) { Gtk::TreeModel::Row row = *iter; path = _treeView.get_model()->get_path(iter); int i = atoi(path.to_string().c_str()); - if (selVec.size() != 0) - { + if ( selVec.size() != 0 ) { selVec.erase(selVec.begin()+i); _sValue.clear(); - if (selVec.size() != 0) - { - for (unsigned i = 0; i < selVec.size(); ++i) - { - std::string selValue = (selVec[i].first + "{" - + selVec[i].second + " }\n"); - _sValue.append(selValue.c_str()); - } - + for ( unsigned i = 0; i < selVec.size(); ++i ) { + std::string selValue = (selVec[i].first + "{" + + selVec[i].second + " }\n"); + _sValue.append(selValue.c_str()); } /** @@ -311,17 +316,13 @@ void StyleDialog::_delSelector() * element is updated else the _styleChild is set and its content * is set to an empty string. */ - if (!_sValue.empty() && _styleChild) + if ( !_sValue.empty() && _styleChild ) _styleChild->firstChild()->setContent(_sValue.c_str()); - else - { - for ( unsigned i = 0; i < _num; ++i ) - { + else { + for ( unsigned i = 0; i < _num; ++i ) { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) - { _styleChild = _document->getReprRoot()->nthChild(i); - } } _styleChild->firstChild()->setContent(""); } @@ -358,20 +359,26 @@ std::vector >StyleDialog::_getSelectorVec() std::string key, value; std::vector > selVec; - for ( unsigned i = 0; i < _num; ++i ) - { + for ( unsigned i = 0; i < _num; ++i ) { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) { std::stringstream str; str << _document->getReprRoot()->nthChild(i)->firstChild()->content(); std::string sel; - while(std::getline(str, sel, '\n')){ + /** + * 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') ){ REMOVE_SPACES(sel); - if (!sel.empty()) + if ( !sel.empty() ) { key = strtok(strdup(sel.c_str()), "{"); - value = strtok(NULL, "}"); + if ( strtok(NULL, "}") != NULL ) + value = strtok(NULL, "}"); + else + value = ""; selVec.push_back(std::make_pair(key, value)); } } @@ -404,18 +411,99 @@ std::string StyleDialog::_populateTree(std::vector 0) del->set_sensitive(true); - for ( unsigned i = 0; i < _num; ++i ) - { + for ( unsigned i = 0; i < _num; ++i ) { if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) - { _styleChild = _document->getReprRoot()->nthChild(i); - } } return selectorValue; } +/** + * @brief StyleDialog::_handleButtonEvent + * @param event + * @return + * This function handles the event when '+' button in front of a selector name + * is clicked. The selected objects (if any) is added to the selector as a child + * in the treeview. + * TODO: Appending children in XML repr. + */ + +bool StyleDialog::_handleButtonEvent(GdkEventButton *event) +{ + if ( event->type == GDK_BUTTON_PRESS && event->button == 1 ) + { + Gtk::TreeViewColumn *col = 0; + + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _treeView.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if ( col == _treeView.get_column(0) ) + { + if ( _desktop->selection ) + { + std::vectorsel = _desktop->selection->list(); + for (unsigned i = 0; i < sel.size(); ++i) + { + SPObject *obj = sel[i]; + Glib::RefPtr refTreeSelection = + _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection-> + get_selected(); + + if ( iter ) + { + Gtk::TreeModel::Row row = *iter; +// SPObject *object = row[_mColumns._colObj]; + + typedef Gtk::TreeModel::Children type_children; + type_children children = row->children(); + Gtk::TreeModel::Row childrow; + + if ( children.size() == 0 && row->parent() == 0 ) + { + childrow = *(_store->append(row->children())); + childrow[_mColumns._selectorLabel] = obj->getId(); + childrow[_mColumns._colAddRemove] = false; +// childrow[_mColumns._colObj] = obj; +// object->getRepr()->appendChild(obj->getRepr()); + } + else + { + for( type_children::iterator it = children.begin(); + it != children.end(); ++it ) + { + Gtk::TreeModel::iterator i = it; + path = _treeView.get_model()->get_path(i); + + if( (*it)->get_value(_mColumns._selectorLabel) + != obj->getId() ) + { + childrow = *(_store->append(row.children())); + childrow[_mColumns._selectorLabel] = obj->getId(); + childrow[_mColumns._colAddRemove] = false; +// childrow[_mColumns._colObj] = obj; +// object->getRepr()->appendChild(obj->getRepr()); + + } + else { + std::cout << "Do nothing" << std::endl; + } + } + } +// std::cout << "repr" << object->getRepr()->content(); + } + } + } + } + } + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape -- cgit v1.2.3 From a401c22ec8acb2a94701ea0fbb7ecf08683ebca1 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sun, 26 Jun 2016 11:33:48 +0530 Subject: Fix a crash when deleting selectors and some coding style corrections (bzr r14949.1.29) --- src/ui/dialog/styledialog.cpp | 134 +++++++++++++++++++----------------------- 1 file changed, 59 insertions(+), 75 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 6cb970eae..3c1ed0a5d 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -148,8 +148,9 @@ void StyleDialog::_addSelector() * is(are) selected and user clicks '+' at the bottom of dialog, the * entrybox will have the id(s) of the selected objects as text. */ - if ( _desktop->selection->isEmpty() ) + if (_desktop->selection->isEmpty()) { textEditPtr->set_text("Class1"); + } else { std::vector selected = _desktop->getSelection()->list(); textEditPtr->set_text(_setClassAttribute(selected)); @@ -166,12 +167,14 @@ void StyleDialog::_addSelector() * selector. If text like 'red' is written in entrybox, it is prefixed * with a dot. */ - if ( !textEditPtr->get_text().empty() ) { - if ( textEditPtr->get_text().at(0) == '#' || - textEditPtr->get_text().at(0) == '.' ) + if (!textEditPtr->get_text().empty()) { + if (textEditPtr->get_text().at(0) == '#' || + textEditPtr->get_text().at(0) == '.') { _selectorName = textEditPtr->get_text(); - else + } + else { _selectorName = "." + textEditPtr->get_text(); + } } else { _selectorName = ".Class1"; @@ -198,43 +201,41 @@ void StyleDialog::_addSelector() * class attribute for the selected object is set too. */ SPObject *obj; - if ( !_desktop->getSelection()->list().empty() ) { + if (!_desktop->getSelection()->list().empty()) { std::vector selected = _desktop->getSelection()->list(); - for ( unsigned i = 0; i < selected.size(); ++i ) { + for (unsigned i = 0; i < selected.size(); ++i) { obj = selected.at(i); std::string style; - if (obj->getRepr()->attribute("style")) - { - for ( List iter = obj->getRepr()->attributeList(); - iter; ++iter ) { + if (obj->getRepr()->attribute("style")) { + for (List iter = obj->getRepr()->attributeList(); + iter; ++iter) { gchar const * property = g_quark_to_string(iter->key); gchar const * value = iter->value; - if ( std::string(property) == "style" ) - { + if (std::string(property) == "style") { _selectorValue = _row[_mColumns._selectorLabel] + "{" + std::string(value) + "}" + "\n"; } } } - - else - { + else { style = " "; obj->getRepr()->setAttribute("style", style); } - if ( strcmp(_selectorName.substr(0,1).c_str(), ".") == 0 ){ - if (!obj->getRepr()->attribute("class")) + if (strcmp(_selectorName.substr(0,1).c_str(), ".") == 0) { + if (!obj->getRepr()->attribute("class")) { obj->getRepr()->setAttribute("class", textEditPtr->get_text() .erase(0,1)); - else + } + else { obj->getRepr()->setAttribute("class", std::string(obj-> getRepr()-> attribute("class")) + " " + textEditPtr->get_text() .erase(0,0)); + } } } } @@ -248,9 +249,9 @@ void StyleDialog::_addSelector() * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - for ( unsigned i = 0; i < _num; ++i ) { - if ( std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style" ) { + for (unsigned i = 0; i < _num; ++i) { + if (std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style") { _styleExists = true; _styleChild = _document->getReprRoot()->nthChild(i); break; @@ -260,7 +261,7 @@ void StyleDialog::_addSelector() } } - if ( _styleExists ) { + if (_styleExists) { _sValue = _sValue + _selectorValue; _styleChild->firstChild()->setContent(_sValue.c_str()); } @@ -300,11 +301,11 @@ void StyleDialog::_delSelector() path = _treeView.get_model()->get_path(iter); int i = atoi(path.to_string().c_str()); - if ( selVec.size() != 0 ) { + if (selVec.size() != 0) { selVec.erase(selVec.begin()+i); _sValue.clear(); - for ( unsigned i = 0; i < selVec.size(); ++i ) { + for (unsigned i = 0; i < selVec.size(); ++i) { std::string selValue = (selVec[i].first + "{" + selVec[i].second + " }\n"); _sValue.append(selValue.c_str()); @@ -316,13 +317,15 @@ void StyleDialog::_delSelector() * element is updated else the _styleChild is set and its content * is set to an empty string. */ - if ( !_sValue.empty() && _styleChild ) + if (!_sValue.empty() && _styleChild) { _styleChild->firstChild()->setContent(_sValue.c_str()); + } else { - for ( unsigned i = 0; i < _num; ++i ) { - if ( std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style" ) + for (unsigned i = 0; i < _num; ++i) { + if (std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style") { _styleChild = _document->getReprRoot()->nthChild(i); + } } _styleChild->firstChild()->setContent(""); } @@ -359,9 +362,8 @@ std::vector >StyleDialog::_getSelectorVec() std::string key, value; std::vector > selVec; - for ( unsigned i = 0; i < _num; ++i ) { - if ( std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style" ) - { + for (unsigned i = 0; i < _num; ++i) { + if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { std::stringstream str; str << _document->getReprRoot()->nthChild(i)->firstChild()->content(); std::string sel; @@ -370,21 +372,19 @@ std::vector >StyleDialog::_getSelectorVec() * 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') ){ + while(std::getline(str, sel, '\n')) { REMOVE_SPACES(sel); - if ( !sel.empty() ) - { + if (!sel.empty()) { key = strtok(strdup(sel.c_str()), "{"); - if ( strtok(NULL, "}") != NULL ) - value = strtok(NULL, "}"); - else - value = ""; + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } selVec.push_back(std::make_pair(key, value)); } } } } - return selVec; } @@ -400,7 +400,7 @@ std::string StyleDialog::_populateTree(std::vector > _selectVec = _selVec; std::string selectorValue; - for( unsigned it = 0; it < _selectVec.size(); ++it ) { + for(unsigned it = 0; it < _selectVec.size(); ++it) { Gtk::TreeModel::Row row = *(_store->append()); row[_mColumns._selectorLabel] = _selectVec[it].first; std::string selValue = _selectVec[it].first + " { " @@ -408,13 +408,15 @@ std::string StyleDialog::_populateTree(std::vector 0) + if (_selectVec.size() > 0) { del->set_sensitive(true); + } - for ( unsigned i = 0; i < _num; ++i ) { - if ( std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style" ) + for (unsigned i = 0; i < _num; ++i) { + if (std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style") { _styleChild = _document->getReprRoot()->nthChild(i); + } } return selectorValue; @@ -432,70 +434,52 @@ std::string StyleDialog::_populateTree(std::vectortype == GDK_BUTTON_PRESS && event->button == 1 ) - { + if (event->type == GDK_BUTTON_PRESS && event->button == 1) { Gtk::TreeViewColumn *col = 0; - Gtk::TreeModel::Path path; int x = static_cast(event->x); int y = static_cast(event->y); int x2 = 0; int y2 = 0; - if ( _treeView.get_path_at_pos( x, y, path, col, x2, y2 ) ) { - if ( col == _treeView.get_column(0) ) - { - if ( _desktop->selection ) - { + if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { + if (col == _treeView.get_column(0)) { + if (_desktop->selection) { std::vectorsel = _desktop->selection->list(); - for (unsigned i = 0; i < sel.size(); ++i) - { + for (unsigned i = 0; i < sel.size(); ++i) { SPObject *obj = sel[i]; Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection-> get_selected(); - if ( iter ) - { + if (iter) { Gtk::TreeModel::Row row = *iter; -// SPObject *object = row[_mColumns._colObj]; - typedef Gtk::TreeModel::Children type_children; type_children children = row->children(); Gtk::TreeModel::Row childrow; - if ( children.size() == 0 && row->parent() == 0 ) - { + if (children.size() == 0 && row->parent() == 0) { childrow = *(_store->append(row->children())); childrow[_mColumns._selectorLabel] = obj->getId(); childrow[_mColumns._colAddRemove] = false; -// childrow[_mColumns._colObj] = obj; -// object->getRepr()->appendChild(obj->getRepr()); } - else - { - for( type_children::iterator it = children.begin(); - it != children.end(); ++it ) - { + else { + for(type_children::iterator it = children.begin(); + it != children.end(); ++it) { Gtk::TreeModel::iterator i = it; path = _treeView.get_model()->get_path(i); - if( (*it)->get_value(_mColumns._selectorLabel) - != obj->getId() ) - { + if((*it)->get_value(_mColumns._selectorLabel) + != obj->getId()) { childrow = *(_store->append(row.children())); childrow[_mColumns._selectorLabel] = obj->getId(); childrow[_mColumns._colAddRemove] = false; -// childrow[_mColumns._colObj] = obj; -// object->getRepr()->appendChild(obj->getRepr()); - } else { std::cout << "Do nothing" << std::endl; } } } -// std::cout << "repr" << object->getRepr()->content(); } } } -- cgit v1.2.3 From 4a85a11d89d34739eb43496047ee7af67d635c1c Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sun, 26 Jun 2016 18:52:52 +0530 Subject: Select objects corresponding to selector selected in treeview (bzr r14949.1.30) --- src/ui/dialog/styledialog.cpp | 79 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 67 insertions(+), 12 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 3c1ed0a5d..1dba1d2df 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -111,6 +111,10 @@ StyleDialog::StyleDialog() : &StyleDialog:: _handleButtonEvent), false); + + _treeView.signal_row_activated().connect(sigc::mem_fun(*this, + &StyleDialog:: + _selectedRowCallback)); } StyleDialog::~StyleDialog() @@ -180,16 +184,6 @@ void StyleDialog::_addSelector() _selectorName = ".Class1"; } - switch (result) { - case Gtk::RESPONSE_OK: - textDialogPtr->hide(); - _row[_mColumns._selectorLabel] = _selectorName; - _row[_mColumns._colAddRemove] = true; - break; - default: - break; - } - del->set_sensitive(true); /** @@ -201,10 +195,12 @@ void StyleDialog::_addSelector() * class attribute for the selected object is set too. */ SPObject *obj; + bool objExists = false; if (!_desktop->getSelection()->list().empty()) { std::vector selected = _desktop->getSelection()->list(); for (unsigned i = 0; i < selected.size(); ++i) { obj = selected.at(i); + objExists = true; std::string style; if (obj->getRepr()->attribute("style")) { @@ -214,7 +210,7 @@ void StyleDialog::_addSelector() gchar const * value = iter->value; if (std::string(property) == "style") { - _selectorValue = _row[_mColumns._selectorLabel] + "{" + _selectorValue = _selectorName + "{" + std::string(value) + "}" + "\n"; } } @@ -241,9 +237,22 @@ void StyleDialog::_addSelector() } else { _selectorValue = _selectorName + "{" + "}" + "\n"; + objExists = false; } - /** + switch (result) { + case Gtk::RESPONSE_OK: + textDialogPtr->hide(); + _row[_mColumns._selectorLabel] = _selectorName; + _row[_mColumns._colAddRemove] = true; + if (objExists) { + _row[_mColumns._colObj] = obj; + } + break; + default: + break; + } + /** * @brief root * A new style element is added to the document with value obtained * from selectorValue above. If style element already exists, then @@ -462,6 +471,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) childrow = *(_store->append(row->children())); childrow[_mColumns._selectorLabel] = obj->getId(); childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = obj; } else { for(type_children::iterator it = children.begin(); @@ -474,6 +484,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) childrow = *(_store->append(row.children())); childrow[_mColumns._selectorLabel] = obj->getId(); childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = obj; } else { std::cout << "Do nothing" << std::endl; @@ -488,6 +499,50 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } +/** + * @brief StyleDialog::_selected_row_callback + * @param path + * This function selects objects in the drawing corresponding to the selector + * selected in the treeview. + */ +void StyleDialog::_selectedRowCallback(const Gtk::TreeModel::Path& path, + Gtk::TreeViewColumn* /* column */) +{ + _desktop->selection->clear(); + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::Children children = row.children(); + + if (row[_mColumns._colObj]) { + SPObject *obj = row[_mColumns._colObj]; + _desktop->selection->add(obj); + } + + if (children) { + _checkAllChildren(children); + } + } +} + +/** + * @brief StyleDialog::_checkAllChildren + * @param children + * This function iterates children of the row selected in treeview and selects + * the objects corresponding to any selector in child rows. + */ +void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) +{ + for (Gtk::TreeModel::Children::iterator iter = children.begin(); + iter!= children.end(); ++iter) { + Gtk::TreeModel::Row childrow = *iter; + if (childrow[_mColumns._colObj]) { + SPObject *obj = childrow[_mColumns._colObj]; + _desktop->selection->add(obj); + } + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape -- cgit v1.2.3 From 94e53ff6ca6d0a595415b6f930a4a05adaeb68be Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 28 Jun 2016 22:18:31 +0530 Subject: Update XML repr when objects are added to selector & some code cleanup (bzr r14949.1.31) --- src/ui/dialog/styledialog.cpp | 180 +++++++++++++++++++++--------------------- 1 file changed, 89 insertions(+), 91 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 1dba1d2df..1b93fb550 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -172,13 +172,7 @@ void StyleDialog::_addSelector() * with a dot. */ if (!textEditPtr->get_text().empty()) { - if (textEditPtr->get_text().at(0) == '#' || - textEditPtr->get_text().at(0) == '.') { _selectorName = textEditPtr->get_text(); - } - else { - _selectorName = "." + textEditPtr->get_text(); - } } else { _selectorName = ".Class1"; @@ -252,27 +246,24 @@ void StyleDialog::_addSelector() default: break; } - /** - * @brief root + + /** * A new style element is added to the document with value obtained * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - for (unsigned i = 0; i < _num; ++i) { - if (std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style") { - _styleExists = true; - _styleChild = _document->getReprRoot()->nthChild(i); - break; - } - else { - _styleExists = false; - } + _selectorVec.push_back(std::make_pair(_selectorName, _selectorValue)); + + if (_styleElementNode()) { + _styleChild = _styleElementNode(); + _styleExists = true; + } + else { + _styleExists = false; } if (_styleExists) { - _sValue = _sValue + _selectorValue; - _styleChild->firstChild()->setContent(_sValue.c_str()); + _updateStyleContent(); } else { _sValue = _selectorValue; @@ -288,7 +279,20 @@ void StyleDialog::_addSelector() root->addChild(newChild, NULL); Inkscape::GC::release(newChild); } - _selectorVec.push_back(std::make_pair(_selectorName, _selectorValue)); +} + +/** + * @brief StyleDialog::_updateStyleContent + * This function updates the content in style element as new selectors (or + * objects) are added/removed. + */ +void StyleDialog::_updateStyleContent() +{ + std::string styleContent = ""; + for (unsigned i = 0; i < _selectorVec.size(); ++i) { + styleContent = styleContent + _selectorVec[i].second; + } + _styleElementNode()->firstChild()->setContent(styleContent.c_str()); } /** @@ -297,12 +301,13 @@ void StyleDialog::_addSelector() * of selected row is obtained and the corresponding selector and its values are * deleted from the selector vector. Then _sValue's content is reset and contains * only selectors remaining in the selVec (or treeview). + * TODO: get index of children of rows for correct deletion of rows having + * children. */ void StyleDialog::_delSelector() { Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); - std::vector >selVec = _getSelectorVec(); Gtk::TreeModel::Path path; if (iter) { @@ -310,39 +315,46 @@ void StyleDialog::_delSelector() path = _treeView.get_model()->get_path(iter); int i = atoi(path.to_string().c_str()); - if (selVec.size() != 0) { - selVec.erase(selVec.begin()+i); - _sValue.clear(); - - for (unsigned i = 0; i < selVec.size(); ++i) { - std::string selValue = (selVec[i].first + "{" - + selVec[i].second + " }\n"); - _sValue.append(selValue.c_str()); - } + if (_selectorVec.size() != 0) { + _selectorVec.erase(_selectorVec.begin()+i); /** - * Only if a value exists in _sValue and there is a _styleChild - * which contains the style element, then the content in style - * element is updated else the _styleChild is set and its content - * is set to an empty string. + * If there is a _styleChild which contains the style element, then + * the content in style element is updated else the _styleChild is + * obtained and its content is set. */ - if (!_sValue.empty() && _styleChild) { - _styleChild->firstChild()->setContent(_sValue.c_str()); + if (_styleChild) { + _updateStyleContent(); } else { - for (unsigned i = 0; i < _num; ++i) { - if (std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style") { - _styleChild = _document->getReprRoot()->nthChild(i); - } - } - _styleChild->firstChild()->setContent(""); + _styleChild = _styleElementNode(); + _updateStyleContent(); } } _store->erase(row); } } +/** + * @brief StyleDialog::_styleElementNode + * @return + * This function returns the node containing style element. The document's + * children are iterated and the repr of the style element that occurs is + * obtained. + */ +Inkscape::XML::Node* StyleDialog::_styleElementNode() +{ + for (unsigned i = 0; i < _num; ++i) { + if (std::string(_document->getReprRoot()->nthChild(i)->name()) + == "svg:style") { + return _document->getReprRoot()->nthChild(i); + } + else { + return NULL; + } + } +} + /** * @brief StyleDialog::_setClassAttribute * @param sel @@ -412,8 +424,8 @@ std::string StyleDialog::_populateTree(std::vectorappend()); row[_mColumns._selectorLabel] = _selectVec[it].first; - std::string selValue = _selectVec[it].first + " { " - + _selectVec[it].second + " }" + "\n"; + std::string selValue = _selectVec[it].first + "{" + + _selectVec[it].second + "}" + "\n"; selectorValue.append(selValue.c_str()); } @@ -421,12 +433,7 @@ std::string StyleDialog::_populateTree(std::vectorset_sensitive(true); } - for (unsigned i = 0; i < _num; ++i) { - if (std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style") { - _styleChild = _document->getReprRoot()->nthChild(i); - } - } + _styleChild = _styleElementNode(); return selectorValue; } @@ -438,9 +445,7 @@ std::string StyleDialog::_populateTree(std::vectortype == GDK_BUTTON_PRESS && event->button == 1) { @@ -461,37 +466,30 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) Gtk::TreeModel::iterator iter = refTreeSelection-> get_selected(); - if (iter) { + if (iter) + { Gtk::TreeModel::Row row = *iter; typedef Gtk::TreeModel::Children type_children; - type_children children = row->children(); Gtk::TreeModel::Row childrow; - - if (children.size() == 0 && row->parent() == 0) { - childrow = *(_store->append(row->children())); - childrow[_mColumns._selectorLabel] = obj->getId(); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = obj; - } - else { - for(type_children::iterator it = children.begin(); + path = _treeView.get_model()->get_path(iter); + childrow = *(_store->append(row->children())); + childrow[_mColumns._selectorLabel] = obj->getId(); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = obj; + Gtk::TreeModel::Children children = row.children(); + std::string childStyle; + if (children) { + for(Gtk::TreeModel::Children::iterator it = children.begin(); it != children.end(); ++it) { - Gtk::TreeModel::iterator i = it; - path = _treeView.get_model()->get_path(i); - - if((*it)->get_value(_mColumns._selectorLabel) - != obj->getId()) { - childrow = *(_store->append(row.children())); - childrow[_mColumns._selectorLabel] = obj->getId(); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = obj; - } - else { - std::cout << "Do nothing" << std::endl; - } + Gtk::TreeModel::Row row = *it; + SPObject *obj = row[_mColumns._colObj]; + childStyle = "#" + std::string(obj->getId()) + "{" + + std::string(obj->getAttribute("style")) + "}\n"; } } + _selectorVec.push_back(std::make_pair(obj->getId(), childStyle)); } + _updateStyleContent(); } } } @@ -506,21 +504,21 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) * selected in the treeview. */ void StyleDialog::_selectedRowCallback(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* /* column */) + Gtk::TreeViewColumn* column ) { _desktop->selection->clear(); - Gtk::TreeModel::iterator iter = _store->get_iter(path); - if (iter) { - Gtk::TreeModel::Row row = *iter; - Gtk::TreeModel::Children children = row.children(); - - if (row[_mColumns._colObj]) { - SPObject *obj = row[_mColumns._colObj]; - _desktop->selection->add(obj); - } - - if (children) { - _checkAllChildren(children); + if (column == _treeView.get_column(1)) { + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::Children children = row.children(); + if (row[_mColumns._colObj]) { + SPObject *obj = row[_mColumns._colObj]; + _desktop->selection->add(obj); + } + if (children) { + _checkAllChildren(children); + } } } } -- cgit v1.2.3 From cc89ba02cda5257f76df813d86318b57469ee81e Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Thu, 30 Jun 2016 15:02:15 +0530 Subject: If selectors(children) of a row in treeview are deleted, XML repr is updated and also remove duplicate style element(if one already exists) (bzr r14949.1.33) --- src/ui/dialog/styledialog.cpp | 96 ++++++++++++++++++++++++++++--------------- 1 file changed, 64 insertions(+), 32 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 1b93fb550..3b01faa10 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -83,7 +83,7 @@ StyleDialog::StyleDialog() : del = manage( new Gtk::Button() ); _styleButton(*del, "list-remove", "Remove a CSS Selector"); del->signal_clicked().connect(sigc::mem_fun(*this, - &StyleDialog::_delSelector)); + &StyleDialog::_delSelector)); del->set_sensitive(false); _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); @@ -105,7 +105,7 @@ StyleDialog::StyleDialog() : _styleExists = false; _document = _targetDesktop->doc(); _num = _document->getReprRoot()->childCount(); - _sValue = _populateTree(_getSelectorVec()); + _selectorValue = _populateTree(_getSelectorVec()); _treeView.signal_button_press_event().connect(sigc::mem_fun(*this, &StyleDialog:: @@ -172,7 +172,7 @@ void StyleDialog::_addSelector() * with a dot. */ if (!textEditPtr->get_text().empty()) { - _selectorName = textEditPtr->get_text(); + _selectorName = textEditPtr->get_text(); } else { _selectorName = ".Class1"; @@ -199,7 +199,7 @@ void StyleDialog::_addSelector() if (obj->getRepr()->attribute("style")) { for (List iter = obj->getRepr()->attributeList(); - iter; ++iter) { + iter; ++iter) { gchar const * property = g_quark_to_string(iter->key); gchar const * value = iter->value; @@ -256,17 +256,12 @@ void StyleDialog::_addSelector() if (_styleElementNode()) { _styleChild = _styleElementNode(); - _styleExists = true; - } - else { - _styleExists = false; + _updateStyleContent(); } - - if (_styleExists) { + else if (_styleExists && !_newDrawing) { _updateStyleContent(); } - else { - _sValue = _selectorValue; + else if (!_styleExists) { Inkscape::XML::Node *root = _document->getReprDoc()->root(); Inkscape::XML::Node *newChild = _document->getReprDoc() ->createElement("svg:style"); @@ -292,17 +287,16 @@ void StyleDialog::_updateStyleContent() for (unsigned i = 0; i < _selectorVec.size(); ++i) { styleContent = styleContent + _selectorVec[i].second; } - _styleElementNode()->firstChild()->setContent(styleContent.c_str()); + _styleChild->firstChild()->setContent(styleContent.c_str()); } /** * @brief StyleDialog::_delSelector * This function deletes selector when '-' at the bottom is clicked. The index * of selected row is obtained and the corresponding selector and its values are - * deleted from the selector vector. Then _sValue's content is reset and contains - * only selectors remaining in the selVec (or treeview). - * TODO: get index of children of rows for correct deletion of rows having - * children. + * deleted from the selector vector. If a row has no parent, it is directly + * erased from the vector else the string containing selector row's selector value + * is updated after parsing. */ void StyleDialog::_delSelector() { @@ -316,7 +310,37 @@ void StyleDialog::_delSelector() int i = atoi(path.to_string().c_str()); if (_selectorVec.size() != 0) { - _selectorVec.erase(_selectorVec.begin()+i); + if (!row.parent()) { + _selectorVec.erase(_selectorVec.begin()+i); + } + else { + std::stringstream str; + std::string sel, key, value; + int i; + + for (unsigned it = 0; it < _selectorVec.size(); ++it) { + str << _selectorVec[it].second; + i = it; + } + + while (std::getline(str, sel, '\n')) { + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok(strdup(sel.c_str()), "{"); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + if (key == "#" + row[_mColumns._selectorLabel]) { + sel = ""; + } + else { + sel = sel; + } + _selectorVec[i].second = sel; + } + } + } /** * If there is a _styleChild which contains the style element, then @@ -347,6 +371,8 @@ Inkscape::XML::Node* StyleDialog::_styleElementNode() for (unsigned i = 0; i < _num; ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { + _styleExists = true; + _newDrawing = true; return _document->getReprRoot()->nthChild(i); } else { @@ -376,15 +402,17 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) * @return selVec * This function returns a vector whose key is the style selector name and value * is the style properties. All style selectors are extracted from svg:style - * element. + * element. _newDrawing is flag is set to false check if an existing drawing is + * opened. */ std::vector >StyleDialog::_getSelectorVec() { std::string key, value; - std::vector > selVec; - for (unsigned i = 0; i < _num; ++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; @@ -401,12 +429,12 @@ std::vector >StyleDialog::_getSelectorVec() if (strtok(temp, "}") != NULL) { value = strtok(temp, "}"); } - selVec.push_back(std::make_pair(key, value)); + _selectorVec.push_back(std::make_pair(key, sel)); } } } } - return selVec; + return _selectorVec; } /** @@ -418,23 +446,21 @@ std::vector >StyleDialog::_getSelectorVec() std::string StyleDialog::_populateTree(std::vector > _selVec) { - std::vector > _selectVec = _selVec; + _selectorVec = _selVec; std::string selectorValue; - for(unsigned it = 0; it < _selectVec.size(); ++it) { + for(unsigned it = 0; it < _selectorVec.size(); ++it) { Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._selectorLabel] = _selectVec[it].first; - std::string selValue = _selectVec[it].first + "{" - + _selectVec[it].second + "}" + "\n"; + row[_mColumns._selectorLabel] = _selectorVec[it].first; + _selectorVec[it].second = _selectorVec[it].second + "\n"; + std::string selValue = _selectorVec[it].second; selectorValue.append(selValue.c_str()); } - if (_selectVec.size() > 0) { + if (_selectorVec.size() > 0) { del->set_sensitive(true); } - _styleChild = _styleElementNode(); - return selectorValue; } @@ -489,7 +515,13 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } _selectorVec.push_back(std::make_pair(obj->getId(), childStyle)); } - _updateStyleContent(); + if (_styleElementNode()) { + _styleChild = _styleElementNode(); + _updateStyleContent(); + } + else if (_styleExists && !_newDrawing) { + _updateStyleContent(); + } } } } -- cgit v1.2.3 From 0af04b99d1160cf2cfc38adb3a0f74c185da4370 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Thu, 30 Jun 2016 18:43:15 +0530 Subject: Solve some compiler errors (bzr r14949.1.34) --- src/ui/dialog/styledialog.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 3b01faa10..3d2091aef 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -316,11 +316,11 @@ void StyleDialog::_delSelector() else { std::stringstream str; std::string sel, key, value; - int i; + int index; for (unsigned it = 0; it < _selectorVec.size(); ++it) { str << _selectorVec[it].second; - i = it; + index = it; } while (std::getline(str, sel, '\n')) { @@ -337,7 +337,7 @@ void StyleDialog::_delSelector() else { sel = sel; } - _selectorVec[i].second = sel; + _selectorVec[index].second = sel; } } } @@ -375,10 +375,8 @@ Inkscape::XML::Node* StyleDialog::_styleElementNode() _newDrawing = true; return _document->getReprRoot()->nthChild(i); } - else { - return NULL; - } } + return NULL; } /** @@ -495,7 +493,6 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) if (iter) { Gtk::TreeModel::Row row = *iter; - typedef Gtk::TreeModel::Children type_children; Gtk::TreeModel::Row childrow; path = _treeView.get_model()->get_path(iter); childrow = *(_store->append(row->children())); @@ -527,6 +524,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } } + return false; } /** -- cgit v1.2.3 From 2c22c31cb8650ad49f5e83c9221524f4cdcd3ddd Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 1 Jul 2016 12:37:35 +0530 Subject: Solve a spacing issue & fix buttons to add selectors when existing drawing is opened (bzr r14949.1.35) --- src/ui/dialog/styledialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 3d2091aef..3ee0e44f7 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -20,7 +20,7 @@ using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; -#define REMOVE_SPACES(x) x.erase(std::remove(x.begin(), x.end(), ' '), x.end()); +#define REMOVE_SPACES(x) x.erase(0, x.find_first_not_of(' ')); namespace Inkscape { namespace UI { @@ -450,6 +450,7 @@ std::string StyleDialog::_populateTree(std::vectorappend()); row[_mColumns._selectorLabel] = _selectorVec[it].first; + row[_mColumns._colAddRemove] = true; _selectorVec[it].second = _selectorVec[it].second + "\n"; std::string selValue = _selectorVec[it].second; selectorValue.append(selValue.c_str()); -- cgit v1.2.3 From 7c35f8e864197a1b2620a5337947bcdfd0b52d5a Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 1 Jul 2016 17:19:45 +0530 Subject: Add support to select corresponding treeview rows when objects are selected (bzr r14949.1.36) --- src/ui/dialog/styledialog.cpp | 55 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 8 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 3ee0e44f7..406b984d7 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -20,7 +20,8 @@ using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; -#define REMOVE_SPACES(x) x.erase(0, x.find_first_not_of(' ')); +#define REMOVE_SPACES(x) x.erase(0, x.find_first_not_of(' ')); \ + x.erase(x.find_last_not_of(' ') + 1); namespace Inkscape { namespace UI { @@ -126,6 +127,8 @@ void StyleDialog::setDesktop( SPDesktop* desktop ) { Panel::setDesktop(desktop); _desktop = Panel::getDesktop(); + _desktop->selection->connectChanged(sigc::mem_fun(*this, &StyleDialog:: + _selectRow)); } /** @@ -189,6 +192,7 @@ void StyleDialog::_addSelector() * class attribute for the selected object is set too. */ SPObject *obj; + SPObject *selectorObj; bool objExists = false; if (!_desktop->getSelection()->list().empty()) { std::vector selected = _desktop->getSelection()->list(); @@ -241,6 +245,7 @@ void StyleDialog::_addSelector() _row[_mColumns._colAddRemove] = true; if (objExists) { _row[_mColumns._colObj] = obj; + selectorObj = obj; } break; default: @@ -252,7 +257,8 @@ void StyleDialog::_addSelector() * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - _selectorVec.push_back(std::make_pair(_selectorName, _selectorValue)); + _selectorVec.push_back(std::make_pair(std::make_pair(_selectorName, selectorObj), + _selectorValue)); if (_styleElementNode()) { _styleChild = _styleElementNode(); @@ -403,7 +409,7 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) * element. _newDrawing is flag is set to false check if an existing drawing is * opened. */ -std::vector >StyleDialog::_getSelectorVec() +std::vector, std::string> > StyleDialog::_getSelectorVec() { std::string key, value; for (unsigned i = 0; i < _num; ++i) { @@ -427,7 +433,12 @@ std::vector >StyleDialog::_getSelectorVec() if (strtok(temp, "}") != NULL) { value = strtok(temp, "}"); } - _selectorVec.push_back(std::make_pair(key, sel)); + std::string selId = key.erase(0, key.find_first_not_of('#')); + REMOVE_SPACES(selId); + REMOVE_SPACES(key); + SPObject *obj = _document->getObjectById(selId); + _selectorVec.push_back(std::make_pair(std::make_pair(key, obj), + sel)); } } } @@ -441,16 +452,17 @@ std::vector >StyleDialog::_getSelectorVec() * This function populates the treeview with selectors available in the * stylesheet. */ -std::string StyleDialog::_populateTree(std::vector > _selVec) +std::string StyleDialog::_populateTree(std::vector, std::string> > _selVec) { _selectorVec = _selVec; std::string selectorValue; for(unsigned it = 0; it < _selectorVec.size(); ++it) { Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._selectorLabel] = _selectorVec[it].first; + row[_mColumns._selectorLabel] = _selectorVec[it].first.first; row[_mColumns._colAddRemove] = true; + row[_mColumns._colObj] = _selectorVec[it].first.second; _selectorVec[it].second = _selectorVec[it].second + "\n"; std::string selValue = _selectorVec[it].second; selectorValue.append(selValue.c_str()); @@ -511,7 +523,9 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) std::string(obj->getAttribute("style")) + "}\n"; } } - _selectorVec.push_back(std::make_pair(obj->getId(), childStyle)); + _selectorVec.push_back(std::make_pair(std::make_pair + (obj->getId(), obj), + childStyle)); } if (_styleElementNode()) { _styleChild = _styleElementNode(); @@ -572,6 +586,31 @@ void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) } } +/** + * @brief StyleDialog::_selectRow + * This function selects the rows in treeview corresponding to an object selected + * in the drawing. + */ +void StyleDialog::_selectRow(Selection */*sel*/) +{ + if (!_desktop->selection->list().empty()) { + SPObject *obj; + std::vector selected = _desktop->getSelection()->list(); + for (unsigned i = 0; i < selected.size(); ++i) { + obj = selected.at(i); + } + + Gtk::TreeModel::Children children = _store->children(); + for(Gtk::TreeModel::Children::iterator iter = children.begin(); + iter != children.end(); ++iter) { + Gtk::TreeModel::Row row = *iter; + if (obj == row[_mColumns._colObj]) { + _treeView.get_selection()->select(row); + } + } + } +} + } // namespace Dialog } // namespace UI } // namespace Inkscape -- cgit v1.2.3 From f7724473cc5e15c9b9d0e7c2fe362ebedaa69f55 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 5 Jul 2016 13:39:43 +0530 Subject: Fix deletion and selection of objects clicking on styledialog rows and vice-versa (bzr r14949.1.39) --- src/ui/dialog/styledialog.cpp | 159 ++++++++++++++++++++++++++++++------------ 1 file changed, 115 insertions(+), 44 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 406b984d7..b6e3d10ec 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -192,7 +192,8 @@ void StyleDialog::_addSelector() * class attribute for the selected object is set too. */ SPObject *obj; - SPObject *selectorObj; + std::vector objVec; + bool objExists = false; if (!_desktop->getSelection()->list().empty()) { std::vector selected = _desktop->getSelection()->list(); @@ -244,8 +245,8 @@ void StyleDialog::_addSelector() _row[_mColumns._selectorLabel] = _selectorName; _row[_mColumns._colAddRemove] = true; if (objExists) { - _row[_mColumns._colObj] = obj; - selectorObj = obj; + _row[_mColumns._colObj] = _desktop->selection->list(); + objVec = _row[_mColumns._colObj]; } break; default: @@ -257,7 +258,7 @@ void StyleDialog::_addSelector() * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - _selectorVec.push_back(std::make_pair(std::make_pair(_selectorName, selectorObj), + _selectorVec.push_back(std::make_pair(std::make_pair(_selectorName, objVec), _selectorValue)); if (_styleElementNode()) { @@ -320,19 +321,14 @@ void StyleDialog::_delSelector() _selectorVec.erase(_selectorVec.begin()+i); } else { - std::stringstream str; std::string sel, key, value; - int index; - for (unsigned it = 0; it < _selectorVec.size(); ++it) { - str << _selectorVec[it].second; - index = it; - } - - while (std::getline(str, sel, '\n')) { + sel = _selectorVec[it].second; REMOVE_SPACES(sel); + std::cout << "sel" << sel << std::endl; if (!sel.empty()) { key = strtok(strdup(sel.c_str()), "{"); + REMOVE_SPACES(key); char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { value = strtok(temp, "}"); @@ -343,7 +339,7 @@ void StyleDialog::_delSelector() else { sel = sel; } - _selectorVec[index].second = sel; + _selectorVec[it].second = sel; } } } @@ -376,7 +372,7 @@ Inkscape::XML::Node* StyleDialog::_styleElementNode() { for (unsigned i = 0; i < _num; ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style") { + == "svg:style") { _styleExists = true; _newDrawing = true; return _document->getReprRoot()->nthChild(i); @@ -409,9 +405,9 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) * element. _newDrawing is flag is set to false check if an existing drawing is * opened. */ -std::vector, std::string> > StyleDialog::_getSelectorVec() +std::vector<_selectorVecType> StyleDialog::_getSelectorVec() { - std::string key, value; + std::string key, value, selId; for (unsigned i = 0; i < _num; ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { _styleExists = true; @@ -426,19 +422,74 @@ std::vector, std::string> > StyleDi * value is set to empty so that its corresponding XML repr is added. */ while(std::getline(str, sel, '\n')) { + std::vectorobjVec; REMOVE_SPACES(sel); if (!sel.empty()) { key = strtok(strdup(sel.c_str()), "{"); + _selectorName = key; char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { value = strtok(temp, "}"); } - std::string selId = key.erase(0, key.find_first_not_of('#')); - REMOVE_SPACES(selId); - REMOVE_SPACES(key); - SPObject *obj = _document->getObjectById(selId); - _selectorVec.push_back(std::make_pair(std::make_pair(key, obj), - sel)); + + 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); + + if (strcmp(token.substr(0,1).c_str(), ".") == 0) { + token.erase(0, token.find_first_not_of('.')); + for (unsigned i = 0; i < _num; ++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 (strcmp(token.substr(0,1).c_str(), "#") == 0) { + token.erase(0, token.find_first_not_of('#')); + selId = token; + objVec.push_back(_document->getObjectById(selId)); + } + else { + std::cout << "simple text" << std::endl; + } + } + } + else { + REMOVE_SPACES(key); + std::string tkn = key; + if (strcmp(tkn.substr(0,1).c_str(), ".") == 0) { + tkn.erase(0, tkn.find_first_not_of('.')); + for (unsigned i = 0; i < _num; ++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 (strcmp(tkn.substr(0,1).c_str(), "#") == 0) { + tkn.erase(0, key.find_first_not_of('#')); + selId = tkn; + objVec.push_back(_document->getObjectById(selId)); + } + else { + std::cout << "simple text" << std::endl; + } + } + _selectorValue = _selectorName + "{" + value + "}\n"; + _selectorVec.push_back(std::make_pair(std::make_pair(key, objVec), + _selectorValue)); } } } @@ -452,8 +503,7 @@ std::vector, std::string> > StyleDi * This function populates the treeview with selectors available in the * stylesheet. */ -std::string StyleDialog::_populateTree(std::vector, std::string> > _selVec) +std::string StyleDialog::_populateTree(std::vector<_selectorVecType> _selVec) { _selectorVec = _selVec; std::string selectorValue; @@ -463,7 +513,6 @@ std::string StyleDialog::_populateTree(std::vectorget_path(iter); - childrow = *(_store->append(row->children())); - childrow[_mColumns._selectorLabel] = obj->getId(); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = obj; - Gtk::TreeModel::Children children = row.children(); + int i = atoi(path.to_string().c_str()); + Gtk::TreeModel::Row row = *iter; std::string childStyle; - if (children) { - for(Gtk::TreeModel::Children::iterator it = children.begin(); - it != children.end(); ++it) { - Gtk::TreeModel::Row row = *it; - SPObject *obj = row[_mColumns._colObj]; + + if (_selectorVec.size() != 0) { + if (!row.parent()) { + Gtk::TreeModel::Row childrow; + childrow = *(_store->append(row->children())); + std::cout << "_store->children() " << _store->children() + ->children().size() << std::endl; + + childrow[_mColumns._selectorLabel] = obj->getId(); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = _desktop->selection->list(); childStyle = "#" + std::string(obj->getId()) + "{" + std::string(obj->getAttribute("style")) + "}\n"; } } + _selectorVec.push_back(std::make_pair(std::make_pair - (obj->getId(), obj), + (obj->getId(), + sel), childStyle)); } if (_styleElementNode()) { @@ -557,8 +609,9 @@ void StyleDialog::_selectedRowCallback(const Gtk::TreeModel::Path& path, if (iter) { Gtk::TreeModel::Row row = *iter; Gtk::TreeModel::Children children = row.children(); - if (row[_mColumns._colObj]) { - SPObject *obj = row[_mColumns._colObj]; + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; _desktop->selection->add(obj); } if (children) { @@ -579,8 +632,9 @@ void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) for (Gtk::TreeModel::Children::iterator iter = children.begin(); iter!= children.end(); ++iter) { Gtk::TreeModel::Row childrow = *iter; - if (childrow[_mColumns._colObj]) { - SPObject *obj = childrow[_mColumns._colObj]; + std::vector objVec = childrow[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; _desktop->selection->add(obj); } } @@ -604,8 +658,25 @@ void StyleDialog::_selectRow(Selection */*sel*/) for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { Gtk::TreeModel::Row row = *iter; - if (obj == row[_mColumns._colObj]) { - _treeView.get_selection()->select(row); + std::vector objVec = row[_mColumns._colObj]; + std::vector childObjVec; + Gtk::TreeModel::Row childRow; + if (row.children()) { + for(Gtk::TreeModel::Children::iterator it = row.children().begin(); + it != row.children().end(); ++it) { + childRow = *it; + childObjVec = childRow[_mColumns._colObj]; + } + } + for (unsigned i = 0; i < objVec.size(); ++i) { + if (obj->getId() == objVec[i]->getId()) { + _treeView.get_selection()->select(row); + } + } + for (unsigned j = 0; j < childObjVec.size(); ++j) { + if (obj->getId() == childObjVec[j]->getId()) { + _treeView.get_selection()->select(childRow); + } } } } -- cgit v1.2.3 From 7c612210cbeecef13c9148a3e35a5f73dd5a6347 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 6 Jul 2016 14:38:04 +0530 Subject: Fix issues related to updating style content and selection of rows in treeview (bzr r14949.1.40) --- src/ui/dialog/styledialog.cpp | 62 ++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 27 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index b6e3d10ec..72fea5dc6 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -200,23 +200,16 @@ void StyleDialog::_addSelector() for (unsigned i = 0; i < selected.size(); ++i) { obj = selected.at(i); objExists = true; - std::string style; - - if (obj->getRepr()->attribute("style")) { - for (List iter = obj->getRepr()->attributeList(); - iter; ++iter) { - gchar const * property = g_quark_to_string(iter->key); - gchar const * value = iter->value; + if (!obj->getRepr()->attribute("style")) { + obj->getRepr()->setAttribute("style", NULL); + } - if (std::string(property) == "style") { - _selectorValue = _selectorName + "{" - + std::string(value) + "}" + "\n"; - } - } + if (obj->getAttribute("style") == NULL) { + _selectorValue = _selectorName + "{" + "}" + "\n"; } else { - style = " "; - obj->getRepr()->setAttribute("style", style); + _selectorValue = _selectorName + "{" + + obj->getAttribute("style") + "}" + "\n"; } if (strcmp(_selectorName.substr(0,1).c_str(), ".") == 0) { @@ -647,13 +640,20 @@ void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) */ void StyleDialog::_selectRow(Selection */*sel*/) { + SPObject *obj = NULL; + bool objExists = false; if (!_desktop->selection->list().empty()) { - SPObject *obj; std::vector selected = _desktop->getSelection()->list(); - for (unsigned i = 0; i < selected.size(); ++i) { - obj = selected.at(i); - } + obj = selected.back(); + } + /** + * If obj has some SPObject, then it is added to desktop's selection. If a + * row in treeview has children, those rows are checked too against selected + * object's id. If an object which is not present in any selector is selected, + * the treeview's selections are unselected. + */ + if (obj != NULL) { Gtk::TreeModel::Children children = _store->children(); for(Gtk::TreeModel::Children::iterator iter = children.begin(); iter != children.end(); ++iter) { @@ -661,24 +661,32 @@ void StyleDialog::_selectRow(Selection */*sel*/) std::vector objVec = row[_mColumns._colObj]; std::vector childObjVec; Gtk::TreeModel::Row childRow; + + for (unsigned i = 0; i < objVec.size(); ++i) { + if (obj->getId() == objVec[i]->getId()) { + _treeView.get_selection()->select(row); + objExists = true; + } + } + if (row.children()) { for(Gtk::TreeModel::Children::iterator it = row.children().begin(); it != row.children().end(); ++it) { childRow = *it; childObjVec = childRow[_mColumns._colObj]; } - } - for (unsigned i = 0; i < objVec.size(); ++i) { - if (obj->getId() == objVec[i]->getId()) { - _treeView.get_selection()->select(row); - } - } - for (unsigned j = 0; j < childObjVec.size(); ++j) { - if (obj->getId() == childObjVec[j]->getId()) { - _treeView.get_selection()->select(childRow); + for (unsigned j = 0; j < childObjVec.size(); ++j) { + if (obj->getId() == childObjVec[j]->getId()) { + _treeView.get_selection()->select(childRow); + objExists = true; + } } } } + + if (!objExists) { + _treeView.get_selection()->unselect_all(); + } } } -- cgit v1.2.3 From 67f04a5e0e1bff0523a97d4aa16357849e51e1d8 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 8 Jul 2016 17:19:12 +0530 Subject: Selects matching objects for single as well as double click on selector (bzr r14949.1.42) --- src/ui/dialog/styledialog.cpp | 89 +++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 32 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 72fea5dc6..7e0cb135f 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -113,9 +113,10 @@ StyleDialog::StyleDialog() : _handleButtonEvent), false); - _treeView.signal_row_activated().connect(sigc::mem_fun(*this, - &StyleDialog:: - _selectedRowCallback)); + _treeView.signal_button_press_event().connect_notify(sigc::mem_fun + (*this, &StyleDialog:: + _buttonEventsSelectObjs), + false); } StyleDialog::~StyleDialog() @@ -548,18 +549,14 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) if (iter) { path = _treeView.get_model()->get_path(iter); - int i = atoi(path.to_string().c_str()); Gtk::TreeModel::Row row = *iter; std::string childStyle; - if (_selectorVec.size() != 0) { if (!row.parent()) { Gtk::TreeModel::Row childrow; childrow = *(_store->append(row->children())); - std::cout << "_store->children() " << _store->children() - ->children().size() << std::endl; - - childrow[_mColumns._selectorLabel] = obj->getId(); + childrow[_mColumns._selectorLabel] = "#" + + std::string(obj->getId()); childrow[_mColumns._colAddRemove] = false; childrow[_mColumns._colObj] = _desktop->selection->list(); childStyle = "#" + std::string(obj->getId()) + "{" + @@ -588,27 +585,59 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } /** - * @brief StyleDialog::_selected_row_callback - * @param path + * @brief StyleDialog::_selectObjects + * @param event + * This function detects single or double click on a selector in any row. Single + * click on a selector selects the matching objects. A double click on any + * selector selects the matching objects as well as will open CSS dialog. It + * calls _selectObjects to add objects to selection. + * TODO: Open CSS dialog on double click. + */ +void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 1) { + int x = static_cast(event->x); + int y = static_cast(event->y); + _selectObjects(x, y); + } + else if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { + int x = static_cast(event->x); + int y = static_cast(event->y); + _selectObjects(x, y); + //Open CSS dialog here. + } +} + +/** + * @brief StyleDialog::_selectObjects + * @param eventX + * @param eventY * This function selects objects in the drawing corresponding to the selector * selected in the treeview. */ -void StyleDialog::_selectedRowCallback(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* column ) +void StyleDialog::_selectObjects(int eventX, int eventY) { _desktop->selection->clear(); - if (column == _treeView.get_column(1)) { - Gtk::TreeModel::iterator iter = _store->get_iter(path); - if (iter) { - Gtk::TreeModel::Row row = *iter; - Gtk::TreeModel::Children children = row.children(); - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - _desktop->selection->add(obj); - } - if (children) { - _checkAllChildren(children); + Gtk::TreeViewColumn *col = _treeView.get_column(1); + Gtk::TreeModel::Path path; + int x = eventX; + int y = eventY; + int x2 = 0; + int y2 = 0; + if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { + if (col == _treeView.get_column(1)) { + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::Children children = row.children(); + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; + _desktop->selection->add(obj); + } + if (children) { + _checkAllChildren(children); + } } } } @@ -641,7 +670,6 @@ void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) void StyleDialog::_selectRow(Selection */*sel*/) { SPObject *obj = NULL; - bool objExists = false; if (!_desktop->selection->list().empty()) { std::vector selected = _desktop->getSelection()->list(); obj = selected.back(); @@ -665,7 +693,6 @@ void StyleDialog::_selectRow(Selection */*sel*/) for (unsigned i = 0; i < objVec.size(); ++i) { if (obj->getId() == objVec[i]->getId()) { _treeView.get_selection()->select(row); - objExists = true; } } @@ -678,15 +705,13 @@ void StyleDialog::_selectRow(Selection */*sel*/) for (unsigned j = 0; j < childObjVec.size(); ++j) { if (obj->getId() == childObjVec[j]->getId()) { _treeView.get_selection()->select(childRow); - objExists = true; } } } } - - if (!objExists) { - _treeView.get_selection()->unselect_all(); - } + } + else { + _treeView.get_selection()->unselect_all(); } } -- cgit v1.2.3 From f57322fc77c604c6102132b6a254280e1f597064 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sat, 9 Jul 2016 16:04:31 +0530 Subject: Delete objects from selector by clicking '-' in front of objects (bzr r14949.1.44) --- src/ui/dialog/styledialog.cpp | 148 +++++++++++++++++++++++++++++------------- 1 file changed, 104 insertions(+), 44 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 7e0cb135f..ac51e36c1 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -223,7 +223,7 @@ void StyleDialog::_addSelector() getRepr()-> attribute("class")) + " " + textEditPtr->get_text() - .erase(0,0)); + .erase(0,1)); } } } @@ -296,46 +296,43 @@ void StyleDialog::_updateStyleContent() * This function deletes selector when '-' at the bottom is clicked. The index * of selected row is obtained and the corresponding selector and its values are * deleted from the selector vector. If a row has no parent, it is directly - * erased from the vector else the string containing selector row's selector value - * is updated after parsing. + * erased from the vector along with its child rows. The style element is updated + * accordingly. */ void StyleDialog::_delSelector() { Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); - Gtk::TreeModel::Path path; - if (iter) { Gtk::TreeModel::Row row = *iter; - path = _treeView.get_model()->get_path(iter); - int i = atoi(path.to_string().c_str()); + std::string sel, key, value; + std::vector<_selectorVecType>::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it ) { + sel = (*it).second; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok(strdup(sel.c_str()), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + } if (_selectorVec.size() != 0) { if (!row.parent()) { - _selectorVec.erase(_selectorVec.begin()+i); - } - else { - std::string sel, key, value; - for (unsigned it = 0; it < _selectorVec.size(); ++it) { - sel = _selectorVec[it].second; - REMOVE_SPACES(sel); - std::cout << "sel" << sel << std::endl; - if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - if (key == "#" + row[_mColumns._selectorLabel]) { - sel = ""; - } - else { - sel = sel; + if (!row.children().empty()) { + for (Gtk::TreeModel::Children::iterator child = row.children().begin(); + child != row.children().end(); ++child) { + Gtk::TreeModel::Row childrow = *child; + if (key == childrow[_mColumns._selectorLabel]) { + _selectorVec.erase(it); } - _selectorVec[it].second = sel; } } + _selectorVec.erase(it); + _store->erase(row); } /** @@ -351,7 +348,6 @@ void StyleDialog::_delSelector() _updateStyleContent(); } } - _store->erase(row); } } @@ -537,22 +533,29 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) int y2 = 0; if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { if (col == _treeView.get_column(0)) { - if (_desktop->selection) { - std::vectorsel = _desktop->selection->list(); - for (unsigned i = 0; i < sel.size(); ++i) { - SPObject *obj = sel[i]; - Glib::RefPtr refTreeSelection = - _treeView.get_selection(); - Gtk::TreeModel::iterator iter = refTreeSelection-> - get_selected(); - - if (iter) - { - path = _treeView.get_model()->get_path(iter); - Gtk::TreeModel::Row row = *iter; + Glib::RefPtr refTreeSelection = + _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection-> + get_selected(); + Gtk::TreeModel::Row row = *iter; + + /** + * This adds child rows to selected rows. If the parent row is + * a class selector, then the class attribute of object added + * to child row is appended with class in the parent row. The + * else below deletes objects from selectors when 'delete' button + * in front of child row is clicked. The class attribute is updated + * by removing the parent row's class selector name. + */ + if (!row.parent()) { + if (_desktop->selection) { + std::vectorsel = _desktop->selection->list(); + for (unsigned i = 0; i < sel.size(); ++i) { + SPObject *obj = sel[i]; std::string childStyle; - if (_selectorVec.size() != 0) { - if (!row.parent()) { + if (iter) { + path = _treeView.get_model()->get_path(iter); + if (_selectorVec.size() != 0) { Gtk::TreeModel::Row childrow; childrow = *(_store->append(row->children())); childrow[_mColumns._selectorLabel] = "#" + @@ -561,6 +564,19 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) childrow[_mColumns._colObj] = _desktop->selection->list(); childStyle = "#" + std::string(obj->getId()) + "{" + std::string(obj->getAttribute("style")) + "}\n"; + Glib::ustring key = row[_mColumns._selectorLabel]; + if (strcmp(key.substr(0,1).c_str(), ".") == 0) { + if (!obj->getRepr()->attribute("class")) { + obj->setAttribute("class", key.erase(0,1)); + } + else { + obj->setAttribute("class", std::string + (obj->getRepr()-> + attribute("class")) + + " " + key + .erase(0,1)); + } + } } } @@ -578,6 +594,50 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } } + + else { + std::string sel, key, value; + std::vector<_selectorVecType>::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it ) { + sel = (*it).second; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok(strdup(sel.c_str()), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + } + if (key == row[_mColumns._selectorLabel]) { + Gtk::TreeModel::Row parentRow = *(row.parent()); + Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; + if (strcmp(parentKey.substr(0,1).c_str(), ".") == 0) { + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; + std::string classAttr = std::string(obj->getRepr() + ->attribute("class")); + std::size_t found = classAttr.find(parentKey.erase(0,1)); + if (found != std::string::npos) { + classAttr.erase(found, parentKey.length()+1); + obj->getRepr()->setAttribute("class", classAttr); + } + } + } + _selectorVec.erase(it); + } + + if (_styleChild) { + _updateStyleContent(); + } + else { + _styleChild = _styleElementNode(); + _updateStyleContent(); + } + _store->erase(row); + } } } } -- cgit v1.2.3 From c1b1cf45b4b1feb43d326c2660e70408185ca64d Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 13 Jul 2016 20:32:24 +0530 Subject: Fix crash when deleting selector (bzr r14949.1.47) --- src/ui/dialog/styledialog.cpp | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index ac51e36c1..ca4f35bb6 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -307,7 +307,7 @@ void StyleDialog::_delSelector() Gtk::TreeModel::Row row = *iter; std::string sel, key, value; std::vector<_selectorVecType>::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it ) { + for (it = _selectorVec.begin(); it != _selectorVec.end();) { sel = (*it).second; REMOVE_SPACES(sel); if (!sel.empty()) { @@ -318,10 +318,11 @@ void StyleDialog::_delSelector() value = strtok(temp, "}"); } } - } - if (_selectorVec.size() != 0) { - if (!row.parent()) { + Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; + std::string matchSelector = selectedRowLabel; + REMOVE_SPACES(s1); + if (key == matchSelector) { if (!row.children().empty()) { for (Gtk::TreeModel::Children::iterator child = row.children().begin(); child != row.children().end(); ++child) { @@ -331,20 +332,24 @@ void StyleDialog::_delSelector() } } } - _selectorVec.erase(it); + it = _selectorVec.erase(it); _store->erase(row); } + else { + ++it; + } /** - * If there is a _styleChild which contains the style element, then - * the content in style element is updated else the _styleChild is - * obtained and its content is set. + * The _stylechild is obtained which contains the style element and + * the content in style element is updated. */ - if (_styleChild) { - _updateStyleContent(); + _styleChild = _styleElementNode(); + + if (_selectorVec.size() == 0) { + _document->getReprRoot()->removeChild(_styleChild); + _styleExists = false; } else { - _styleChild = _styleElementNode(); _updateStyleContent(); } } -- cgit v1.2.3 From 0799f58bb7144addd85ba4601899eaf29d92d26c Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 13 Jul 2016 20:38:56 +0530 Subject: Replace s1 with matchSelector (bzr r14949.1.48) --- src/ui/dialog/styledialog.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index ca4f35bb6..4c4cb03aa 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -321,7 +321,7 @@ void StyleDialog::_delSelector() Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(s1); + REMOVE_SPACES(matchSelector); if (key == matchSelector) { if (!row.children().empty()) { for (Gtk::TreeModel::Children::iterator child = row.children().begin(); @@ -341,10 +341,11 @@ void StyleDialog::_delSelector() /** * The _stylechild is obtained which contains the style element and - * the content in style element is updated. + * the content in style element is updated. If _selectorVec is + * empty, the style element is removed from the XML repr else + * the content is updated simply using _updateStyleContent(). */ _styleChild = _styleElementNode(); - if (_selectorVec.size() == 0) { _document->getReprRoot()->removeChild(_styleChild); _styleExists = false; -- cgit v1.2.3 From 593e73c62fd16032ddd1ec85f21fb32ae543d753 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 13 Jul 2016 22:22:20 +0530 Subject: Correct deletion of child rows when parent selector is deleted (bzr r14949.1.49) --- src/ui/dialog/styledialog.cpp | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 4c4cb03aa..bf731466f 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -327,8 +327,25 @@ void StyleDialog::_delSelector() for (Gtk::TreeModel::Children::iterator child = row.children().begin(); child != row.children().end(); ++child) { Gtk::TreeModel::Row childrow = *child; - if (key == childrow[_mColumns._selectorLabel]) { - _selectorVec.erase(it); + std::string childSel, childKey; + std::vector<_selectorVecType>::iterator i; + for (i = _selectorVec.begin(); i != _selectorVec.end();) { + childSel = (*i).second; + REMOVE_SPACES(childSel); + if (!childSel.empty()) { + childKey = strtok(strdup(childSel.c_str()), "{"); + REMOVE_SPACES(childKey); + } + Glib::ustring selectedChildRowLabel = + childrow[_mColumns._selectorLabel]; + std::string matchChildSelector = selectedChildRowLabel; + REMOVE_SPACES(matchChildSelector); + if (childKey == matchChildSelector) { + i = _selectorVec.erase(i); + } + else { + ++i; + } } } } @@ -568,8 +585,14 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) std::string(obj->getId()); childrow[_mColumns._colAddRemove] = false; childrow[_mColumns._colObj] = _desktop->selection->list(); - childStyle = "#" + std::string(obj->getId()) + "{" + - std::string(obj->getAttribute("style")) + "}\n"; + if (obj->getAttribute("style") != NULL) { + childStyle = "#" + std::string(obj->getId()) + "{" + + std::string(obj->getAttribute("style")) + "}\n"; + } + else { + childStyle = "#" + std::string(obj->getId()) + + "{" + "}\n"; + } Glib::ustring key = row[_mColumns._selectorLabel]; if (strcmp(key.substr(0,1).c_str(), ".") == 0) { if (!obj->getRepr()->attribute("class")) { -- cgit v1.2.3 From c72fde648673730e259453b05df66287b1b6d779 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 13 Jul 2016 23:46:40 +0530 Subject: Change expander column of treeview and set indentation of child rows (bzr r14949.1.50) --- src/ui/dialog/styledialog.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index bf731466f..174dd5ece 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -75,6 +75,8 @@ StyleDialog::StyleDialog() : } _treeView.append_column("Selector Name", _mColumns._selectorLabel); + _treeView.set_expander_column(*(_treeView.get_column(1))); + _treeView.set_level_indentation(-12); create = manage( new Gtk::Button() ); _styleButton(*create, "list-add", "Add a new CSS Selector"); -- cgit v1.2.3 From e0396836d3738f9b6d2182f310795fc6fe9d8857 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Mon, 18 Jul 2016 00:14:29 +0530 Subject: Add CSS panel with editing support (no changes reflected yet) (bzr r14949.1.52) --- src/ui/dialog/styledialog.cpp | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 174dd5ece..8eeeda3e6 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -119,6 +119,8 @@ StyleDialog::StyleDialog() : (*this, &StyleDialog:: _buttonEventsSelectObjs), false); + + _cssPane = new CssDialog; } StyleDialog::~StyleDialog() @@ -695,7 +697,60 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) int x = static_cast(event->x); int y = static_cast(event->y); _selectObjects(x, y); + //Open CSS dialog here. + if (!_cssPane->get_visible()) { + _mainBox.pack_end(*_cssPane, Gtk::PACK_SHRINK); + _cssPane->show_all(); + } + Glib::RefPtr refTreeSelection = _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + std::string sel, key, value; + std::vector<_selectorVecType>::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { + sel = (*it).second; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok(strdup(sel.c_str()), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + + Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; + std::string matchSelector = selectedRowLabel; + REMOVE_SPACES(matchSelector); + + if (key == matchSelector) { + _cssPane->_store->clear(); + std::stringstream ss(value); + std::string token; + std::size_t found = value.find(";"); + if (found!=std::string::npos) { + while(std::getline(ss, token, ';')) { + REMOVE_SPACES(token); + if (!token.empty()) { + _cssPane->propRow = *(_cssPane->_store->append()); + _cssPane->propRow[_cssPane->_cssColumns._colUnsetProp] = false; + _cssPane->propRow[_cssPane->_cssColumns._propertyLabel] = token; + _cssPane->_propCol->add_attribute(_cssPane->_textRenderer + ->property_text(), + _cssPane->_cssColumns + ._propertyLabel); + } + } + } + } + } + } + else { + _cssPane->_store->clear(); + _cssPane->hide(); + } } } -- cgit v1.2.3 From 96b7038386f56aa59a9d0935989469105234d2fe Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 19 Jul 2016 14:39:24 +0530 Subject: Update XML & hence drawing when properties are edited in CSS panel (bzr r14949.1.54) --- src/ui/dialog/styledialog.cpp | 77 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 4 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 8eeeda3e6..efbde1767 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -684,7 +684,6 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) * click on a selector selects the matching objects. A double click on any * selector selects the matching objects as well as will open CSS dialog. It * calls _selectObjects to add objects to selection. - * TODO: Open CSS dialog on double click. */ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) { @@ -703,6 +702,7 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) _mainBox.pack_end(*_cssPane, Gtk::PACK_SHRINK); _cssPane->show_all(); } + Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if (iter) { @@ -734,9 +734,9 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) while(std::getline(ss, token, ';')) { REMOVE_SPACES(token); if (!token.empty()) { - _cssPane->propRow = *(_cssPane->_store->append()); - _cssPane->propRow[_cssPane->_cssColumns._colUnsetProp] = false; - _cssPane->propRow[_cssPane->_cssColumns._propertyLabel] = token; + _cssPane->_propRow = *(_cssPane->_store->append()); + _cssPane->_propRow[_cssPane->_cssColumns._colUnsetProp] = false; + _cssPane->_propRow[_cssPane->_cssColumns._propertyLabel] = token; _cssPane->_propCol->add_attribute(_cssPane->_textRenderer ->property_text(), _cssPane->_cssColumns @@ -746,6 +746,9 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) } } } + _cssPane->_textRenderer->signal_edited().connect(sigc::mem_fun(*this, + &StyleDialog:: + _handleEdited)); } else { _cssPane->_store->clear(); @@ -754,6 +757,72 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) } } +/** + * @brief StyleDialog::_handleEdited + * @param path + * @param new_text + * This function edits CSS properties of the selector chosen. new_text is used + * to update the property in XML repr. The value from selected selector is + * obtained and modified as per value of new_text. Later _updateStyleContent() is + * called to update XML repr and hence changes are reflected in the drawing too. + */ +void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iterCss = _cssPane->_treeView.get_model()->get_iter(path); + if (iterCss) { + Gtk::TreeModel::Row row = *iterCss; + row[_cssPane->_cssColumns._propertyLabel] = new_text; + _cssPane->_editedProp = new_text; + } + + Glib::RefPtr refTreeSelection = _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + std::string sel, key, value; + std::vector<_selectorVecType>::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { + sel = (*it).second; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok(strdup(sel.c_str()), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + + Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; + std::string matchSelector = selectedRowLabel; + REMOVE_SPACES(matchSelector); + + if (key == matchSelector) { + std::stringstream ss(value); + std::string token; + std::size_t found = value.find(";"); + if (found!=std::string::npos) { + while(std::getline(ss, token, ';')) { + REMOVE_SPACES(token); + if (!token.empty()) { + if (token.substr(0, token.find(":")) == _cssPane + ->_editedProp.substr(0, _cssPane->_editedProp + .find(":"))) + { + token = _cssPane->_editedProp; + value.clear(); + value += token + ";"; + (*it).second = key + " { " + value + " }\n"; + _updateStyleContent(); + } + } + } + } + } + } + } +} + /** * @brief StyleDialog::_selectObjects * @param eventX -- cgit v1.2.3 From fe2e3fdfc7a546795e4a7221300aefd96d05f215 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 19 Jul 2016 16:57:19 +0530 Subject: Update XML correctly when editing properties (bzr r14949.1.55) --- src/ui/dialog/styledialog.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index efbde1767..99d5cd7e1 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -799,7 +799,7 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& if (key == matchSelector) { std::stringstream ss(value); - std::string token; + std::string token, editedToken; std::size_t found = value.find(";"); if (found!=std::string::npos) { while(std::getline(ss, token, ';')) { @@ -807,12 +807,11 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& if (!token.empty()) { if (token.substr(0, token.find(":")) == _cssPane ->_editedProp.substr(0, _cssPane->_editedProp - .find(":"))) - { - token = _cssPane->_editedProp; - value.clear(); - value += token + ";"; - (*it).second = key + " { " + value + " }\n"; + .find(":"))) { + editedToken = _cssPane->_editedProp; + size_t startPos = value.find(token); + value.replace(startPos, token.length(), editedToken); + (*it).second = key + "{" + value + "}\n"; _updateStyleContent(); } } -- cgit v1.2.3 From be3b537680814fd07a0a5776724028f09f78a023 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 20 Jul 2016 12:51:39 +0530 Subject: Separate CSS dialog from Style Dialog visually (bzr r14949.1.56) --- src/ui/dialog/styledialog.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 99d5cd7e1..f3e682062 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -55,6 +55,7 @@ StyleDialog::StyleDialog() : { set_size_request(200, 200); + _paned.pack1(_mainBox, Gtk::SHRINK); _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); _treeView.set_headers_visible(false); _scrolledWindow.add(_treeView); @@ -76,7 +77,6 @@ StyleDialog::StyleDialog() : _treeView.append_column("Selector Name", _mColumns._selectorLabel); _treeView.set_expander_column(*(_treeView.get_column(1))); - _treeView.set_level_indentation(-12); create = manage( new Gtk::Button() ); _styleButton(*create, "list-add", "Add a new CSS Selector"); @@ -94,7 +94,7 @@ StyleDialog::StyleDialog() : _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); _buttonBox.pack_start(*del, Gtk::PACK_SHRINK); - _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); + _getContents()->pack_start(_paned, Gtk::PACK_EXPAND_WIDGET); _targetDesktop = getDesktop(); setDesktop(_targetDesktop); @@ -699,7 +699,7 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) //Open CSS dialog here. if (!_cssPane->get_visible()) { - _mainBox.pack_end(*_cssPane, Gtk::PACK_SHRINK); + _paned.pack2(*_cssPane, Gtk::SHRINK); _cssPane->show_all(); } -- cgit v1.2.3 From 55a8a393851d289cf5699cc2d4f1bc5241d7b256 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sun, 24 Jul 2016 18:49:23 +0530 Subject: Add InkSelector class with some code improvements (bzr r14949.1.58) --- src/ui/dialog/styledialog.cpp | 92 +++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 43 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index f3e682062..1004fa151 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -107,7 +107,6 @@ StyleDialog::StyleDialog() : */ _styleExists = false; _document = _targetDesktop->doc(); - _num = _document->getReprRoot()->childCount(); _selectorValue = _populateTree(_getSelectorVec()); _treeView.signal_button_press_event().connect(sigc::mem_fun(*this, @@ -217,7 +216,7 @@ void StyleDialog::_addSelector() + obj->getAttribute("style") + "}" + "\n"; } - if (strcmp(_selectorName.substr(0,1).c_str(), ".") == 0) { + if (_selectorName[0] == '.') { if (!obj->getRepr()->attribute("class")) { obj->getRepr()->setAttribute("class", textEditPtr->get_text() .erase(0,1)); @@ -256,8 +255,10 @@ void StyleDialog::_addSelector() * from selectorValue above. If style element already exists, then * the new selector's content is appended to its previous content. */ - _selectorVec.push_back(std::make_pair(std::make_pair(_selectorName, objVec), - _selectorValue)); + inkSelector._selector = _selectorName; + inkSelector._matchingObjs = objVec; + inkSelector._xmlContent = _selectorValue; + _selectorVec.push_back(inkSelector); if (_styleElementNode()) { _styleChild = _styleElementNode(); @@ -290,7 +291,7 @@ void StyleDialog::_updateStyleContent() { std::string styleContent = ""; for (unsigned i = 0; i < _selectorVec.size(); ++i) { - styleContent = styleContent + _selectorVec[i].second; + styleContent = styleContent + _selectorVec[i]._xmlContent; } _styleChild->firstChild()->setContent(styleContent.c_str()); } @@ -310,12 +311,12 @@ void StyleDialog::_delSelector() if (iter) { Gtk::TreeModel::Row row = *iter; std::string sel, key, value; - std::vector<_selectorVecType>::iterator it; + std::vector::iterator it; for (it = _selectorVec.begin(); it != _selectorVec.end();) { - sel = (*it).second; + sel = (*it)._xmlContent; REMOVE_SPACES(sel); if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); + key = strtok((char*)sel.c_str(), "{"); REMOVE_SPACES(key); char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { @@ -332,12 +333,12 @@ void StyleDialog::_delSelector() child != row.children().end(); ++child) { Gtk::TreeModel::Row childrow = *child; std::string childSel, childKey; - std::vector<_selectorVecType>::iterator i; + std::vector::iterator i; for (i = _selectorVec.begin(); i != _selectorVec.end();) { - childSel = (*i).second; + childSel = (*i)._xmlContent; REMOVE_SPACES(childSel); if (!childSel.empty()) { - childKey = strtok(strdup(childSel.c_str()), "{"); + childKey = strtok((char*)childSel.c_str(), "{"); REMOVE_SPACES(childKey); } Glib::ustring selectedChildRowLabel = @@ -387,7 +388,7 @@ void StyleDialog::_delSelector() */ Inkscape::XML::Node* StyleDialog::_styleElementNode() { - for (unsigned i = 0; i < _num; ++i) { + for (unsigned i = 0; i < _document->getReprRoot()->childCount(); ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { _styleExists = true; @@ -422,10 +423,10 @@ std::string StyleDialog::_setClassAttribute(std::vector sel) * element. _newDrawing is flag is set to false check if an existing drawing is * opened. */ -std::vector<_selectorVecType> StyleDialog::_getSelectorVec() +std::vector StyleDialog::_getSelectorVec() { std::string key, value, selId; - for (unsigned i = 0; i < _num; ++i) { + for (unsigned i = 0; i < _document->getReprRoot()->childCount(); ++i) { if (std::string(_document->getReprRoot()->nthChild(i)->name()) == "svg:style") { _styleExists = true; _newDrawing = false; @@ -442,7 +443,7 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() std::vectorobjVec; REMOVE_SPACES(sel); if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); + key = strtok((char*)sel.c_str(), "{"); _selectorName = key; char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { @@ -456,9 +457,10 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() while(std::getline(ss, token, ',')) { REMOVE_SPACES(token); - if (strcmp(token.substr(0,1).c_str(), ".") == 0) { + if (token[0] == '.') { token.erase(0, token.find_first_not_of('.')); - for (unsigned i = 0; i < _num; ++i) { + for (unsigned i = 0; i < _document->getReprRoot() + ->childCount(); ++i) { if (_document->getReprRoot()-> nthChild(i)->attribute("class") && _document->getReprRoot()->nthChild(i) @@ -469,7 +471,7 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() } } } - else if (strcmp(token.substr(0,1).c_str(), "#") == 0) { + else if (token[0] == '#') { token.erase(0, token.find_first_not_of('#')); selId = token; objVec.push_back(_document->getObjectById(selId)); @@ -482,9 +484,10 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() else { REMOVE_SPACES(key); std::string tkn = key; - if (strcmp(tkn.substr(0,1).c_str(), ".") == 0) { + if (tkn[0] == '.') { tkn.erase(0, tkn.find_first_not_of('.')); - for (unsigned i = 0; i < _num; ++i) { + for (unsigned i = 0; i < _document->getReprRoot() + ->childCount(); ++i) { if (_document->getReprRoot()-> nthChild(i)->attribute("class") && _document->getReprRoot()->nthChild(i) @@ -495,7 +498,7 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() } } } - else if (strcmp(tkn.substr(0,1).c_str(), "#") == 0) { + else if (tkn[0] == '#') { tkn.erase(0, key.find_first_not_of('#')); selId = tkn; objVec.push_back(_document->getObjectById(selId)); @@ -505,8 +508,11 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() } } _selectorValue = _selectorName + "{" + value + "}\n"; - _selectorVec.push_back(std::make_pair(std::make_pair(key, objVec), - _selectorValue)); + + inkSelector._selector = key; + inkSelector._matchingObjs = objVec; + inkSelector._xmlContent = _selectorValue; + _selectorVec.push_back(inkSelector); } } } @@ -520,17 +526,17 @@ std::vector<_selectorVecType> StyleDialog::_getSelectorVec() * This function populates the treeview with selectors available in the * stylesheet. */ -std::string StyleDialog::_populateTree(std::vector<_selectorVecType> _selVec) +std::string StyleDialog::_populateTree(std::vector _selVec) { _selectorVec = _selVec; std::string selectorValue; for(unsigned it = 0; it < _selectorVec.size(); ++it) { Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._selectorLabel] = _selectorVec[it].first.first; + row[_mColumns._selectorLabel] = _selectorVec[it]._selector; row[_mColumns._colAddRemove] = true; - row[_mColumns._colObj] = _selectorVec[it].first.second; - std::string selValue = _selectorVec[it].second; + row[_mColumns._colObj] = _selectorVec[it]._matchingObjs; + std::string selValue = _selectorVec[it]._xmlContent; selectorValue.append(selValue.c_str()); } @@ -598,7 +604,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) + "{" + "}\n"; } Glib::ustring key = row[_mColumns._selectorLabel]; - if (strcmp(key.substr(0,1).c_str(), ".") == 0) { + if (key[0] == '.') { if (!obj->getRepr()->attribute("class")) { obj->setAttribute("class", key.erase(0,1)); } @@ -613,10 +619,10 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } - _selectorVec.push_back(std::make_pair(std::make_pair - (obj->getId(), - sel), - childStyle)); + inkSelector._selector = obj->getId(); + inkSelector._matchingObjs = sel; + inkSelector._xmlContent = childStyle; + _selectorVec.push_back(inkSelector); } if (_styleElementNode()) { _styleChild = _styleElementNode(); @@ -630,12 +636,12 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) else { std::string sel, key, value; - std::vector<_selectorVecType>::iterator it; + std::vector::iterator it; for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it ) { - sel = (*it).second; + sel = (*it)._xmlContent; REMOVE_SPACES(sel); if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); + key = strtok((char*)sel.c_str(), "{"); REMOVE_SPACES(key); char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { @@ -646,7 +652,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) if (key == row[_mColumns._selectorLabel]) { Gtk::TreeModel::Row parentRow = *(row.parent()); Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; - if (strcmp(parentKey.substr(0,1).c_str(), ".") == 0) { + if (parentKey[0] == '.') { std::vector objVec = row[_mColumns._colObj]; for (unsigned i = 0; i < objVec.size(); ++i) { SPObject *obj = objVec[i]; @@ -708,12 +714,12 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) if (iter) { Gtk::TreeModel::Row row = *iter; std::string sel, key, value; - std::vector<_selectorVecType>::iterator it; + std::vector::iterator it; for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it).second; + sel = (*it)._xmlContent; REMOVE_SPACES(sel); if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); + key = strtok((char*)sel.c_str(), "{"); REMOVE_SPACES(key); char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { @@ -780,12 +786,12 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& if (iter) { Gtk::TreeModel::Row row = *iter; std::string sel, key, value; - std::vector<_selectorVecType>::iterator it; + std::vector::iterator it; for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it).second; + sel = (*it)._xmlContent; REMOVE_SPACES(sel); if (!sel.empty()) { - key = strtok(strdup(sel.c_str()), "{"); + key = strtok((char*)sel.c_str(), "{"); REMOVE_SPACES(key); char *temp = strtok(NULL, "}"); if (strtok(temp, "}") != NULL) { @@ -811,7 +817,7 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& editedToken = _cssPane->_editedProp; size_t startPos = value.find(token); value.replace(startPos, token.length(), editedToken); - (*it).second = key + "{" + value + "}\n"; + (*it)._xmlContent = key + "{" + value + "}\n"; _updateStyleContent(); } } -- cgit v1.2.3 From 6641c2e8c586612aad47e1296584ca6447e11b15 Mon Sep 17 00:00:00 2001 From: "Tavmjong Bah, Kamalpreet Grewal" <> Date: Mon, 25 Jul 2016 19:10:59 +0530 Subject: Add robust implementation of _getSelectorVec() (bzr r14949.1.60) --- src/ui/dialog/styledialog.cpp | 141 ++++++++++++++++++++---------------------- 1 file changed, 67 insertions(+), 74 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') 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 sel) */ std::vector 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 regex1 = + // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}"); + // + // Glib::MatchInfo minfo; + // regex1->match(content, minfo); + + // Split on curly brackets. Even tokens are selectors, odd are values. + std::vector 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::vectorobjVec; - 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 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 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 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); } } } -- cgit v1.2.3 From 39c55178f470bf12c6a7fc51d5d17b65b319faf2 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 26 Jul 2016 21:45:08 +0530 Subject: Add functionality to add and delete CSS property in CSS panel (bzr r14949.1.61) --- src/ui/dialog/styledialog.cpp | 146 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 126 insertions(+), 20 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 259f326e4..7deac22d8 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -120,6 +120,10 @@ StyleDialog::StyleDialog() : false); _cssPane = new CssDialog; + + _treeView.get_selection()->signal_changed().connect(sigc::mem_fun(*this, + &StyleDialog:: + _selChanged)); } StyleDialog::~StyleDialog() @@ -279,6 +283,7 @@ void StyleDialog::_addSelector() root->addChild(newChild, NULL); Inkscape::GC::release(newChild); + _styleChild = newChild; } } @@ -745,14 +750,29 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) } } } - _cssPane->_textRenderer->signal_edited().connect(sigc::mem_fun(*this, - &StyleDialog:: - _handleEdited)); } else { _cssPane->_store->clear(); _cssPane->hide(); } + + _cssPane->_textRenderer->signal_edited().connect(sigc::mem_fun(*this, + &StyleDialog:: + _handleEdited)); + _cssPane->_treeView.signal_button_press_event().connect(sigc::mem_fun + (*this, &StyleDialog:: + _delProperty), + false); + } +} + +/** + * @brief StyleDialog::_selChanged + * When no row in _treeView of Style Dialog is selected, the _cssPane is hidden. + */ +void StyleDialog::_selChanged() { + if (_treeView.get_selection()->count_selected_rows() == 0) { + _cssPane->hide(); } } @@ -762,8 +782,9 @@ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) * @param new_text * This function edits CSS properties of the selector chosen. new_text is used * to update the property in XML repr. The value from selected selector is - * obtained and modified as per value of new_text. Later _updateStyleContent() is - * called to update XML repr and hence changes are reflected in the drawing too. + * obtained and modified as per value of new_text. If a new property is added, + * value is appended with new_text. Later _updateStyleContent() is called to + * update XML repr and hence changes are reflected in the drawing too. */ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) { @@ -774,6 +795,7 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& _cssPane->_editedProp = new_text; } + // Selected selector row is obtained here to get corresponding key and value. Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if (iter) { @@ -797,30 +819,114 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& REMOVE_SPACES(matchSelector); if (key == matchSelector) { - std::stringstream ss(value); - std::string token, editedToken; - std::size_t found = value.find(";"); - if (found!=std::string::npos) { - while(std::getline(ss, token, ';')) { - REMOVE_SPACES(token); - if (!token.empty()) { - if (token.substr(0, token.find(":")) == _cssPane - ->_editedProp.substr(0, _cssPane->_editedProp - .find(":"))) { - editedToken = _cssPane->_editedProp; - size_t startPos = value.find(token); - value.replace(startPos, token.length(), editedToken); - (*it)._xmlContent = key + "{" + value + "}\n"; - _updateStyleContent(); + /** If a new property is added, existing value is appended with new + * property, else replacements in value are done in the 'else' block. + */ + if (_cssPane->_newProperty) { + value.append((new_text + ";").c_str()); + _cssPane->_propCol->add_attribute(_cssPane->_textRenderer + ->property_text(), + _cssPane->_cssColumns + ._propertyLabel); + _cssPane->_newProperty = false; + } + else { + std::stringstream ss(value); + std::string token, editedToken; + std::size_t found = value.find(";"); + if (found!=std::string::npos) { + while(std::getline(ss, token, ';')) { + REMOVE_SPACES(token); + if (!token.empty()) { + if (token.substr(0, token.find(":")) == _cssPane + ->_editedProp.substr(0, _cssPane->_editedProp + .find(":"))) { + editedToken = _cssPane->_editedProp; + size_t startPos = value.find(token); + value.replace(startPos, token.length(), editedToken); + } } } } } + value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); + (*it)._xmlContent = key + "{" + value + "}\n"; + _updateStyleContent(); } } } } + +/** + * @brief StyleDialog::_delProperty + * @param event + * @return + * This function deletes property when '-' in front of property in CSS panel is + * clicked. The property row is deleted from CSS panel and XML repr is updated. + * toDelProperty is the property to be deleted which is looked in 'value' and is + * erased from 'value'. + */ +bool StyleDialog::_delProperty(GdkEventButton *event) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 1) { + Gtk::TreeViewColumn *col = 0; + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + Gtk::TreeModel::Row cssRow; + Glib::ustring toDelProperty; + if (_cssPane->_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { + if (col == _cssPane->_treeView.get_column(0)) { + Gtk::TreeModel::iterator cssIter = _cssPane->_treeView.get_selection() + ->get_selected(); + if (cssIter) { + cssRow = *cssIter; + toDelProperty = cssRow[_cssPane->_cssColumns._propertyLabel]; + } + + Gtk::TreeModel::iterator iter = _treeView.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + std::string sel, key, value; + std::vector::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { + sel = (*it)._xmlContent; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok((char*)sel.c_str(), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + + Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; + std::string matchSelector = selectedRowLabel; + REMOVE_SPACES(matchSelector); + + if (key == matchSelector) { + std::size_t found = value.find(toDelProperty); + if (found!=std::string::npos) { + if (!toDelProperty.empty()) { + value.erase(found, toDelProperty.length()+1); + (*it)._xmlContent = key + "{" + value + "}\n"; + _updateStyleContent(); + } + } + } + } + } + _cssPane->_store->erase(cssRow); + } + } + } + return false; +} + /** * @brief StyleDialog::_selectObjects * @param eventX -- cgit v1.2.3 From eb5f0b5abdd139e2ded503eba6642f18deac2159 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Thu, 4 Aug 2016 11:51:07 +0530 Subject: Solve crash when deleting CSS property (bzr r14949.1.63) --- src/ui/dialog/styledialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 7deac22d8..370b0ab47 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -915,12 +915,12 @@ bool StyleDialog::_delProperty(GdkEventButton *event) value.erase(found, toDelProperty.length()+1); (*it)._xmlContent = key + "{" + value + "}\n"; _updateStyleContent(); + _cssPane->_store->erase(cssRow); } } } } } - _cssPane->_store->erase(cssRow); } } } -- cgit v1.2.3 From 11e0546b1c039fc84c1a0f86a4681df34642916b Mon Sep 17 00:00:00 2001 From: Tavmjong Bah & Kamalpreet Grewal <> Date: Mon, 15 Aug 2016 10:45:09 +0530 Subject: Add changes for compilation with trunk (bzr r14949.1.65) --- src/ui/dialog/styledialog.cpp | 120 ++++++++++++++++++++++-------------------- 1 file changed, 63 insertions(+), 57 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 370b0ab47..e43934c57 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -16,7 +16,8 @@ #include "sp-object.h" #include "selection.h" #include "xml/attribute-record.h" - +#include + using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; @@ -135,8 +136,8 @@ void StyleDialog::setDesktop( SPDesktop* desktop ) { Panel::setDesktop(desktop); _desktop = Panel::getDesktop(); - _desktop->selection->connectChanged(sigc::mem_fun(*this, &StyleDialog:: - _selectRow)); + _desktop->getSelection()->connectChanged(sigc::mem_fun(*this, &StyleDialog:: + _selectRow)); } /** @@ -163,11 +164,15 @@ void StyleDialog::_addSelector() * is(are) selected and user clicks '+' at the bottom of dialog, the * entrybox will have the id(s) of the selected objects as text. */ - if (_desktop->selection->isEmpty()) { + if (_desktop->getSelection()->isEmpty()) { textEditPtr->set_text("Class1"); } else { - std::vector selected = _desktop->getSelection()->list(); + Inkscape::Selection* selection = _desktop->getSelection(); + std::vector selected = std::vector(selection + ->objects().begin(), + selection-> + objects().end()); textEditPtr->set_text(_setClassAttribute(selected)); } @@ -199,14 +204,11 @@ void StyleDialog::_addSelector() * created with an empty value. Also if a class selector is added, then * class attribute for the selected object is set too. */ - SPObject *obj; std::vector objVec; bool objExists = false; - if (!_desktop->getSelection()->list().empty()) { - std::vector selected = _desktop->getSelection()->list(); - for (unsigned i = 0; i < selected.size(); ++i) { - obj = selected.at(i); + if (!_desktop->getSelection()->isEmpty()) { + for (auto& obj: _desktop->getSelection()->objects()) { objExists = true; if (!obj->getRepr()->attribute("style")) { obj->getRepr()->setAttribute("style", NULL); @@ -246,7 +248,10 @@ void StyleDialog::_addSelector() _row[_mColumns._selectorLabel] = _selectorName; _row[_mColumns._colAddRemove] = true; if (objExists) { - _row[_mColumns._colObj] = _desktop->selection->list(); + Inkscape::Selection* selection = _desktop->getSelection(); + _row[_mColumns._colObj] = std::vector(selection->objects() + .begin(), selection + ->objects().end()); objVec = _row[_mColumns._colObj]; } break; @@ -579,56 +584,55 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) * by removing the parent row's class selector name. */ if (!row.parent()) { - if (_desktop->selection) { - std::vectorsel = _desktop->selection->list(); - for (unsigned i = 0; i < sel.size(); ++i) { - SPObject *obj = sel[i]; - std::string childStyle; - if (iter) { - path = _treeView.get_model()->get_path(iter); - if (_selectorVec.size() != 0) { - Gtk::TreeModel::Row childrow; - childrow = *(_store->append(row->children())); - childrow[_mColumns._selectorLabel] = "#" + - std::string(obj->getId()); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = _desktop->selection->list(); - if (obj->getAttribute("style") != NULL) { - childStyle = "#" + std::string(obj->getId()) + "{" + - std::string(obj->getAttribute("style")) + "}\n"; + Inkscape::Selection* selection = _desktop->getSelection(); + std::vector sel = std::vector + (selection->objects().begin(), selection->objects().end()); + for (auto& obj: selection->objects()) { + std::string childStyle; + if (iter) { + path = _treeView.get_model()->get_path(iter); + if (_selectorVec.size() != 0) { + Gtk::TreeModel::Row childrow; + childrow = *(_store->append(row->children())); + childrow[_mColumns._selectorLabel] = "#" + + std::string(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = sel; + if (obj->getAttribute("style") != NULL) { + childStyle = "#" + std::string(obj->getId()) + "{" + + std::string(obj->getAttribute("style")) + "}\n"; + } + else { + childStyle = "#" + std::string(obj->getId()) + + "{" + "}\n"; + } + Glib::ustring key = row[_mColumns._selectorLabel]; + if (key[0] == '.') { + if (!obj->getRepr()->attribute("class")) { + obj->setAttribute("class", key.erase(0,1)); } else { - childStyle = "#" + std::string(obj->getId()) - + "{" + "}\n"; - } - Glib::ustring key = row[_mColumns._selectorLabel]; - if (key[0] == '.') { - if (!obj->getRepr()->attribute("class")) { - obj->setAttribute("class", key.erase(0,1)); - } - else { - obj->setAttribute("class", std::string - (obj->getRepr()-> - attribute("class")) - + " " + key - .erase(0,1)); - } + obj->setAttribute("class", std::string + (obj->getRepr()-> + attribute("class")) + + " " + key + .erase(0,1)); } } } - - inkSelector._selector = obj->getId(); - inkSelector._matchingObjs = sel; - inkSelector._xmlContent = childStyle; - _selectorVec.push_back(inkSelector); - } - if (_styleElementNode()) { - _styleChild = _styleElementNode(); - _updateStyleContent(); - } - else if (_styleExists && !_newDrawing) { - _updateStyleContent(); } + + inkSelector._selector = obj->getId(); + inkSelector._matchingObjs = sel; + inkSelector._xmlContent = childStyle; + _selectorVec.push_back(inkSelector); + } + if (_styleElementNode()) { + _styleChild = _styleElementNode(); + _updateStyleContent(); + } + else if (_styleExists && !_newDrawing) { + _updateStyleContent(); } } @@ -989,8 +993,10 @@ void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) void StyleDialog::_selectRow(Selection */*sel*/) { SPObject *obj = NULL; - if (!_desktop->selection->list().empty()) { - std::vector selected = _desktop->getSelection()->list(); + if (!_desktop->selection->isEmpty()) { + Inkscape::Selection* selection = _desktop->getSelection(); + std::vector selected = std::vector + (selection->objects().begin(), selection->objects().end()); obj = selected.back(); } -- cgit v1.2.3 From be9439742ea5d6924d290fd56849b29cd264b331 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Tue, 16 Aug 2016 21:01:49 +0530 Subject: Solve issue with addition of missing CSS properties (bzr r14949.1.67) --- src/ui/dialog/styledialog.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index e43934c57..bf3562ad3 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -827,12 +827,14 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& * property, else replacements in value are done in the 'else' block. */ if (_cssPane->_newProperty) { - value.append((new_text + ";").c_str()); - _cssPane->_propCol->add_attribute(_cssPane->_textRenderer - ->property_text(), - _cssPane->_cssColumns - ._propertyLabel); - _cssPane->_newProperty = false; + if (!new_text.empty()) { + value.append((new_text + ";").c_str()); + _cssPane->_propCol->add_attribute(_cssPane->_textRenderer + ->property_text(), + _cssPane->_cssColumns + ._propertyLabel); + _cssPane->_newProperty = false; + } } else { std::stringstream ss(value); -- cgit v1.2.3 From 8cb11cfc6b279853dc8cb092bff5595c64f32655 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Wed, 17 Aug 2016 00:21:41 +0530 Subject: Pass tests while adding & removing objects from class selectors (bzr r14949.1.68) --- src/ui/dialog/styledialog.cpp | 49 +++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 16 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index bf3562ad3..cec5d26ca 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -574,6 +574,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) Gtk::TreeModel::iterator iter = refTreeSelection-> get_selected(); Gtk::TreeModel::Row row = *iter; + Glib::ustring selectorName; /** * This adds child rows to selected rows. If the parent row is @@ -607,6 +608,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) + "{" + "}\n"; } Glib::ustring key = row[_mColumns._selectorLabel]; + selectorName = row[_mColumns._selectorLabel]; if (key[0] == '.') { if (!obj->getRepr()->attribute("class")) { obj->setAttribute("class", key.erase(0,1)); @@ -624,7 +626,19 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) inkSelector._selector = obj->getId(); inkSelector._matchingObjs = sel; - inkSelector._xmlContent = childStyle; + + /** + * If the object's parent row is a class selector, then + * there are no changes in style element except the class + * attribute is updated. For the id selector cases, XML + * content's style element is updated. + */ + if (selectorName[0] == '.') { + inkSelector._xmlContent = ""; + } + else { + inkSelector._xmlContent = childStyle; + } _selectorVec.push_back(inkSelector); } if (_styleElementNode()) { @@ -651,23 +665,26 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } } - if (key == row[_mColumns._selectorLabel]) { - Gtk::TreeModel::Row parentRow = *(row.parent()); - Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; - if (parentKey[0] == '.') { - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - std::string classAttr = std::string(obj->getRepr() - ->attribute("class")); - std::size_t found = classAttr.find(parentKey.erase(0,1)); - if (found != std::string::npos) { - classAttr.erase(found, parentKey.length()+1); - obj->getRepr()->setAttribute("class", classAttr); - } + + Gtk::TreeModel::Row parentRow = *(row.parent()); + Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; + + if (key == row[_mColumns._selectorLabel]) { + _selectorVec.erase(it); + } + + if (parentKey[0] == '.') { + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; + std::string classAttr = std::string(obj->getRepr() + ->attribute("class")); + std::size_t found = classAttr.find(parentKey.erase(0,1)); + if (found != std::string::npos) { + classAttr.erase(found, parentKey.length()+1); + obj->getRepr()->setAttribute("class", classAttr); } } - _selectorVec.erase(it); } if (_styleChild) { -- cgit v1.2.3 From 303781617a238c95fe345b22d2a53afb7e8e3cca Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 19 Aug 2016 01:49:57 +0530 Subject: Passing test when adding id selectors (bzr r14949.1.70) --- src/ui/dialog/styledialog.cpp | 289 ++++++++++++++++++++++++------------------ 1 file changed, 163 insertions(+), 126 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index cec5d26ca..e0aeaf09d 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -147,7 +147,7 @@ void StyleDialog::setDesktop( SPDesktop* desktop ) */ void StyleDialog::_addSelector() { - _row = *(_store->append()); + Gtk::TreeModel::Row row = *(_store->append()); /** * On clicking '+' button, an entrybox with default text opens up. If an @@ -245,14 +245,14 @@ void StyleDialog::_addSelector() switch (result) { case Gtk::RESPONSE_OK: textDialogPtr->hide(); - _row[_mColumns._selectorLabel] = _selectorName; - _row[_mColumns._colAddRemove] = true; + row[_mColumns._selectorLabel] = _selectorName; + row[_mColumns._colAddRemove] = true; if (objExists) { Inkscape::Selection* selection = _desktop->getSelection(); - _row[_mColumns._colObj] = std::vector(selection->objects() + row[_mColumns._colObj] = std::vector(selection->objects() .begin(), selection ->objects().end()); - objVec = _row[_mColumns._colObj]; + objVec = row[_mColumns._colObj]; } break; default: @@ -290,6 +290,8 @@ void StyleDialog::_addSelector() Inkscape::GC::release(newChild); _styleChild = newChild; } + +// _selAdd(row); } /** @@ -574,7 +576,6 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) Gtk::TreeModel::iterator iter = refTreeSelection-> get_selected(); Gtk::TreeModel::Row row = *iter; - Glib::ustring selectorName; /** * This adds child rows to selected rows. If the parent row is @@ -585,69 +586,7 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) * by removing the parent row's class selector name. */ if (!row.parent()) { - Inkscape::Selection* selection = _desktop->getSelection(); - std::vector sel = std::vector - (selection->objects().begin(), selection->objects().end()); - for (auto& obj: selection->objects()) { - std::string childStyle; - if (iter) { - path = _treeView.get_model()->get_path(iter); - if (_selectorVec.size() != 0) { - Gtk::TreeModel::Row childrow; - childrow = *(_store->append(row->children())); - childrow[_mColumns._selectorLabel] = "#" + - std::string(obj->getId()); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = sel; - if (obj->getAttribute("style") != NULL) { - childStyle = "#" + std::string(obj->getId()) + "{" + - std::string(obj->getAttribute("style")) + "}\n"; - } - else { - childStyle = "#" + std::string(obj->getId()) - + "{" + "}\n"; - } - Glib::ustring key = row[_mColumns._selectorLabel]; - selectorName = row[_mColumns._selectorLabel]; - if (key[0] == '.') { - if (!obj->getRepr()->attribute("class")) { - obj->setAttribute("class", key.erase(0,1)); - } - else { - obj->setAttribute("class", std::string - (obj->getRepr()-> - attribute("class")) - + " " + key - .erase(0,1)); - } - } - } - } - - inkSelector._selector = obj->getId(); - inkSelector._matchingObjs = sel; - - /** - * If the object's parent row is a class selector, then - * there are no changes in style element except the class - * attribute is updated. For the id selector cases, XML - * content's style element is updated. - */ - if (selectorName[0] == '.') { - inkSelector._xmlContent = ""; - } - else { - inkSelector._xmlContent = childStyle; - } - _selectorVec.push_back(inkSelector); - } - if (_styleElementNode()) { - _styleChild = _styleElementNode(); - _updateStyleContent(); - } - else if (_styleExists && !_newDrawing) { - _updateStyleContent(); - } + _selAdd(row); } else { @@ -664,25 +603,42 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) value = strtok(temp, "}"); } } - } - Gtk::TreeModel::Row parentRow = *(row.parent()); - Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; - - if (key == row[_mColumns._selectorLabel]) { - _selectorVec.erase(it); - } + Gtk::TreeModel::Row parentRow = *(row.parent()); + Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; + + if (key[0] == '#') { + std::string s = parentKey; + Glib::ustring toDelRow = row[_mColumns._selectorLabel]; + std::string toDelKey = toDelRow; + std::size_t idFound = s.find(toDelKey); + if (idFound != std::string::npos) { + if (idFound == 0) { + s.erase(idFound, toDelKey.length()+1); + parentKey = s; + parentRow[_mColumns._selectorLabel] = parentKey; + (*it)._xmlContent.erase(idFound, toDelKey.length()); + } + else { + s.erase(idFound-2, toDelKey.length()+2); + parentKey = s; + parentRow[_mColumns._selectorLabel] = parentKey; + (*it)._xmlContent.erase(idFound-2, toDelKey.length()+2); + } + } + } - if (parentKey[0] == '.') { - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - std::string classAttr = std::string(obj->getRepr() - ->attribute("class")); - std::size_t found = classAttr.find(parentKey.erase(0,1)); - if (found != std::string::npos) { - classAttr.erase(found, parentKey.length()+1); - obj->getRepr()->setAttribute("class", classAttr); + if (parentKey[0] == '.') { + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; + std::string classAttr = std::string(obj->getRepr() + ->attribute("class")); + std::size_t found = classAttr.find(parentKey.erase(0,1)); + if (found != std::string::npos) { + classAttr.erase(found, parentKey.length()+1); + obj->getRepr()->setAttribute("class", classAttr); + } } } } @@ -702,6 +658,87 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) return false; } +void StyleDialog::_selAdd(Gtk::TreeModel::Row row) +{ + Glib::ustring selectorName; + Gtk::TreeModel::Row childrow; + Inkscape::Selection* selection = _desktop->getSelection(); + std::vector sel = std::vector + (selection->objects().begin(), selection->objects().end()); + for (auto& obj: selection->objects()) { + if (*row) { + if (_selectorVec.size() != 0) { + childrow = *(_store->append(row->children())); + childrow[_mColumns._selectorLabel] = "#" + + std::string(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = sel; + Glib::ustring key = row[_mColumns._selectorLabel]; + if (key[0] == '.') { + if (!obj->getRepr()->attribute("class")) { + obj->setAttribute("class", key.erase(0,1)); + } + else { + obj->setAttribute("class", std::string + (obj->getRepr()-> + attribute("class")) + + " " + key + .erase(0,1)); + } + } + } + selectorName = row[_mColumns._selectorLabel]; + } + + /** + * If the object's parent row is a class selector, then + * there are no changes in style element except the class + * attribute is updated. For the id selector cases, XML + * content's style element is updated. + */ + REMOVE_SPACES(selectorName); + std::vector::iterator it; + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { + std::string sel, key, value; + sel = (*it)._xmlContent; + REMOVE_SPACES(sel); + if (!sel.empty()) { + key = strtok((char*)sel.c_str(), "{"); + REMOVE_SPACES(key); + char *temp = strtok(NULL, "}"); + if (strtok(temp, "}") != NULL) { + value = strtok(temp, "}"); + } + } + + REMOVE_SPACES((*it)._selector); + if ("#" + std::string(obj->getId()) != selectorName) { + inkSelector._selector = (*it)._selector; + inkSelector._selector.append(", #" + std::string(obj->getId())); + } + + inkSelector._xmlContent = inkSelector._selector + "{" + value + "}"; + if (selectorName != childrow[_mColumns._selectorLabel]) { + row[_mColumns._selectorLabel] = selectorName + ", " + + childrow[_mColumns._selectorLabel]; + } + it = _selectorVec.erase(it); + it = _selectorVec.insert(it, inkSelector); + } + +// if (selectorName[0] == '.') { +// inkSelector._xmlContent = ""; +// } + } + if (_styleElementNode()) { + _styleChild = _styleElementNode(); + _updateStyleContent(); + } + else if (_styleExists && !_newDrawing) { + _updateStyleContent(); + } +} + /** * @brief StyleDialog::_selectObjects * @param event @@ -839,43 +876,43 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& std::string matchSelector = selectedRowLabel; REMOVE_SPACES(matchSelector); - if (key == matchSelector) { +// if (key == matchSelector) { /** If a new property is added, existing value is appended with new * property, else replacements in value are done in the 'else' block. */ - if (_cssPane->_newProperty) { - if (!new_text.empty()) { - value.append((new_text + ";").c_str()); - _cssPane->_propCol->add_attribute(_cssPane->_textRenderer - ->property_text(), - _cssPane->_cssColumns - ._propertyLabel); - _cssPane->_newProperty = false; - } + if (_cssPane->_newProperty) { + if (!new_text.empty()) { + value.append((new_text + ";").c_str()); + _cssPane->_propCol->add_attribute(_cssPane->_textRenderer + ->property_text(), + _cssPane->_cssColumns + ._propertyLabel); + _cssPane->_newProperty = false; } - else { - std::stringstream ss(value); - std::string token, editedToken; - std::size_t found = value.find(";"); - if (found!=std::string::npos) { - while(std::getline(ss, token, ';')) { - REMOVE_SPACES(token); - if (!token.empty()) { - if (token.substr(0, token.find(":")) == _cssPane - ->_editedProp.substr(0, _cssPane->_editedProp - .find(":"))) { - editedToken = _cssPane->_editedProp; - size_t startPos = value.find(token); - value.replace(startPos, token.length(), editedToken); - } + } + else { + std::stringstream ss(value); + std::string token, editedToken; + std::size_t found = value.find(";"); + if (found!=std::string::npos) { + while(std::getline(ss, token, ';')) { + REMOVE_SPACES(token); + if (!token.empty()) { + if (token.substr(0, token.find(":")) == _cssPane + ->_editedProp.substr(0, _cssPane->_editedProp + .find(":"))) { + editedToken = _cssPane->_editedProp; + size_t startPos = value.find(token); + value.replace(startPos, token.length(), editedToken); } } } } - value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); - (*it)._xmlContent = key + "{" + value + "}\n"; - _updateStyleContent(); } + value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); + (*it)._xmlContent = key + "{" + value + "}\n"; + _updateStyleContent(); +// } } } } @@ -1040,18 +1077,18 @@ void StyleDialog::_selectRow(Selection */*sel*/) } } - if (row.children()) { - for(Gtk::TreeModel::Children::iterator it = row.children().begin(); - it != row.children().end(); ++it) { - childRow = *it; - childObjVec = childRow[_mColumns._colObj]; - } - for (unsigned j = 0; j < childObjVec.size(); ++j) { - if (obj->getId() == childObjVec[j]->getId()) { - _treeView.get_selection()->select(childRow); - } - } - } +// if (row.children()) { +// for(Gtk::TreeModel::Children::iterator it = row.children().begin(); +// it != row.children().end(); ++it) { +// childRow = *it; +// childObjVec = childRow[_mColumns._colObj]; +// } +// for (unsigned j = 0; j < childObjVec.size(); ++j) { +// if (obj->getId() == childObjVec[j]->getId()) { +// _treeView.get_selection()->select(childRow); +// } +// } +// } } } else { -- cgit v1.2.3 From 8c41342f5523120bd50ba3c39e11a67e31e90835 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 19 Aug 2016 01:55:57 +0530 Subject: Uncommenting for editing CSS properties (bzr r14949.1.71) --- src/ui/dialog/styledialog.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index e0aeaf09d..fa092a602 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -876,7 +876,7 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& std::string matchSelector = selectedRowLabel; REMOVE_SPACES(matchSelector); -// if (key == matchSelector) { + if (key == matchSelector) { /** If a new property is added, existing value is appended with new * property, else replacements in value are done in the 'else' block. */ @@ -912,7 +912,7 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); (*it)._xmlContent = key + "{" + value + "}\n"; _updateStyleContent(); -// } + } } } } -- cgit v1.2.3 From 43d547744d82337cb375c789083333a18cb74c86 Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 19 Aug 2016 13:07:39 +0530 Subject: Complete passing of test to add ID selectors (bzr r14949.1.73) --- src/ui/dialog/styledialog.cpp | 116 ++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 61 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index fa092a602..e9b00bf1c 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -291,7 +291,7 @@ void StyleDialog::_addSelector() _styleChild = newChild; } -// _selAdd(row); + _selAdd(row); } /** @@ -340,32 +340,6 @@ void StyleDialog::_delSelector() std::string matchSelector = selectedRowLabel; REMOVE_SPACES(matchSelector); if (key == matchSelector) { - if (!row.children().empty()) { - for (Gtk::TreeModel::Children::iterator child = row.children().begin(); - child != row.children().end(); ++child) { - Gtk::TreeModel::Row childrow = *child; - std::string childSel, childKey; - std::vector::iterator i; - for (i = _selectorVec.begin(); i != _selectorVec.end();) { - childSel = (*i)._xmlContent; - REMOVE_SPACES(childSel); - if (!childSel.empty()) { - childKey = strtok((char*)childSel.c_str(), "{"); - REMOVE_SPACES(childKey); - } - Glib::ustring selectedChildRowLabel = - childrow[_mColumns._selectorLabel]; - std::string matchChildSelector = selectedChildRowLabel; - REMOVE_SPACES(matchChildSelector); - if (childKey == matchChildSelector) { - i = _selectorVec.erase(i); - } - else { - ++i; - } - } - } - } it = _selectorVec.erase(it); _store->erase(row); } @@ -380,7 +354,7 @@ void StyleDialog::_delSelector() * the content is updated simply using _updateStyleContent(). */ _styleChild = _styleElementNode(); - if (_selectorVec.size() == 0) { + if (_store->children().empty()) { _document->getReprRoot()->removeChild(_styleChild); _styleExists = false; } @@ -592,7 +566,10 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) else { std::string sel, key, value; std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it ) { + Gtk::TreeModel::Row parentRow = *(row).parent(); + Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; + + for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { sel = (*it)._xmlContent; REMOVE_SPACES(sel); if (!sel.empty()) { @@ -604,26 +581,28 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } - Gtk::TreeModel::Row parentRow = *(row.parent()); - Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; - - if (key[0] == '#') { - std::string s = parentKey; - Glib::ustring toDelRow = row[_mColumns._selectorLabel]; - std::string toDelKey = toDelRow; - std::size_t idFound = s.find(toDelKey); - if (idFound != std::string::npos) { - if (idFound == 0) { - s.erase(idFound, toDelKey.length()+1); - parentKey = s; - parentRow[_mColumns._selectorLabel] = parentKey; - (*it)._xmlContent.erase(idFound, toDelKey.length()); - } - else { - s.erase(idFound-2, toDelKey.length()+2); - parentKey = s; - parentRow[_mColumns._selectorLabel] = parentKey; - (*it)._xmlContent.erase(idFound-2, toDelKey.length()+2); + std::string matchSelector = parentKey; + REMOVE_SPACES(matchSelector); + if (key == matchSelector) { + if (key[0] == '#') { + std::string s = parentKey; + Glib::ustring toDelRow = row[_mColumns._selectorLabel]; + std::string toDelKey = toDelRow; + std::size_t idFound = s.find(toDelKey); + if (idFound != std::string::npos) { + if (idFound == 0) { + s.erase(idFound, toDelKey.length()+1); + parentKey = s; + parentRow[_mColumns._selectorLabel] = parentKey; + (*it)._xmlContent.erase(idFound, toDelKey.length()); + } + else { + s.erase(idFound-2, toDelKey.length()+2); + parentKey = s; + parentRow[_mColumns._selectorLabel] = parentKey; + (*it)._xmlContent.erase(idFound-2, toDelKey. + length()+2); + } } } } @@ -641,6 +620,10 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } } + + if (parentKey.empty()) { + (*it)._xmlContent = ""; + } } if (_styleChild) { @@ -650,7 +633,16 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) _styleChild = _styleElementNode(); _updateStyleContent(); } + _store->erase(row); + if (parentKey.empty()) { + _store->erase(parentRow); + } + + if (parentKey.empty() && _store->children().empty()) { + _document->getReprRoot()->removeChild(_styleChild); + _styleExists = false; + } } } } @@ -711,19 +703,21 @@ void StyleDialog::_selAdd(Gtk::TreeModel::Row row) } } - REMOVE_SPACES((*it)._selector); - if ("#" + std::string(obj->getId()) != selectorName) { - inkSelector._selector = (*it)._selector; - inkSelector._selector.append(", #" + std::string(obj->getId())); - } - - inkSelector._xmlContent = inkSelector._selector + "{" + value + "}"; - if (selectorName != childrow[_mColumns._selectorLabel]) { - row[_mColumns._selectorLabel] = selectorName + ", " + - childrow[_mColumns._selectorLabel]; + Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; + std::string matchSelector = selectedRowLabel; + REMOVE_SPACES(matchSelector); + if (key == matchSelector) { + REMOVE_SPACES((*it)._selector); + if ("#" + std::string(obj->getId()) != selectorName) { + inkSelector._selector = (*it)._selector; + inkSelector._selector.append(", #" + std::string(obj->getId())); + inkSelector._xmlContent = inkSelector._selector + "{" + value + "}\n"; + row[_mColumns._selectorLabel] = selectorName + ", " + + childrow[_mColumns._selectorLabel]; + } + it = _selectorVec.erase(it); + it = _selectorVec.insert(it, inkSelector); } - it = _selectorVec.erase(it); - it = _selectorVec.insert(it, inkSelector); } // if (selectorName[0] == '.') { -- cgit v1.2.3 From 0cb42f2ea44a9d5da0c3a3ff5cca6fa82511d81b Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Fri, 19 Aug 2016 13:23:45 +0530 Subject: Pass remaining simple class selector tests (bzr r14949.1.74) --- src/ui/dialog/styledialog.cpp | 35 ++++++++++++++++++++--------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index e9b00bf1c..878ab1926 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -671,11 +671,14 @@ void StyleDialog::_selAdd(Gtk::TreeModel::Row row) obj->setAttribute("class", key.erase(0,1)); } else { - obj->setAttribute("class", std::string - (obj->getRepr()-> - attribute("class")) - + " " + key - .erase(0,1)); + if (obj->getRepr()->attribute("class") != key + .erase(0,1)) { + obj->setAttribute("class", std::string + (obj->getRepr()-> + attribute("class")) + + " " + key + .erase(0,1)); + } } } } @@ -708,21 +711,23 @@ void StyleDialog::_selAdd(Gtk::TreeModel::Row row) REMOVE_SPACES(matchSelector); if (key == matchSelector) { REMOVE_SPACES((*it)._selector); - if ("#" + std::string(obj->getId()) != selectorName) { - inkSelector._selector = (*it)._selector; - inkSelector._selector.append(", #" + std::string(obj->getId())); - inkSelector._xmlContent = inkSelector._selector + "{" + value + "}\n"; - row[_mColumns._selectorLabel] = selectorName + ", " + - childrow[_mColumns._selectorLabel]; + if (selectorName[0] == '#') { + if ("#" + std::string(obj->getId()) != selectorName) { + inkSelector._selector = (*it)._selector; + inkSelector._selector.append(", #" + std::string(obj->getId())); + inkSelector._xmlContent = inkSelector._selector + "{" + value + "}\n"; + row[_mColumns._selectorLabel] = selectorName + ", " + + childrow[_mColumns._selectorLabel]; + } + } + else if (selectorName[0] == '.') { + inkSelector._xmlContent = (*it)._selector + "{" + value + "}\n"; } + it = _selectorVec.erase(it); it = _selectorVec.insert(it, inkSelector); } } - -// if (selectorName[0] == '.') { -// inkSelector._xmlContent = ""; -// } } if (_styleElementNode()) { _styleChild = _styleElementNode(); -- cgit v1.2.3 From bb2023c0d4971e15f12394b85dc52b8ae49225eb Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sat, 20 Aug 2016 12:39:45 +0530 Subject: Add some more comments to improve code understanding (bzr r14949.1.75) --- src/ui/dialog/styledialog.cpp | 116 ++++++++++++++++++++++++------------------ 1 file changed, 66 insertions(+), 50 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 878ab1926..5246290b4 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -21,6 +21,10 @@ using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; +/** + * This macro is used to remove spaces around selectors or any strings when + * parsing is done to update XML style element or row labels in this dialog. + */ #define REMOVE_SPACES(x) x.erase(0, x.find_first_not_of(' ')); \ x.erase(x.find_last_not_of(' ') + 1); @@ -48,7 +52,8 @@ void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, /** * Constructor * A treeview and a set of two buttons are added to the dialog. _addSelector - * adds selectors to treeview. Currently, delete button is disabled. + * adds selectors to treeview. _delSelector deletes the selector from the dialog. + * Any addition/deletion of the selectors updates XML style element accordingly. */ StyleDialog::StyleDialog() : UI::Widget::Panel("", "/dialogs/style", SP_VERB_DIALOG_STYLE), @@ -127,11 +132,20 @@ StyleDialog::StyleDialog() : _selChanged)); } +/** + * @brief StyleDialog::~StyleDialog + * Class destructor + */ StyleDialog::~StyleDialog() { setDesktop(NULL); } +/** + * @brief StyleDialog::setDesktop + * @param desktop + * This function sets the 'desktop' for the Style Dialog. + */ void StyleDialog::setDesktop( SPDesktop* desktop ) { Panel::setDesktop(desktop); @@ -182,10 +196,9 @@ void StyleDialog::_addSelector() /** * @brief selectorName - * This string stores selector name. If '#' or a '.' is present in the - * beginning of string, text from entrybox is saved directly as name for - * selector. If text like 'red' is written in entrybox, it is prefixed - * with a dot. + * This string stores selector name. The text from entrybox is saved as name + * for selector. If the entrybox is empty, the text (thus selectorName) is + * set to ".Class1" */ if (!textEditPtr->get_text().empty()) { _selectorName = textEditPtr->get_text(); @@ -290,7 +303,6 @@ void StyleDialog::_addSelector() Inkscape::GC::release(newChild); _styleChild = newChild; } - _selAdd(row); } @@ -581,6 +593,12 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } } + /** + * @brief matchSelector + * For id selectors, whenever any child row is deleted, + * the row label is updated and so is the entry for the + * selector in style element. + */ std::string matchSelector = parentKey; REMOVE_SPACES(matchSelector); if (key == matchSelector) { @@ -635,6 +653,15 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) } _store->erase(row); + + /** + * On continuous deletion of objects (child rows) from the + * selector (parent row), if the parent row has no child, then + * the row is erased from the _store. Further if there is no + * row left in _store, which implies there is no content in + * XML style element, then the 'svg:style' element is also + * removed. + */ if (parentKey.empty()) { _store->erase(parentRow); } @@ -650,6 +677,12 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) return false; } +/** + * @brief StyleDialog::_selAdd + * @param row + * This routine is called when an object is added to a selector by clicking on + * '+' in front of the row with selector's label. + */ void StyleDialog::_selAdd(Gtk::TreeModel::Row row) { Glib::ustring selectorName; @@ -879,44 +912,43 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& /** If a new property is added, existing value is appended with new * property, else replacements in value are done in the 'else' block. */ - if (_cssPane->_newProperty) { - if (!new_text.empty()) { - value.append((new_text + ";").c_str()); - _cssPane->_propCol->add_attribute(_cssPane->_textRenderer - ->property_text(), - _cssPane->_cssColumns - ._propertyLabel); - _cssPane->_newProperty = false; + if (_cssPane->_newProperty) { + if (!new_text.empty()) { + value.append((new_text + ";").c_str()); + _cssPane->_propCol->add_attribute(_cssPane->_textRenderer + ->property_text(), + _cssPane->_cssColumns + ._propertyLabel); + _cssPane->_newProperty = false; + } } - } - else { - std::stringstream ss(value); - std::string token, editedToken; - std::size_t found = value.find(";"); - if (found!=std::string::npos) { - while(std::getline(ss, token, ';')) { - REMOVE_SPACES(token); - if (!token.empty()) { - if (token.substr(0, token.find(":")) == _cssPane - ->_editedProp.substr(0, _cssPane->_editedProp - .find(":"))) { - editedToken = _cssPane->_editedProp; - size_t startPos = value.find(token); - value.replace(startPos, token.length(), editedToken); + else { + std::stringstream ss(value); + std::string token, editedToken; + std::size_t found = value.find(";"); + if (found!=std::string::npos) { + while(std::getline(ss, token, ';')) { + REMOVE_SPACES(token); + if (!token.empty()) { + if (token.substr(0, token.find(":")) == _cssPane + ->_editedProp.substr(0, _cssPane->_editedProp + .find(":"))) { + editedToken = _cssPane->_editedProp; + size_t startPos = value.find(token); + value.replace(startPos, token.length(), editedToken); + } } } } } - } - value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); - (*it)._xmlContent = key + "{" + value + "}\n"; - _updateStyleContent(); + value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); + (*it)._xmlContent = key + "{" + value + "}\n"; + _updateStyleContent(); } } } } - /** * @brief StyleDialog::_delProperty * @param event @@ -1067,27 +1099,11 @@ void StyleDialog::_selectRow(Selection */*sel*/) iter != children.end(); ++iter) { Gtk::TreeModel::Row row = *iter; std::vector objVec = row[_mColumns._colObj]; - std::vector childObjVec; - Gtk::TreeModel::Row childRow; - for (unsigned i = 0; i < objVec.size(); ++i) { if (obj->getId() == objVec[i]->getId()) { _treeView.get_selection()->select(row); } } - -// if (row.children()) { -// for(Gtk::TreeModel::Children::iterator it = row.children().begin(); -// it != row.children().end(); ++it) { -// childRow = *it; -// childObjVec = childRow[_mColumns._colObj]; -// } -// for (unsigned j = 0; j < childObjVec.size(); ++j) { -// if (obj->getId() == childObjVec[j]->getId()) { -// _treeView.get_selection()->select(childRow); -// } -// } -// } } } else { -- cgit v1.2.3 From ddb9f75a21c83c5979e467c5adf1b8a7cdf7b98e Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 8 Feb 2017 10:36:56 +0100 Subject: Allow dialog to be resizable. (Fixed inheritance.) Also basic housekeeping. (bzr r15496) --- src/ui/dialog/styledialog.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 5246290b4..8d56e10e7 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -1114,3 +1114,14 @@ void StyleDialog::_selectRow(Selection */*sel*/) } // namespace Dialog } // namespace UI } // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 116c4c4853a080ff7210de2d4e999959c0c0e0ce Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 8 Feb 2017 13:09:58 +0100 Subject: Add naive selector validation on entry in style dialog. (bzr r15497) --- src/ui/dialog/styledialog.cpp | 64 +++++++++++++++++++++++++++---------------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 8d56e10e7..7b68cfe53 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -16,8 +16,11 @@ #include "sp-object.h" #include "selection.h" #include "xml/attribute-record.h" +#include "attribute-rel-svg.h" + +#include #include - + using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; @@ -169,45 +172,60 @@ void StyleDialog::_addSelector() * is added to a new style element. */ Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); - Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); textDialogPtr->add_button("Add", Gtk::RESPONSE_OK); + + Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); textDialogPtr->get_vbox()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); + Gtk::Label *textLabelPtr = manage ( new Gtk::Label( + _("Invalid entry: Not an id (#), class (.), or element CSS selector.") + ) ); + textDialogPtr->get_vbox()->pack_start(*textLabelPtr, Gtk::PACK_SHRINK); + /** * By default, the entrybox contains 'Class1' as text. However, if object(s) * is(are) selected and user clicks '+' at the bottom of dialog, the * entrybox will have the id(s) of the selected objects as text. */ if (_desktop->getSelection()->isEmpty()) { - textEditPtr->set_text("Class1"); - } - else { + textEditPtr->set_text(".Class1"); + } else { Inkscape::Selection* selection = _desktop->getSelection(); - std::vector selected = std::vector(selection - ->objects().begin(), - selection-> - objects().end()); + std::vector selected = + std::vector(selection->objects().begin(), + selection->objects().end()); textEditPtr->set_text(_setClassAttribute(selected)); } textDialogPtr->set_size_request(200, 100); - textDialogPtr->show_all(); - int result = textDialogPtr->run(); + textEditPtr->show(); + textLabelPtr->hide(); + textDialogPtr->show(); - /** - * @brief selectorName - * This string stores selector name. The text from entrybox is saved as name - * for selector. If the entrybox is empty, the text (thus selectorName) is - * set to ".Class1" - */ - if (!textEditPtr->get_text().empty()) { + int result = -1; + bool invalid = true; + + while (invalid) { + result = textDialogPtr->run(); + + /** + * @brief selectorName + * This string stores selector name. The text from entrybox is saved as name + * for selector. If the entrybox is empty, the text (thus selectorName) is + * set to ".Class1" + */ _selectorName = textEditPtr->get_text(); - } - else { - _selectorName = ".Class1"; - } - del->set_sensitive(true); + del->set_sensitive(true); + + if (_selectorName[0] == '.' || + _selectorName[0] == '#' || + SPAttributeRelSVG::isSVGElement( _selectorName ) ) { + invalid = false; + } else { + textLabelPtr->show(); + } + } /** * The selector name objects is set to the text that the user sets in the -- cgit v1.2.3 From db37e627f21d79c6968f681725c7a4dd8de21081 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Tue, 14 Feb 2017 16:39:13 +0100 Subject: Rewrite and cleanup of style dialog. Still WIP. Missing undo and document tracking. (bzr r15520) --- src/ui/dialog/styledialog.cpp | 1529 +++++++++++++++++++---------------------- 1 file changed, 691 insertions(+), 838 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 7b68cfe53..581911a1b 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -3,8 +3,10 @@ */ /* Authors: * Kamalpreet Kaur Grewal + * Tavmjong Bah * * Copyright (C) Kamalpreet Kaur Grewal 2016 + * Copyright (C) Tavmjong Bah 2017 * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -21,6 +23,8 @@ #include #include +//#define DEBUG_STYLEDIALOG + using Inkscape::Util::List; using Inkscape::XML::AttributeRecord; @@ -35,22 +39,6 @@ namespace Inkscape { namespace UI { namespace Dialog { -/** - * @brief StyleDialog::_styleButton - * @param btn - * @param iconName - * @param tooltip - * This function sets the style of '+' and '-' buttons at the bottom of dialog. - */ -void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, - char const* tooltip) -{ - GtkWidget *child = sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName); - gtk_widget_show(child); - btn.add(*manage(Glib::wrap(child))); - btn.set_relief(Gtk::RELIEF_NONE); - btn.set_tooltip_text (tooltip); -} /** * Constructor @@ -60,42 +48,39 @@ void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, */ StyleDialog::StyleDialog() : UI::Widget::Panel("", "/dialogs/style", SP_VERB_DIALOG_STYLE), - _desktop(0) + _desktop(0), + _updating(false) { - set_size_request(200, 200); - - _paned.pack1(_mainBox, Gtk::SHRINK); - _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); - _treeView.set_headers_visible(false); - _scrolledWindow.add(_treeView); - _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - - _store = Gtk::TreeStore::create(_mColumns); - _treeView.set_model(_store); + // Tree Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon() ); addRenderer->property_active() = true; + _store = Gtk::TreeStore::create(_mColumns); + _treeView.set_model(_store); + _treeView.set_headers_visible(false); int addCol = _treeView.append_column("type", *addRenderer) - 1; - Gtk::TreeViewColumn *col = _treeView.get_column(addCol); if ( col ) { col->add_attribute( addRenderer->property_active(), _mColumns._colAddRemove ); } - - _treeView.append_column("Selector Name", _mColumns._selectorLabel); + _treeView.append_column("Selector Name", _mColumns._colSelector); _treeView.set_expander_column(*(_treeView.get_column(1))); + + // Pack widgets + _paned.pack1(_mainBox, Gtk::SHRINK); + _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); + _scrolledWindow.add(_treeView); + _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); create = manage( new Gtk::Button() ); _styleButton(*create, "list-add", "Add a new CSS Selector"); - create->signal_clicked().connect(sigc::mem_fun(*this, - &StyleDialog::_addSelector)); + create->signal_clicked().connect(sigc::mem_fun(*this, &StyleDialog::_addSelector)); del = manage( new Gtk::Button() ); _styleButton(*del, "list-remove", "Remove a CSS Selector"); - del->signal_clicked().connect(sigc::mem_fun(*this, - &StyleDialog::_delSelector)); + del->signal_clicked().connect(sigc::mem_fun(*this, &StyleDialog::_delSelector)); del->set_sensitive(false); _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); @@ -105,8 +90,40 @@ StyleDialog::StyleDialog() : _getContents()->pack_start(_paned, Gtk::PACK_EXPAND_WIDGET); - _targetDesktop = getDesktop(); - setDesktop(_targetDesktop); + // Dialog size request + Gtk::Requisition sreq1, sreq2; + get_preferred_size(sreq1, sreq2); + int minWidth = 200; + int minHeight = 300; + minWidth = (sreq2.width > minWidth ? sreq2.width : minWidth ); + minHeight = (sreq2.height > minHeight ? sreq2.height : minHeight); + set_size_request(minWidth, minHeight); + + // Signal handlers + _treeView.signal_button_release_event().connect( // Needs to be release, not press. + sigc::mem_fun(*this, &StyleDialog::_handleButtonEvent), + false); + + _treeView.signal_button_release_event().connect_notify( + sigc::mem_fun(*this, &StyleDialog::_buttonEventsSelectObjs), + false); + + _treeView.get_selection()->signal_changed().connect( + sigc::mem_fun(*this, &StyleDialog::_selChanged)); + + // Add CSS dialog + _cssPane = new CssDialog; + _paned.pack2(*_cssPane, Gtk::SHRINK); + _cssPane->show_all(); + + _cssPane->_textRenderer->signal_edited().connect( + sigc::mem_fun(*this, &StyleDialog::_handleEdited)); + _cssPane->_treeView.signal_button_release_event().connect( + sigc::mem_fun(*this, &StyleDialog::_delProperty), + false); + + // Document & Desktop TO DO: Fix this brokeness + setDesktop(getDesktop()); // Adds signal handler /** * @brief document @@ -114,27 +131,17 @@ StyleDialog::StyleDialog() : * and is then used to populate the treeview with the already existing * selectors in the style element. */ - _styleExists = false; - _document = _targetDesktop->doc(); - _selectorValue = _populateTree(_getSelectorVec()); + _document = _desktop->doc(); - _treeView.signal_button_press_event().connect(sigc::mem_fun(*this, - &StyleDialog:: - _handleButtonEvent), - false); + _readStyleElement(); - _treeView.signal_button_press_event().connect_notify(sigc::mem_fun - (*this, &StyleDialog:: - _buttonEventsSelectObjs), - false); - - _cssPane = new CssDialog; + if (!_store->children().empty()) { + del->set_sensitive(true); + } - _treeView.get_selection()->signal_changed().connect(sigc::mem_fun(*this, - &StyleDialog:: - _selChanged)); } + /** * @brief StyleDialog::~StyleDialog * Class destructor @@ -144,429 +151,619 @@ StyleDialog::~StyleDialog() setDesktop(NULL); } + /** * @brief StyleDialog::setDesktop * @param desktop - * This function sets the 'desktop' for the Style Dialog. + * Set the 'desktop' for the Style Dialog. */ void StyleDialog::setDesktop( SPDesktop* desktop ) { +#ifdef DEBUG_STYLEDIALOOG + std::cout << "StyleDialog::setDesktop" << std::endl; +#endif Panel::setDesktop(desktop); _desktop = Panel::getDesktop(); - _desktop->getSelection()->connectChanged(sigc::mem_fun(*this, &StyleDialog:: - _selectRow)); + _desktop->getSelection()->connectChanged(sigc::mem_fun(*this, &StyleDialog::_selectRow)); } + /** - * @brief StyleDialog::_addSelector - * This function is the slot to the signal emitted when '+' at the bottom of - * the dialog is clicked. + * @brief StyleDialog::_styleTextNode + * @return Inkscape::XML::Node* pointing to a style element's text node. + * Returns the style element's text node. If there is no style element, one is created. + * Ditto for text node. */ -void StyleDialog::_addSelector() +Inkscape::XML::Node* StyleDialog::_getStyleTextNode() { - Gtk::TreeModel::Row row = *(_store->append()); + Inkscape::XML::Node *root = _document->getReprRoot(); + for (unsigned i = 0; i < root->childCount(); ++i) { + if (Glib::ustring(root->nthChild(i)->name()) == "svg:style") { + Inkscape::XML::Node * styleNode = root->nthChild(i); + + for (unsigned j = 0; j < styleNode->childCount(); ++j) { + if (styleNode->nthChild(j)->type() == Inkscape::XML::TEXT_NODE) { + return styleNode->nthChild(j); + } + } - /** - * On clicking '+' button, an entrybox with default text opens up. If an - * object is already selected, a selector with value in the entry - * is added to a new style element. - */ - Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); - textDialogPtr->add_button("Add", Gtk::RESPONSE_OK); + // Style element found but does not contain text node! + std::cerr << "StyleDialog::_getStyleTextNode(): No text node!" << std::endl; + Inkscape::XML::Node *textNode = _document->getReprDoc()->createTextNode(""); + styleNode->appendChild(textNode); + Inkscape::GC::release(textNode); - Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); - textDialogPtr->get_vbox()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); + return textNode; + } + } - Gtk::Label *textLabelPtr = manage ( new Gtk::Label( - _("Invalid entry: Not an id (#), class (.), or element CSS selector.") - ) ); - textDialogPtr->get_vbox()->pack_start(*textLabelPtr, Gtk::PACK_SHRINK); + // Style element not found, create one + Inkscape::XML::Node *styleNode = _document->getReprDoc()->createElement("svg:style"); + Inkscape::XML::Node *textNode = _document->getReprDoc()->createTextNode(""); - /** - * By default, the entrybox contains 'Class1' as text. However, if object(s) - * is(are) selected and user clicks '+' at the bottom of dialog, the - * entrybox will have the id(s) of the selected objects as text. - */ - if (_desktop->getSelection()->isEmpty()) { - textEditPtr->set_text(".Class1"); - } else { - Inkscape::Selection* selection = _desktop->getSelection(); - std::vector selected = - std::vector(selection->objects().begin(), - selection->objects().end()); - textEditPtr->set_text(_setClassAttribute(selected)); - } + styleNode->appendChild(textNode); + Inkscape::GC::release(textNode); - textDialogPtr->set_size_request(200, 100); - textEditPtr->show(); - textLabelPtr->hide(); - textDialogPtr->show(); + root->addChild(styleNode, NULL); + Inkscape::GC::release(styleNode); - int result = -1; - bool invalid = true; + return textNode; +} + + +/** + * @brief StyleDialog::_readStyleElement + * @return selVec + * Fill the Gtk::TreeStore from the svg:style element. + */ +void StyleDialog::_readStyleElement() +{ + + Inkscape::XML::Node * textNode = _getStyleTextNode(); + if (textNode == NULL) { + std::cerr << "StyleDialog::_readStyleElement: No text node!" << std::endl; + } + + // Get content from style text node. + std::string content = (textNode->content() ? textNode->content() : ""); - while (invalid) { - result = textDialogPtr->run(); + // 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 regex1 = + // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}"); + // + // Glib::MatchInfo minfo; + // regex1->match(content, minfo); + + // Split on curly brackets. Even tokens are selectors, odd are values. + std::vector tokens = Glib::Regex::split_simple("[}{]", content); + + // If text node is empty, return (avoids problem with negative below). + if (tokens.size() == 0) { + return; + } - /** - * @brief selectorName - * This string stores selector name. The text from entrybox is saved as name - * for selector. If the entrybox is empty, the text (thus selectorName) is - * set to ".Class1" - */ - _selectorName = textEditPtr->get_text(); + for (unsigned i = 0; i < tokens.size()-1; i += 2) { - del->set_sensitive(true); + Glib::ustring selector = tokens[i]; + REMOVE_SPACES(selector); // Remove leading/trailing spaces - if (_selectorName[0] == '.' || - _selectorName[0] == '#' || - SPAttributeRelSVG::isSVGElement( _selectorName ) ) { - invalid = false; + // Get list of objects selector matches + std::vector objVec = _getObjVec( selector ); + + Glib::ustring properties; + // Check to make sure we do have a value to match selector. + if ((i+1) < tokens.size()) { + properties = tokens[i+1]; } else { - textLabelPtr->show(); + std::cerr << "StyleDialog::_readStyleElement: Missing values " + "for last selector!" << std::endl; + } + REMOVE_SPACES(properties); + + Gtk::TreeModel::Row row = *(_store->append()); + row[_mColumns._colSelector] = selector; + row[_mColumns._colAddRemove] = true; + row[_mColumns._colObj] = objVec; + row[_mColumns._colProperties] = properties; + + // Add as children, objects that match selector. + for (auto& obj: objVec) { + Gtk::TreeModel::Row childrow = *(_store->append(row->children())); + childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = std::vector(1, obj); + childrow[_mColumns._colProperties] = ""; // Unused } } +} - /** - * The selector name objects is set to the text that the user sets in the - * entrybox. If the attribute does not exist, it is - * created. In case the attribute already has a value, the new value entered - * is appended to the values. If a style attribute does not exist, it is - * created with an empty value. Also if a class selector is added, then - * class attribute for the selected object is set too. - */ - std::vector objVec; - bool objExists = false; - if (!_desktop->getSelection()->isEmpty()) { - for (auto& obj: _desktop->getSelection()->objects()) { - objExists = true; - if (!obj->getRepr()->attribute("style")) { - obj->getRepr()->setAttribute("style", NULL); - } +/** + * @brief StyleDialog::_writeStyleElement + * Update the content of the style element as selectors (or objects) are added/removed. + */ +void StyleDialog::_writeStyleElement() +{ + Glib::ustring styleContent; + for (auto& row: _store->children()) { + styleContent = styleContent + row[_mColumns._colSelector] + + " { " + row[_mColumns._colProperties] + " }\n"; + } + // We could test if styleContent is empty and then delete the style node here but there is no + // harm in keeping it around ... - if (obj->getAttribute("style") == NULL) { - _selectorValue = _selectorName + "{" + "}" + "\n"; - } - else { - _selectorValue = _selectorName + "{" - + obj->getAttribute("style") + "}" + "\n"; - } + Inkscape::XML::Node *textNode = _getStyleTextNode(); + textNode->setContent(styleContent.c_str()); - if (_selectorName[0] == '.') { - if (!obj->getRepr()->attribute("class")) { - obj->getRepr()->setAttribute("class", textEditPtr->get_text() - .erase(0,1)); +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_writeStyleElement(): |" << styleContent << "|" << std::endl; +#endif +} + + +/** + * @brief StyleDialog::_addToSelector + * @param row + * Add selected objects on the desktop to the selector corresponding to 'row'. + */ +void StyleDialog::_addToSelector(Gtk::TreeModel::Row row) +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_addToSelector: Entrance" << std::endl; +#endif + if (*row) { + + Glib::ustring selector = row[_mColumns._colSelector]; + + if (selector[0] == '#') { + // 'id' selector... add selected object's id's to list. + Inkscape::Selection* selection = _desktop->getSelection(); + for (auto& obj: selection->objects()) { + + Glib::ustring id = (obj->getId()?obj->getId():""); + + std::vector objVec = row[_mColumns._colObj]; + bool found = false; + for (auto& obj: objVec) { + if (id == obj->getId()) { + found = true; + break; + } } - else { - obj->getRepr()->setAttribute("class", std::string(obj-> - getRepr()-> - attribute("class")) - + " " + textEditPtr->get_text() - .erase(0,1)); + + if (!found) { + // Update row + objVec.push_back(obj); // Adding to copy so need to update tree + row[_mColumns._colObj] = objVec; + row[_mColumns._colSelector] = _getIdList( objVec ); + + // Add child row + Gtk::TreeModel::Row childrow = *(_store->append(row->children())); + childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = std::vector(1, obj); } } } - } - else { - _selectorValue = _selectorName + "{" + "}" + "\n"; - objExists = false; - } - switch (result) { - case Gtk::RESPONSE_OK: - textDialogPtr->hide(); - row[_mColumns._selectorLabel] = _selectorName; - row[_mColumns._colAddRemove] = true; - if (objExists) { + else if (selector[0] == '.') { + // 'class' selector... add value to class attribute of selected objects. + + // Get first class (split on white space or comma) + std::vector tokens = Glib::Regex::split_simple("[,\\s]+", selector); + Glib::ustring className = tokens[0]; + className.erase(0,1); + + // Get list of objects to modify Inkscape::Selection* selection = _desktop->getSelection(); - row[_mColumns._colObj] = std::vector(selection->objects() - .begin(), selection - ->objects().end()); - objVec = row[_mColumns._colObj]; + std::vector objVec( selection->objects().begin(), + selection->objects().end() ); + + _insertClass( objVec, className ); + + row[_mColumns._colObj] = _getObjVec( selector ); + + for (auto& obj: objVec) { + // Add child row + Gtk::TreeModel::Row childrow = *(_store->append(row->children())); + childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = std::vector(1, obj); + } } - break; - default: - break; - } - /** - * A new style element is added to the document with value obtained - * from selectorValue above. If style element already exists, then - * the new selector's content is appended to its previous content. - */ - inkSelector._selector = _selectorName; - inkSelector._matchingObjs = objVec; - inkSelector._xmlContent = _selectorValue; - _selectorVec.push_back(inkSelector); - - if (_styleElementNode()) { - _styleChild = _styleElementNode(); - _updateStyleContent(); - } - else if (_styleExists && !_newDrawing) { - _updateStyleContent(); - } - else if (!_styleExists) { - Inkscape::XML::Node *root = _document->getReprDoc()->root(); - Inkscape::XML::Node *newChild = _document->getReprDoc() - ->createElement("svg:style"); - Inkscape::XML::Node *smallChildren = _document->getReprDoc() - ->createTextNode(_selectorValue.c_str()); - - newChild->appendChild(smallChildren); - Inkscape::GC::release(smallChildren); - - root->addChild(newChild, NULL); - Inkscape::GC::release(newChild); - _styleChild = newChild; + else { + // Do nothing for element selectors. + // std::cout << " Element selector... doing nothing!" << std::endl; + } } - _selAdd(row); -} -/** - * @brief StyleDialog::_updateStyleContent - * This function updates the content in style element as new selectors (or - * objects) are added/removed. - */ -void StyleDialog::_updateStyleContent() -{ - std::string styleContent = ""; - for (unsigned i = 0; i < _selectorVec.size(); ++i) { - styleContent = styleContent + _selectorVec[i]._xmlContent; - } - _styleChild->firstChild()->setContent(styleContent.c_str()); + _writeStyleElement(); } + /** - * @brief StyleDialog::_delSelector - * This function deletes selector when '-' at the bottom is clicked. The index - * of selected row is obtained and the corresponding selector and its values are - * deleted from the selector vector. If a row has no parent, it is directly - * erased from the vector along with its child rows. The style element is updated - * accordingly. + * @brief StyleDialog::_removeFromSelector + * @param row + * Remove the object corresponding to 'row' from the parent selector. */ -void StyleDialog::_delSelector() +void StyleDialog::_removeFromSelector(Gtk::TreeModel::Row row) { - Glib::RefPtr refTreeSelection = _treeView.get_selection(); - Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); - if (iter) { - Gtk::TreeModel::Row row = *iter; - std::string sel, key, value; - std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end();) { - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_removeFromSelector: Entrance" << std::endl; +#endif + if (*row) { + + Glib::ustring objectLabel = row[_mColumns._colSelector]; + Gtk::TreeModel::iterator iter = row->parent(); + if (iter) { + Gtk::TreeModel::Row parent = *iter; + Glib::ustring selector = parent[_mColumns._colSelector]; + + if (selector[0] == '#') { + // 'id' selector... remove selected object's id's to list. + + // Erase from selector label. + auto i = selector.find(objectLabel); + if (i != Glib::ustring::npos) { + selector.erase(i, objectLabel.length()); + } + // Erase any comma/space + if (i != Glib::ustring::npos && selector[i] == ',') { + selector.erase(i, 1); + } + if (i != Glib::ustring::npos && selector[i] == ' ') { + selector.erase(i, 1); + } + + // Update store + if (selector.empty()) { + _store->erase(parent); + } else { + // Save new selector and update object vector. + parent[_mColumns._colSelector] = selector; + parent[_mColumns._colObj] = _getObjVec( selector ); + _store->erase(row); } } - Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; - std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(matchSelector); - if (key == matchSelector) { - it = _selectorVec.erase(it); + else if (selector[0] == '.') { + // 'class' selector... remove value to class attribute of selected objects. + + std::vector objVec = row[_mColumns._colObj]; // Just one + + // Get first class (split on white space or comma) + std::vector tokens = Glib::Regex::split_simple("[,\\s]+", selector); + Glib::ustring className = tokens[0]; + className.erase(0,1); // Erase '.' + + // Erase class name from 'class' attribute. + Glib::ustring classAttr = objVec[0]->getRepr()->attribute("class"); + auto i = classAttr.find( className ); + if (i != Glib::ustring::npos) { + classAttr.erase(i, className.length()); + } + if (i != Glib::ustring::npos && classAttr[i] == ' ') { + classAttr.erase(i, 1); + } + objVec[0]->getRepr()->setAttribute("class", classAttr); + + parent[_mColumns._colObj] = _getObjVec( selector ); _store->erase(row); } - else { - ++it; - } - /** - * The _stylechild is obtained which contains the style element and - * the content in style element is updated. If _selectorVec is - * empty, the style element is removed from the XML repr else - * the content is updated simply using _updateStyleContent(). - */ - _styleChild = _styleElementNode(); - if (_store->children().empty()) { - _document->getReprRoot()->removeChild(_styleChild); - _styleExists = false; - } else { - _updateStyleContent(); + // Do nothing for element selectors. + // std::cout << " Element selector... doing nothing!" << std::endl; } } } + + _writeStyleElement(); + } + /** - * @brief StyleDialog::_styleElementNode - * @return - * This function returns the node containing style element. The document's - * children are iterated and the repr of the style element that occurs is - * obtained. + * @brief StyleDialog::_getIdList + * @param sel + * @return This function returns a comma seperated list of ids for objects in input vector. + * It is used in creating an 'id' selector. It relies on objects having 'id's. */ -Inkscape::XML::Node* StyleDialog::_styleElementNode() +Glib::ustring StyleDialog::_getIdList(std::vector sel) { - for (unsigned i = 0; i < _document->getReprRoot()->childCount(); ++i) { - if (std::string(_document->getReprRoot()->nthChild(i)->name()) - == "svg:style") { - _styleExists = true; - _newDrawing = true; - return _document->getReprRoot()->nthChild(i); - } + Glib::ustring str; + for (auto& obj: sel) { + str += "#" + Glib::ustring(obj->getId()) + ", "; + } + if (!str.empty()) { + str.erase(str.size()-1); // Remove space at end. c++11 has pop_back() but not ustring. + str.erase(str.size()-1); // Remove comma at end. } - return NULL; + return str; } /** - * @brief StyleDialog::_setClassAttribute - * @param sel - * @return This function returns the ids of objects selected which are passed - * to entrybox. + * @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. */ -std::string StyleDialog::_setClassAttribute(std::vector sel) -{ - std::string str = ""; - for ( unsigned i = 0; i < sel.size(); ++i ) { - SPObject *obj = sel.at(i); - str = str + "#" + std::string(obj->getId()) + " "; +std::vector StyleDialog::_getObjVec(Glib::ustring selector) { + + // Split selector string into individual selectors (which are comma separated). + std::vector tokens = Glib::Regex::split_simple("\\s*,\\s*", selector ); + + std::vector objVec; + + for (auto& token: tokens) { + + // Find objects that match class selector + if (token[0] == '.') { + token.erase(0,1); + std::vector 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 objects = _document->getObjectsByElement( token ); + objVec.insert(objVec.end(), objects.begin(), objects.end()); + } + } - return str; + +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_getObjVec: |" << selector << "|" << std::endl; + for (auto& obj: objVec) { + std::cout << " " << (obj->getId()?obj->getId():"null") << std::endl; + } +#endif + + return objVec; } + /** - * @brief StyleDialog::_getSelectorVec - * @return selVec - * This function returns a vector whose key is the style selector name and value - * is the style properties. All style selectors are extracted from svg:style - * element. _newDrawing is flag is set to false check if an existing drawing is - * opened. + * @brief StyleDialog::_insertClass + * @param objs: list of objects to insert class + * @param class: class to insert + * Insert a class name into objects' 'class' attribute. */ -std::vector StyleDialog::_getSelectorVec() -{ - 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); - - // 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 regex1 = - // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}"); - // - // Glib::MatchInfo minfo; - // regex1->match(content, minfo); - - // Split on curly brackets. Even tokens are selectors, odd are values. - std::vector 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::vectorobjVec; - - // Split selector string into individual selectors (which are comma separated). - std::vector tokens2 = Glib::Regex::split_simple - ("\\s*,\\s*", selectors ); - - 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 objects = _document - ->getObjectsByClass(token2); - objVec.insert(objVec.end(), objects.begin(), objects.end()); - } +void StyleDialog::_insertClass(const std::vector& objVec, const Glib::ustring& className) { - // 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); - } - } + for (auto& obj: objVec) { - // Find objects that match element selector - else { - std::vector objects = _document-> - getObjectsByElement(token2); - objVec.insert(objVec.end(), objects.begin(), objects.end()); - } + if (!obj->getRepr()->attribute("class")) { + // 'class' attribute does not exist, create it. + obj->getRepr()->setAttribute("class", className); + } else { + // 'class' attribute exists, append. + Glib::ustring classAttr = obj->getRepr()->attribute("class"); + + // Split on white space. + std::vector tokens = Glib::Regex::split_simple("\\s+", classAttr); + bool add = true; + for (auto& token: tokens) { + if (token == className) { + add = false; // Might be useful to still add... + break; } + } + if (add) { + obj->getRepr()->setAttribute("class", classAttr + " " + className ); + } + } + } + } - 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); +/** + * @brief StyleDialog::_selectObjects + * @param eventX + * @param eventY + * This function selects objects in the drawing corresponding to the selector + * selected in the treeview. + */ +void StyleDialog::_selectObjects(int eventX, int eventY) +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_selectObjects: " << eventX << ", " << eventY << std::endl; +#endif + + _desktop->selection->clear(); + Gtk::TreeViewColumn *col = _treeView.get_column(1); + Gtk::TreeModel::Path path; + int x2 = 0; + int y2 = 0; + // To do: We should be able to do this via passing in row. + if (_treeView.get_path_at_pos(eventX, eventY, path, col, x2, y2)) { + if (col == _treeView.get_column(1)) { + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + Gtk::TreeModel::Children children = row.children(); + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + SPObject *obj = objVec[i]; + _desktop->selection->add(obj); + } } } } - return _selectorVec; } + /** - * @brief StyleDialog::_populateTree - * @param _selVec - * This function populates the treeview with selectors available in the - * stylesheet. + * @brief StyleDialog::_addSelector + * + * This function opens a dialog to add a selector. The dialog is prefilled + * with an 'id' selector containing a list of the id's of selected objects + * or with a 'class' selector if no objects are selected. */ -std::string StyleDialog::_populateTree(std::vector _selVec) +void StyleDialog::_addSelector() { - _selectorVec = _selVec; - std::string selectorValue; +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_addSelector: Entrance" << std::endl; +#endif - for(unsigned it = 0; it < _selectorVec.size(); ++it) { - Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._selectorLabel] = _selectorVec[it]._selector; - row[_mColumns._colAddRemove] = true; - row[_mColumns._colObj] = _selectorVec[it]._matchingObjs; - std::string selValue = _selectorVec[it]._xmlContent; - selectorValue.append(selValue.c_str()); + // Store list of selected elements on desktop (not to be confused with selector). + Inkscape::Selection* selection = _desktop->getSelection(); + std::vector objVec( selection->objects().begin(), + selection->objects().end() ); + + // ==== Create popup dialog ==== + Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); + textDialogPtr->add_button(_("Cancel"), Gtk::RESPONSE_CANCEL); + textDialogPtr->add_button(_("Add"), Gtk::RESPONSE_OK); + + Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); + textDialogPtr->get_vbox()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); + + Gtk::Label *textLabelPtr = manage ( new Gtk::Label( + _("Invalid entry: Not an id (#), class (.), or element CSS selector.") + ) ); + textDialogPtr->get_vbox()->pack_start(*textLabelPtr, Gtk::PACK_SHRINK); + + /** + * By default, the entrybox contains 'Class1' as text. However, if object(s) + * is(are) selected and user clicks '+' at the bottom of dialog, the + * entrybox will have the id(s) of the selected objects as text. + */ + if (_desktop->getSelection()->isEmpty()) { + textEditPtr->set_text(".Class1"); + } else { + textEditPtr->set_text(_getIdList(objVec)); } - if (_selectorVec.size() > 0) { + Gtk::Requisition sreq1, sreq2; + 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); + textEditPtr->show(); + textLabelPtr->hide(); + textDialogPtr->show(); + + + // ==== Get response ==== + int result = -1; + bool invalid = true; + Glib::ustring selectorValue; + + while (invalid) { + result = textDialogPtr->run(); + if (result != Gtk::RESPONSE_OK) { // Cancel, close dialog, etc. + textDialogPtr->hide(); + return; + } + /** + * @brief selectorName + * This string stores selector name. The text from entrybox is saved as name + * for selector. If the entrybox is empty, the text (thus selectorName) is + * set to ".Class1" + */ + selectorValue = textEditPtr->get_text(); + del->set_sensitive(true); + + if (selectorValue[0] == '.' || + selectorValue[0] == '#' || + SPAttributeRelSVG::isSVGElement( selectorValue ) ) { + invalid = false; + } else { + textLabelPtr->show(); + } } + delete textDialogPtr; - return selectorValue; + // ==== Handle response ==== + + // If class selector, add selector name to class attribute for each object + if (selectorValue[0] == '.') { + + Glib::ustring className = selectorValue; + className.erase(0,1); + _insertClass(objVec, className); + } + + // If 'id' selector, regenerate objVec in case user modified list. + if (selectorValue[0] == '#') { + // To do + } + + // Add entry to GUI tree + Gtk::TreeModel::Row row = *(_store->append()); + row[_mColumns._colSelector] = selectorValue; + row[_mColumns._colAddRemove] = true; + row[_mColumns._colObj] = objVec; + + // Add as children objects that match selector. + for (auto& obj: objVec) { + Gtk::TreeModel::Row childrow = *(_store->append(row->children())); + childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); + childrow[_mColumns._colAddRemove] = false; + childrow[_mColumns._colObj] = std::vector(1, obj); + } + + // Add entry to style element + _writeStyleElement(); +} + +/** + * @brief StyleDialog::_delSelector + * This function deletes selector when '-' at the bottom is clicked. + * Note: If deleting a class selector, class attributes are NOT changed. + */ +void StyleDialog::_delSelector() +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_delSelector" << std::endl; +#endif + Glib::RefPtr refTreeSelection = _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + _store->erase(iter); + _writeStyleElement(); + } } /** * @brief StyleDialog::_handleButtonEvent * @param event * @return - * This function handles the event when '+' button in front of a selector name - * is clicked. The selected objects (if any) is added to the selector as a child - * in the treeview. + * Handles the event when '+' button in front of a selector name is clicked or when a '-' button in + * front of a child object is clicked. In the first case, the selected objects on the desktop (if + * any) are added as children of the selector in the treeview. In the latter case, the object + * corresponding to the row is removed from the selector. */ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) { - if (event->type == GDK_BUTTON_PRESS && event->button == 1) { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_handleButtonEvent: Entrance" << std::endl; +#endif + if (event->type == GDK_BUTTON_RELEASE && event->button == 1) { Gtk::TreeViewColumn *col = 0; Gtk::TreeModel::Path path; int x = static_cast(event->x); @@ -575,119 +772,16 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) int y2 = 0; if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { if (col == _treeView.get_column(0)) { - Glib::RefPtr refTreeSelection = - _treeView.get_selection(); - Gtk::TreeModel::iterator iter = refTreeSelection-> - get_selected(); + Gtk::TreeModel::iterator iter = _store->get_iter(path); Gtk::TreeModel::Row row = *iter; - /** - * This adds child rows to selected rows. If the parent row is - * a class selector, then the class attribute of object added - * to child row is appended with class in the parent row. The - * else below deletes objects from selectors when 'delete' button - * in front of child row is clicked. The class attribute is updated - * by removing the parent row's class selector name. - */ + // Add or remove objects from a if (!row.parent()) { - _selAdd(row); - } - - else { - std::string sel, key, value; - std::vector::iterator it; - Gtk::TreeModel::Row parentRow = *(row).parent(); - Glib::ustring parentKey = parentRow[_mColumns._selectorLabel]; - - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - } - - /** - * @brief matchSelector - * For id selectors, whenever any child row is deleted, - * the row label is updated and so is the entry for the - * selector in style element. - */ - std::string matchSelector = parentKey; - REMOVE_SPACES(matchSelector); - if (key == matchSelector) { - if (key[0] == '#') { - std::string s = parentKey; - Glib::ustring toDelRow = row[_mColumns._selectorLabel]; - std::string toDelKey = toDelRow; - std::size_t idFound = s.find(toDelKey); - if (idFound != std::string::npos) { - if (idFound == 0) { - s.erase(idFound, toDelKey.length()+1); - parentKey = s; - parentRow[_mColumns._selectorLabel] = parentKey; - (*it)._xmlContent.erase(idFound, toDelKey.length()); - } - else { - s.erase(idFound-2, toDelKey.length()+2); - parentKey = s; - parentRow[_mColumns._selectorLabel] = parentKey; - (*it)._xmlContent.erase(idFound-2, toDelKey. - length()+2); - } - } - } - } - - if (parentKey[0] == '.') { - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - std::string classAttr = std::string(obj->getRepr() - ->attribute("class")); - std::size_t found = classAttr.find(parentKey.erase(0,1)); - if (found != std::string::npos) { - classAttr.erase(found, parentKey.length()+1); - obj->getRepr()->setAttribute("class", classAttr); - } - } - } - - if (parentKey.empty()) { - (*it)._xmlContent = ""; - } - } - - if (_styleChild) { - _updateStyleContent(); - } - else { - _styleChild = _styleElementNode(); - _updateStyleContent(); - } - - _store->erase(row); - - /** - * On continuous deletion of objects (child rows) from the - * selector (parent row), if the parent row has no child, then - * the row is erased from the _store. Further if there is no - * row left in _store, which implies there is no content in - * XML style element, then the 'svg:style' element is also - * removed. - */ - if (parentKey.empty()) { - _store->erase(parentRow); - } - - if (parentKey.empty() && _store->children().empty()) { - _document->getReprRoot()->removeChild(_styleChild); - _styleExists = false; - } + // Add selected objects to selector. + _addToSelector(row); + } else { + // Remove object from selector + _removeFromSelector(row); } } } @@ -695,275 +789,129 @@ bool StyleDialog::_handleButtonEvent(GdkEventButton *event) return false; } -/** - * @brief StyleDialog::_selAdd - * @param row - * This routine is called when an object is added to a selector by clicking on - * '+' in front of the row with selector's label. - */ -void StyleDialog::_selAdd(Gtk::TreeModel::Row row) -{ - Glib::ustring selectorName; - Gtk::TreeModel::Row childrow; - Inkscape::Selection* selection = _desktop->getSelection(); - std::vector sel = std::vector - (selection->objects().begin(), selection->objects().end()); - for (auto& obj: selection->objects()) { - if (*row) { - if (_selectorVec.size() != 0) { - childrow = *(_store->append(row->children())); - childrow[_mColumns._selectorLabel] = "#" + - std::string(obj->getId()); - childrow[_mColumns._colAddRemove] = false; - childrow[_mColumns._colObj] = sel; - Glib::ustring key = row[_mColumns._selectorLabel]; - if (key[0] == '.') { - if (!obj->getRepr()->attribute("class")) { - obj->setAttribute("class", key.erase(0,1)); - } - else { - if (obj->getRepr()->attribute("class") != key - .erase(0,1)) { - obj->setAttribute("class", std::string - (obj->getRepr()-> - attribute("class")) - + " " + key - .erase(0,1)); - } - } - } - } - selectorName = row[_mColumns._selectorLabel]; - } - - /** - * If the object's parent row is a class selector, then - * there are no changes in style element except the class - * attribute is updated. For the id selector cases, XML - * content's style element is updated. - */ - REMOVE_SPACES(selectorName); - std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - std::string sel, key, value; - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - } - - Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; - std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(matchSelector); - if (key == matchSelector) { - REMOVE_SPACES((*it)._selector); - if (selectorName[0] == '#') { - if ("#" + std::string(obj->getId()) != selectorName) { - inkSelector._selector = (*it)._selector; - inkSelector._selector.append(", #" + std::string(obj->getId())); - inkSelector._xmlContent = inkSelector._selector + "{" + value + "}\n"; - row[_mColumns._selectorLabel] = selectorName + ", " + - childrow[_mColumns._selectorLabel]; - } - } - else if (selectorName[0] == '.') { - inkSelector._xmlContent = (*it)._selector + "{" + value + "}\n"; - } - - it = _selectorVec.erase(it); - it = _selectorVec.insert(it, inkSelector); - } - } - } - if (_styleElementNode()) { - _styleChild = _styleElementNode(); - _updateStyleContent(); - } - else if (_styleExists && !_newDrawing) { - _updateStyleContent(); - } -} /** - * @brief StyleDialog::_selectObjects + * @brief StyleDialog::_buttonEventsSelectObjs * @param event - * This function detects single or double click on a selector in any row. Single - * click on a selector selects the matching objects. A double click on any - * selector selects the matching objects as well as will open CSS dialog. It - * calls _selectObjects to add objects to selection. + * This function detects single or double click on a selector in any row. Clicking + * on a selector selects the matching objects on the desktop. A double click will + * in addition open the CSS dialog. */ void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) { - if (event->type == GDK_BUTTON_PRESS && event->button == 1) { - int x = static_cast(event->x); - int y = static_cast(event->y); - _selectObjects(x, y); - } - else if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_buttonEventsSelectObjs" << std::endl; +#endif + _updating = true; + + if (event->type == GDK_BUTTON_RELEASE && event->button == 1) { int x = static_cast(event->x); int y = static_cast(event->y); _selectObjects(x, y); + //} + //else if (event->type == GDK_2BUTTON_PRESS && event->button == 1) { + //int x = static_cast(event->x); + //int y = static_cast(event->y); + //_selectObjects(x, y); - //Open CSS dialog here. - if (!_cssPane->get_visible()) { - _paned.pack2(*_cssPane, Gtk::SHRINK); - _cssPane->show_all(); - } + _cssPane->_store->clear(); + // This should probably be in a member function of CSSDialog. Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; - std::string sel, key, value; - std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } + Glib::ustring properties = row[_mColumns._colProperties]; + REMOVE_SPACES(properties); // Remove leading/trailing spaces + + std::vector tokens = + Glib::Regex::split_simple("\\s*;\\s*", properties); + for (auto& token: tokens) { + if (!token.empty()) { + _cssPane->_propRow = *(_cssPane->_store->append()); + _cssPane->_propRow[_cssPane->_cssColumns._colUnsetProp] = false; + _cssPane->_propRow[_cssPane->_cssColumns._propertyLabel] = token; } + } + } + } + _updating = false; +} - Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; - std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(matchSelector); - - if (key == matchSelector) { - _cssPane->_store->clear(); - std::stringstream ss(value); - std::string token; - std::size_t found = value.find(";"); - if (found!=std::string::npos) { - while(std::getline(ss, token, ';')) { - REMOVE_SPACES(token); - if (!token.empty()) { - _cssPane->_propRow = *(_cssPane->_store->append()); - _cssPane->_propRow[_cssPane->_cssColumns._colUnsetProp] = false; - _cssPane->_propRow[_cssPane->_cssColumns._propertyLabel] = token; - _cssPane->_propCol->add_attribute(_cssPane->_textRenderer - ->property_text(), - _cssPane->_cssColumns - ._propertyLabel); - } - } - } + +/** + * @brief StyleDialog::_selectRow + * This function selects the row in treeview corresponding to an object selected + * in the drawing. If more than one row matches, the first is chosen. + */ +void StyleDialog::_selectRow(Selection */*sel*/) +{ + if (_updating) return; // Avoid updating if we have set row via dialog. + + Inkscape::Selection* selection = _desktop->getSelection(); + if (!selection->isEmpty()) { + SPObject *obj = selection->objects().back(); + + Gtk::TreeModel::Children children = _store->children(); + for(Gtk::TreeModel::Children::iterator iter = children.begin(); + iter != children.end(); ++iter) { + + Gtk::TreeModel::Row row = *iter; + std::vector objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { + if (obj->getId() == objVec[i]->getId()) { + _treeView.get_selection()->select(row); + return; } } } - else { - _cssPane->_store->clear(); - _cssPane->hide(); - } - - _cssPane->_textRenderer->signal_edited().connect(sigc::mem_fun(*this, - &StyleDialog:: - _handleEdited)); - _cssPane->_treeView.signal_button_press_event().connect(sigc::mem_fun - (*this, &StyleDialog:: - _delProperty), - false); } + + // Selection empty or no row matches. + _treeView.get_selection()->unselect_all(); } + /** * @brief StyleDialog::_selChanged - * When no row in _treeView of Style Dialog is selected, the _cssPane is hidden. */ void StyleDialog::_selChanged() { - if (_treeView.get_selection()->count_selected_rows() == 0) { - _cssPane->hide(); - } +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_selChanged" << std::endl; +#endif } /** * @brief StyleDialog::_handleEdited * @param path * @param new_text - * This function edits CSS properties of the selector chosen. new_text is used - * to update the property in XML repr. The value from selected selector is - * obtained and modified as per value of new_text. If a new property is added, - * value is appended with new_text. Later _updateStyleContent() is called to - * update XML repr and hence changes are reflected in the drawing too. + * Update trees when new text is entered into a CSS dialog row. */ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_handleEdited: path: " << path + << " new_text: " << new_text << std::endl; +#endif + Gtk::TreeModel::iterator iterCss = _cssPane->_treeView.get_model()->get_iter(path); if (iterCss) { Gtk::TreeModel::Row row = *iterCss; row[_cssPane->_cssColumns._propertyLabel] = new_text; - _cssPane->_editedProp = new_text; } - // Selected selector row is obtained here to get corresponding key and value. + Glib::ustring properties; + for (auto& crow: _cssPane->_store->children()) { + properties = properties + crow[_cssPane->_cssColumns._propertyLabel] + "; "; + } + + // Update selector data. Glib::RefPtr refTreeSelection = _treeView.get_selection(); Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; - std::string sel, key, value; - std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - } - - Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; - std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(matchSelector); - - if (key == matchSelector) { - /** If a new property is added, existing value is appended with new - * property, else replacements in value are done in the 'else' block. - */ - if (_cssPane->_newProperty) { - if (!new_text.empty()) { - value.append((new_text + ";").c_str()); - _cssPane->_propCol->add_attribute(_cssPane->_textRenderer - ->property_text(), - _cssPane->_cssColumns - ._propertyLabel); - _cssPane->_newProperty = false; - } - } - else { - std::stringstream ss(value); - std::string token, editedToken; - std::size_t found = value.find(";"); - if (found!=std::string::npos) { - while(std::getline(ss, token, ';')) { - REMOVE_SPACES(token); - if (!token.empty()) { - if (token.substr(0, token.find(":")) == _cssPane - ->_editedProp.substr(0, _cssPane->_editedProp - .find(":"))) { - editedToken = _cssPane->_editedProp; - size_t startPos = value.find(token); - value.replace(startPos, token.length(), editedToken); - } - } - } - } - } - value.erase(std::remove(value.begin(), value.end(), '\n'), value.end()); - (*it)._xmlContent = key + "{" + value + "}\n"; - _updateStyleContent(); - } - } + row[_mColumns._colProperties] = properties; + _writeStyleElement(); } } @@ -971,14 +919,15 @@ void StyleDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& * @brief StyleDialog::_delProperty * @param event * @return - * This function deletes property when '-' in front of property in CSS panel is - * clicked. The property row is deleted from CSS panel and XML repr is updated. - * toDelProperty is the property to be deleted which is looked in 'value' and is - * erased from 'value'. + * Delete a property from the CSS dialog and then update trees. */ bool StyleDialog::_delProperty(GdkEventButton *event) { - if (event->type == GDK_BUTTON_PRESS && event->button == 1) { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_delProperty" << std::endl; +#endif + + if (event->type == GDK_BUTTON_RELEASE && event->button == 1) { Gtk::TreeViewColumn *col = 0; Gtk::TreeModel::Path path; int x = static_cast(event->x); @@ -989,45 +938,23 @@ bool StyleDialog::_delProperty(GdkEventButton *event) Glib::ustring toDelProperty; if (_cssPane->_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { if (col == _cssPane->_treeView.get_column(0)) { - Gtk::TreeModel::iterator cssIter = _cssPane->_treeView.get_selection() - ->get_selected(); + Gtk::TreeModel::iterator cssIter = + _cssPane->_treeView.get_selection()->get_selected(); if (cssIter) { - cssRow = *cssIter; - toDelProperty = cssRow[_cssPane->_cssColumns._propertyLabel]; - } + _cssPane->_store->erase(cssIter); + + Glib::ustring properties; + for (auto& crow: _cssPane->_store->children()) { + properties = properties + crow[_cssPane->_cssColumns._propertyLabel] + "; "; + } - Gtk::TreeModel::iterator iter = _treeView.get_selection()->get_selected(); - if (iter) { - Gtk::TreeModel::Row row = *iter; - std::string sel, key, value; - std::vector::iterator it; - for (it = _selectorVec.begin(); it != _selectorVec.end(); ++it) { - sel = (*it)._xmlContent; - REMOVE_SPACES(sel); - if (!sel.empty()) { - key = strtok((char*)sel.c_str(), "{"); - REMOVE_SPACES(key); - char *temp = strtok(NULL, "}"); - if (strtok(temp, "}") != NULL) { - value = strtok(temp, "}"); - } - } - - Glib::ustring selectedRowLabel = row[_mColumns._selectorLabel]; - std::string matchSelector = selectedRowLabel; - REMOVE_SPACES(matchSelector); - - if (key == matchSelector) { - std::size_t found = value.find(toDelProperty); - if (found!=std::string::npos) { - if (!toDelProperty.empty()) { - value.erase(found, toDelProperty.length()+1); - (*it)._xmlContent = key + "{" + value + "}\n"; - _updateStyleContent(); - _cssPane->_store->erase(cssRow); - } - } - } + // Update selector data. + Glib::RefPtr refTreeSelection = _treeView.get_selection(); + Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + row[_mColumns._colProperties] = properties; + _writeStyleElement(); } } } @@ -1036,98 +963,24 @@ bool StyleDialog::_delProperty(GdkEventButton *event) return false; } -/** - * @brief StyleDialog::_selectObjects - * @param eventX - * @param eventY - * This function selects objects in the drawing corresponding to the selector - * selected in the treeview. - */ -void StyleDialog::_selectObjects(int eventX, int eventY) -{ - _desktop->selection->clear(); - Gtk::TreeViewColumn *col = _treeView.get_column(1); - Gtk::TreeModel::Path path; - int x = eventX; - int y = eventY; - int x2 = 0; - int y2 = 0; - if (_treeView.get_path_at_pos(x, y, path, col, x2, y2)) { - if (col == _treeView.get_column(1)) { - Gtk::TreeModel::iterator iter = _store->get_iter(path); - if (iter) { - Gtk::TreeModel::Row row = *iter; - Gtk::TreeModel::Children children = row.children(); - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - _desktop->selection->add(obj); - } - if (children) { - _checkAllChildren(children); - } - } - } - } -} /** - * @brief StyleDialog::_checkAllChildren - * @param children - * This function iterates children of the row selected in treeview and selects - * the objects corresponding to any selector in child rows. + * @brief StyleDialog::_styleButton + * @param btn + * @param iconName + * @param tooltip + * Set the style of '+' and '-' buttons at the bottom of dialog. */ -void StyleDialog::_checkAllChildren(Gtk::TreeModel::Children& children) +void StyleDialog::_styleButton(Gtk::Button& btn, char const* iconName, + char const* tooltip) { - for (Gtk::TreeModel::Children::iterator iter = children.begin(); - iter!= children.end(); ++iter) { - Gtk::TreeModel::Row childrow = *iter; - std::vector objVec = childrow[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - SPObject *obj = objVec[i]; - _desktop->selection->add(obj); - } - } + GtkWidget *child = sp_icon_new(Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName); + gtk_widget_show(child); + btn.add(*manage(Glib::wrap(child))); + btn.set_relief(Gtk::RELIEF_NONE); + btn.set_tooltip_text (tooltip); } -/** - * @brief StyleDialog::_selectRow - * This function selects the rows in treeview corresponding to an object selected - * in the drawing. - */ -void StyleDialog::_selectRow(Selection */*sel*/) -{ - SPObject *obj = NULL; - if (!_desktop->selection->isEmpty()) { - Inkscape::Selection* selection = _desktop->getSelection(); - std::vector selected = std::vector - (selection->objects().begin(), selection->objects().end()); - obj = selected.back(); - } - - /** - * If obj has some SPObject, then it is added to desktop's selection. If a - * row in treeview has children, those rows are checked too against selected - * object's id. If an object which is not present in any selector is selected, - * the treeview's selections are unselected. - */ - if (obj != NULL) { - Gtk::TreeModel::Children children = _store->children(); - for(Gtk::TreeModel::Children::iterator iter = children.begin(); - iter != children.end(); ++iter) { - Gtk::TreeModel::Row row = *iter; - std::vector objVec = row[_mColumns._colObj]; - for (unsigned i = 0; i < objVec.size(); ++i) { - if (obj->getId() == objVec[i]->getId()) { - _treeView.get_selection()->select(row); - } - } - } - } - else { - _treeView.get_selection()->unselect_all(); - } -} } // namespace Dialog } // namespace UI -- cgit v1.2.3 From 7494443a3f6c759f615e4e98676c0ed027e3ad47 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sat, 18 Feb 2017 09:42:01 +0100 Subject: Implement Undo. Respond to external changes to