diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2017-06-14 12:33:02 +0000 |
|---|---|---|
| committer | Tavmjong Bah <tavmjong@free.fr> | 2017-06-14 12:33:02 +0000 |
| commit | 73fcfc9f34395148fceda89b892886291b509cb2 (patch) | |
| tree | 108ac18d167d41feb853cab2e0e3b890a51c39f4 /src | |
| parent | Prevent crash due to clones. (diff) | |
| download | inkscape-73fcfc9f34395148fceda89b892886291b509cb2.tar.gz inkscape-73fcfc9f34395148fceda89b892886291b509cb2.zip | |
Update dialog when object is added, deleted, or changed.
Diffstat (limited to 'src')
| -rw-r--r-- | src/ui/dialog/styledialog.cpp | 137 | ||||
| -rw-r--r-- | src/ui/dialog/styledialog.h | 12 |
2 files changed, 149 insertions, 0 deletions
diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 5a1ebc532..8679659ce 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -45,6 +45,7 @@ namespace Inkscape { namespace UI { namespace Dialog { +// Keeps a watch on style element class StyleDialog::NodeObserver : public Inkscape::XML::NodeObserver { public: NodeObserver(StyleDialog* styleDialog) : @@ -78,6 +79,93 @@ StyleDialog::NodeObserver::notifyContentChanged( } +// Keeps a watch for new/removed/changed nodes +// (Must update objects that selectors match.) +class StyleDialog::NodeWatcher : public Inkscape::XML::NodeObserver { +public: + NodeWatcher(StyleDialog* styleDialog, Inkscape::XML::Node *repr) : + _styleDialog(styleDialog), + _repr(repr) + { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::NodeWatcher: Constructor" << std::endl; +#endif + }; + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, + Inkscape::XML::Node &child, + Inkscape::XML::Node */*prev*/ ) + { + if ( _styleDialog && _repr ) { + _styleDialog->_nodeAdded( child ); + } + } + + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, + Inkscape::XML::Node &child, + Inkscape::XML::Node */*prev*/ ) + { + if ( _styleDialog && _repr ) { + _styleDialog->_nodeRemoved( child ); + } + } + + virtual void notifyAttributeChanged( Inkscape::XML::Node &node, + GQuark qname, + Util::ptr_shared<char> /*old_value*/, + Util::ptr_shared<char> /*new_value*/ ) { + if ( _styleDialog && _repr ) { + + // For the moment only care about attributes that are directly used in selectors. + const gchar * cname = g_quark_to_string (qname ); + Glib::ustring name; + if (cname) { + name = cname; + } + + if ( name == "id" || name == "class" ) { + _styleDialog->_nodeChanged( node ); + } + } + } + + StyleDialog * _styleDialog; + Inkscape::XML::Node * _repr; // Need to track if document changes. +}; + +void +StyleDialog::_nodeAdded( Inkscape::XML::Node &node ) { + + StyleDialog::NodeWatcher *w = new StyleDialog::NodeWatcher (this, &node); + node.addObserver (*w); + _nodeWatchers.push_back(w); + + _readStyleElement(); + _selectRow(); +} + +void +StyleDialog::_nodeRemoved( Inkscape::XML::Node &repr ) { + + for (auto it = _nodeWatchers.begin(); it != _nodeWatchers.end(); ++it) { + if ( (*it)->_repr == &repr ) { + (*it)->_repr->removeObserver (**it); + _nodeWatchers.erase( it ); + break; + } + } + + _readStyleElement(); + _selectRow(); +} + +void +StyleDialog::_nodeChanged( Inkscape::XML::Node &object ) { + + _readStyleElement(); + _selectRow(); +} + StyleDialog::TreeStore::TreeStore() { } @@ -248,6 +336,9 @@ StyleDialog::StyleDialog() : _selection_changed_connection = getDesktop()->getSelection()->connectChanged( sigc::hide(sigc::mem_fun(this, &StyleDialog::_handleSelectionChanged))); + // Add watchers + _updateWatchers(); + // Load tree _readStyleElement(); _selectRow(); @@ -447,6 +538,49 @@ void StyleDialog::_writeStyleElement() } +void StyleDialog::_addWatcherRecursive(Inkscape::XML::Node *node) { + +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_addWatcherRecursive()" << std::endl; +#endif + + StyleDialog::NodeWatcher *w = new StyleDialog::NodeWatcher(this, node); + node->addObserver(*w); + _nodeWatchers.push_back(w); + + for (unsigned i = 0; i < node->childCount(); ++i) { + _addWatcherRecursive(node->nthChild(i)); + } +} + +/** + * @brief StyleDialog::_updateWatchers + * Update the watchers on objects. + */ +void StyleDialog::_updateWatchers() +{ + _updating = true; + + // Remove old document watchers + while (!_nodeWatchers.empty()) { + StyleDialog::NodeWatcher *w = _nodeWatchers.back(); + w->_repr->removeObserver(*w); + _nodeWatchers.pop_back(); + delete w; + } + + // Recursively add new watchers + Inkscape::XML::Node *root = SP_ACTIVE_DOCUMENT->getReprRoot(); + _addWatcherRecursive(root); + +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_updateWatchers(): " << _nodeWatchers.size() << std::endl; +#endif + + _updating = false; +} + + /** * @brief StyleDialog::_addToSelector * @param row @@ -712,6 +846,7 @@ void StyleDialog::_selectObjects(int eventX, int eventY) Gtk::TreeModel::Row row = *iter; Gtk::TreeModel::Children children = row.children(); std::vector<SPObject *> objVec = row[_mColumns._colObj]; + for (unsigned i = 0; i < objVec.size(); ++i) { SPObject *obj = objVec[i]; getDesktop()->selection->add(obj); @@ -1047,6 +1182,7 @@ StyleDialog::_handleDocumentReplaced(SPDesktop *desktop, SPDocument * /* documen _selection_changed_connection = desktop->getSelection()->connectChanged( sigc::hide(sigc::mem_fun(this, &StyleDialog::_handleSelectionChanged))); + _updateWatchers(); _readStyleElement(); _selectRow(); } @@ -1077,6 +1213,7 @@ StyleDialog::_handleDesktopChanged(SPDesktop* desktop) { _document_replaced_connection = desktop->connectDocumentReplaced( sigc::mem_fun(this, &StyleDialog::_handleDocumentReplaced)); + _updateWatchers(); _readStyleElement(); _selectRow(); } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index e84489e66..dbbc1e480 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -58,6 +58,14 @@ private: // Monitor <style> element for changes. class NodeObserver; + // Monitor all objects for addition/removal/attribute change + class NodeWatcher; + + std::vector<StyleDialog::NodeWatcher*> _nodeWatchers; + void _nodeAdded( Inkscape::XML::Node &repr ); + void _nodeRemoved( Inkscape::XML::Node &repr ); + void _nodeChanged( Inkscape::XML::Node &repr ); + // Data structure class ModelColumns : public Gtk::TreeModel::ColumnRecord { public: @@ -112,6 +120,10 @@ private: Inkscape::XML::Node *_getStyleTextNode(); void _readStyleElement(); void _writeStyleElement(); + + // Update watchers + void _addWatcherRecursive(Inkscape::XML::Node *node); + void _updateWatchers(); // Manipulate Tree void _addToSelector(Gtk::TreeModel::Row row); |
