diff options
| author | Tavmjong Bah <tavmjong@free.fr> | 2017-02-19 09:00:27 +0000 |
|---|---|---|
| committer | tavmjong-free <tavmjong@free.fr> | 2017-02-19 09:00:27 +0000 |
| commit | f352e76fcf5cc4d12d456cff756135008ad5fe06 (patch) | |
| tree | b46cf5d2e74e51d255e6d5180e68417e7f3dfc71 /src | |
| parent | [Bug #1664372] preset filter names inconsistent. (diff) | |
| download | inkscape-f352e76fcf5cc4d12d456cff756135008ad5fe06.tar.gz inkscape-f352e76fcf5cc4d12d456cff756135008ad5fe06.zip | |
Implement selector reordering via drag and drop. A few other tweeks.
(bzr r15533)
Diffstat (limited to 'src')
| -rw-r--r-- | src/ui/dialog/cssdialog.cpp | 6 | ||||
| -rw-r--r-- | src/ui/dialog/styledialog.cpp | 92 | ||||
| -rw-r--r-- | src/ui/dialog/styledialog.h | 26 |
3 files changed, 113 insertions, 11 deletions
diff --git a/src/ui/dialog/cssdialog.cpp b/src/ui/dialog/cssdialog.cpp index d0ae822bd..a5736513f 100644 --- a/src/ui/dialog/cssdialog.cpp +++ b/src/ui/dialog/cssdialog.cpp @@ -38,7 +38,7 @@ CssDialog::CssDialog(): { set_size_request(20, 15); _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); - _treeView.set_headers_visible(false); + _treeView.set_headers_visible(true); _scrolledWindow.add(_treeView); _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); @@ -48,7 +48,7 @@ CssDialog::CssDialog(): Inkscape::UI::Widget::AddToIcon * addRenderer = manage(new Inkscape::UI::Widget::AddToIcon()); addRenderer->property_active() = false; - int addCol = _treeView.append_column("Unset Property", *addRenderer) - 1; + int addCol = _treeView.append_column("", *addRenderer) - 1; Gtk::TreeViewColumn *col = _treeView.get_column(addCol); if (col) { col->add_attribute(addRenderer->property_active(), _cssColumns._colUnsetProp); @@ -56,7 +56,7 @@ CssDialog::CssDialog(): _textRenderer = Gtk::manage(new Gtk::CellRendererText()); _textRenderer->property_editable() = true; - int nameColNum = _treeView.append_column("Property", *_textRenderer) - 1; + int nameColNum = _treeView.append_column("CSS Property", *_textRenderer) - 1; _propCol = _treeView.get_column(nameColNum); if (_propCol) { _propCol->add_attribute(_textRenderer->property_text(), diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index 09fca0074..9916551d8 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -75,6 +75,71 @@ StyleDialog::NodeObserver::notifyContentChanged( } +StyleDialog::TreeStore::TreeStore() +{ +} + + +/** + * Allow dragging only selectors. + */ +bool +StyleDialog::TreeStore::row_draggable_vfunc(const Gtk::TreeModel::Path& path) const +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::TreeStore::row_draggable_vfunc" << std::endl; +#endif + auto unconstThis = const_cast<StyleDialog::TreeStore*>(this); + const_iterator iter = unconstThis->get_iter(path); + if (iter) { + Gtk::TreeModel::Row row = *iter; + bool is_draggable = row[_styledialog->_mColumns._colAddRemove]; + return is_draggable; + } + return Gtk::TreeStore::row_draggable_vfunc(path); +} + + +/** + * Allow dropping only inbetween other selectors. + */ +bool +StyleDialog::TreeStore::row_drop_possible_vfunc(const Gtk::TreeModel::Path& dest, + const Gtk::SelectionData& selection_data) const +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::TreeStore::row_drop_possible_vfunc" << std::endl; +#endif + + Gtk::TreeModel::Path dest_parent = dest; + dest_parent.up(); + return dest_parent.empty(); +} + + +// This is only here to handle updating style element after a drag and drop. +void +StyleDialog::TreeStore::on_row_deleted(const TreeModel::Path& path) +{ +#ifdef DEBUG_STYLEDIALOG + std::cout << "on_row_deleted" << std::endl; +#endif + + if (_styledialog->_updating) return; // Don't write if we deleted row (other than from DND) + + _styledialog->_writeStyleElement(); +} + + +Glib::RefPtr<StyleDialog::TreeStore> StyleDialog::TreeStore::create(StyleDialog *styledialog) +{ + StyleDialog::TreeStore * store = new StyleDialog::TreeStore(); + store->_styledialog = styledialog; + store->set_column_types( store->_styledialog->_mColumns ); + return Glib::RefPtr<StyleDialog::TreeStore>( store ); +} + + /** * Constructor * A treeview and a set of two buttons are added to the dialog. _addSelector @@ -94,19 +159,21 @@ StyleDialog::StyleDialog() : // Tree Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon() ); - addRenderer->property_active() = true; - _store = Gtk::TreeStore::create(_mColumns); + _store = TreeStore::create(this); _treeView.set_model(_store); - _treeView.set_headers_visible(false); - int addCol = _treeView.append_column("type", *addRenderer) - 1; + _treeView.set_headers_visible(true); + _treeView.enable_model_drag_source(); + _treeView.enable_model_drag_dest( Gdk::ACTION_MOVE ); + + int addCol = _treeView.append_column("", *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._colSelector); + _treeView.append_column("CSS Selector", _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); @@ -273,6 +340,13 @@ Inkscape::XML::Node* StyleDialog::_getStyleTextNode() */ void StyleDialog::_readStyleElement() { +#ifdef DEBUG_STYLEDIALOG + std::cout << "StyleDialog::_readStyleElement: updating " << (_updating?"true":"false")<< std::endl; +#endif + + if (_updating) return; // Don't read if we wrote style element. + _updating = true; + _store->clear(); Inkscape::XML::Node * textNode = _getStyleTextNode(); @@ -338,6 +412,7 @@ void StyleDialog::_readStyleElement() childrow[_mColumns._colProperties] = ""; // Unused } } + _updating = false; } @@ -347,6 +422,8 @@ void StyleDialog::_readStyleElement() */ void StyleDialog::_writeStyleElement() { + _updating = true; + Glib::ustring styleContent; for (auto& row: _store->children()) { styleContent = styleContent + row[_mColumns._colSelector] + @@ -360,6 +437,7 @@ void StyleDialog::_writeStyleElement() DocumentUndo::done(_document, SP_VERB_DIALOG_STYLE, _("Edited style element.")); + _updating = false; #ifdef DEBUG_STYLEDIALOG std::cout << "StyleDialog::_writeStyleElement(): |" << styleContent << "|" << std::endl; #endif @@ -802,7 +880,9 @@ void StyleDialog::_delSelector() Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); if (iter) { Gtk::TreeModel::Row row = *iter; + _updating = true; _store->erase(iter); + _updating = false; _writeStyleElement(); } } diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h index 1f7be158f..1b3bebae6 100644 --- a/src/ui/dialog/styledialog.h +++ b/src/ui/dialog/styledialog.h @@ -53,6 +53,7 @@ public: private: + // Monitor <style> element for changes. class NodeObserver; // Data structure @@ -71,9 +72,30 @@ private: }; ModelColumns _mColumns; + // Override Gtk::TreeStore to control drag-n-drop (only allow dragging and dropping of selectors). + // See: https://developer.gnome.org/gtkmm-tutorial/stable/sec-treeview-examples.html.en + // + // TreeStore implements simple drag and drop (DND) but there appears no way to know when a DND + // has been completed (other than doing the whole DND ourselves). As a hack, we use + // on_row_deleted to trigger write of style element. + class TreeStore : public Gtk::TreeStore { + protected: + TreeStore(); + bool row_draggable_vfunc(const Gtk::TreeModel::Path& path) const override; + bool row_drop_possible_vfunc(const Gtk::TreeModel::Path& path, + const Gtk::SelectionData& selection_data) const override; + void on_row_deleted(const TreeModel::Path& path) override; + + public: + static Glib::RefPtr<StyleDialog::TreeStore> create(StyleDialog *styledialog); + + private: + StyleDialog *_styledialog; + }; + // TreeView Gtk::TreeView _treeView; - Glib::RefPtr<Gtk::TreeStore> _store; + Glib::RefPtr<TreeStore> _store; // Widgets Gtk::VPaned _paned; @@ -87,7 +109,7 @@ private: // Variables - Inkscape SPDesktop* _desktop; // To do: use panel _desktop SPDocument* _document; - bool _updating; + bool _updating; // Prevent cyclic actions: read <-> write, select via dialog <-> via desktop Inkscape::XML::Node *_textNode; // Reading and writing the style element. |
