summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorTavmjong Bah <tavmjong@free.fr>2017-02-19 09:00:27 +0000
committertavmjong-free <tavmjong@free.fr>2017-02-19 09:00:27 +0000
commitf352e76fcf5cc4d12d456cff756135008ad5fe06 (patch)
treeb46cf5d2e74e51d255e6d5180e68417e7f3dfc71 /src
parent[Bug #1664372] preset filter names inconsistent. (diff)
downloadinkscape-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.cpp6
-rw-r--r--src/ui/dialog/styledialog.cpp92
-rw-r--r--src/ui/dialog/styledialog.h26
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.