From 35a635e53826eecdf3b5932dffbcaab708770771 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Date: Sat, 20 Apr 2019 18:40:55 +0200 Subject: reorder dialogs --- src/ui/dialog/styledialog.cpp | 510 ++++++------------------------------------ 1 file changed, 64 insertions(+), 446 deletions(-) (limited to 'src/ui/dialog/styledialog.cpp') diff --git a/src/ui/dialog/styledialog.cpp b/src/ui/dialog/styledialog.cpp index cc1c6acb8..08e5117b5 100644 --- a/src/ui/dialog/styledialog.cpp +++ b/src/ui/dialog/styledialog.cpp @@ -32,8 +32,7 @@ static void on_attr_changed(Inkscape::XML::Node *repr, const gchar *name, const gchar * /*old_value*/, const gchar *new_value, bool /*is_interactive*/, gpointer data) { - CSS_DIALOG(data)->onAttrChanged(repr, name, new_value); - CSS_DIALOG(data)->styledialog = new Inkscape::UI::Dialog::StyleDialog(); + STYLE_DIALOG(data)->onAttrChanged(repr, name, new_value); } Inkscape::XML::NodeEventVector css_repr_events = { @@ -56,97 +55,33 @@ namespace Dialog { * and clicking 'Enter' updates the property with changes reflected in the * drawing. */ -StyleDialog::StyleDialog(bool stylemode) : - UI::Widget::Panel("/dialogs/style", SP_VERB_DIALOG_STYLE), - _updating(false), - _textNode(nullptr), - _desktopTracker(), - _stylemode(stylemode) +StyleDialog::StyleDialog() + : UI::Widget::Panel("/dialogs/css", SP_VERB_DIALOG_CSS) + , _desktop(nullptr) + , _repr(nullptr) { - g_debug("StyleDialog::StyleDialog"); - - // Tree - Inkscape::UI::Widget::IconRenderer * addRenderer = manage( - new Inkscape::UI::Widget::IconRenderer() ); - addRenderer->add_icon("edit-delete"); - addRenderer->add_icon("list-add"); - addRenderer->add_icon("object-locked"); - - _store = TreeStore::create(this); - _modelfilter = Gtk::TreeModelFilter::create(_store); - _modelfilter->set_visible_column(_mColumns._colVisible); - _treeView.set_model(_modelfilter); + set_size_request(20, 15); _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_icon(), _mColumns._colType); - } - _treeView.append_column("CSS Selector", _mColumns._colSelector); - _treeView.set_expander_column(*(_treeView.get_column(1))); - - // Pack widgets - _paned.set_orientation(Gtk::ORIENTATION_VERTICAL); - _paned.pack1(_mainBox, Gtk::SHRINK); - _mainBox.set_orientation(Gtk::ORIENTATION_VERTICAL); - if (!_stylemode) { - _mainBox.pack_start(_scrolledWindow, Gtk::PACK_EXPAND_WIDGET); - _scrolledWindow.add(_treeView); - _scrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); - create = manage( new Gtk::Button() ); - _styleButton(*create, "list-add", "Add a new CSS Selector"); - create->signal_clicked().connect(sigc::mem_fun(*this, &StyleDialog::_addSelector)); - - del = manage( new Gtk::Button() ); - _styleButton(*del, "list-remove", "Remove a CSS Selector"); - del->signal_clicked().connect(sigc::mem_fun(*this, &StyleDialog::_delSelector)); - del->set_sensitive(false); - _mainBox.pack_end(_buttonBox, Gtk::PACK_SHRINK); - - _buttonBox.pack_start(*create, Gtk::PACK_SHRINK); - _buttonBox.pack_start(*del, Gtk::PACK_SHRINK); - } else { - _mainBox.pack_start(_treeView, Gtk::PACK_EXPAND_WIDGET); - } - _getContents()->pack_start(_paned, Gtk::PACK_EXPAND_WIDGET); - - - // Signal handlers - _treeView.signal_button_release_event().connect( // Needs to be release, not press. - sigc::mem_fun(*this, &StyleDialog::_handleButtonEvent), - false); - - _treeView.signal_button_release_event().connect_notify( - sigc::mem_fun(*this, &StyleDialog::_buttonEventsSelectObjs), - false); - - _treeView.signal_row_expanded().connect(sigc::mem_fun(*this, &StyleDialog::_rowExpand)); - - _treeView.signal_row_collapsed().connect(sigc::mem_fun(*this, &StyleDialog::_rowCollapse)); - - // Document & Desktop - _desktop_changed_connection = _desktopTracker.connectDesktopChanged( - sigc::mem_fun(*this, &StyleDialog::_handleDesktopChanged) ); - _desktopTracker.connect(GTK_WIDGET(gobj())); - - _document_replaced_connection = getDesktop()->connectDocumentReplaced( - sigc::mem_fun(this, &StyleDialog::_handleDocumentReplaced)); - - _selection_changed_connection = getDesktop()->getSelection()->connectChanged( - sigc::hide(sigc::mem_fun(this, &StyleDialog::_handleSelectionChanged))); - - // Add watchers - _updateWatchers(); + auto _scrolledWindow = new Gtk::ScrolledWindow(); + _selectordialog = new Inkscape::UI::Dialog::SelectorDialog(true); + Gtk::Box *css_box = Gtk::manage(new Gtk::Box(Gtk::ORIENTATION_VERTICAL)); + css_box->set_homogeneous(false); + css_box->pack_start(_treeView, Gtk::PACK_SHRINK); + css_box->pack_start(*_selectordialog, Gtk::PACK_EXPAND_WIDGET); + _scrolledWindow->add(*css_box); + _scrolledWindow->set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); + + _store = Gtk::ListStore::create(_cssColumns); + _treeView.set_model(_store); Inkscape::UI::Widget::IconRenderer *addRenderer = manage(new Inkscape::UI::Widget::IconRenderer()); addRenderer->add_icon("edit-delete"); addRenderer->signal_activated().connect(sigc::mem_fun(*this, &StyleDialog::onPropertyDelete)); - if (!_stylemode && !_store->children().empty()) { - del->set_sensitive(true); - } + _message_stack = std::make_shared(); + _message_context = std::unique_ptr(new Inkscape::MessageContext(_message_stack)); + _message_changed_connection = + _message_stack->connectChanged(sigc::bind(sigc::ptr_fun(_set_status_message), GTK_WIDGET(status.gobj()))); int addCol = _treeView.append_column("", *addRenderer) - 1; Gtk::TreeViewColumn *col = _treeView.get_column(addCol); @@ -173,7 +108,7 @@ StyleDialog::StyleDialog(bool stylemode) : _propCol->add_attribute(renderer->property_text(), _cssColumns.label); _propCol->add_attribute(renderer->property_foreground_rgba(), _cssColumns.label_color); } - renderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog::nameEdited)); + renderer->signal_edited().connect(sigc::mem_fun(*this, &StyleDialog::nameEdited)); renderer = Gtk::manage(new Gtk::CellRendererText()); renderer->property_editable() = true; int attrColNum = _treeView.append_column("Value", *renderer) - 1; @@ -182,7 +117,7 @@ StyleDialog::StyleDialog(bool stylemode) : _attrCol->add_attribute(renderer->property_text(), _cssColumns._styleAttrVal); _attrCol->add_attribute(renderer->property_foreground_rgba(), _cssColumns.attr_color); } - renderer->signal_edited().connect(sigc::mem_fun(*this, &CssDialog::valueEdited)); + renderer->signal_edited().connect(sigc::mem_fun(*this, &StyleDialog::valueEdited)); renderer = Gtk::manage(new Gtk::CellRendererText()); renderer->property_editable() = true; @@ -224,113 +159,7 @@ void StyleDialog::_set_status_message(Inkscape::MessageType /*type*/, const gcha */ void StyleDialog::setDesktop(SPDesktop* desktop) { - g_debug("StyleDialog::_readStyleElement: updating %s", (_updating ? "true" : "false")); - - if (_updating) return; // Don't read if we wrote style element. - _updating = true; - - Inkscape::XML::Node * textNode = _getStyleTextNode(); - if (textNode == nullptr) { - std::cerr << "StyleDialog::_readStyleElement: No text node!" << std::endl; - } - - // Get content from style text node. - std::string content = (textNode->content() ? textNode->content() : ""); - - // Remove end-of-lines (check it works on Windoze). - content.erase(std::remove(content.begin(), content.end(), '\n'), content.end()); - - // Remove comments (/* xxx */) - while(content.find("/*") != std::string::npos) { - size_t start = content.find("/*"); - content.erase(start, (content.find("*/", start) - start) +2); - } - - // First split into selector/value chunks. - // An attempt to use Glib::Regex failed. A C++11 version worked but - // reportedly has problems on Windows. Using split_simple() is simpler - // and probably faster. - // - // Glib::RefPtr regex1 = - // Glib::Regex::create("([^\\{]+)\\{([^\\{]+)\\}"); - // - // Glib::MatchInfo minfo; - // regex1->match(content, minfo); - - // Split on curly brackets. Even tokens are selectors, odd are values. - std::cout << content << std::endl; - std::cout << "aaaaaaaaaaaaaaaaaaaaaaaaaa" << std::endl; - std::vector tokens = Glib::Regex::split_simple("[}{]", content); - - // If text node is empty, return (avoids problem with negative below). - if (tokens.size() == 0) { - _updating = false; - return; - } - std::vector> expanderstatus; - for (unsigned i = 0; i < tokens.size() - 1; i += 2) { - Glib::ustring selector = tokens[i]; - REMOVE_SPACES(selector); // Remove leading/trailing spaces - for (auto &row : _store->children()) { - Glib::ustring selectorold = row[_mColumns._colSelector]; - if (selectorold == selector) { - expanderstatus.emplace_back(selector, row[_mColumns._colExpand]); - } - } - } - _store->clear(); - - for (unsigned i = 0; i < tokens.size()-1; i += 2) { - - Glib::ustring selector = tokens[i]; - REMOVE_SPACES(selector); // Remove leading/trailing spaces - std::vector tokensplus = Glib::Regex::split_simple("[,]+", selector); - coltype colType = SELECTOR; - for (auto tok : tokensplus) { - REMOVE_SPACES(tok); - if (tok.find(" ") != -1 || tok.erase(0, 1).find(".") != -1) { - colType = UNHANDLED; - } - } - // Get list of objects selector matches - std::vector objVec = _getObjVec( selector ); - - Glib::ustring properties; - // Check to make sure we do have a value to match selector. - if ((i+1) < tokens.size()) { - properties = tokens[i+1]; - } else { - std::cerr << "StyleDialog::_readStyleElement: Missing values " - "for last selector!" << std::endl; - } - REMOVE_SPACES(properties); - bool colExpand = false; - for (auto rowstatus : expanderstatus) { - if (selector == rowstatus.first) { - colExpand = rowstatus.second; - } - } - Gtk::TreeModel::Row row = *(_store->append()); - row[_mColumns._colSelector] = selector; - row[_mColumns._colExpand] = colExpand; - row[_mColumns._colType] = colType; - row[_mColumns._colObj] = objVec; - row[_mColumns._colProperties] = properties; - row[_mColumns._colVisible] = true; - if (colType == SELECTOR) { - // Add as children, objects that match selector. - for (auto &obj : objVec) { - Gtk::TreeModel::Row childrow = *(_store->append(row->children())); - childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); - childrow[_mColumns._colExpand] = false; - childrow[_mColumns._colType] = OBJECT; - childrow[_mColumns._colObj] = std::vector(1, obj); - childrow[_mColumns._colProperties] = ""; // Unused - childrow[_mColumns._colVisible] = true; // Unused - } - } - } - _updating = false; + _desktop = desktop; } /** @@ -369,63 +198,10 @@ std::map StyleDialog::parseStyle(Glib::ustring sty REMOVE_SPACES(style_string); // We'd use const, but we need to trip spaces std::vector props = r_props->split(style_string); - if (!found) { - // Update row - objVec.push_back(obj); // Adding to copy so need to update tree - row[_mColumns._colObj] = objVec; - row[_mColumns._colSelector] = _getIdList( objVec ); - row[_mColumns._colExpand] = true; - // Add child row - Gtk::TreeModel::Row childrow = *(_store->append(row->children())); - childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); - childrow[_mColumns._colType] = OBJECT; - childrow[_mColumns._colObj] = std::vector(1, obj); - childrow[_mColumns._colProperties] = ""; // Unused - childrow[_mColumns._colVisible] = true; // Unused - } - } - } - - else if (selector[0] == '.') { - // 'class' selector... add value to class attribute of selected objects. - - // Get first class (split on white space or comma) - std::vector tokens = Glib::Regex::split_simple("[,\\s]+", selector); - Glib::ustring className = tokens[0]; - className.erase(0,1); - Inkscape::Selection* selection = getDesktop()->getSelection(); - std::vector sel_obj(selection->objects().begin(), selection->objects().end()); - _insertClass(sel_obj, className); - std::vector objVec = _getObjVec(selector); - ; - for (auto &obj : sel_obj) { - - Glib::ustring id = (obj->getId() ? obj->getId() : ""); - bool found = false; - for (auto &obj : objVec) { - if (id == obj->getId()) { - found = true; - break; - } - } - - if (!found) { - // Update row - objVec.push_back(obj); // Adding to copy so need to update tree - row[_mColumns._colObj] = objVec; - row[_mColumns._colExpand] = true; - - // Update row - Gtk::TreeModel::Row childrow = *(_store->append(row->children())); - childrow[_mColumns._colSelector] = "#" + Glib::ustring(obj->getId()); - childrow[_mColumns._colExpand] = false; - childrow[_mColumns._colType] = OBJECT; - childrow[_mColumns._colObj] = std::vector(1, obj); - childrow[_mColumns._colProperties] = ""; // Unused - childrow[_mColumns._colVisible] = true; // Unused - } - } - } + for (auto const token : props) { + if (token.empty()) + break; + std::vector pair = r_pair->split(token); if (pair.size() > 1) { ret[pair[0]] = pair[1]; @@ -507,30 +283,13 @@ void StyleDialog::onAttrChanged(Inkscape::XML::Node *repr, const gchar *name, co */ void StyleDialog::css_reset_context(gint css) { - g_debug("StyleDialog::_selectObjects: %d, %d", eventX, eventY); - - getDesktop()->selection->clear(); - Gtk::TreeViewColumn *col = _treeView.get_column(1); - Gtk::TreeModel::Path path; - int x2 = 0; - 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 (col == _treeView.get_column(1)) { - Gtk::TreeModel::iterator iter = _store->get_iter(path); - if (iter) { - Gtk::TreeModel::Row row = *iter; - Gtk::TreeModel::Children children = row.children(); - if (children.empty() && !_stylemode) { - del->set_sensitive(true); - } - std::vector objVec = row[_mColumns._colObj]; - - for (auto obj : objVec) { - getDesktop()->selection->add(obj); - } - } - } + if (css == 0) { + _message_context->set(Inkscape::NORMAL_MESSAGE, _("Click CSS property to edit.")); + } else { + const gchar *name = g_quark_to_string(css); + _message_context->setF( + Inkscape::NORMAL_MESSAGE, + _("Property %s selected. Press Ctrl+Enter when done editing to commit changes."), name); } } @@ -541,82 +300,15 @@ void StyleDialog::css_reset_context(gint css) */ bool StyleDialog::setStyleProperty(Glib::ustring name, Glib::ustring value) { - g_debug("StyleDialog::_addSelector: Entrance"); - - // Store list of selected elements on desktop (not to be confused with selector). - Inkscape::Selection* selection = getDesktop()->getSelection(); - std::vector objVec( selection->objects().begin(), - selection->objects().end() ); - - // ==== Create popup dialog ==== - Gtk::Dialog *textDialogPtr = new Gtk::Dialog(); - textDialogPtr->add_button(_("Cancel"), Gtk::RESPONSE_CANCEL); - textDialogPtr->add_button(_("Add"), Gtk::RESPONSE_OK); - - Gtk::Entry *textEditPtr = manage ( new Gtk::Entry() ); - textEditPtr->signal_activate().connect( - sigc::bind(sigc::mem_fun(*this, &StyleDialog::_closeDialog), textDialogPtr)); - textDialogPtr->get_content_area()->pack_start(*textEditPtr, Gtk::PACK_SHRINK); - - Gtk::Label *textLabelPtr = manage ( new Gtk::Label( - _("Invalid entry: Not an id (#), class (.), or element CSS selector.") - ) ); - textDialogPtr->get_content_area()->pack_start(*textLabelPtr, Gtk::PACK_SHRINK); - - /** - * By default, the entrybox contains 'Class1' as text. However, if object(s) - * is(are) selected and user clicks '+' at the bottom of dialog, the - * entrybox will have the id(s) of the selected objects as text. - */ - if (getDesktop()->getSelection()->isEmpty()) { - textEditPtr->set_text(".Class1"); - } else { - textEditPtr->set_text(_getIdList(objVec)); - } - - Gtk::Requisition sreq1, sreq2; - textDialogPtr->get_preferred_size(sreq1, sreq2); - int minWidth = 200; - int minHeight = 100; - minWidth = (sreq2.width > minWidth ? sreq2.width : minWidth ); - minHeight = (sreq2.height > minHeight ? sreq2.height : minHeight); - textDialogPtr->set_size_request(minWidth, minHeight); - textEditPtr->show(); - textLabelPtr->hide(); - textDialogPtr->show(); - - - // ==== Get response ==== - int result = -1; - bool invalid = true; - Glib::ustring selectorValue; - bool handled = true; - while (invalid) { - result = textDialogPtr->run(); - if (result != Gtk::RESPONSE_OK) { // Cancel, close dialog, etc. - textDialogPtr->hide(); - delete textDialogPtr; - return; - } - /** - * @brief selectorName - * This string stores selector name. The text from entrybox is saved as name - * for selector. If the entrybox is empty, the text (thus selectorName) is - * set to ".Class1" - */ - selectorValue = textEditPtr->get_text(); - Glib::ustring firstWord = selectorValue.substr(0, selectorValue.find_first_of(" >+~")); - if (firstWord != selectorValue) { - handled = false; - } - if (!_stylemode) { - del->set_sensitive(true); - } - if (selectorValue[0] == '.' || selectorValue[0] == '#' || selectorValue[0] == '*' || - SPAttributeRelSVG::isSVGElement(selectorValue)) { - invalid = false; - } else { - textLabelPtr->show(); + auto original = this->_repr->attribute("style"); + std::map properties = parseStyle(original); + + bool updated = false; + if (!value.empty()) { + if (properties[name] != value) { + // Set value (create or update) + properties[name] = value; + updated = true; } } else if (properties.count(name)) { // Delete value @@ -639,23 +331,9 @@ bool StyleDialog::setStyleProperty(Glib::ustring name, Glib::ustring value) */ void StyleDialog::onPropertyDelete(Glib::ustring path) { - g_debug("StyleDialog::_delSelector"); - - Glib::RefPtr refTreeSelection = _treeView.get_selection(); - _treeView.get_selection()->set_mode(Gtk::SELECTION_SINGLE); - Gtk::TreeModel::iterator iter = refTreeSelection->get_selected(); - if (iter) { - Gtk::TreeModel::Row row = *iter; - if (!row.children().empty()) { - return; - } - _updating = true; - _store->erase(iter); - _updating = false; - _writeStyleElement(); - if (!_stylemode) { - del->set_sensitive(false); - } + Gtk::TreeModel::Row row = *_store->get_iter(path); + if (row) { + this->setStyleProperty(row[_cssColumns.label], ""); } } @@ -676,109 +354,49 @@ bool StyleDialog::onPropertyCreate(GdkEventButton *event) } /** - * @brief CssDialog::onKeyPressed + * @brief StyleDialog::onKeyPressed * @param event_description * @return * Send an undo message and mark this point for undo */ -void CssDialog::setUndo(Glib::ustring const &event_description) +void StyleDialog::setUndo(Glib::ustring const &event_description) { SPDocument *document = this->_desktop->doc(); DocumentUndo::done(document, SP_VERB_DIALOG_XML_EDITOR, event_description); } /** - * @brief CssDialog::nameEdited + * @brief StyleDialog::nameEdited * @param event - * This function detects single or double click on a selector in any row. Clicking - * on a selector selects the matching objects on the desktop. A double click will - * in addition open the CSS dialog. - */ -void StyleDialog::_buttonEventsSelectObjs(GdkEventButton* event ) -{ - g_debug("StyleDialog::_buttonEventsSelectObjs"); - _treeView.get_selection()->set_mode(Gtk::SELECTION_SINGLE); - _updating = true; - if (!_stylemode) { - del->set_sensitive(true); - } - if (event->type == GDK_BUTTON_RELEASE && event->button == 1) { - int x = static_cast(event->x); - int y = static_cast(event->y); - _selectObjects(x, y); - } - _updating = false; -} - - -/** - * @brief StyleDialog::_selectRow - * This function selects the row in treeview corresponding to an object selected - * in the drawing. If more than one row matches, the first is chosen. + * @return + * Called when the name is edited in the TreeView editable column */ -void CssDialog::nameEdited (const Glib::ustring& path, const Glib::ustring& name) +void StyleDialog::nameEdited (const Glib::ustring& path, const Glib::ustring& name) { - g_debug("StyleDialog::_selectRow: updating: %s", (_updating ? "true" : "false")); - if (!_stylemode) { - del->set_sensitive(false); - } - if (_updating || !getDesktop()) return; // Avoid updating if we have set row via dialog. - if (SP_ACTIVE_DESKTOP != getDesktop()) { - std::cerr << "StyleDialog::_selectRow: SP_ACTIVE_DESKTOP != getDesktop()" << std::endl; - return; - } - _treeView.get_selection()->unselect_all(); - Gtk::TreeModel::Children children = _store->children(); - Inkscape::Selection* selection = getDesktop()->getSelection(); - SPObject *obj = nullptr; - if (!selection->isEmpty()) { - obj = selection->objects().back(); - } - for (auto row : children) { - std::vector objVec = row[_mColumns._colObj]; - if (obj) { - for (auto & i : objVec) { - if (obj->getId() == i->getId()) { - _treeView.get_selection()->select(row); - row[_mColumns._colVisible] = true; - } else if(_stylemode) { - row[_mColumns._colVisible] = false; - } - } + Gtk::TreeModel::Row row = *_store->get_iter(path); + if(row && this->_repr) { + Glib::ustring old_name = row[_cssColumns.label]; + Glib::ustring value = row[_cssColumns._styleAttrVal]; + // Move to editing value, we set the name as a temporary store value + if (!old_name.empty()) { + // Remove old named value + onPropertyDelete(path); + setStyleProperty(name, " "); } if (!name.empty()) { row[_cssColumns.label] = name; } this->setUndo(_("Rename CSS attribute")); } - if (_stylemode) { - _modelfilter->refilter(); - _treeView.get_selection()->unselect_all(); - } -/* if (_stylemode) { - _store->foreach_iter(sigc::bind >(sigc::mem_fun(*this, &StyleDialog::_showStyleSelectors), toshow)); - } */ } -/* bool StyleDialog::_showStyleSelectors(const Gtk::TreeModel::iterator& iter, std::vector toshow) -{ - Gtk::TreeModel::Row row = *iter; - if (std::find(toshow.begin(), toshow.end(), row)!= toshow.end()) { - std::cout << "fasdsfaasfasfasfasfasf" << std::endl; - } else { - - } - _store->erase(row); - std::cout << "1111111111111111111" << std::endl; - return true; -} */ /** - * @brief CssDialog::valueEdited + * @brief StyleDialog::valueEdited * @param event * @return * Called when the value is edited in the TreeView editable column */ -void CssDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& value) +void StyleDialog::valueEdited (const Glib::ustring& path, const Glib::ustring& value) { Gtk::TreeModel::Row row = *_store->get_iter(path); if(row && this->_repr) { -- cgit v1.2.3