diff options
| author | Jabier Arraiza <jabier.arraiza@marker.es> | 2019-08-22 01:39:49 +0000 |
|---|---|---|
| committer | Jabier Arraiza <jabier.arraiza@marker.es> | 2019-08-22 01:39:49 +0000 |
| commit | d1a647def410422f10d4386529efbcbf14532ce4 (patch) | |
| tree | 19e7e1b57cd5c8e048b434a44122577cda134729 /src/ui/dialog/attrdialog.cpp | |
| parent | Update it.po (diff) | |
| download | inkscape-d1a647def410422f10d4386529efbcbf14532ce4.tar.gz inkscape-d1a647def410422f10d4386529efbcbf14532ce4.zip | |
Merge XML and CSS widgets improvements from https://gitlab.com/inkscape/inkscape/merge_requests/801
Diffstat (limited to 'src/ui/dialog/attrdialog.cpp')
| -rw-r--r-- | src/ui/dialog/attrdialog.cpp | 207 |
1 files changed, 183 insertions, 24 deletions
diff --git a/src/ui/dialog/attrdialog.cpp b/src/ui/dialog/attrdialog.cpp index 3db739059..a499602ce 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<Gtk::TextBuffer> 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<Gtk::Entry *>(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<AttrDialog *>(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<Gtk::Entry *>(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<Gtk::TextBuffer> 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<Gtk::TextBuffer> 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<AttrDialog *>(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")); } } |
