diff --git a/share/icons/Tango/scalable/actions/horizontal.svg b/share/icons/Tango/scalable/actions/horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..41f42514a9cbe6ab31282912db2a655b5820f1ad
--- /dev/null
+++ b/share/icons/Tango/scalable/actions/horizontal.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/icons/Tango/scalable/actions/vertical.svg b/share/icons/Tango/scalable/actions/vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d625d286795d29c1bef33ac9f742bba8cd952276
--- /dev/null
+++ b/share/icons/Tango/scalable/actions/vertical.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/icons/hicolor/scalable/actions/horizontal.svg b/share/icons/hicolor/scalable/actions/horizontal.svg
new file mode 100644
index 0000000000000000000000000000000000000000..41f42514a9cbe6ab31282912db2a655b5820f1ad
--- /dev/null
+++ b/share/icons/hicolor/scalable/actions/horizontal.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/icons/hicolor/scalable/actions/vertical.svg b/share/icons/hicolor/scalable/actions/vertical.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d625d286795d29c1bef33ac9f742bba8cd952276
--- /dev/null
+++ b/share/icons/hicolor/scalable/actions/vertical.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/horizontal-symbolic.svg b/share/icons/hicolor/symbolic/actions/horizontal-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..41f42514a9cbe6ab31282912db2a655b5820f1ad
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/horizontal-symbolic.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/icons/hicolor/symbolic/actions/vertical-symbolic.svg b/share/icons/hicolor/symbolic/actions/vertical-symbolic.svg
new file mode 100644
index 0000000000000000000000000000000000000000..d625d286795d29c1bef33ac9f742bba8cd952276
--- /dev/null
+++ b/share/icons/hicolor/symbolic/actions/vertical-symbolic.svg
@@ -0,0 +1,157 @@
+
+
diff --git a/share/ui/dialog-css.ui b/share/ui/dialog-css.ui
index 6ffcabc71fef206d5d6259f8e6f2f4b88fcfbfbb..682df1b9315df186c408436d8a04d54def192a92 100644
--- a/share/ui/dialog-css.ui
+++ b/share/ui/dialog-css.ui
@@ -31,10 +31,16 @@
-
+
+
+ True
+ True
+
+
+ False
+ True
+ 2
+
+
True
@@ -51,7 +68,7 @@
False
True
- 2
+ 4
@@ -68,7 +85,6 @@
True
natural
natural
- False
False
True
True
diff --git a/share/ui/style.css b/share/ui/style.css
index a7bed5d5963063568c0008921607703e72b8c098..6287a1622cecae3a2cf9bb31e7cb8f264c2f3538 100644
--- a/share/ui/style.css
+++ b/share/ui/style.css
@@ -66,7 +66,7 @@
* ::::::: Color based
* ::::::: apply to colors
* ::::::: scope widget and all his childs
- * ".invert" invert colors
+ * ".inverted" invert colors
* :::::::: Icon Based.
* ".symbolic" Force icon symbolic
* ".regular" Force colorful icons
@@ -91,37 +91,22 @@ image {
-gtk-icon-style: regular;
}
-.invert {
- color: @theme_bg_color;
- background-color: @theme_fg_color;
- background-image: image(@theme_fg_color);
-}
-
-.dark .forcebright {
- color: @theme_bg_color;
- background-color: @theme_fg_color;
- background-image: image(@theme_fg_color);
-}
-
+.inverted,
+.dark .forcebright,
.bright .forcedark {
color: @theme_bg_color;
background-color: @theme_fg_color;
background-image: image(@theme_fg_color);
}
-.invert :not(overshoot):not(undershoot):not(.rawimage) {
- color: inherit;
- background-color: inherit;
-}
-.dark .forcebright :not(overshoot):not(undershoot):not(.rawimage) {
- color: inherit;
- background-color: inherit;
-}
-.bright .forcedark :not(overshoot):not(undershoot):not(.rawimage) {
+.inverted :not(menuitem):not(.rawstyle):not(overshoot):not(undershoot):not(selection),
+.bright .forcedark :not(menuitem):not(.rawstyle):not(overshoot):not(undershoot):not(selection),
+.dark .forcebright :not(menuitem):not(.rawstyle):not(overshoot):not(undershoot):not(selection) {
color: inherit;
background-color: inherit;
+ background-image: inherit;
}
.combobright * {
@@ -225,8 +210,8 @@ spinbutton undershoot {
#LPESelectorFlowBox flowboxchild:selected image,
#LPESelectorFlowBox flowboxchild:selected label {
- background-color: @theme_selected_bg_color;
color: @theme_selected_fg_color;
+ background-color: @theme_selected_bg_color;
background-image: image(@theme_selected_bg_color);
}
@@ -311,6 +296,41 @@ spinbutton undershoot {
padding-bottom: 0;
}
+#XMLAndAttributesDialog .radio.image-button,
+#SelectorsAndStyleDialog .radio.image-button {
+ margin: 0;
+ padding: 0px;
+ border-radius: 2px 0 0 2px;
+}
+
+#XMLAndAttributesDialog .radio.image-button:last-child,
+#SelectorsAndStyleDialog .radio.image-button:last-child {
+ border-radius: 0 2px 2px 0;
+ border-left-width: 0;
+}
+
+#SelectorsAndStyleDialog treeview button {
+ border-width: 0;
+ margin: 0 0 1px 0;
+}
+
+#SelectorsAndStyleDialog treeview button:nth-child(3),
+#SelectorsAndStyleDialog treeview.style_sheet button:nth-child(4) {
+ border-width: 0 0 0 2px;
+ border-color: @theme_fg_color;
+ border-style: solid;
+ opacity: 0.5;
+}
+
+#SelectorsAndStyleDialog treeview.style_sheet button:nth-child(3) {
+ border-width: 0;
+}
+
+#SelectorsAndStyleDialog treeview button {
+ min-height: 3px;
+ font-size: 1px;
+}
+
#InkRuler {
font-size: 7pt;
}
diff --git a/src/inkscape.cpp b/src/inkscape.cpp
index 6614417293576dbed083823fb06d458ad6b0830f..f76ea3c22731b923aff1729bfec4f0a5427f3643 100644
--- a/src/inkscape.cpp
+++ b/src/inkscape.cpp
@@ -526,16 +526,23 @@ Glib::ustring Application::get_symbolic_colors()
css_str += colornamederror;
css_str += ";}";
css_str += "#InkRuler,";
- css_str += "image:not(.rawimage)";
+ /* ":not(.rawstyle) > image" works only on images in first level of widget container
+ if in the future we use a complex widget with more levels and we dont want to tweak the color
+ here, retaining default we can add more lines like ":not(.rawstyle) > > image" */
+ css_str += ":not(.rawstyle) > image";
css_str += "{color:";
css_str += colornamed;
css_str += ";}";
- css_str += ".dark .forcebright image:not(.rawimage),";
- css_str += ".bright .forcedark image:not(.rawimage),";
- css_str += ".dark image.forcebright:not(.rawimage),";
- css_str += ".bright image.forcedark:not(.rawimage),";
- css_str += ".invert image:not(.rawimage),";
- css_str += "image.invert:not(.rawimage)";
+ css_str += ".dark .forcebright :not(.rawstyle) > image,";
+ css_str += ".dark .forcebright image:not(.rawstyle),";
+ css_str += ".bright .forcedark :not(.rawstyle) > image,";
+ css_str += ".bright .forcedark image:not(.rawstyle),";
+ css_str += ".dark :not(.rawstyle) > image.forcebright,";
+ css_str += ".dark image.forcebright:not(.rawstyle),";
+ css_str += ".bright :not(.rawstyle) > image.forcedark,";
+ css_str += ".bright image.forcedark:not(.rawstyle),";
+ css_str += ".inverse :not(.rawstyle) > image,";
+ css_str += ".inverse image:not(.rawstyle)";
css_str += "{color:";
css_str += colornamed_inverse;
css_str += ";}";
diff --git a/src/ui/dialog/attrdialog.cpp b/src/ui/dialog/attrdialog.cpp
index 3db739059d2cc02d8070bec8e8ee3e4646496985..a499602ce4dc9f016636f24b89759aaf74b48920 100644
--- a/src/ui/dialog/attrdialog.cpp
+++ b/src/ui/dialog/attrdialog.cpp
@@ -58,7 +58,6 @@ namespace Inkscape {
namespace UI {
namespace Dialog {
-
/**
* Constructor
* A treeview whose each row corresponds to an XML attribute of a selected node
@@ -72,6 +71,9 @@ AttrDialog::AttrDialog()
set_size_request(20, 15);
_mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET);
_treeView.set_headers_visible(true);
+ _treeView.set_hover_selection(true);
+ _treeView.set_activate_on_single_click(true);
+ _treeView.set_can_focus(false);
_scrolledWindow.add(_treeView);
_scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
@@ -103,16 +105,19 @@ AttrDialog::AttrDialog()
_nameRenderer->property_editable() = true;
_nameRenderer->property_placeholder_text().set_value(_("Attribute Name"));
_nameRenderer->signal_edited().connect(sigc::mem_fun(*this, &AttrDialog::nameEdited));
+ _nameRenderer->signal_editing_started().connect(sigc::mem_fun(*this, &AttrDialog::startNameEdit));
_treeView.append_column(_("Name"), *_nameRenderer);
_nameCol = _treeView.get_column(1);
if (_nameCol) {
- _nameCol->add_attribute(_nameRenderer->property_text(), _attrColumns._attributeName);
+ _nameCol->set_resizable(true);
+ _nameCol->add_attribute(_nameRenderer->property_text(), _attrColumns._attributeName);
}
status.set_halign(Gtk::ALIGN_START);
status.set_valign(Gtk::ALIGN_CENTER);
status.set_size_request(1, -1);
status.set_markup("");
status.set_line_wrap(true);
+ status.get_style_context()->add_class("inksmall");
status_box.pack_start(status, TRUE, TRUE, 0);
_getContents()->pack_end(status_box, false, false, 2);
@@ -126,19 +131,44 @@ AttrDialog::AttrDialog()
_valueRenderer->property_placeholder_text().set_value(_("Attribute Value"));
_valueRenderer->property_ellipsize().set_value(Pango::ELLIPSIZE_MIDDLE);
_valueRenderer->signal_edited().connect(sigc::mem_fun(*this, &AttrDialog::valueEdited));
+ _valueRenderer->signal_editing_started().connect(sigc::mem_fun(*this, &AttrDialog::startValueEdit));
_treeView.append_column(_("Value"), *_valueRenderer);
_valueCol = _treeView.get_column(2);
if (_valueCol) {
_valueCol->add_attribute(_valueRenderer->property_text(), _attrColumns._attributeValue);
}
+ _popover = Gtk::manage(new Gtk::Popover());
+ Gtk::Box *vbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL));
+ Gtk::Box *hbox = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
+ _textview = Gtk::manage(new Gtk::TextView());
+ _textview->set_wrap_mode(Gtk::WrapMode::WRAP_CHAR);
+ _textview->set_editable(true);
+ _textview->set_monospace(true);
+ _textview->set_border_width(6);
+ Glib::RefPtr textbuffer = Gtk::TextBuffer::create();
+ textbuffer->set_text("");
+ _textview->set_buffer(textbuffer);
+ _scrolled_text_view.add(*_textview);
+ _scrolled_text_view.set_max_content_height(450);
+ _scrolled_text_view.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+ _scrolled_text_view.set_propagate_natural_width(true);
+ _update = Gtk::manage(new Gtk::Button(_("Update")));
+ _update->signal_clicked().connect(sigc::mem_fun(*this, &AttrDialog::valueEditedPop));
+ hbox->pack_end(*_update, Gtk::PACK_EXPAND_WIDGET, 3);
+ vbox->pack_start(_scrolled_text_view, Gtk::PACK_EXPAND_WIDGET, 3);
+ vbox->pack_start(*hbox, Gtk::PACK_EXPAND_WIDGET, 3);
+ _popover->add(*vbox);
+ _popover->hide();
+ _popover->set_relative_to(_treeView);
+ _popover->set_position(Gtk::PositionType::POS_BOTTOM);
+ _popover->signal_closed().connect(sigc::mem_fun(*this, &AttrDialog::popClosed));
+ _popover->get_style_context()->add_class("inverted");
attr_reset_context(0);
_getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET);
-
setDesktop(getDesktop());
+ _updating = false;
}
-
-
/**
* @brief AttrDialog::~AttrDialog
* Class destructor
@@ -152,6 +182,71 @@ AttrDialog::~AttrDialog()
_message_changed_connection.~connection();
}
+void AttrDialog::startNameEdit(Gtk::CellEditable *cell, const Glib::ustring &path)
+{
+ Gtk::Entry *entry = dynamic_cast(cell);
+ entry->signal_key_press_event().connect(sigc::bind(sigc::mem_fun(*this, &AttrDialog::onNameKeyPressed), entry));
+}
+
+gboolean sp_show_attr_pop(gpointer data)
+{
+ AttrDialog *attrdialog = reinterpret_cast(data);
+ auto vscroll = attrdialog->_scrolled_text_view.get_vadjustment();
+ int height = vscroll->get_upper() + 12; // padding 6+6
+ if (height < 450) {
+ attrdialog->_scrolled_text_view.set_min_content_height(height);
+ } else {
+ attrdialog->_scrolled_text_view.set_min_content_height(450);
+ }
+ return FALSE;
+}
+
+void AttrDialog::startValueEdit(Gtk::CellEditable *cell, const Glib::ustring &path)
+{
+ Gtk::Entry *entry = dynamic_cast(cell);
+ entry->signal_key_press_event().connect(sigc::bind(sigc::mem_fun(*this, &AttrDialog::onValueKeyPressed), entry));
+ int width = 0;
+ int height = 0;
+ int colwidth = _valueCol->get_width();
+ _textview->set_size_request(colwidth - 6, -1);
+ _popover->set_size_request(colwidth, -1);
+ valuepath = path;
+ entry->get_layout()->get_pixel_size(width, height);
+ Gtk::TreeIter iter = *_store->get_iter(path);
+ Gtk::TreeModel::Row row = *iter;
+ if (row && this->_repr) {
+ Glib::ustring name = row[_attrColumns._attributeName];
+ if (colwidth < width || name == "content") {
+ Gtk::TreeIter iter = *_store->get_iter(path);
+ Gdk::Rectangle rect;
+ _treeView.get_cell_area((Gtk::TreeModel::Path)iter, *_valueCol, rect);
+ if (_popover->get_position() == Gtk::PositionType::POS_BOTTOM) {
+ rect.set_y(rect.get_y() + 20);
+ }
+ _popover->set_pointing_to(rect);
+ Glib::RefPtr textbuffer = Gtk::TextBuffer::create();
+ textbuffer->set_text(entry->get_text());
+ _textview->set_buffer(textbuffer);
+ cell->editing_done();
+ cell->remove_widget();
+ int scrolledcontentheight = 20;
+ if (name == "content") {
+ scrolledcontentheight = 450;
+ }
+ _scrolled_text_view.set_min_content_height(scrolledcontentheight);
+ _popover->show_all();
+ _popover->check_resize();
+ g_timeout_add(50, &sp_show_attr_pop, this);
+ }
+ }
+}
+
+void AttrDialog::popClosed()
+{
+ Glib::RefPtr textbuffer = Gtk::TextBuffer::create();
+ textbuffer->set_text("");
+ _textview->set_buffer(textbuffer);
+}
/**
* @brief AttrDialog::setDesktop
@@ -224,6 +319,9 @@ void AttrDialog::attr_reset_context(gint attr)
*/
void AttrDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, const gchar * new_value)
{
+ if (_updating) {
+ return;
+ }
for(auto iter: this->_store->children())
{
Gtk::TreeModel::Row row = *iter;
@@ -235,6 +333,7 @@ void AttrDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, co
} else {
_store->erase(iter);
}
+ break;
}
}
if (new_value && strcmp(new_value, "") != 0) {
@@ -243,7 +342,7 @@ void AttrDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, co
{
return;
} else {
- Gtk::TreeModel::Row row = *(_store->append());
+ Gtk::TreeModel::Row row = *(_store->prepend());
row[_attrColumns._attributeName] = name;
row[_attrColumns._attributeValue] = new_value;
}
@@ -257,7 +356,7 @@ void AttrDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, co
bool AttrDialog::onAttrCreate(GdkEventButton *event)
{
if(event->type == GDK_BUTTON_RELEASE && event->button == 1 && this->_repr) {
- Gtk::TreeIter iter = _store->append();
+ Gtk::TreeIter iter = _store->prepend();
Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter;
_treeView.set_cursor(path, *_nameCol, true);
grab_focus();
@@ -298,39 +397,80 @@ bool AttrDialog::onKeyPressed(GdkEventKey *event)
if(this->_repr) {
auto selection = this->_treeView.get_selection();
Gtk::TreeModel::Row row = *(selection->get_selected());
+ Gtk::TreeIter iter = *(selection->get_selected());
+ bool ret = false;
switch (event->keyval)
{
case GDK_KEY_Delete:
- case GDK_KEY_KP_Delete:
- {
+ case GDK_KEY_KP_Delete: {
// Create new attribute (repeat code, fold into above event!)
Glib::ustring name = row[_attrColumns._attributeName];
- if(name == "content") {
- return true;
- } else {
+ if (name != "content") {
this->_store->erase(row);
this->_repr->setAttribute(name.c_str(), nullptr, false);
this->setUndo(_("Delete attribute"));
}
- return true;
- }
+ ret = true;
+ } break;
case GDK_KEY_plus:
case GDK_KEY_Insert:
{
// Create new attribute (repeat code, fold into above event!)
- Gtk::TreeIter iter = this->_store->append();
+ Gtk::TreeIter iter = this->_store->prepend();
Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter;
this->_treeView.set_cursor(path, *this->_nameCol, true);
grab_focus();
- return true;
- }
+ ret = true;
+ } break;
}
}
return false;
}
+bool AttrDialog::onNameKeyPressed(GdkEventKey *event, Gtk::Entry *entry)
+{
+ g_debug("StyleDialog::_onNameKeyPressed");
+ bool ret = false;
+ switch (event->keyval) {
+ case GDK_KEY_Tab:
+ case GDK_KEY_KP_Tab:
+ entry->editing_done();
+ ret = true;
+ break;
+ }
+ return ret;
+}
+
+
+bool AttrDialog::onValueKeyPressed(GdkEventKey *event, Gtk::Entry *entry)
+{
+ g_debug("StyleDialog::_onValueKeyPressed");
+ bool ret = false;
+ switch (event->keyval) {
+ case GDK_KEY_Tab:
+ case GDK_KEY_KP_Tab:
+ entry->editing_done();
+ ret = true;
+ break;
+ }
+ return ret;
+}
+
+gboolean sp_attrdialog_store_move_to_next(gpointer data)
+{
+ AttrDialog *attrdialog = reinterpret_cast(data);
+ auto selection = attrdialog->_treeView.get_selection();
+ Gtk::TreeIter iter = *(selection->get_selected());
+ Gtk::TreeModel::Path model = (Gtk::TreeModel::Path)iter;
+ if (model == attrdialog->_modelpath) {
+ attrdialog->_treeView.set_cursor(attrdialog->_modelpath, *attrdialog->_valueCol, true);
+ }
+ return FALSE;
+}
/**
+ *
+ *
* @brief AttrDialog::nameEdited
* @param event
* @return
@@ -339,36 +479,44 @@ bool AttrDialog::onKeyPressed(GdkEventKey *event)
void AttrDialog::nameEdited (const Glib::ustring& path, const Glib::ustring& name)
{
Gtk::TreeIter iter = *_store->get_iter(path);
- Gtk::TreeModel::Path modelpath = (Gtk::TreeModel::Path)iter;
+ _modelpath = (Gtk::TreeModel::Path)iter;
Gtk::TreeModel::Row row = *iter;
if(row && this->_repr) {
Glib::ustring old_name = row[_attrColumns._attributeName];
if (old_name == name) {
- _treeView.set_cursor(modelpath, *_valueCol, true);
+ g_timeout_add(50, &sp_attrdialog_store_move_to_next, this);
grab_focus();
return;
}
- if (old_name == "content" ||
- old_name == name)
- {
+ if (old_name == "content") {
return;
}
Glib::ustring value = row[_attrColumns._attributeValue];
// Move to editing value, we set the name as a temporary store value
if (!old_name.empty()) {
// Remove old named value
+ _updating = true;
_repr->setAttribute(old_name.c_str(), nullptr, false);
+ _updating = false;
}
if (!name.empty()) {
row[_attrColumns._attributeName] = name;
- _repr->setAttribute(name.c_str(), value, false);
- _treeView.set_cursor(modelpath, *_valueCol, true);
grab_focus();
+ _updating = true;
+ _repr->setAttribute(name.c_str(), value, false);
+ _updating = false;
+ g_timeout_add(50, &sp_attrdialog_store_move_to_next, this);
}
this->setUndo(_("Rename attribute"));
}
}
+void AttrDialog::valueEditedPop()
+{
+ Glib::ustring value = _textview->get_buffer()->get_text();
+ valueEdited(valuepath, value);
+}
+
/**
* @brief AttrDialog::valueEdited
* @param event
@@ -380,6 +528,10 @@ void AttrDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& va
Gtk::TreeModel::Row row = *_store->get_iter(path);
if(row && this->_repr) {
Glib::ustring name = row[_attrColumns._attributeName];
+ Glib::ustring old_value = row[_attrColumns._attributeValue];
+ if (old_value == value) {
+ return;
+ }
if(name.empty()) return;
if (name == "content") {
_repr->setContent(value.c_str());
@@ -389,7 +541,14 @@ void AttrDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& va
if(!value.empty()) {
row[_attrColumns._attributeValue] = value;
}
+ Inkscape::Selection *selection = _desktop->getSelection();
+ SPObject *obj = nullptr;
+ if (selection->objects().size() == 1) {
+ obj = selection->objects().back();
+ obj->style->readFromObject(obj);
+ obj->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ }
this->setUndo(_("Change attribute value"));
}
}
diff --git a/src/ui/dialog/attrdialog.h b/src/ui/dialog/attrdialog.h
index 68ea14cc9ff4a60f4f41e460219a4f24b460bae1..2c57447c4dd0cd5031f9ac752ac7289bd125175c 100644
--- a/src/ui/dialog/attrdialog.h
+++ b/src/ui/dialog/attrdialog.h
@@ -17,7 +17,9 @@
#include "message.h"
#include
#include
+#include
#include
+#include
#include
#include
@@ -61,6 +63,11 @@ public:
Gtk::CellRendererText *_valueRenderer;
Gtk::TreeViewColumn *_nameCol;
Gtk::TreeViewColumn *_valueCol;
+ Gtk::TreeModel::Path _modelpath;
+ Gtk::Popover *_popover;
+ Gtk::TextView *_textview;
+ Gtk::Button *_update;
+ Glib::ustring valuepath;
/**
* Status bar
@@ -71,14 +78,15 @@ public:
// Widgets
Gtk::VBox _mainBox;
Gtk::ScrolledWindow _scrolledWindow;
+ Gtk::ScrolledWindow _scrolled_text_view;
Gtk::HBox _buttonBox;
Gtk::Button _buttonAddAttribute;
-
// Variables - Inkscape
SPDesktop* _desktop;
Inkscape::XML::Node* _repr;
Gtk::HBox status_box;
Gtk::Label status;
+ bool _updating;
// Helper functions
void setDesktop(SPDesktop* desktop) override;
@@ -95,12 +103,17 @@ public:
*/
sigc::connection _message_changed_connection;
void onAttrChanged(Inkscape::XML::Node *repr, const gchar * name, const gchar * new_value);
+ bool onNameKeyPressed(GdkEventKey *event, Gtk::Entry *entry);
+ bool onValueKeyPressed(GdkEventKey *event, Gtk::Entry *entry);
void onAttrDelete(Glib::ustring path);
bool onAttrCreate(GdkEventButton *event);
bool onKeyPressed(GdkEventKey *event);
+ void popClosed();
+ void startNameEdit(Gtk::CellEditable *cell, const Glib::ustring &path);
+ void startValueEdit(Gtk::CellEditable *cell, const Glib::ustring &path);
void nameEdited(const Glib::ustring &path, const Glib::ustring &name);
void valueEdited(const Glib::ustring &path, const Glib::ustring &value);
-
+ void valueEditedPop();
};
diff --git a/src/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h
index b681c9ca16ec0d54d8535506e0e2e7ca8ca4e742..7b94390068aa65ce7d46b02095726335c80940fc 100644
--- a/src/ui/dialog/desktop-tracker.h
+++ b/src/ui/dialog/desktop-tracker.h
@@ -46,7 +46,7 @@ private:
SPDesktop *base;
SPDesktop *desktop;
GtkWidget *widget;
- gulong hierID;
+ unsigned long hierID;
sigc::connection inkID;
bool trackActive;
sigc::signal desktopChangedSig;
diff --git a/src/ui/dialog/selectorsdialog.cpp b/src/ui/dialog/selectorsdialog.cpp
index eda036c589e6f7606f464181ed0d863949128622..89d109ae9d4f75bdae63469a2411c7b95605ed4f 100644
--- a/src/ui/dialog/selectorsdialog.cpp
+++ b/src/ui/dialog/selectorsdialog.cpp
@@ -19,9 +19,10 @@
#include "inkscape.h"
#include "selection.h"
#include "style.h"
-#include "verbs.h"
#include "ui/icon-loader.h"
+#include "ui/icon-names.h"
#include "ui/widget/iconrenderer.h"
+#include "verbs.h"
#include "xml/attribute-record.h"
#include "xml/node-observer.h"
@@ -200,69 +201,6 @@ bool SelectorsDialog::TreeStore::row_draggable_vfunc(const Gtk::TreeModel::Path
return Gtk::TreeStore::row_draggable_vfunc(path);
}
-void SelectorsDialog::fixCSSSelectors(Glib::ustring &selector)
-{
- g_debug("SelectorsDialog::fixCSSSelectors");
- REMOVE_SPACES(selector);
- Glib::ustring my_selector = selector + " {"; // Parsing fails sometimes without '{'. Fix me
- CRSelector *cr_selector = cr_selector_parse_from_buf((guchar *)my_selector.c_str(), CR_UTF_8);
- selector = Glib::ustring("");
- CRSelector const *cur = nullptr;
- for (cur = cr_selector; cur; cur = cur->next) {
- if (cur->simple_sel) {
- gchar *selectorchar = reinterpret_cast(cr_simple_sel_to_string(cur->simple_sel));
- if (selectorchar) {
- Glib::ustring toadd = Glib::ustring(selectorchar);
- selector = selector.empty() ? toadd : selector + "," + toadd;
- g_free(selectorchar);
- }
- }
- }
- std::vector tokens = Glib::Regex::split_simple("[,]+", selector);
- std::vector selectorresult;
- selector = Glib::ustring("");
- for (auto token : tokens) {
- REMOVE_SPACES(token);
- std::vector tokensplus = Glib::Regex::split_simple("[ ]+", token);
- Glib::ustring selectorpart = Glib::ustring("");
- for (auto tokenplus : tokensplus) {
- REMOVE_SPACES(tokenplus);
- Glib::ustring toparse = Glib::ustring(tokenplus);
- Glib::ustring tag = Glib::ustring("");
- if (toparse[0] != '.' && toparse[0] != '#') {
- auto i = std::min(toparse.find("#"), toparse.find("."));
- tag = toparse.substr(0, i);
- if (!SPAttributeRelSVG::isSVGElement(tag)) {
- continue;
- }
- if (i != std::string::npos) {
- toparse.erase(0, i);
- } else {
- toparse = tag;
- selectorpart = selectorpart == Glib::ustring("") ? toparse : selectorpart + " " + toparse;
- continue;
- }
- }
- auto i = toparse.find("#");
- if (i != std::string::npos) {
- toparse.erase(i, 1);
- }
- auto j = toparse.find("#");
- if (i != std::string::npos && j != std::string::npos) {
- continue;
- } else if (i != std::string::npos) {
- toparse.insert(i, "#");
- }
- toparse = tag + toparse;
- selectorpart = selectorpart == Glib::ustring("") ? toparse : selectorpart + " " + toparse;
- }
- selectorresult.push_back(selectorpart);
- }
- for (auto selectorpart : selectorresult) {
- selector = selector == Glib::ustring("") ? selectorpart : selector + "," + selectorpart;
- }
-}
-
/**
* Allow dropping only in between other selectors.
*/
@@ -404,19 +342,30 @@ void SelectorsDialog::_showWidgets()
_vadj = _scrolled_window_selectors.get_vadjustment();
_vadj->signal_value_changed().connect(sigc::mem_fun(*this, &SelectorsDialog::_vscrool));
_selectors_box.pack_start(_scrolled_window_selectors, Gtk::PACK_EXPAND_WIDGET);
- Gtk::Label *dirtogglerlabel = Gtk::manage(new Gtk::Label(_("Paned vertical")));
+ /* Gtk::Label *dirtogglerlabel = Gtk::manage(new Gtk::Label(_("Paned vertical")));
dirtogglerlabel->get_style_context()->add_class("inksmall");
_direction.property_active() = dir;
_direction.property_active().signal_changed().connect(sigc::mem_fun(*this, &SelectorsDialog::_toggleDirection));
- _direction.get_style_context()->add_class("inkswitch");
+ _direction.get_style_context()->add_class("inkswitch"); */
_styleButton(_create, "list-add", "Add a new CSS Selector");
_create.signal_clicked().connect(sigc::mem_fun(*this, &SelectorsDialog::_addSelector));
_styleButton(_del, "list-remove", "Remove a CSS Selector");
_button_box.pack_start(_create, Gtk::PACK_SHRINK);
_button_box.pack_start(_del, Gtk::PACK_SHRINK);
- _button_box.pack_start(_direction, false, false, 0);
- _button_box.pack_start(*dirtogglerlabel, false, false, 0);
- _selectors_box.pack_end(_button_box, false, false, 0);
+ Gtk::RadioButton::Group group;
+ Gtk::RadioButton *_horizontal = Gtk::manage(new Gtk::RadioButton());
+ Gtk::RadioButton *_vertical = Gtk::manage(new Gtk::RadioButton());
+ _horizontal->set_image_from_icon_name(INKSCAPE_ICON("horizontal"));
+ _vertical->set_image_from_icon_name(INKSCAPE_ICON("vertical"));
+ _horizontal->set_group(group);
+ _vertical->set_group(group);
+ _vertical->set_active(dir);
+ _vertical->signal_toggled().connect(
+ sigc::bind(sigc::mem_fun(*this, &SelectorsDialog::_toggleDirection), _vertical));
+ _horizontal->property_draw_indicator() = false;
+ _vertical->property_draw_indicator() = false;
+ _button_box.pack_end(*_horizontal, false, false, 0);
+ _button_box.pack_end(*_vertical, false, false, 0);
_del.signal_clicked().connect(sigc::mem_fun(*this, &SelectorsDialog::_delSelector));
_del.hide();
_style_dialog = new StyleDialog;
@@ -424,36 +373,62 @@ void SelectorsDialog::_showWidgets()
_paned.pack1(*_style_dialog, Gtk::SHRINK);
_paned.pack2(_selectors_box, true, true);
_getContents()->pack_start(_paned, Gtk::PACK_EXPAND_WIDGET);
+ _getContents()->pack_start(_button_box, false, false, 0);
show_all();
int widthpos = _paned.property_max_position();
int panedpos = prefs->getInt("/dialogs/selectors/panedpos", 130);
_paned.set_position(panedpos);
_paned.property_wide_handle() = true;
- _paned.signal_button_release_event().connect(sigc::mem_fun(*this, &SelectorsDialog::_resized), false);
+ _paned.property_position().signal_changed().connect(sigc::mem_fun(*this, &SelectorsDialog::_childresized));
+ _paned.signal_size_allocate().connect(sigc::mem_fun(*this, &SelectorsDialog::_panedresized));
set_size_request(320, 260);
set_name("SelectorsAndStyleDialog");
}
-bool SelectorsDialog::_resized(GdkEventButton *event)
+void SelectorsDialog::_panedresized(Gtk::Allocation allocation)
+{
+ g_debug("SelectorsDialog::_panedresized");
+ _resized();
+}
+
+void SelectorsDialog::_childresized()
+{
+ g_debug("SelectorsDialog::_childresized");
+ _resized();
+}
+
+void SelectorsDialog::_resized()
{
g_debug("SelectorsDialog::_resized");
_scroollock = true;
+ if (_updating) {
+ return;
+ }
+ _updating = true;
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ bool dir = !prefs->getBool("/dialogs/selectors/vertical", true);
+ int max = int(_paned.property_max_position() * 0.95);
+ int min = int(_paned.property_max_position() * 0.05);
+ if (_paned.get_position() > max) {
+ _paned.property_position() = max;
+ }
+ if (_paned.get_position() < min) {
+ _paned.property_position() = min;
+ }
prefs->setInt("/dialogs/selectors/panedpos", _paned.get_position());
- return false;
+ _updating = false;
}
-
-void SelectorsDialog::_toggleDirection()
+void SelectorsDialog::_toggleDirection(Gtk::RadioButton *vertical)
{
g_debug("SelectorsDialog::_toggleDirection");
-
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- bool dir = !prefs->getBool("/dialogs/selectors/vertical", true);
+ bool dir = vertical->get_active();
prefs->setBool("/dialogs/selectors/vertical", dir);
_paned.set_orientation(dir ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL);
- int widthpos = _paned.property_max_position();
+ _paned.check_resize();
+ int widthpos = _paned.property_max_position() - _paned.property_min_position();
prefs->setInt("/dialogs/selectors/panedpos", widthpos / 2);
_paned.set_position(widthpos / 2);
}
@@ -573,7 +548,7 @@ void SelectorsDialog::_readStyleElement()
for (unsigned i = 0; i < tokens.size() - 1; i += 2) {
Glib::ustring selector = tokens[i];
REMOVE_SPACES(selector); // Remove leading/trailing spaces
- fixCSSSelectors(selector);
+ selector = _style_dialog->fixCSSSelectors(selector);
for (auto &row : _store->children()) {
Glib::ustring selectorold = row[_mColumns._colSelector];
if (selectorold == selector) {
@@ -588,7 +563,7 @@ void SelectorsDialog::_readStyleElement()
Glib::ustring selector = tokens[i];
REMOVE_SPACES(selector); // Remove leading/trailing spaces
Glib::ustring selector_old = selector;
- fixCSSSelectors(selector);
+ selector = _style_dialog->fixCSSSelectors(selector);
if (selector_old != selector) {
rewrite = true;
}
@@ -778,8 +753,12 @@ Glib::ustring sp_get_selector_classes(Glib::ustring selector) //, SelectorType s
REMOVE_SPACES(selector);
Glib::ustring toparse = Glib::ustring(selector);
selector = Glib::ustring("");
+ auto i = toparse.find(".");
+ if (i == std::string::npos) {
+ return "";
+ }
if (toparse[0] != '.' && toparse[0] != '#') {
- auto i = std::min(toparse.find("#"), toparse.find("."));
+ i = std::min(toparse.find("#"), toparse.find("."));
Glib::ustring tag = toparse.substr(0, i);
if (!SPAttributeRelSVG::isSVGElement(tag)) {
return selector;
@@ -788,7 +767,7 @@ Glib::ustring sp_get_selector_classes(Glib::ustring selector) //, SelectorType s
toparse.erase(0, i);
}
}
- auto i = toparse.find("#");
+ i = toparse.find("#");
if (i != std::string::npos) {
toparse.erase(i, 1);
}
@@ -856,7 +835,7 @@ void SelectorsDialog::_addToSelector(Gtk::TreeModel::Row row)
if (insertid) {
multiselector = multiselector + ",#" + id;
}
- Gtk::TreeModel::Row childrow = *(_store->append(row->children()));
+ Gtk::TreeModel::Row childrow = *(_store->prepend(row->children()));
childrow[_mColumns._colSelector] = "#" + Glib::ustring(id);
childrow[_mColumns._colExpand] = false;
childrow[_mColumns._colType] = OBJECT;
@@ -1093,6 +1072,9 @@ void SelectorsDialog::_selectObjects(int eventX, int eventY)
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 (_lastpath.size() && _lastpath == path) {
+ return;
+ }
if (col == _treeView.get_column(1) && x2 > 25) {
getDesktop()->selection->clear();
Gtk::TreeModel::iterator iter = _store->get_iter(path);
@@ -1108,6 +1090,7 @@ void SelectorsDialog::_selectObjects(int eventX, int eventY)
getDesktop()->selection->add(obj);
}
}
+ _lastpath = path;
}
}
}
@@ -1179,9 +1162,8 @@ void SelectorsDialog::_addSelector()
* for selector. If the entrybox is empty, the text (thus selectorName) is
* set to ".Class1"
*/
- selectorValue = textEditPtr->get_text();
+ selectorValue = _style_dialog->fixCSSSelectors(Glib::ustring(textEditPtr->get_text()));
_del.show();
- fixCSSSelectors(selectorValue);
if (selectorValue.empty()) {
textLabelPtr->show();
} else {
@@ -1190,7 +1172,6 @@ void SelectorsDialog::_addSelector()
}
delete textDialogPtr;
// ==== Handle response ====
-
// If class selector, add selector name to class attribute for each object
REMOVE_SPACES(selectorValue);
std::vector tokens = Glib::Regex::split_simple("[,]+", selectorValue);
@@ -1214,7 +1195,7 @@ void SelectorsDialog::_addSelector()
}
}
objVec = _getObjVec(selectorValue);
- Gtk::TreeModel::Row row = *(_store->append());
+ Gtk::TreeModel::Row row = *(_store->prepend());
row[_mColumns._colExpand] = true;
row[_mColumns._colType] = SELECTOR;
row[_mColumns._colSelector] = selectorValue;
@@ -1223,7 +1204,7 @@ void SelectorsDialog::_addSelector()
row[_mColumns._colVisible] = true;
row[_mColumns._colSelected] = 400;
for (auto &obj : objVec) {
- Gtk::TreeModel::Row childrow = *(_store->append(row->children()));
+ Gtk::TreeModel::Row childrow = *(_store->prepend(row->children()));
childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId());
childrow[_mColumns._colExpand] = false;
childrow[_mColumns._colType] = OBJECT;
@@ -1382,6 +1363,7 @@ void SelectorsDialog::_handleDesktopChanged(SPDesktop *desktop)
void SelectorsDialog::_handleSelectionChanged()
{
g_debug("SelectorsDialog::_handleSelectionChanged()");
+ _lastpath.clear();
_treeView.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE);
_selectRow();
}
diff --git a/src/ui/dialog/selectorsdialog.h b/src/ui/dialog/selectorsdialog.h
index 6830a0124e709285b5dcca56e360189d85e985cb..66d9bb859f86ca84e5ae745c7c65607d54712188 100644
--- a/src/ui/dialog/selectorsdialog.h
+++ b/src/ui/dialog/selectorsdialog.h
@@ -15,12 +15,13 @@
#ifndef SELECTORSDIALOG_H
#define SELECTORSDIALOG_H
-#include "ui/dialog/styledialog.h"
#include "ui/dialog/desktop-tracker.h"
#include "ui/dialog/dialog-manager.h"
+#include "ui/dialog/styledialog.h"
#include "ui/widget/panel.h"
#include
#include
+#include
#include
#include
#include
@@ -64,7 +65,6 @@ class SelectorsDialog : public Widget::Panel {
// Monitor all objects for addition/removal/attribute change
class NodeWatcher;
enum SelectorType { CLASS, ID, TAG };
- void fixCSSSelectors(Glib::ustring &selector);
std::vector _nodeWatchers;
void _nodeAdded( Inkscape::XML::Node &repr );
void _nodeRemoved( Inkscape::XML::Node &repr );
@@ -117,10 +117,10 @@ class SelectorsDialog : public Widget::Panel {
Glib::RefPtr _modelfilter;
Glib::RefPtr _store;
Gtk::TreeView _treeView;
+ Gtk::TreeModel::Path _lastpath;
// Widgets
Gtk::Paned _paned;
Glib::RefPtr _vadj;
- Gtk::Switch _direction;
Gtk::Box _button_box;
Gtk::Box _selectors_box;
Gtk::ScrolledWindow _scrolled_window_selectors;
@@ -146,9 +146,11 @@ class SelectorsDialog : public Widget::Panel {
void _insertClass(SPObject *obj, const Glib::ustring &className);
void _removeClass(const std::vector &objVec, const Glib::ustring &className, bool all = false);
void _removeClass(SPObject *obj, const Glib::ustring &className, bool all = false);
- void _toggleDirection();
+ void _toggleDirection(Gtk::RadioButton *vertical);
void _showWidgets();
- bool _resized(GdkEventButton *event);
+ void _resized();
+ void _childresized();
+ void _panedresized(Gtk::Allocation allocation);
void _selectObjects(int, int);
// Variables
diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp
index 75b44f8318658c4227af14ab1cb57a0ba35bd215..884da2df2906f2b211d5b965439caa3409a94964 100644
--- a/src/ui/dialog/styledialog.cpp
+++ b/src/ui/dialog/styledialog.cpp
@@ -201,18 +201,11 @@ StyleDialog::StyleDialog()
Gtk::Box *alltoggler = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_HORIZONTAL));
Gtk::Label *infotoggler = Gtk::manage(new Gtk::Label(_("Edit Full Stylesheet")));
infotoggler->get_style_context()->add_class("inksmall");
- _all_css = Gtk::manage(new Gtk::Switch());
_vadj = _scrolledWindow.get_vadjustment();
_vadj->signal_value_changed().connect(sigc::mem_fun(*this, &StyleDialog::_vscrool));
- //_all_css->property_active().signal_changed().connect(sigc::mem_fun(*this, &StyleDialog::_reload));
- // alltoggler->pack_start(*_all_css, false, false, 0);
- // alltoggler->pack_start(*infotoggler, false, false, 0);
- //_all_css->set_active(false);
- //_mainBox.pack_start(*alltoggler, false, false, 0);
_mainBox.set_orientation(Gtk::ORIENTATION_VERTICAL);
_getContents()->pack_start(_mainBox, Gtk::PACK_EXPAND_WIDGET);
- //_all_css->get_style_context()->add_class("inkswitch");
// Document & Desktop
_desktop_changed_connection =
_desktopTracker.connectDesktopChanged(sigc::mem_fun(*this, &StyleDialog::_handleDesktopChanged));
@@ -223,6 +216,7 @@ StyleDialog::StyleDialog()
_selection_changed_connection = getDesktop()->getSelection()->connectChanged(
sigc::hide(sigc::mem_fun(this, &StyleDialog::_handleSelectionChanged)));
+
// Add watchers
_updateWatchers();
@@ -240,6 +234,43 @@ void StyleDialog::_vscrool()
}
}
+Glib::ustring StyleDialog::fixCSSSelectors(Glib::ustring selector)
+{
+ g_debug("SelectorsDialog::fixCSSSelectors");
+ REMOVE_SPACES(selector);
+ Glib::ustring selector_out = "";
+ std::vector tokens = Glib::Regex::split_simple("[,]+", selector);
+ for (auto token : tokens) {
+ if (!selector_out.empty()) {
+ selector_out += ",";
+ }
+ REMOVE_SPACES(token);
+ std::vector subtokens = Glib::Regex::split_simple("[ ]+", token);
+ for (auto subtoken : subtokens) {
+ REMOVE_SPACES(subtoken);
+ Glib::ustring my_selector = subtoken + " {"; // Parsing fails sometimes without '{'. Fix me
+ CRSelector *cr_selector = cr_selector_parse_from_buf((guchar *)my_selector.c_str(), CR_UTF_8);
+ gchar *selectorchar = reinterpret_cast(cr_selector_to_string(cr_selector));
+ if (selectorchar) {
+ Glib::ustring toadd = Glib::ustring(selectorchar);
+ g_free(selectorchar);
+ if (toadd[0] != '.' && toadd[0] != '#' && toadd.size() > 1) {
+ auto i = std::min(toadd.find("#"), toadd.find("."));
+ Glib::ustring tag = toadd;
+ if (i != std::string::npos) {
+ tag = tag.substr(0, i);
+ }
+ if (!SPAttributeRelSVG::isSVGElement(tag)) {
+ return "";
+ }
+ }
+ selector_out = selector_out.empty() ? toadd : selector_out + " " + toadd;
+ }
+ }
+ }
+ return selector_out;
+}
+
/**
* Class destructor
*/
@@ -466,6 +497,7 @@ void StyleDialog::_readStyleElement()
css_selector->set_text("element");
Gtk::TreeView *css_tree;
_builder->get_widget("CSSTree", css_tree);
+ css_tree->get_style_context()->add_class("style_element");
Glib::RefPtr store = Gtk::TreeStore::create(_mColumns);
css_tree->set_model(store);
css_selector_event_add->signal_button_release_event().connect(
@@ -473,7 +505,7 @@ void StyleDialog::_readStyleElement()
sigc::mem_fun(*this, &StyleDialog::_addRow), store, css_tree, "style_properties", selectorpos));
Inkscape::UI::Widget::IconRenderer *addRenderer = manage(new Inkscape::UI::Widget::IconRenderer());
addRenderer->add_icon("edit-delete");
- int addCol = css_tree->append_column("Delete row", *addRenderer) - 1;
+ int addCol = css_tree->append_column("", *addRenderer) - 1;
Gtk::TreeViewColumn *col = css_tree->get_column(addCol);
if (col) {
addRenderer->signal_activated().connect(
@@ -485,9 +517,10 @@ void StyleDialog::_readStyleElement()
label->signal_edited().connect(sigc::bind, Gtk::TreeView *>(
sigc::mem_fun(*this, &StyleDialog::_nameEdited), store, css_tree));
label->signal_editing_started().connect(sigc::mem_fun(*this, &StyleDialog::_startNameEdit));
- addCol = css_tree->append_column("CSS Property", *label) - 1;
+ addCol = css_tree->append_column("", *label) - 1;
col = css_tree->get_column(addCol);
if (col) {
+ col->set_resizable(true);
col->add_attribute(label->property_text(), _mColumns._colName);
}
Gtk::CellRendererText *value = Gtk::manage(new Gtk::CellRendererText());
@@ -497,7 +530,7 @@ void StyleDialog::_readStyleElement()
sigc::bind>(sigc::mem_fun(*this, &StyleDialog::_valueEdited), store));
value->signal_editing_started().connect(
sigc::bind>(sigc::mem_fun(*this, &StyleDialog::_startValueEdit), store));
- addCol = css_tree->append_column("CSS Value", *value) - 1;
+ addCol = css_tree->append_column("", *value) - 1;
col = css_tree->get_column(addCol);
if (col) {
col->add_attribute(value->property_text(), _mColumns._colValue);
@@ -506,7 +539,7 @@ void StyleDialog::_readStyleElement()
Inkscape::UI::Widget::IconRenderer *urlRenderer = manage(new Inkscape::UI::Widget::IconRenderer());
urlRenderer->add_icon("empty");
urlRenderer->add_icon("edit-redo");
- int urlCol = css_tree->append_column("Go to", *urlRenderer) - 1;
+ int urlCol = css_tree->append_column("", *urlRenderer) - 1;
Gtk::TreeViewColumn *urlcol = css_tree->get_column(urlCol);
if (urlcol) {
urlRenderer->signal_activated().connect(
@@ -515,19 +548,19 @@ void StyleDialog::_readStyleElement()
}
std::map attr_prop;
Gtk::TreeModel::Path path;
- if (!_all_css->get_active() && obj && obj->getRepr()->attribute("style")) {
+ if (obj && obj->getRepr()->attribute("style")) {
Glib::ustring style = obj->getRepr()->attribute("style");
attr_prop = parseStyle(style);
for (auto iter : obj->style->properties()) {
if (attr_prop.count(iter->name)) {
- Gtk::TreeModel::Row row = *(store->append());
+ Gtk::TreeModel::Row row = *(store->prepend());
row[_mColumns._colSelector] = "style_properties";
row[_mColumns._colSelectorPos] = 0;
row[_mColumns._colActive] = true;
row[_mColumns._colName] = iter->name;
row[_mColumns._colValue] = iter->get_value();
row[_mColumns._colStrike] = false;
- row[_mColumns._colOwner] = Glib::ustring("Value active");
+ row[_mColumns._colOwner] = Glib::ustring("Current value");
row[_mColumns._colHref] = nullptr;
row[_mColumns._colLinked] = false;
if (is_url(iter->get_value().c_str())) {
@@ -554,7 +587,7 @@ void StyleDialog::_readStyleElement()
REMOVE_SPACES(selector); // Remove leading/trailing spaces
// Get list of objects selector matches
std::vector objVec = _getObjVec(selector);
- if (obj && !_all_css->get_active()) {
+ if (obj) {
bool stop = true;
for (auto objel : objVec) {
if (objel->getId() == obj->getId()) {
@@ -592,14 +625,25 @@ void StyleDialog::_readStyleElement()
_builder->get_widget("CSSSelectorContainer", css_selector_container);
Gtk::Label *css_selector;
_builder->get_widget("CSSSelector", css_selector);
+ Gtk::EventBox *css_selector_event_box;
+ _builder->get_widget("CSSSelectorEventBox", css_selector_event_box);
+ Gtk::Entry *css_edit_selector;
+ _builder->get_widget("CSSEditSelector", css_edit_selector);
Gtk::EventBox *css_selector_event_add;
_builder->get_widget("CSSSelectorEventAdd", css_selector_event_add);
css_selector_event_add->add_events(Gdk::BUTTON_RELEASE_MASK);
css_selector->set_text(selector);
Gtk::TreeView *css_tree;
_builder->get_widget("CSSTree", css_tree);
+ css_tree->get_style_context()->add_class("style_sheet");
Glib::RefPtr store = Gtk::TreeStore::create(_mColumns);
css_tree->set_model(store);
+ css_selector_event_box->signal_button_release_event().connect(
+ sigc::bind(sigc::mem_fun(*this, &StyleDialog::_selectorStartEdit), css_selector, css_edit_selector));
+ css_edit_selector->signal_key_press_event().connect(sigc::bind(
+ sigc::mem_fun(*this, &StyleDialog::_selectorEditKeyPress), store, css_selector, css_edit_selector));
+ css_edit_selector->signal_activate().connect(
+ sigc::bind(sigc::mem_fun(*this, &StyleDialog::_selectorActivate), store, css_selector, css_edit_selector));
Inkscape::UI::Widget::IconRenderer *addRenderer = manage(new Inkscape::UI::Widget::IconRenderer());
addRenderer->add_icon("edit-delete");
int addCol = css_tree->append_column("Delete row", *addRenderer) - 1;
@@ -625,6 +669,7 @@ void StyleDialog::_readStyleElement()
addCol = css_tree->append_column("CSS Selector", *label) - 1;
col = css_tree->get_column(addCol);
if (col) {
+ col->set_resizable(true);
col->add_attribute(label->property_text(), _mColumns._colName);
}
Gtk::CellRendererText *value = Gtk::manage(new Gtk::CellRendererText());
@@ -662,7 +707,7 @@ void StyleDialog::_readStyleElement()
css_selector_event_add->signal_button_release_event().connect(
sigc::bind, Gtk::TreeView *, Glib::ustring, gint>(
sigc::mem_fun(*this, &StyleDialog::_addRow), store, css_tree, selector, selectorpos));
- if (obj && !_all_css->get_active()) {
+ if (obj) {
for (auto iter : result_props) {
Gtk::TreeIter iterstore = store->append();
Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iterstore;
@@ -690,7 +735,7 @@ void StyleDialog::_readStyleElement()
row[_mColumns._colOwner] = Glib::ustring("");
} else {
row[_mColumns._colStrike] = false;
- row[_mColumns._colOwner] = Glib::ustring("Value active");
+ row[_mColumns._colOwner] = Glib::ustring("Current value");
_addOwnerStyle(iter.first, selector);
}
} else {
@@ -701,7 +746,7 @@ void StyleDialog::_readStyleElement()
}
} else {
for (auto iter : result_props) {
- Gtk::TreeModel::Row row = *(store->append());
+ Gtk::TreeModel::Row row = *(store->prepend());
row[_mColumns._colSelector] = selector;
row[_mColumns._colSelectorPos] = selectorpos;
row[_mColumns._colActive] = iter.second.second;
@@ -727,12 +772,13 @@ void StyleDialog::_readStyleElement()
css_selector_event_add->add_events(Gdk::BUTTON_RELEASE_MASK);
store = Gtk::TreeStore::create(_mColumns);
_builder->get_widget("CSSTree", css_tree);
+ css_tree->get_style_context()->add_class("style_attribute");
css_tree->set_model(store);
css_selector_event_add->signal_button_release_event().connect(
sigc::bind, Gtk::TreeView *, Glib::ustring, gint>(
sigc::mem_fun(*this, &StyleDialog::_addRow), store, css_tree, "attributes", selectorpos));
bool hasattributes = false;
- if (obj && !_all_css->get_active()) {
+ if (obj) {
for (auto iter : obj->style->properties()) {
if (iter->style_src != SP_STYLE_SRC_UNSET) {
if (iter->name != "font" && iter->name != "d" && iter->name != "marker") {
@@ -757,6 +803,7 @@ void StyleDialog::_readStyleElement()
addCol = css_tree->append_column("CSS Property", *label) - 1;
col = css_tree->get_column(addCol);
if (col) {
+ col->set_resizable(true);
col->add_attribute(label->property_text(), _mColumns._colName);
}
Gtk::CellRendererText *value = Gtk::manage(new Gtk::CellRendererText());
@@ -774,7 +821,7 @@ void StyleDialog::_readStyleElement()
col->add_attribute(value->property_strikethrough(), _mColumns._colStrike);
}
}
- Gtk::TreeIter iterstore = store->append();
+ Gtk::TreeIter iterstore = store->prepend();
Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iterstore;
Gtk::TreeModel::Row row = *(iterstore);
row[_mColumns._colSelector] = "attributes";
@@ -788,7 +835,7 @@ void StyleDialog::_readStyleElement()
row[_mColumns._colOwner] = tooltiptext;
} else {
row[_mColumns._colStrike] = false;
- row[_mColumns._colOwner] = Glib::ustring("Value active");
+ row[_mColumns._colOwner] = Glib::ustring("Current value");
_addOwnerStyle(iter->name, "inline attributes");
}
hasattributes = true;
@@ -826,6 +873,43 @@ void StyleDialog::_readStyleElement()
_updating = false;
}
+bool StyleDialog::_selectorStartEdit(GdkEventButton *event, Gtk::Label *selector, Gtk::Entry *selector_edit)
+{
+ g_debug("StyleDialog::_selectorStartEdit");
+ if (event->type == GDK_BUTTON_RELEASE && event->button == 1) {
+ selector->hide();
+ selector_edit->set_text(selector->get_text());
+ selector_edit->show();
+ }
+ return false;
+}
+
+void StyleDialog::_selectorActivate(Glib::RefPtr store, Gtk::Label *selector, Gtk::Entry *selector_edit)
+{
+ g_debug("StyleDialog::_selectorEditKeyPress");
+ bool ret = false;
+ Glib::ustring newselector = fixCSSSelectors(selector_edit->get_text());
+ if (newselector.empty()) {
+ selector_edit->get_style_context()->add_class("system_error_color");
+ return;
+ }
+ _writeStyleElement(store, selector->get_text(), selector_edit->get_text());
+}
+
+bool StyleDialog::_selectorEditKeyPress(GdkEventKey *event, Glib::RefPtr store, Gtk::Label *selector,
+ Gtk::Entry *selector_edit)
+{
+ g_debug("StyleDialog::_selectorEditKeyPress");
+ switch (event->keyval) {
+ case GDK_KEY_Escape:
+ selector->show();
+ selector_edit->hide();
+ selector_edit->get_style_context()->remove_class("system_error_color");
+ break;
+ }
+ return false;
+}
+
bool StyleDialog::_on_foreach_iter(const Gtk::TreeModel::iterator &iter)
{
g_debug("StyleDialog::_on_foreach_iter");
@@ -921,7 +1005,8 @@ std::map StyleDialog::parseStyle(Glib::ustring sty
/**
* Update the content of the style element as selectors (or objects) are added/removed.
*/
-void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::ustring selector)
+void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::ustring selector,
+ Glib::ustring new_selector)
{
g_debug("StyleDialog::_writeStyleElemen");
if (_updating) {
@@ -936,7 +1021,7 @@ void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::u
if (!obj) {
obj = getDesktop()->getDocument()->getXMLDialogSelectedObject();
}
- if (selection->objects().size() < 2 && !obj && !_all_css->get_active()) {
+ if (selection->objects().size() < 2 && !obj) {
_readStyleElement();
return;
}
@@ -944,6 +1029,9 @@ void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::u
gint selectorpos = 0;
std::string styleContent = "";
if (selector != "style_properties" && selector != "attributes") {
+ if (!new_selector.empty()) {
+ selector = new_selector;
+ }
styleContent = "\n" + selector + " { \n";
}
for (auto &row : store->children()) {
@@ -965,13 +1053,17 @@ void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::u
styleContent = styleContent + "}";
}
if (selector == "style_properties") {
+ _updating = true;
obj->getRepr()->setAttribute("style", styleContent, false);
+ _updating = false;
} else if (selector == "attributes") {
for (auto iter : obj->style->properties()) {
if (iter->name != "font" && iter->name != "d" && iter->name != "marker") {
const gchar *attr = obj->getRepr()->attribute(iter->name.c_str());
if (attr) {
+ _updating = true;
obj->getRepr()->setAttribute(iter->name.c_str(), nullptr);
+ _updating = false;
}
}
}
@@ -979,13 +1071,15 @@ void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::u
Glib::ustring name = row[_mColumns._colName];
Glib::ustring value = row[_mColumns._colValue];
if (!(name.empty() && value.empty())) {
+ _updating = true;
obj->getRepr()->setAttribute(name.c_str(), value, false);
+ _updating = false;
}
}
} else if (!selector.empty()) { // styleshet
// We could test if styleContent is empty and then delete the style node here but there is no
// harm in keeping it around ...
- SPDocument *document = SP_ACTIVE_DOCUMENT;
+
std::string pos = std::to_string(selectorpos);
std::string selectormatch = "(";
for (selectorpos; selectorpos > 1; selectorpos--) {
@@ -998,14 +1092,16 @@ void StyleDialog::_writeStyleElement(Glib::RefPtr store, Glib::u
std::string result;
std::regex_replace(std::back_inserter(result), content.begin(), content.end(), e, "$1" + styleContent + "$3");
textNode->setContent(result.c_str());
- INKSCAPE.readStyleSheets();
- for (auto iter : document->getObjectsBySelector(selector)) {
- iter->style->readFromObject(iter);
- iter->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
- }
+ INKSCAPE.readStyleSheets(true);
}
_updating = false;
_readStyleElement();
+ /* SPDocument *document = SP_ACTIVE_DOCUMENT;
+ for (auto iter : document->getObjectsBySelector(selector)) {
+ std::cout << std::endl;
+ iter->style->readFromObject(iter);
+ iter->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ } */
DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_STYLE, _("Edited style element."));
g_debug("StyleDialog::_writeStyleElement(): | %s |", styleContent.c_str());
@@ -1017,7 +1113,7 @@ bool StyleDialog::_addRow(GdkEventButton *evt, Glib::RefPtr stor
g_debug("StyleDialog::_addRow");
if (evt->type == GDK_BUTTON_RELEASE && evt->button == 1) {
- Gtk::TreeIter iter = store->append();
+ Gtk::TreeIter iter = store->prepend();
Gtk::TreeModel::Path path = (Gtk::TreeModel::Path)iter;
Gtk::TreeModel::Row row = *(iter);
row[_mColumns._colSelector] = selector;
@@ -1050,7 +1146,7 @@ void StyleDialog::_setAutocompletion(Gtk::Entry *entry, SPStyleEnum const cssenu
gint counter = 0;
const char * key = cssenum[counter].key;
while (key) {
- Gtk::TreeModel::Row row = *(completionModel->append());
+ Gtk::TreeModel::Row row = *(completionModel->prepend());
row[_mCSSData._colCSSData] = Glib::ustring(key);
counter++;
key = cssenum[counter].key;
@@ -1144,7 +1240,9 @@ StyleDialog::_startValueEdit(Gtk::CellEditable* cell, const Glib::ustring& path,
_setAutocompletion(entry, enum_color_interpolation);
}
entry->signal_key_release_event().connect(
- sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onValueKeyReleased), cell));
+ sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onValueKeyReleased), entry));
+ entry->signal_key_press_event().connect(
+ sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onValueKeyPressed), entry));
}
}
@@ -1165,7 +1263,22 @@ void StyleDialog::_startNameEdit(Gtk::CellEditable *cell, const Glib::ustring &p
}
Gtk::Entry *entry = dynamic_cast(cell);
entry->set_completion(entry_completion);
- entry->signal_key_release_event().connect(sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onNameKeyReleased), cell));
+ entry->signal_key_release_event().connect(
+ sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onNameKeyReleased), entry));
+ entry->signal_key_press_event().connect(sigc::bind(sigc::mem_fun(*this, &StyleDialog::_onNameKeyPressed), entry));
+}
+
+
+gboolean sp_styledialog_store_move_to_next(gpointer data)
+{
+ StyleDialog *styledialog = reinterpret_cast(data);
+ auto selection = styledialog->_current_css_tree->get_selection();
+ Gtk::TreeIter iter = *(selection->get_selected());
+ Gtk::TreeModel::Path model = (Gtk::TreeModel::Path)iter;
+ if (model == styledialog->_current_path) {
+ styledialog->_current_css_tree->set_cursor(styledialog->_current_path, *styledialog->_current_value_col, true);
+ }
+ return FALSE;
}
/**
@@ -1181,9 +1294,10 @@ void StyleDialog::_nameEdited(const Glib::ustring &path, const Glib::ustring &na
_scroollock = true;
Gtk::TreeModel::Row row = *store->get_iter(path);
- Gtk::TreeModel::Path pathel = (Gtk::TreeModel::Path)*store->get_iter(path);
+ _current_path = (Gtk::TreeModel::Path)*store->get_iter(path);
if (row) {
+ _current_css_tree = css_tree;
Glib::ustring finalname = name;
auto i = std::min(finalname.find(";"), finalname.find(":"));
if (i != std::string::npos) {
@@ -1197,7 +1311,7 @@ void StyleDialog::_nameEdited(const Glib::ustring &path, const Glib::ustring &na
Glib::ustring selector = row[_mColumns._colSelector];
Glib::ustring value = row[_mColumns._colValue];
bool is_attr = selector == "attributes";
-
+ Glib::ustring old_name = row[_mColumns._colName];
row[_mColumns._colName] = finalname;
if (finalname.empty() && value.empty()) {
store->erase(row);
@@ -1206,10 +1320,11 @@ void StyleDialog::_nameEdited(const Glib::ustring &path, const Glib::ustring &na
if (pos < 1 || is_attr) {
col = 2;
}
- if (write) {
+ _current_value_col = css_tree->get_column(col);
+ if (write && old_name != name) {
_writeStyleElement(store, selector);
} else {
- css_tree->set_cursor(pathel, *(css_tree->get_column(col)), true);
+ g_timeout_add(50, &sp_styledialog_store_move_to_next, this);
grab_focus();
}
}
@@ -1235,6 +1350,10 @@ void StyleDialog::_valueEdited(const Glib::ustring &path, const Glib::ustring &v
if (i != std::string::npos) {
finalvalue.erase(i, finalvalue.size() - i);
}
+ Glib::ustring old_value = row[_mColumns._colValue];
+ if (old_value == finalvalue) {
+ return;
+ }
row[_mColumns._colValue] = finalvalue;
Glib::ustring selector = row[_mColumns._colSelector];
Glib::ustring name = row[_mColumns._colName];
@@ -1258,56 +1377,81 @@ void StyleDialog::_activeToggled(const Glib::ustring &path, Glib::RefPtrkeyval) {
case GDK_KEY_Tab:
case GDK_KEY_KP_Tab:
- case GDK_KEY_colon: {
- cell->editing_done();
- return true;
- }
+ entry->editing_done();
+ ret = true;
+ break;
+ }
+ return ret;
+}
+
+bool StyleDialog::_onNameKeyReleased(GdkEventKey *event, Gtk::Entry *entry)
+{
+ g_debug("StyleDialog::_onNameKeyReleased");
+ bool ret = false;
+ switch (event->keyval) {
+ case GDK_KEY_equal:
+ case GDK_KEY_colon:
+ entry->editing_done();
+ ret = true;
+ break;
case GDK_KEY_Shift_L:
case GDK_KEY_Shift_R:
case GDK_KEY_semicolon: {
- Gtk::Entry *entry = dynamic_cast(cell);
Glib::ustring text = entry->get_text();
auto i = std::min(text.find(";"), text.find(":"));
if (i != std::string::npos) {
- cell->editing_done();
- return true;
+ entry->editing_done();
+ ret = true;
}
+ break;
}
}
- return false;
+ return ret;
}
-bool StyleDialog::_onValueKeyReleased(GdkEventKey *event, Gtk::CellEditable *cell)
+bool StyleDialog::_onValueKeyPressed(GdkEventKey *event, Gtk::Entry *entry)
{
g_debug("StyleDialog::_onValueKeyReleased");
-
+ bool ret = false;
switch (event->keyval) {
case GDK_KEY_Tab:
case GDK_KEY_KP_Tab:
- case GDK_KEY_semicolon: {
- cell->editing_done();
- return true;
- }
+ entry->editing_done();
+ ret = true;
+ break;
+ }
+ return ret;
+}
+
+bool StyleDialog::_onValueKeyReleased(GdkEventKey *event, Gtk::Entry *entry)
+{
+ g_debug("StyleDialog::_onValueKeyReleased");
+ bool ret = false;
+ switch (event->keyval) {
+ case GDK_KEY_semicolon:
+ entry->editing_done();
+ ret = true;
+ break;
case GDK_KEY_Shift_L:
case GDK_KEY_Shift_R:
case GDK_KEY_colon: {
- Gtk::Entry *entry = dynamic_cast(cell);
Glib::ustring text = entry->get_text();
auto i = std::min(text.find(";"), text.find(":"));
if (i != std::string::npos) {
- cell->editing_done();
- return true;
+ entry->editing_done();
+ ret = true;
}
+ break;
}
}
- return false;
+ return ret;
}
void StyleDialog::_addWatcherRecursive(Inkscape::XML::Node *node)
diff --git a/src/ui/dialog/styledialog.h b/src/ui/dialog/styledialog.h
index 90b9d298fc552732b432fc47febf9219570fb2a1..b7ccf661999f019886e6b67e1bcf130af62494ba 100644
--- a/src/ui/dialog/styledialog.h
+++ b/src/ui/dialog/styledialog.h
@@ -67,6 +67,10 @@ class StyleDialog : public Widget::Panel {
static StyleDialog &getInstance() { return *new StyleDialog(); }
void setCurrentSelector(Glib::ustring current_selector);
+ Gtk::TreeView *_current_css_tree;
+ Gtk::TreeViewColumn *_current_value_col;
+ Gtk::TreeModel::Path _current_path;
+ Glib::ustring fixCSSSelectors(Glib::ustring selector);
private:
// Monitor