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/CMakeLists.txt | 2 + src/ui/dialog/dialog-manager.cpp | 3 ++ src/ui/dialog/styledialog.cpp | 113 +++++++++++++++++++++++++++++++++++++++ src/ui/dialog/styledialog.h | 69 ++++++++++++++++++++++++ 4 files changed, 187 insertions(+) create mode 100644 src/ui/dialog/styledialog.cpp create mode 100644 src/ui/dialog/styledialog.h (limited to 'src/ui') diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 587974b90..4be3fa3d2 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -99,6 +99,7 @@ set(ui_SRC dialog/print-colors-preview-dialog.cpp dialog/print.cpp dialog/spellcheck.cpp + dialog/styledialog.cpp dialog/svg-fonts-dialog.cpp dialog/swatches.cpp dialog/symbols.cpp @@ -240,6 +241,7 @@ set(ui_SRC dialog/print-colors-preview-dialog.h dialog/print.h dialog/spellcheck.h + dialog/styledialog.h dialog/svg-fonts-dialog.h dialog/swatches.h dialog/symbols.h diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 49853277c..4bb5215fd 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -60,6 +60,7 @@ #include "ui/dialog/svg-fonts-dialog.h" #include "ui/dialog/objects.h" #include "ui/dialog/tags.h" +#include "ui/dialog/styledialog.h" namespace Inkscape { namespace UI { @@ -128,6 +129,7 @@ DialogManager::DialogManager() { registerFactory("Swatches", &create); registerFactory("TileDialog", &create); registerFactory("Symbols", &create); + registerFactory("StyleDialog", &create); #if HAVE_POTRACE registerFactory("Trace", &create); @@ -167,6 +169,7 @@ DialogManager::DialogManager() { registerFactory("Swatches", &create); registerFactory("TileDialog", &create); registerFactory("Symbols", &create); + registerFactory("StyleDialog", &create); #if HAVE_POTRACE registerFactory("Trace", &create); 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h new file mode 100644 index 000000000..044737add --- /dev/null +++ b/src/ui/dialog/styledialog.h @@ -0,0 +1,69 @@ +/** @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 + */ + +#ifndef STYLEDIALOG_H +#define STYLEDIALOG_H + +#include +#include +#include +#include +#include + +#include "desktop.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +/** + * @brief The StyleDialog class + * A list of CSS selectors will show up in this dialog. + */ + +class StyleDialog : public UI::Widget::Panel +{ +public: + StyleDialog(); + ~StyleDialog(); + + static StyleDialog &getInstance() { return *new StyleDialog(); } + void setDesktop( SPDesktop* desktop); + +private: + void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); + + class ModelColumns : public Gtk::TreeModel::ColumnRecord + { + public: + ModelColumns() + { add(_selectorNumber); add(_selectorLabel); } + Gtk::TreeModelColumn _selectorNumber; + Gtk::TreeModelColumn _selectorLabel; + }; + + SPDesktop* _desktop; + ModelColumns _mColumns; + Gtk::VBox _mainBox; + Gtk::HBox _buttonBox; + Gtk::TreeView _treeView; + Glib::RefPtr _store; + Gtk::ScrolledWindow _scrolledWindow; + + // Signal handlers + void _addSelector(); +}; + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // STYLEDIALOG_H -- 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 +++++++++++++++++++++++++++++++++++++++++-- src/ui/dialog/styledialog.h | 1 + 2 files changed, 70 insertions(+), 2 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 044737add..281585d9d 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -40,6 +40,7 @@ public: private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); + std::string _setClassAttribute(std::vector); class ModelColumns : public Gtk::TreeModel::ColumnRecord { -- 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 +++++++++++++++++++++++++++++++++--------- src/ui/dialog/styledialog.h | 2 + 2 files changed, 81 insertions(+), 21 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 281585d9d..21c33ab6e 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -41,6 +41,8 @@ public: private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); + std::map_selectorMap; + void _populateTree(std::map); class ModelColumns : public Gtk::TreeModel::ColumnRecord { -- 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 +++++++++++++++++++++++++++++++------------ src/ui/dialog/styledialog.h | 4 ++-- 2 files changed, 38 insertions(+), 15 deletions(-) (limited to 'src/ui') 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; } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 21c33ab6e..79ff41559 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -19,6 +19,7 @@ #include #include "desktop.h" +#include "document.h" namespace Inkscape { namespace UI { @@ -48,8 +49,7 @@ private: { public: ModelColumns() - { add(_selectorNumber); add(_selectorLabel); } - Gtk::TreeModelColumn _selectorNumber; + { add(_selectorLabel); } Gtk::TreeModelColumn _selectorLabel; }; -- cgit v1.2.3 From 3bbe3debb72ae45a17eaa0133f73d8bc37c55b7b Mon Sep 17 00:00:00 2001 From: kamalpreetgrewal Date: Sat, 11 Jun 2016 10:57:36 +0530 Subject: Apply patch for broken automake (bzr r14949.1.9) --- src/ui/dialog/Makefile_insert | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/ui') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 71628973e..982908731 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -92,6 +92,8 @@ ink_common_sources += \ ui/dialog/print-colors-preview-dialog.h \ ui/dialog/spellcheck.cpp \ ui/dialog/spellcheck.h \ + ui/dialog/styledialog.cpp \ + ui/dialog/styledialog.h \ ui/dialog/svg-fonts-dialog.cpp \ ui/dialog/svg-fonts-dialog.h \ ui/dialog/swatches.cpp \ -- 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 +++++++++++++++++++++++++++++++++--------- src/ui/dialog/styledialog.h | 7 +++ 2 files changed, 97 insertions(+), 25 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 79ff41559..f206b1e23 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -17,6 +17,7 @@ #include #include #include +#include #include "desktop.h" #include "document.h" @@ -43,6 +44,7 @@ private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); std::map_selectorMap; + std::map _getSelectorMap(); void _populateTree(std::map); class ModelColumns : public Gtk::TreeModel::ColumnRecord @@ -54,15 +56,20 @@ private: }; SPDesktop* _desktop; + SPDesktop* _targetDesktop; ModelColumns _mColumns; Gtk::VBox _mainBox; Gtk::HBox _buttonBox; Gtk::TreeView _treeView; Glib::RefPtr _store; Gtk::ScrolledWindow _scrolledWindow; + Gtk::Button* del; + Gtk::Button* create; + SPDocument* _document; // Signal handlers void _addSelector(); + void _delSelector(); }; } // 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') 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') 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') 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 +++++++++++++++++++++++++++--------------- src/ui/dialog/styledialog.h | 8 ++-- 2 files changed, 74 insertions(+), 40 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index f206b1e23..0cba3bf5b 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -43,9 +43,9 @@ public: private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); - std::map_selectorMap; - std::map _getSelectorMap(); - void _populateTree(std::map); + std::vector >_selectorVec; + std::vector > _getSelectorVec(); + std::string _populateTree(std::vector >); class ModelColumns : public Gtk::TreeModel::ColumnRecord { @@ -66,6 +66,8 @@ private: Gtk::Button* del; Gtk::Button* create; SPDocument* _document; + bool _styleExists; + std::string _sValue ; // Signal handlers void _addSelector(); -- 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 ++++++++++++++++++++----------------------- src/ui/dialog/styledialog.h | 2 ++ 2 files changed, 34 insertions(+), 38 deletions(-) (limited to 'src/ui') 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; } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 0cba3bf5b..502a7a3d4 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -68,6 +68,8 @@ private: SPDocument* _document; bool _styleExists; std::string _sValue ; + Inkscape::XML::Node *_styleChild; + unsigned _num; // Signal handlers void _addSelector(); -- 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') 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') 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') 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 ++++++++++++++++++++++++++++-------------- src/ui/dialog/styledialog.h | 11 +- 2 files changed, 178 insertions(+), 85 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 502a7a3d4..ff4de9a97 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -14,7 +14,7 @@ #include #include -#include +#include #include #include #include @@ -46,13 +46,15 @@ private: std::vector >_selectorVec; std::vector > _getSelectorVec(); std::string _populateTree(std::vector >); + bool _handleButtonEvent(GdkEventButton *event); class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() - { add(_selectorLabel); } + { add(_selectorLabel); add(_colAddRemove); } Gtk::TreeModelColumn _selectorLabel; + Gtk::TreeModelColumn _colAddRemove; }; SPDesktop* _desktop; @@ -61,7 +63,7 @@ private: Gtk::VBox _mainBox; Gtk::HBox _buttonBox; Gtk::TreeView _treeView; - Glib::RefPtr _store; + Glib::RefPtr _store; Gtk::ScrolledWindow _scrolledWindow; Gtk::Button* del; Gtk::Button* create; @@ -70,6 +72,9 @@ private: std::string _sValue ; Inkscape::XML::Node *_styleChild; unsigned _num; + std::string _selectorName = ""; + std::string _selectorValue; + Gtk::TreeModel::Row _row; // Signal handlers void _addSelector(); -- 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') 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 ++++++++++++++++++++++++++++++++++++------- src/ui/dialog/styledialog.h | 6 +++- 2 files changed, 72 insertions(+), 13 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index ff4de9a97..79897a5b6 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -47,14 +47,18 @@ private: std::vector > _getSelectorVec(); std::string _populateTree(std::vector >); bool _handleButtonEvent(GdkEventButton *event); + void _selectedRowCallback(const Gtk::TreeModel::Path& path, + Gtk::TreeViewColumn* /* column */); + void _checkAllChildren(Gtk::TreeModel::Children& children); class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() - { add(_selectorLabel); add(_colAddRemove); } + { add(_selectorLabel); add(_colAddRemove); add(_colObj); } Gtk::TreeModelColumn _selectorLabel; Gtk::TreeModelColumn _colAddRemove; + Gtk::TreeModelColumn _colObj; }; SPDesktop* _desktop; -- 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 +++++++++++++++++++++--------------------- src/ui/dialog/styledialog.h | 2 + 2 files changed, 91 insertions(+), 91 deletions(-) (limited to 'src/ui') 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); + } } } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 79897a5b6..4193752e3 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -50,6 +50,8 @@ private: void _selectedRowCallback(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* /* column */); void _checkAllChildren(Gtk::TreeModel::Children& children); + Inkscape::XML::Node *_styleElementNode(); + void _updateStyleContent(); class ModelColumns : public Gtk::TreeModel::ColumnRecord { -- 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 ++++++++++++++++++++++++++++--------------- src/ui/dialog/styledialog.h | 2 +- 2 files changed, 65 insertions(+), 33 deletions(-) (limited to 'src/ui') 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(); + } } } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 4193752e3..fef1a954b 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -75,12 +75,12 @@ private: Gtk::Button* create; SPDocument* _document; bool _styleExists; - std::string _sValue ; Inkscape::XML::Node *_styleChild; unsigned _num; std::string _selectorName = ""; std::string _selectorValue; Gtk::TreeModel::Row _row; + bool _newDrawing; // Signal handlers void _addSelector(); -- 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 +++++------- src/ui/dialog/styledialog.h | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/ui') 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; } /** diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index fef1a954b..0192b3987 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -77,7 +77,7 @@ private: bool _styleExists; Inkscape::XML::Node *_styleChild; unsigned _num; - std::string _selectorName = ""; + std::string _selectorName; std::string _selectorValue; Gtk::TreeModel::Row _row; bool _newDrawing; -- 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') 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 ++++++++++++++++++++++++++++++++++++------- src/ui/dialog/styledialog.h | 8 ++++--- 2 files changed, 52 insertions(+), 11 deletions(-) (limited to 'src/ui') 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 0192b3987..6e1ffbb2c 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -43,15 +43,17 @@ public: private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); - std::vector >_selectorVec; - std::vector > _getSelectorVec(); - std::string _populateTree(std::vector >); + std::vector, std::string> >_selectorVec; + std::vector, std::string> > _getSelectorVec(); + std::string _populateTree(std::vector, + std::string> >); bool _handleButtonEvent(GdkEventButton *event); void _selectedRowCallback(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* /* column */); void _checkAllChildren(Gtk::TreeModel::Children& children); Inkscape::XML::Node *_styleElementNode(); void _updateStyleContent(); + void _selectRow(Selection *); class ModelColumns : public Gtk::TreeModel::ColumnRecord { -- 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 ++++++++++++++++++++++++++++++------------ src/ui/dialog/styledialog.h | 12 ++-- 2 files changed, 122 insertions(+), 49 deletions(-) (limited to 'src/ui') 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); + } } } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 6e1ffbb2c..e47fbc96d 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -30,6 +30,8 @@ namespace Dialog { * @brief The StyleDialog class * A list of CSS selectors will show up in this dialog. */ +typedef std::pair >, std::string> +_selectorVecType; class StyleDialog : public UI::Widget::Panel { @@ -43,10 +45,10 @@ public: private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); - std::vector, std::string> >_selectorVec; - std::vector, std::string> > _getSelectorVec(); - std::string _populateTree(std::vector, - std::string> >); + + std::vector<_selectorVecType>_selectorVec; + std::vector<_selectorVecType> _getSelectorVec(); + std::string _populateTree(std::vector<_selectorVecType>); bool _handleButtonEvent(GdkEventButton *event); void _selectedRowCallback(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* /* column */); @@ -62,7 +64,7 @@ private: { add(_selectorLabel); add(_colAddRemove); add(_colObj); } Gtk::TreeModelColumn _selectorLabel; Gtk::TreeModelColumn _colAddRemove; - Gtk::TreeModelColumn _colObj; + Gtk::TreeModelColumn > _colObj; }; SPDesktop* _desktop; -- 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') 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 +++++++++++++++++++++++++++---------------- src/ui/dialog/styledialog.h | 4 +- 2 files changed, 59 insertions(+), 34 deletions(-) (limited to 'src/ui') 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(); } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index e47fbc96d..08061d923 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -50,8 +50,8 @@ private: std::vector<_selectorVecType> _getSelectorVec(); std::string _populateTree(std::vector<_selectorVecType>); bool _handleButtonEvent(GdkEventButton *event); - void _selectedRowCallback(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* /* column */); + void _buttonEventsSelectObjs(GdkEventButton *event); + void _selectObjects(int, int); void _checkAllChildren(Gtk::TreeModel::Children& children); Inkscape::XML::Node *_styleElementNode(); void _updateStyleContent(); -- 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') 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') 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') 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') 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') 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/CMakeLists.txt | 2 + src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/cssdialog.cpp | 83 ++++++++++++++++++++++++++++++++++++++++ src/ui/dialog/cssdialog.h | 66 ++++++++++++++++++++++++++++++++ src/ui/dialog/dialog-manager.cpp | 3 ++ src/ui/dialog/styledialog.cpp | 55 ++++++++++++++++++++++++++ src/ui/dialog/styledialog.h | 2 + 7 files changed, 213 insertions(+) create mode 100644 src/ui/dialog/cssdialog.cpp create mode 100644 src/ui/dialog/cssdialog.h (limited to 'src/ui') diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 4be3fa3d2..4d838eb7f 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -57,6 +57,7 @@ set(ui_SRC dialog/calligraphic-profile-rename.cpp dialog/clonetiler.cpp dialog/color-item.cpp + dialog/cssdialog.cpp dialog/debug.cpp dialog/desktop-tracker.cpp dialog/dialog-manager.cpp @@ -197,6 +198,7 @@ set(ui_SRC dialog/calligraphic-profile-rename.h dialog/clonetiler.h dialog/color-item.h + dialog/cssdialog.h dialog/debug.h dialog/desktop-tracker.h dialog/dialog-manager.h diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 982908731..3add3f214 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -13,6 +13,8 @@ ink_common_sources += \ ui/dialog/clonetiler.h \ ui/dialog/color-item.cpp \ ui/dialog/color-item.h \ + ui/dialog/cssdialog.cpp \ + ui/dialog/cssdialog.h \ ui/dialog/debug.cpp \ ui/dialog/debug.h \ ui/dialog/desktop-tracker.cpp \ diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp new file mode 100644 index 000000000..b0123482b --- /dev/null +++ b/src/ui/dialog/cssdialog.cpp @@ -0,0 +1,83 @@ +/** @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 "cssdialog.h" +#include "ui/widget/addtoicon.h" +#include "widgets/icon.h" +#include "verbs.h" +#include "sp-object.h" +#include "selection.h" +#include "xml/attribute-record.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +CssDialog::CssDialog(): + UI::Widget::Panel("", "/dialogs/css", SP_VERB_DIALOG_CSS), + _desktop(0) +{ + set_size_request(50, 50); + _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(_cssColumns); + _treeView.set_model(_store); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( + new Inkscape::UI::Widget::AddToIcon() ); + addRenderer->property_active() = false; + + int addCol = _treeView.append_column("Unset Property", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _treeView.get_column(addCol); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _cssColumns._colUnsetProp); + } + _textRenderer = Gtk::manage(new Gtk::CellRendererText()); + _textRenderer->property_editable() = true; + + int nameColNum = _treeView.append_column("Property", *_textRenderer) - 1; + _propCol = _treeView.get_column(nameColNum); + + _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); + + _targetDesktop = getDesktop(); + setDesktop(_targetDesktop); + + _textRenderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog:: + _handleEdited)); +} + +CssDialog::~CssDialog() +{ + setDesktop(NULL); +} + +void CssDialog::setDesktop( SPDesktop* desktop ) +{ + _desktop = desktop; +} + +void CssDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _treeView.get_model()->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + row[_cssColumns._propertyLabel] = new_text; + editedProp = new_text; + } +} + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h new file mode 100644 index 000000000..03ffdf972 --- /dev/null +++ b/src/ui/dialog/cssdialog.h @@ -0,0 +1,66 @@ +/** @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 + */ + +#ifndef CSSDIALOG_H +#define CSSDIALOG_H + +#include +#include +#include +#include +#include + +#include "desktop.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class CssDialog : public UI::Widget::Panel +{ +public: + CssDialog(); + ~CssDialog(); + + static CssDialog &getInstance() { return *new CssDialog(); } + void setDesktop( SPDesktop* desktop); + + class CssColumns : public Gtk::TreeModel::ColumnRecord + { + public: + CssColumns() + { add(_colUnsetProp); add(_propertyLabel); } + Gtk::TreeModelColumn _colUnsetProp; + Gtk::TreeModelColumn _propertyLabel; + }; + + SPDesktop* _desktop; + SPDesktop* _targetDesktop; + CssColumns _cssColumns; + Gtk::VBox _mainBox; + Gtk::TreeView _treeView; + Glib::RefPtr _store; + Gtk::ScrolledWindow _scrolledWindow; + Gtk::TreeModel::Row propRow; + Gtk::CellRendererText *_textRenderer; + Gtk::TreeViewColumn *_propCol; + Glib::ustring editedProp; + + void _handleButtonEvent(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn*col); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); +}; + + +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // CSSDIALOG_H diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 4bb5215fd..a225d193c 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -61,6 +61,7 @@ #include "ui/dialog/objects.h" #include "ui/dialog/tags.h" #include "ui/dialog/styledialog.h" +#include "ui/dialog/cssdialog.h" namespace Inkscape { namespace UI { @@ -130,6 +131,7 @@ DialogManager::DialogManager() { registerFactory("TileDialog", &create); registerFactory("Symbols", &create); registerFactory("StyleDialog", &create); + registerFactory("CssDialog", &create); #if HAVE_POTRACE registerFactory("Trace", &create); @@ -170,6 +172,7 @@ DialogManager::DialogManager() { registerFactory("TileDialog", &create); registerFactory("Symbols", &create); registerFactory("StyleDialog", &create); + registerFactory("CssDialog", &create); #if HAVE_POTRACE registerFactory("Trace", &create); 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(); + } } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 08061d923..4f5f212b2 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -21,6 +21,7 @@ #include "desktop.h" #include "document.h" +#include "ui/dialog/cssdialog.h" namespace Inkscape { namespace UI { @@ -85,6 +86,7 @@ private: std::string _selectorValue; Gtk::TreeModel::Row _row; bool _newDrawing; + CssDialog *_cssPane; // Signal handlers void _addSelector(); -- 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/cssdialog.cpp | 18 +++------- src/ui/dialog/cssdialog.h | 11 ++++--- src/ui/dialog/styledialog.cpp | 77 ++++++++++++++++++++++++++++++++++++++++--- src/ui/dialog/styledialog.h | 3 ++ 4 files changed, 88 insertions(+), 21 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index b0123482b..e12716d6e 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -21,6 +21,11 @@ namespace Inkscape { namespace UI { namespace Dialog { +/** + * Constructor + * A treeview whose each row corresponds to a CSS property of selector selected. + * TODO: Further, buttons to add and delete properties will be added. + */ CssDialog::CssDialog(): UI::Widget::Panel("", "/dialogs/css", SP_VERB_DIALOG_CSS), _desktop(0) @@ -53,9 +58,6 @@ CssDialog::CssDialog(): _targetDesktop = getDesktop(); setDesktop(_targetDesktop); - - _textRenderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog:: - _handleEdited)); } CssDialog::~CssDialog() @@ -68,16 +70,6 @@ void CssDialog::setDesktop( SPDesktop* desktop ) _desktop = desktop; } -void CssDialog::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _treeView.get_model()->get_iter(path); - if (iter) { - Gtk::TreeModel::Row row = *iter; - row[_cssColumns._propertyLabel] = new_text; - editedProp = new_text; - } -} - } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h index 03ffdf972..4ff79c219 100644 --- a/src/ui/dialog/cssdialog.h +++ b/src/ui/dialog/cssdialog.h @@ -24,6 +24,10 @@ namespace Inkscape { namespace UI { namespace Dialog { +/** + * @brief The CssDialog class + * A list of CSS properties will show up in this dialog. + */ class CssDialog : public UI::Widget::Panel { public: @@ -49,13 +53,12 @@ public: Gtk::TreeView _treeView; Glib::RefPtr _store; Gtk::ScrolledWindow _scrolledWindow; - Gtk::TreeModel::Row propRow; + Gtk::TreeModel::Row _propRow; Gtk::CellRendererText *_textRenderer; Gtk::TreeViewColumn *_propCol; - Glib::ustring editedProp; + Glib::ustring _editedProp; - void _handleButtonEvent(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn*col); - void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleButtonEvent(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *col); }; 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 4f5f212b2..31a28dc1f 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -91,6 +91,9 @@ private: // Signal handlers void _addSelector(); void _delSelector(); + + // Signal handler for CssDialog + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); }; } // namespace Dialog -- 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') 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/cssdialog.cpp | 2 +- src/ui/dialog/styledialog.cpp | 6 +++--- src/ui/dialog/styledialog.h | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index e12716d6e..9007faafc 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -30,7 +30,7 @@ CssDialog::CssDialog(): UI::Widget::Panel("", "/dialogs/css", SP_VERB_DIALOG_CSS), _desktop(0) { - set_size_request(50, 50); + set_size_request(20, 15); _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); _treeView.set_headers_visible(false); _scrolledWindow.add(_treeView); 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(); } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 31a28dc1f..b3a8580f1 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "desktop.h" #include "document.h" @@ -71,6 +72,7 @@ private: SPDesktop* _desktop; SPDesktop* _targetDesktop; ModelColumns _mColumns; + Gtk::VPaned _paned; Gtk::VBox _mainBox; Gtk::HBox _buttonBox; Gtk::TreeView _treeView; -- 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 +++++++++++++++++++++++-------------------- src/ui/dialog/styledialog.h | 15 +++++-- 2 files changed, 60 insertions(+), 47 deletions(-) (limited to 'src/ui') 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(); } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index b3a8580f1..54d6f5528 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -48,9 +48,17 @@ private: void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); std::string _setClassAttribute(std::vector); - std::vector<_selectorVecType>_selectorVec; - std::vector<_selectorVecType> _getSelectorVec(); - std::string _populateTree(std::vector<_selectorVecType>); + class InkSelector { + public: + std::string _selector; + std::vector _matchingObjs; + std::string _xmlContent; + }; + + InkSelector inkSelector; + std::vector _selectorVec; + std::vector _getSelectorVec(); + std::string _populateTree(std::vector); bool _handleButtonEvent(GdkEventButton *event); void _buttonEventsSelectObjs(GdkEventButton *event); void _selectObjects(int, int); @@ -83,7 +91,6 @@ private: SPDocument* _document; bool _styleExists; Inkscape::XML::Node *_styleChild; - unsigned _num; std::string _selectorName; std::string _selectorValue; Gtk::TreeModel::Row _row; -- 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') 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/cssdialog.cpp | 37 +++++++++++ src/ui/dialog/cssdialog.h | 6 +- src/ui/dialog/styledialog.cpp | 146 ++++++++++++++++++++++++++++++++++++------ src/ui/dialog/styledialog.h | 2 + 4 files changed, 170 insertions(+), 21 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index 9007faafc..cd2f74d15 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -21,6 +21,23 @@ namespace Inkscape { namespace UI { namespace Dialog { +/** + * @brief CssDialog::_styleButton + * @param btn + * @param iconName + * @param tooltip + * This function sets the style of '+'button at the bottom of dialog. + */ +void CssDialog::_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 whose each row corresponds to a CSS property of selector selected. @@ -54,10 +71,18 @@ CssDialog::CssDialog(): int nameColNum = _treeView.append_column("Property", *_textRenderer) - 1; _propCol = _treeView.get_column(nameColNum); + create = manage(new Gtk::Button()); + _styleButton(*create, "list-add", "Add a new property"); + + _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); + _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); + _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); _targetDesktop = getDesktop(); setDesktop(_targetDesktop); + + create->signal_clicked().connect(sigc::mem_fun(*this, &CssDialog::_addProperty)); } CssDialog::~CssDialog() @@ -70,6 +95,18 @@ void CssDialog::setDesktop( SPDesktop* desktop ) _desktop = desktop; } +/** + * @brief CssDialog::_addProperty + * This function is a slot to signal_clicked for '+' button at the bottom of CSS + * panel. A new row is added, double clicking which text for new property can be + * added. _newProperty is set to true in which case the value is appended. + */ +void CssDialog::_addProperty() +{ + _propRow = *(_store->append()); + _newProperty = true; +} + } // namespace Dialog } // namespace UI } // namespace Inkscape diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h index 4ff79c219..ef48686cc 100644 --- a/src/ui/dialog/cssdialog.h +++ b/src/ui/dialog/cssdialog.h @@ -50,6 +50,7 @@ public: SPDesktop* _targetDesktop; CssColumns _cssColumns; Gtk::VBox _mainBox; + Gtk::HBox _buttonBox; Gtk::TreeView _treeView; Glib::RefPtr _store; Gtk::ScrolledWindow _scrolledWindow; @@ -57,8 +58,11 @@ public: Gtk::CellRendererText *_textRenderer; Gtk::TreeViewColumn *_propCol; Glib::ustring _editedProp; + Gtk::Button* create; + bool _newProperty; - void _handleButtonEvent(const Gtk::TreeModel::Path &path, Gtk::TreeViewColumn *col); + void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); + void _addProperty(); }; 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 54d6f5528..a1048a97d 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -100,9 +100,11 @@ private: // Signal handlers void _addSelector(); void _delSelector(); + void _selChanged(); // Signal handler for CssDialog void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + bool _delProperty(GdkEventButton *event); }; } // namespace Dialog -- 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') 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') 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') 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') 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 ++++++++++++++++++++++++------------------ src/ui/dialog/styledialog.h | 2 +- 2 files changed, 164 insertions(+), 127 deletions(-) (limited to 'src/ui') 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 { diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index a1048a97d..af3014f88 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -93,9 +93,9 @@ private: Inkscape::XML::Node *_styleChild; std::string _selectorName; std::string _selectorValue; - Gtk::TreeModel::Row _row; bool _newDrawing; CssDialog *_cssPane; + void _selAdd(Gtk::TreeModel::Row row); // Signal handlers void _addSelector(); -- 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') 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') 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') 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/cssdialog.cpp | 29 ++++++++--- src/ui/dialog/cssdialog.h | 10 ++-- src/ui/dialog/styledialog.cpp | 116 ++++++++++++++++++++++++------------------ src/ui/dialog/styledialog.h | 11 ++-- 4 files changed, 100 insertions(+), 66 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index cd2f74d15..fa266b012 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -35,13 +35,17 @@ void CssDialog::_styleButton(Gtk::Button& btn, char const* iconName, gtk_widget_show(child); btn.add(*manage(Glib::wrap(child))); btn.set_relief(Gtk::RELIEF_NONE); - btn.set_tooltip_text (tooltip); + btn.set_tooltip_text(tooltip); } /** * Constructor * A treeview whose each row corresponds to a CSS property of selector selected. - * TODO: Further, buttons to add and delete properties will be added. + * New CSS property can be added by clicking '+' at bottom of the CSS pane. '-' + * in front of the CSS property row can be clicked to delete the CSS property. + * Besides clicking on an already selected property row makes the property editable + * and clicking 'Enter' updates the property with changes reflected in the + * drawing. */ CssDialog::CssDialog(): UI::Widget::Panel("", "/dialogs/css", SP_VERB_DIALOG_CSS), @@ -56,14 +60,14 @@ CssDialog::CssDialog(): _store = Gtk::ListStore::create(_cssColumns); _treeView.set_model(_store); - Inkscape::UI::Widget::AddToIcon * addRenderer = manage( - new Inkscape::UI::Widget::AddToIcon() ); + Inkscape::UI::Widget::AddToIcon * addRenderer = manage(new Inkscape::UI:: + Widget::AddToIcon()); addRenderer->property_active() = false; int addCol = _treeView.append_column("Unset Property", *addRenderer) - 1; Gtk::TreeViewColumn *col = _treeView.get_column(addCol); - if ( col ) { - col->add_attribute( addRenderer->property_active(), _cssColumns._colUnsetProp); + if (col) { + col->add_attribute(addRenderer->property_active(), _cssColumns._colUnsetProp); } _textRenderer = Gtk::manage(new Gtk::CellRendererText()); _textRenderer->property_editable() = true; @@ -71,7 +75,7 @@ CssDialog::CssDialog(): int nameColNum = _treeView.append_column("Property", *_textRenderer) - 1; _propCol = _treeView.get_column(nameColNum); - create = manage(new Gtk::Button()); + Gtk::Button* create = manage(new Gtk::Button()); _styleButton(*create, "list-add", "Add a new property"); _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); @@ -85,12 +89,21 @@ CssDialog::CssDialog(): create->signal_clicked().connect(sigc::mem_fun(*this, &CssDialog::_addProperty)); } +/** + * @brief CssDialog::~CssDialog + * Class destructor + */ CssDialog::~CssDialog() { setDesktop(NULL); } -void CssDialog::setDesktop( SPDesktop* desktop ) +/** + * @brief CssDialog::setDesktop + * @param desktop + * This function sets the 'desktop' for the CSS pane. + */ +void CssDialog::setDesktop(SPDesktop* desktop) { _desktop = desktop; } diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h index ef48686cc..3bbab5031 100644 --- a/src/ui/dialog/cssdialog.h +++ b/src/ui/dialog/cssdialog.h @@ -26,7 +26,10 @@ namespace Dialog { /** * @brief The CssDialog class - * A list of CSS properties will show up in this dialog. + * This dialog allows to add, delete and modify CSS properties for selectors + * created in Style Dialog. Double clicking any selector in Style dialog, a list + * of CSS properties will show up in this dialog (if any exist), else new properties + * can be added and each new property forms a new row in this pane. */ class CssDialog : public UI::Widget::Panel { @@ -35,7 +38,7 @@ public: ~CssDialog(); static CssDialog &getInstance() { return *new CssDialog(); } - void setDesktop( SPDesktop* desktop); + void setDesktop(SPDesktop* desktop); class CssColumns : public Gtk::TreeModel::ColumnRecord { @@ -58,10 +61,9 @@ public: Gtk::CellRendererText *_textRenderer; Gtk::TreeViewColumn *_propCol; Glib::ustring _editedProp; - Gtk::Button* create; bool _newProperty; - void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); + void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); void _addProperty(); }; 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 { diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index af3014f88..b03a1d2e1 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -30,7 +30,10 @@ namespace Dialog { /** * @brief The StyleDialog class - * A list of CSS selectors will show up in this dialog. + * A list of CSS selectors will show up in this dialog. This dialog allows to + * add and delete selectors. Objects can be added to and removed from the selectors + * in the dialog. Besides, selection of any selector row selects the matching + * objects in the drawing and vice-versa. */ typedef std::pair >, std::string> _selectorVecType; @@ -42,11 +45,11 @@ public: ~StyleDialog(); static StyleDialog &getInstance() { return *new StyleDialog(); } - void setDesktop( SPDesktop* desktop); + void setDesktop(SPDesktop* desktop); private: - void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip); - std::string _setClassAttribute(std::vector); + void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); + std::string _setClassAttribute(std::vector); class InkSelector { public: -- cgit v1.2.3 From bfcc1fb5a5142a71469834cac2d507f15626a8b5 Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Wed, 4 Jan 2017 03:32:40 +0200 Subject: Extract some common code into a routine. (bzr r15369.1.8) --- src/ui/clipboard.cpp | 11 ++--------- src/ui/interface.cpp | 11 ++--------- 2 files changed, 4 insertions(+), 18 deletions(-) (limited to 'src/ui') diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index a8e708597..73b632a2c 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -76,6 +76,7 @@ #include "sp-namedview.h" #include "persp3d.h" #include "object-set.h" +#include "extension/find_extension_by_mime.h" /// Made up mimetype to represent Gdk::Pixbuf clipboard contents. #define CLIPBOARD_GDK_PIXBUF_TARGET "image/x-gdk-pixbuf" @@ -945,15 +946,7 @@ bool ClipboardManagerImpl::_pasteImage(SPDocument *doc) return false; } - // TODO unify with interface.cpp's sp_ui_drag_data_received() - // AARGH stupid - Inkscape::Extension::DB::InputList o; - Inkscape::Extension::db.get_input_list(o); - Inkscape::Extension::DB::InputList::const_iterator i = o.begin(); - while (i != o.end() && strcmp( (*i)->get_mimetype(), "image/png" ) != 0) { - ++i; - } - Inkscape::Extension::Extension *png = *i; + Inkscape::Extension::Extension *png = Inkscape::Extension::find_by_mime("image/png"); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Glib::ustring attr_saved = prefs->getString("/dialogs/import/link"); bool ask_saved = prefs->getBool("/dialogs/import/ask"); diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp index d50c56b76..5e85065d1 100644 --- a/src/ui/interface.cpp +++ b/src/ui/interface.cpp @@ -72,6 +72,7 @@ #include "sp-mask.h" #include "message-stack.h" #include "ui/dialog/layer-properties.h" +#include "extension/find_extension_by_mime.h" using Inkscape::DocumentUndo; @@ -1234,15 +1235,7 @@ sp_ui_drag_data_received(GtkWidget *widget, case PNG_DATA: case JPEG_DATA: case IMAGE_DATA: { - const char *mime = (info == JPEG_DATA ? "image/jpeg" : "image/png"); - - Inkscape::Extension::DB::InputList o; - Inkscape::Extension::db.get_input_list(o); - Inkscape::Extension::DB::InputList::const_iterator i = o.begin(); - while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) { - ++i; - } - Inkscape::Extension::Extension *ext = *i; + Inkscape::Extension::Extension *ext = Inkscape::Extension::find_by_mime((info == JPEG_DATA ? "image/jpeg" : "image/png")); bool save = (strcmp(ext->get_param_optiongroup("link"), "embed") == 0); ext->set_param_optiongroup("link", "embed"); ext->set_gui(false); -- cgit v1.2.3 From 16f60109208481bdf7c28e7ea4c93c661bc49d9d Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Wed, 4 Jan 2017 21:01:13 +0200 Subject: Correct/rephrase a comment. Remove trailing space. (bzr r15369.1.11) --- src/ui/tools/freehand-base.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/ui') diff --git a/src/ui/tools/freehand-base.h b/src/ui/tools/freehand-base.h index a3e7b42f9..3ee4cd7d0 100644 --- a/src/ui/tools/freehand-base.h +++ b/src/ui/tools/freehand-base.h @@ -76,8 +76,10 @@ public: GSList *white_curves; GSList *white_anchors; - //ALternative curve to use on continuing exisiting curve in case of bspline or spirolive - //because usigh anchor curves give memory and random bugs, - and obscure code- in some plataform reported by su_v in mac + // Alternative curve to use on continuing the exisiting curve in case of + // bspline or spirolive, because using anchor curves gives random memory + // bugs as reported by su_v when running this code on macOS (as well as + // making the code hard to understand). SPCurve *overwrite_curve; // Start anchor -- cgit v1.2.3 From bbb714926033738fb53a2d1fd794a391d4c5a292 Mon Sep 17 00:00:00 2001 From: jabiertxof <> Date: Thu, 26 Jan 2017 02:24:46 +0100 Subject: defaults to about.svg when localized versions fail (bzr r15453) --- src/ui/dialog/aboutbox.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/ui') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 8f0545e96..e7572b3ce 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -162,6 +162,9 @@ Gtk::Widget *build_splash_widget() { // should be in UTF-*8.. char *about=g_build_filename(INKSCAPE_SCREENSDIR, _("about.svg"), NULL); + if (!g_file_test (about, G_FILE_TEST_EXISTS)) { + about=g_build_filename(INKSCAPE_SCREENSDIR, "about.svg", NULL); + } SPDocument *doc=SPDocument::createNewDoc (about, TRUE); g_free(about); g_return_val_if_fail(doc != NULL, NULL); -- cgit v1.2.3 From 4a81c0fc9ecb2b9196f6cedeaf2ea39d68408936 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 26 Jan 2017 16:50:34 +0100 Subject: [Bug #1659426] About screen - Missing image and small window - Translation comment. Fixed bugs: - https://launchpad.net/bugs/1659426 (bzr r15456) --- src/ui/dialog/aboutbox.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index e7572b3ce..40b948a23 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -152,10 +152,7 @@ Gtk::Widget *build_splash_widget() { the `screens' directory. Thus the translation of "about.svg" should be the filename of its translated version, e.g. about.zh.svg for Chinese. - N.B. about.svg changes once per release. (We should probably rename - the original to about-0.40.svg etc. as soon as we have a translation. - If we do so, then add an item to release-checklist saying that the - string here should be changed.) */ + Please don't translate the filename unless the translated picture exists. */ // FIXME? INKSCAPE_SCREENSDIR and "about.svg" are in UTF-8, not the // native filename encoding... and the filename passed to sp_document_new -- cgit v1.2.3 From 09f59f6114bb5d31bdc8bf0768cd55a111a35349 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Wed, 1 Feb 2017 21:19:06 +0100 Subject: Fix typo. (bzr r15463) --- src/ui/tools/mesh-tool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui') diff --git a/src/ui/tools/mesh-tool.cpp b/src/ui/tools/mesh-tool.cpp index e628094d9..ac43b6c9d 100644 --- a/src/ui/tools/mesh-tool.cpp +++ b/src/ui/tools/mesh-tool.cpp @@ -1137,7 +1137,7 @@ static void sp_mesh_new_default(MeshTool &rc) { Inkscape::FOR_FILL : Inkscape::FOR_STROKE; // Ensure mesh is immediately editable. - // Editting both fill and stroke at same time doesn't work well so avoid. + // Editing both fill and stroke at same time doesn't work well so avoid. if (fill_or_stroke == Inkscape::FOR_FILL) { prefs->setBool("/tools/mesh/edit_fill", true ); prefs->setBool("/tools/mesh/edit_stroke", false); -- cgit v1.2.3 From 349536d49558ec5841e799eb33a4cbbb3fa9722d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sun, 5 Feb 2017 16:04:35 +0000 Subject: Fix C++11 errors and warnings with g++-7 Fixed bugs: - https://launchpad.net/bugs/1660992 (bzr r15477) --- src/ui/tools/flood-tool.cpp | 59 +++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 18 deletions(-) (limited to 'src/ui') diff --git a/src/ui/tools/flood-tool.cpp b/src/ui/tools/flood-tool.cpp index 1801a0ea0..6e1d085aa 100644 --- a/src/ui/tools/flood-tool.cpp +++ b/src/ui/tools/flood-tool.cpp @@ -21,6 +21,7 @@ #include #endif +#include #include "trace/potrace/inkscape-potrace.h" #include <2geom/pathvector.h> #include @@ -185,6 +186,21 @@ inline unsigned char * get_trace_pixel(guchar *trace_px, int x, int y, int width return trace_px + (x + y * width); } +/** + * \brief Check whether two unsigned integers are close to each other + * + * \param[in] a The 1st unsigned int + * \param[in] b The 2nd unsigned int + * \param[in] d The threshold for comparison + * + * \return true if |a-b| <= d; false otherwise + */ +static bool compare_guint32(guint32 const a, guint32 const b, guint32 const d) +{ + const int difference = std::abs(static_cast(a) - static_cast(b)); + return difference <= d; +} + /** * Compare a pixel in a pixel buffer with another pixel to determine if a point should be included in the fill operation. * @param check The pixel in the pixel buffer to check. @@ -196,7 +212,6 @@ inline unsigned char * get_trace_pixel(guchar *trace_px, int x, int y, int width */ static bool compare_pixels(guint32 check, guint32 orig, guint32 merged_orig_pixel, guint32 dtc, int threshold, PaintBucketChannels method) { - int diff = 0; float hsl_check[3] = {0,0,0}, hsl_orig[3] = {0,0,0}; guint32 ac = 0, rc = 0, gc = 0, bc = 0; @@ -222,27 +237,35 @@ static bool compare_pixels(guint32 check, guint32 orig, guint32 merged_orig_pixe switch (method) { case FLOOD_CHANNELS_ALPHA: - return abs(static_cast(ac) - ao) <= threshold; + return compare_guint32(ac, ao, threshold); case FLOOD_CHANNELS_R: - return abs(static_cast(ac ? unpremul_alpha(rc, ac) : 0) - (ao ? unpremul_alpha(ro, ao) : 0)) <= threshold; + return compare_guint32(ac ? unpremul_alpha(rc, ac) : 0, + ao ? unpremul_alpha(ro, ao) : 0, + threshold); case FLOOD_CHANNELS_G: - return abs(static_cast(ac ? unpremul_alpha(gc, ac) : 0) - (ao ? unpremul_alpha(go, ao) : 0)) <= threshold; + return compare_guint32(ac ? unpremul_alpha(gc, ac) : 0, + ao ? unpremul_alpha(go, ao) : 0, + threshold); case FLOOD_CHANNELS_B: - return abs(static_cast(ac ? unpremul_alpha(bc, ac) : 0) - (ao ? unpremul_alpha(bo, ao) : 0)) <= threshold; + return compare_guint32(ac ? unpremul_alpha(bc, ac) : 0, + ao ? unpremul_alpha(bo, ao) : 0, + threshold); case FLOOD_CHANNELS_RGB: - guint32 amc, rmc, bmc, gmc; - //amc = 255*255 - (255-ac)*(255-ad); amc = (amc + 127) / 255; - //amc = (255-ac)*ad + 255*ac; amc = (amc + 127) / 255; - amc = 255; // Why are we looking at desktop? Cairo version ignores destop alpha - rmc = (255-ac)*rd + 255*rc; rmc = (rmc + 127) / 255; - gmc = (255-ac)*gd + 255*gc; gmc = (gmc + 127) / 255; - bmc = (255-ac)*bd + 255*bc; bmc = (bmc + 127) / 255; - - diff += abs(static_cast(amc ? unpremul_alpha(rmc, amc) : 0) - (amop ? unpremul_alpha(rmop, amop) : 0)); - diff += abs(static_cast(amc ? unpremul_alpha(gmc, amc) : 0) - (amop ? unpremul_alpha(gmop, amop) : 0)); - diff += abs(static_cast(amc ? unpremul_alpha(bmc, amc) : 0) - (amop ? unpremul_alpha(bmop, amop) : 0)); - return ((diff / 3) <= ((threshold * 3) / 4)); - + { + guint32 amc, rmc, bmc, gmc; + //amc = 255*255 - (255-ac)*(255-ad); amc = (amc + 127) / 255; + //amc = (255-ac)*ad + 255*ac; amc = (amc + 127) / 255; + amc = 255; // Why are we looking at desktop? Cairo version ignores destop alpha + rmc = (255-ac)*rd + 255*rc; rmc = (rmc + 127) / 255; + gmc = (255-ac)*gd + 255*gc; gmc = (gmc + 127) / 255; + bmc = (255-ac)*bd + 255*bc; bmc = (bmc + 127) / 255; + + int diff = 0; // The total difference between each of the 3 color components + diff += std::abs(static_cast(amc ? unpremul_alpha(rmc, amc) : 0) - static_cast(amop ? unpremul_alpha(rmop, amop) : 0)); + diff += std::abs(static_cast(amc ? unpremul_alpha(gmc, amc) : 0) - static_cast(amop ? unpremul_alpha(gmop, amop) : 0)); + diff += std::abs(static_cast(amc ? unpremul_alpha(bmc, amc) : 0) - static_cast(amop ? unpremul_alpha(bmop, amop) : 0)); + return ((diff / 3) <= ((threshold * 3) / 4)); + } case FLOOD_CHANNELS_H: return ((int)(fabs(hsl_check[0] - hsl_orig[0]) * 100.0) <= threshold); case FLOOD_CHANNELS_S: -- cgit v1.2.3 From 57cb0b342004378ad4065f07443ab1d835aefaad Mon Sep 17 00:00:00 2001 From: Shlomi Fish Date: Sun, 5 Feb 2017 18:50:57 +0100 Subject: fix crash when inserting nodes Fixed bugs: - https://launchpad.net/bugs/1617615 (bzr r15479) --- src/ui/tool/multi-path-manipulator.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/ui') diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index c908cede2..4f152e0a2 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -82,8 +82,19 @@ private: template void invokeForAll(R (PathManipulator::*method)()) { - for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) { - ((i->second.get())->*method)(); + for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ) { + // Sometimes the PathManipulator got freed at loop end, thus + // invalidating the iterator so make sure that next_i will + // be a valid iterator and then assign i to it. + MapType::iterator next_i = i; + ++next_i; + // i->second is a boost::shared_ptr so try to hold on to it so + // it won't get freed prematurely by the WriteXML() method or + // whatever. See https://bugs.launchpad.net/inkscape/+bug/1617615 + // Applicable to empty paths. + boost::shared_ptr hold(i->second); + ((hold.get())->*method)(); + i = next_i; } } template -- cgit v1.2.3 From 1e3e159499532a145cf09af2dbd1de2ae4d8d565 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Mon, 6 Feb 2017 15:34:17 +0000 Subject: Remove some unneeded < C++11 fallback code (bzr r15485) --- src/ui/tool/node.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/ui') diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index 025c460e2..a05f0e3b9 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -20,12 +20,7 @@ #include #include #include - -#if __cplusplus >= 201103L #include -#else -#include -#endif #include #include -- 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 +++++++++++ src/ui/dialog/styledialog.h | 30 ++++++++++++++++++++++-------- 2 files changed, 33 insertions(+), 8 deletions(-) (limited to 'src/ui') 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 : diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index b03a1d2e1..3cc4349e6 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -30,16 +30,16 @@ namespace Dialog { /** * @brief The StyleDialog class - * A list of CSS selectors will show up in this dialog. This dialog allows to - * add and delete selectors. Objects can be added to and removed from the selectors - * in the dialog. Besides, selection of any selector row selects the matching - * objects in the drawing and vice-versa. + * A list of CSS selectors will show up in this dialog. This dialog allows one to + * add and delete selectors. Elements can be added to and removed from the selectors + * in the dialog. Selection of any selector row selects the matching objects in + * the drawing and vice-versa. */ typedef std::pair >, std::string> _selectorVecType; -class StyleDialog : public UI::Widget::Panel -{ +class StyleDialog : public Widget::Panel { + public: StyleDialog(); ~StyleDialog(); @@ -73,8 +73,11 @@ private: class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: - ModelColumns() - { add(_selectorLabel); add(_colAddRemove); add(_colObj); } + ModelColumns() { + add(_selectorLabel); + add(_colAddRemove); + add(_colObj); + } Gtk::TreeModelColumn _selectorLabel; Gtk::TreeModelColumn _colAddRemove; Gtk::TreeModelColumn > _colObj; @@ -115,3 +118,14 @@ private: } // namespace Inkscape #endif // STYLEDIALOG_H + +/* + 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') 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 bd4bad24c8e2c428e07d8afc5bc1009e9809be1b Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Fri, 10 Feb 2017 22:26:04 +0100 Subject: Fix encoding/escaping issues with symbols loaded from .vss (Visio stencils) files There were three issues: - When loading a .vss file an SVG document is created internally and the file name is used to derive this document's "title". This could result in illegal characters (e.g. the ampersand "&") in the title making the document fail to load. The title is now properly escaped. - Loading of files with non-ANSI characers in filename failed on Windows. Fix is equivalent to r15421, see also bug #1416949. - The .vss file name is also used to derive symbol IDs, which were not properly sanitized before (i.e. could cause broken hrefs later or even prevent to load the .vss file). Characters that do not match [a-zA-Z0-9_-] are now laways replaced with an underscore "_") which will result in valid IDs in almost all cases Fixed bugs: - https://launchpad.net/bugs/1662465 (bzr r15501) --- src/ui/dialog/symbols.cpp | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 4840b897b..c8a11b112 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -127,7 +127,7 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : sigc::connection connSet = symbolSet->signal_changed().connect( sigc::mem_fun(*this, &SymbolsDialog::rebuild)); instanceConns.push_back(connSet); - + ++row; /********************* Icon View **************************/ @@ -342,7 +342,7 @@ void SymbolsDialog::rebuild() { addSymbol->set_sensitive( true ); removeSymbol->set_sensitive( true ); } else { - addSymbol->set_sensitive( false ); + addSymbol->set_sensitive( false ); removeSymbol->set_sensitive( false ); } add_symbols( symbolDocument ); @@ -451,7 +451,14 @@ void SymbolsDialog::iconChanged() { #ifdef WITH_LIBVISIO // Read Visio stencil files -SPDocument* read_vss( gchar* fullname, gchar* filename ) { +SPDocument* read_vss( gchar* fullname, Glib::ustring name ) { + + #ifdef WIN32 + // RVNGFileStream uses fopen() internally which unfortunately only uses ANSI encoding on Windows + // therefore attempt to convert uri to the system codepage + // even if this is not possible the alternate short (8.3) file name will be used if available + fullname = g_win32_locale_filename_from_utf8(fullname); + #endif RVNGFileStream input(fullname); @@ -474,6 +481,12 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) { return NULL; } + // prepare a valid title for the symbol file + Glib::ustring title = Glib::Markup::escape_text(name); + // prepare a valid id prefix for the symbols (unfortunately libvisio doesn't give us a name) + Glib::RefPtr regex1 = Glib::Regex::create("[^a-zA-Z0-9_-]"); + Glib::ustring id = regex1->replace(name, 0, "_", Glib::REGEX_MATCH_PARTIAL); + Glib::ustring tmpSVGOutput; tmpSVGOutput += "\n"; tmpSVGOutput += "\n"; tmpSVGOutput += " "; - tmpSVGOutput += filename; + tmpSVGOutput += title; tmpSVGOutput += "\n"; tmpSVGOutput += " \n"; - // Create a string we can use for the symbol id (libvisio doesn't give us a name) - std::string sanitized( filename ); - sanitized.erase( sanitized.find_last_of(".vss")-3 ); - sanitized.erase( std::remove_if( sanitized.begin(), sanitized.end(), ispunct ), sanitized.end() ); - std::replace( sanitized.begin(), sanitized.end(), ' ', '_' ); - // std::cout << filename << " |" << sanitized << "|" << std::endl; - // Each "symbol" is in it's own SVG file, we wrap with and merge into one file. for (unsigned i=0; i\n"; @@ -521,12 +527,12 @@ SPDocument* read_vss( gchar* fullname, gchar* filename ) { tmpSVGOutput += " \n"; tmpSVGOutput += "\n"; - + return SPDocument::createNewDocFromMem( tmpSVGOutput.c_str(), strlen( tmpSVGOutput.c_str()), 0 ); } #endif - + /* Hunts preference directories for symbol files */ void SymbolsDialog::get_symbols() { @@ -565,11 +571,14 @@ void SymbolsDialog::get_symbols() { #ifdef WITH_LIBVISIO if( tag.compare( "vss" ) == 0 ) { + // strip extension from filename and use it as name for the symbol set + Glib::ustring name = Glib::ustring(filename); + name = name.erase(name.rfind('.')); - symbol_doc = read_vss( fullname, filename ); + symbol_doc = read_vss( fullname, name ); if( symbol_doc ) { - symbolSets[Glib::ustring(filename)]= symbol_doc; - symbolSet->append(filename); + symbolSets[name]= symbol_doc; + symbolSet->append(name); } } #endif @@ -630,7 +639,7 @@ GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { } GSList* SymbolsDialog::use_in_doc_recursive (SPObject *r, GSList *l) -{ +{ if ( dynamic_cast(r) ) { l = g_slist_prepend (l, r); @@ -816,7 +825,7 @@ SPDocument* SymbolsDialog::symbols_preview_doc() " xmlns:sodipodi=\"http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd\"" " xmlns:inkscape=\"http://www.inkscape.org/namespaces/inkscape\"" " xmlns:xlink=\"http://www.w3.org/1999/xlink\">" -" " +" " " " " " " " -- cgit v1.2.3 From 9f806b86e925bc6817cb111bc50e244cfa302d4a Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Fri, 10 Feb 2017 23:04:01 +0100 Subject: Add missing "#include " for previous commit (bzr r15502) --- src/ui/dialog/symbols.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/ui') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index c8a11b112..dcfb7f242 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include -- cgit v1.2.3 From 9faf941d45ce7d23f5cb0d066bd23346f7e3aedf Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Sat, 11 Feb 2017 01:16:53 +0100 Subject: Fix a memory leak introduced in r15421 and r15501 respectively (bzr r15505) --- src/ui/dialog/symbols.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/ui') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index dcfb7f242..740ff4f39 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -463,6 +463,10 @@ SPDocument* read_vss( gchar* fullname, Glib::ustring name ) { RVNGFileStream input(fullname); + #ifdef WIN32 + g_free(fullname); + #endif + if (!libvisio::VisioDocument::isSupported(&input)) { return NULL; } -- cgit v1.2.3 From 38ecca9e4639b8aecc55a4becfc1ed9b2793fadc Mon Sep 17 00:00:00 2001 From: Eduard Braun Date: Mon, 13 Feb 2017 22:37:42 +0100 Subject: AboutBox: Remove superfluous space in website URL (bzr r15516) --- src/ui/dialog/aboutbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 40b948a23..805bfb562 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -115,7 +115,7 @@ AboutBox::AboutBox() : Gtk::Dialog(_("About Inkscape")) { Gtk::Label *link = new Gtk::Label(); const gchar *website_link = - " https://www.inkscape.org"; + "https://www.inkscape.org"; link->set_markup(website_link); link->set_alignment(Gtk::ALIGN_END); -- 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/cssdialog.cpp | 53 +- src/ui/dialog/cssdialog.h | 35 +- src/ui/dialog/styledialog.cpp | 1529 +++++++++++++++++++---------------------- src/ui/dialog/styledialog.h | 93 +-- 4 files changed, 791 insertions(+), 919 deletions(-) (limited to 'src/ui') diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index fa266b012..d0ae822bd 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.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,23 +23,6 @@ namespace Inkscape { namespace UI { namespace Dialog { -/** - * @brief CssDialog::_styleButton - * @param btn - * @param iconName - * @param tooltip - * This function sets the style of '+'button at the bottom of dialog. - */ -void CssDialog::_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 whose each row corresponds to a CSS property of selector selected. @@ -60,8 +45,7 @@ CssDialog::CssDialog(): _store = Gtk::ListStore::create(_cssColumns); _treeView.set_model(_store); - Inkscape::UI::Widget::AddToIcon * addRenderer = manage(new Inkscape::UI:: - Widget::AddToIcon()); + Inkscape::UI::Widget::AddToIcon * addRenderer = manage(new Inkscape::UI::Widget::AddToIcon()); addRenderer->property_active() = false; int addCol = _treeView.append_column("Unset Property", *addRenderer) - 1; @@ -74,6 +58,10 @@ CssDialog::CssDialog(): int nameColNum = _treeView.append_column("Property", *_textRenderer) - 1; _propCol = _treeView.get_column(nameColNum); + if (_propCol) { + _propCol->add_attribute(_textRenderer->property_text(), + _cssColumns._propertyLabel); + } Gtk::Button* create = manage(new Gtk::Button()); _styleButton(*create, "list-add", "Add a new property"); @@ -83,12 +71,12 @@ CssDialog::CssDialog(): _getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET); - _targetDesktop = getDesktop(); - setDesktop(_targetDesktop); + setDesktop(getDesktop()); create->signal_clicked().connect(sigc::mem_fun(*this, &CssDialog::_addProperty)); } + /** * @brief CssDialog::~CssDialog * Class destructor @@ -98,6 +86,7 @@ CssDialog::~CssDialog() setDesktop(NULL); } + /** * @brief CssDialog::setDesktop * @param desktop @@ -108,16 +97,34 @@ void CssDialog::setDesktop(SPDesktop* desktop) _desktop = desktop; } + +/** + * @brief CssDialog::_styleButton + * @param btn + * @param iconName + * @param tooltip + * This function sets the style of '+'button at the bottom of dialog. + */ +void CssDialog::_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); +} + + /** * @brief CssDialog::_addProperty * This function is a slot to signal_clicked for '+' button at the bottom of CSS * panel. A new row is added, double clicking which text for new property can be - * added. _newProperty is set to true in which case the value is appended. + * added. */ void CssDialog::_addProperty() { _propRow = *(_store->append()); - _newProperty = true; } } // namespace Dialog diff --git a/src/ui/dialog/cssdialog.h b/src/ui/dialog/cssdialog.h index 3bbab5031..1f8b7ca98 100644 --- a/src/ui/dialog/cssdialog.h +++ b/src/ui/dialog/cssdialog.h @@ -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 */ @@ -38,32 +40,39 @@ public: ~CssDialog(); static CssDialog &getInstance() { return *new CssDialog(); } - void setDesktop(SPDesktop* desktop); - class CssColumns : public Gtk::TreeModel::ColumnRecord - { + // Data structure + class CssColumns : public Gtk::TreeModel::ColumnRecord { public: - CssColumns() - { add(_colUnsetProp); add(_propertyLabel); } + CssColumns() { + add(_colUnsetProp); + add(_propertyLabel); + } Gtk::TreeModelColumn _colUnsetProp; Gtk::TreeModelColumn _propertyLabel; }; - - SPDesktop* _desktop; - SPDesktop* _targetDesktop; CssColumns _cssColumns; - Gtk::VBox _mainBox; - Gtk::HBox _buttonBox; + + // TreeView Gtk::TreeView _treeView; Glib::RefPtr _store; - Gtk::ScrolledWindow _scrolledWindow; Gtk::TreeModel::Row _propRow; Gtk::CellRendererText *_textRenderer; Gtk::TreeViewColumn *_propCol; - Glib::ustring _editedProp; - bool _newProperty; + // Widgets + Gtk::VBox _mainBox; + Gtk::ScrolledWindow _scrolledWindow; + Gtk::HBox _buttonBox; + + // Variables - Inkscape + SPDesktop* _desktop; + + // Helper functions + void setDesktop(SPDesktop* desktop); void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); + + // Signal handlers void _addProperty(); }; 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 diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 3cc4349e6..37a186e40 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -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 */ @@ -33,11 +35,12 @@ namespace Dialog { * A list of CSS selectors will show up in this dialog. This dialog allows one to * add and delete selectors. Elements can be added to and removed from the selectors * in the dialog. Selection of any selector row selects the matching objects in - * the drawing and vice-versa. + * the drawing and vice-versa. (Only simple selectors supported for now.) + * + * This class must keep two things in sync: + * 1. The text node of the style element. + * 2. The Gtk::TreeModel. */ -typedef std::pair >, std::string> -_selectorVecType; - class StyleDialog : public Widget::Panel { public: @@ -45,75 +48,75 @@ public: ~StyleDialog(); static StyleDialog &getInstance() { return *new StyleDialog(); } + void setDesktop(SPDesktop* desktop); private: - void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); - std::string _setClassAttribute(std::vector); - class InkSelector { - public: - std::string _selector; - std::vector _matchingObjs; - std::string _xmlContent; - }; - - InkSelector inkSelector; - std::vector _selectorVec; - std::vector _getSelectorVec(); - std::string _populateTree(std::vector); - bool _handleButtonEvent(GdkEventButton *event); - void _buttonEventsSelectObjs(GdkEventButton *event); - void _selectObjects(int, int); - void _checkAllChildren(Gtk::TreeModel::Children& children); - Inkscape::XML::Node *_styleElementNode(); - void _updateStyleContent(); - void _selectRow(Selection *); - - class ModelColumns : public Gtk::TreeModel::ColumnRecord - { + // Data structure + class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: ModelColumns() { - add(_selectorLabel); + add(_colSelector); add(_colAddRemove); add(_colObj); + add(_colProperties); } - Gtk::TreeModelColumn _selectorLabel; - Gtk::TreeModelColumn _colAddRemove; - Gtk::TreeModelColumn > _colObj; + Gtk::TreeModelColumn _colSelector; // Selector or matching object id. + Gtk::TreeModelColumn _colAddRemove; // Selector row or child object row. + Gtk::TreeModelColumn > _colObj; // List of matching objects. + Gtk::TreeModelColumn _colProperties; // List of properties. }; - - SPDesktop* _desktop; - SPDesktop* _targetDesktop; ModelColumns _mColumns; + + // TreeView + Gtk::TreeView _treeView; + Glib::RefPtr _store; + + // Widgets Gtk::VPaned _paned; Gtk::VBox _mainBox; Gtk::HBox _buttonBox; - Gtk::TreeView _treeView; - Glib::RefPtr _store; Gtk::ScrolledWindow _scrolledWindow; Gtk::Button* del; Gtk::Button* create; - SPDocument* _document; - bool _styleExists; - Inkscape::XML::Node *_styleChild; - std::string _selectorName; - std::string _selectorValue; - bool _newDrawing; CssDialog *_cssPane; - void _selAdd(Gtk::TreeModel::Row row); + + // Variables - Inkscape + SPDesktop* _desktop; // To do: use panel _desktop + SPDocument* _document; + bool _updating; + + // Reading and writing the style element. + Inkscape::XML::Node *_getStyleTextNode(); + void _readStyleElement(); + void _writeStyleElement(); + + // Manipulate Tree + void _addToSelector(Gtk::TreeModel::Row row); + void _removeFromSelector(Gtk::TreeModel::Row row); + Glib::ustring _getIdList(std::vector); + std::vector _getObjVec(Glib::ustring selector); + void _insertClass(const std::vector& objVec, const Glib::ustring& className); + void _selectObjects(int, int); // Signal handlers void _addSelector(); void _delSelector(); + bool _handleButtonEvent(GdkEventButton *event); + void _buttonEventsSelectObjs(GdkEventButton *event); + void _selectRow(Selection *); // Select row in tree when selection changed. void _selChanged(); - // Signal handler for CssDialog + // Signal handlers for CssDialog void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); bool _delProperty(GdkEventButton *event); + + // GUI + void _styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip); }; -} // namespace Dialog +} // namespace Dialogc } // namespace UI } // namespace Inkscape -- 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