From 1d854ff519b9c0867bfa4ecaf2f6329ca256f06a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 10:29:06 -0500 Subject: Experimental merge of Ponyscape features into trunk (will not compile) (bzr r13090.1.1) --- src/ui/dialog/Makefile_insert | 4 + src/ui/dialog/lpe-powerstroke-properties.cpp | 203 +++ src/ui/dialog/lpe-powerstroke-properties.h | 99 ++ src/ui/dialog/objects.cpp | 2048 ++++++++++++++++++++++++++ src/ui/dialog/objects.h | 255 ++++ src/ui/dialog/tags.cpp | 1182 +++++++++++++++ src/ui/dialog/tags.h | 181 +++ 7 files changed, 3972 insertions(+) create mode 100644 src/ui/dialog/lpe-powerstroke-properties.cpp create mode 100644 src/ui/dialog/lpe-powerstroke-properties.h create mode 100644 src/ui/dialog/objects.cpp create mode 100644 src/ui/dialog/objects.h create mode 100644 src/ui/dialog/tags.cpp create mode 100644 src/ui/dialog/tags.h (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index c37767a08..1cf667f2a 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -109,4 +109,8 @@ ink_common_sources += \ ui/dialog/undo-history.h \ ui/dialog/xml-tree.cpp \ ui/dialog/xml-tree.h \ + ui/dialog/lpe-powerstroke-properties.cpp \ + ui/dialog/lpe-powerstroke-properties.h \ + ui/dialog/objects.cpp \ + ui/dialog/objects.h \ $(inkboard_dialogs) diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp new file mode 100644 index 000000000..cef6f494e --- /dev/null +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -0,0 +1,203 @@ +/** + * @file + * Dialog for renaming layers. + */ +/* Author: + * Bryce W. Harrington + * Andrius R. + * Abhishek Sharma + * + * Copyright (C) 2004 Bryce Harrington + * Copyright (C) 2006 Andrius R. + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#include "lpe-powerstroke-properties.h" +#include +#include +#include +#include +#include "inkscape.h" +#include "desktop.h" +#include "document.h" +#include "document-undo.h" +#include "layer-manager.h" +#include "message-stack.h" +#include "desktop-handles.h" +#include "sp-object.h" +#include "sp-item.h" +#include "verbs.h" +#include "selection.h" +#include "selection-chemistry.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +//#include "event-context.h" + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +PowerstrokePropertiesDialog::PowerstrokePropertiesDialog() +: _desktop(NULL), _knotpoint(NULL), _position_visible(false) +{ + Gtk::Box *mainVBox = get_vbox(); + + _layout_table.set_spacings(4); + _layout_table.resize (2, 2); + + // Layer name widgets + _powerstroke_position_entry.set_activates_default(true); + _powerstroke_position_label.set_label(_("Position:")); + _powerstroke_position_label.set_alignment(1.0, 0.5); + + _powerstroke_width_entry.set_activates_default(true); + _powerstroke_width_label.set_label(_("Width:")); + _powerstroke_width_label.set_alignment(1.0, 0.5); + + _layout_table.attach(_powerstroke_position_label, + 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); + _layout_table.attach(_powerstroke_position_entry, + 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + + _layout_table.attach(_powerstroke_width_label, 0, 1, 1, 2, Gtk::FILL, Gtk::FILL); + _layout_table.attach(_powerstroke_width_entry, 1, 2, 1, 2, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + + mainVBox->pack_start(_layout_table, true, true, 4); + + // Buttons + _close_button.set_use_stock(true); + _close_button.set_label(Gtk::Stock::CANCEL.id); + _close_button.set_can_default(); + + _apply_button.set_use_underline(true); + _apply_button.set_can_default(); + + _close_button.signal_clicked() + .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close)); + _apply_button.signal_clicked() + .connect(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_apply)); + + signal_delete_event().connect( + sigc::bind_return( + sigc::hide(sigc::mem_fun(*this, &PowerstrokePropertiesDialog::_close)), + true + ) + ); + + add_action_widget(_close_button, Gtk::RESPONSE_CLOSE); + add_action_widget(_apply_button, Gtk::RESPONSE_APPLY); + + _apply_button.grab_default(); + + show_all_children(); + + set_focus(_powerstroke_width_entry); +} + +PowerstrokePropertiesDialog::~PowerstrokePropertiesDialog() { + + _setDesktop(NULL); +} + +void PowerstrokePropertiesDialog::showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt) +{ + PowerstrokePropertiesDialog *dialog = new PowerstrokePropertiesDialog(); + + dialog->_setDesktop(desktop); + dialog->_setKnotPoint(knotpoint); + dialog->_setPt(pt); + + dialog->set_title(_("Modify Node Position")); + dialog->_apply_button.set_label(_("_Move")); + + dialog->set_modal(true); + desktop->setWindowTransient (dialog->gobj()); + dialog->property_destroy_with_parent() = true; + + dialog->show(); + dialog->present(); +} + +void +PowerstrokePropertiesDialog::_apply() +{ + std::istringstream i_pos(_powerstroke_position_entry.get_text()); + std::istringstream i_width(_powerstroke_width_entry.get_text()); + double d_pos, d_width; + if ((i_pos >> d_pos) && i_width >> d_width) { + _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); + } + _close(); +} + +void +PowerstrokePropertiesDialog::_close() +{ + _setDesktop(NULL); + destroy_(); + Glib::signal_idle().connect( + sigc::bind_return( + sigc::bind(sigc::ptr_fun(&::operator delete), this), + false + ) + ); +} + +bool PowerstrokePropertiesDialog::_handleKeyEvent(GdkEventKey *event) +{ + + /*switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: { + _apply(); + return true; + } + break; + }*/ + return false; +} + +void PowerstrokePropertiesDialog::_handleButtonEvent(GdkEventButton* event) +{ + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + _apply(); + } +} + +void PowerstrokePropertiesDialog::_setKnotPoint(Geom::Point knotpoint) +{ + _powerstroke_position_entry.set_text(boost::lexical_cast(knotpoint.x())); + _powerstroke_width_entry.set_text(boost::lexical_cast(knotpoint.y())); +} + +void PowerstrokePropertiesDialog::_setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt) +{ + _knotpoint = const_cast(pt); +} + +void PowerstrokePropertiesDialog::_setDesktop(SPDesktop *desktop) { + if (desktop) { + Inkscape::GC::anchor (desktop); + } + if (_desktop) { + Inkscape::GC::release (_desktop); + } + _desktop = desktop; +} + +} // namespace +} // namespace +} // namespace + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/lpe-powerstroke-properties.h b/src/ui/dialog/lpe-powerstroke-properties.h new file mode 100644 index 000000000..c53eac0d9 --- /dev/null +++ b/src/ui/dialog/lpe-powerstroke-properties.h @@ -0,0 +1,99 @@ +/** @file + * @brief Dialog for renaming layers + */ +/* Author: + * Bryce W. Harrington + * + * Copyright (C) 2004 Bryce Harrington + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H +#define INKSCAPE_DIALOG_POWERSTROKE_PROPERTIES_H + +#include <2geom/point.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "live_effects/parameter/powerstrokepointarray.h" + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +class PowerstrokePropertiesDialog : public Gtk::Dialog { + public: + PowerstrokePropertiesDialog(); + virtual ~PowerstrokePropertiesDialog(); + + Glib::ustring getName() const { return "LayerPropertiesDialog"; } + + static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt); + +protected: + + SPDesktop *_desktop; + Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *_knotpoint; + + Gtk::Label _powerstroke_position_label; + Gtk::Entry _powerstroke_position_entry; + Gtk::Label _powerstroke_width_label; + Gtk::Entry _powerstroke_width_entry; + Gtk::Table _layout_table; + bool _position_visible; + + Gtk::Button _close_button; + Gtk::Button _apply_button; + + sigc::connection _destroy_connection; + + static PowerstrokePropertiesDialog &_instance() { + static PowerstrokePropertiesDialog instance; + return instance; + } + + void _setDesktop(SPDesktop *desktop); + void _setPt(const Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity *pt); + + void _apply(); + void _close(); + + void _setKnotPoint(Geom::Point knotpoint); + void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); + + bool _handleKeyEvent(GdkEventKey *event); + void _handleButtonEvent(GdkEventButton* event); + + friend class Inkscape::LivePathEffect::PowerStrokePointArrayParamKnotHolderEntity; + +private: + PowerstrokePropertiesDialog(PowerstrokePropertiesDialog const &); // no copy + PowerstrokePropertiesDialog &operator=(PowerstrokePropertiesDialog const &); // no assign +}; + +} // namespace +} // namespace +} // namespace + + +#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp new file mode 100644 index 000000000..31e73db29 --- /dev/null +++ b/src/ui/dialog/objects.cpp @@ -0,0 +1,2048 @@ +/* + * A simple panel for objects + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "objects.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/insertordericon.h" +#include "ui/widget/clipmaskicon.h" +#include "ui/widget/highlight-picker.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +//#include "event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "layer-manager.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +/** + * Gets an instance of the Objects panel + */ +ObjectsPanel& ObjectsPanel::getInstance() +{ + return *new ObjectsPanel(); +} + +/** + * Column enumeration + */ +enum { + COL_VISIBLE = 1, + COL_LOCKED, + COL_TYPE, + COL_INSERTORDER, + COL_CLIPMASK, + COL_HIGHLIGHT +}; + +/** + * Button enumeration + */ +enum { + BUTTON_NEW = 0, + BUTTON_RENAME, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DUPLICATE, + BUTTON_DELETE, + BUTTON_SOLO, + BUTTON_SHOW_ALL, + BUTTON_HIDE_ALL, + BUTTON_LOCK_OTHERS, + BUTTON_LOCK_ALL, + BUTTON_UNLOCK_ALL, + BUTTON_SETCLIP, + BUTTON_CLIPGROUP, + BUTTON_SETINVCLIP, + BUTTON_UNSETCLIP, + BUTTON_SETMASK, + BUTTON_UNSETMASK, + BUTTON_GROUP, + BUTTON_UNGROUP, + BUTTON_COLLAPSE_ALL, + DRAGNDROP +}; + +/** + * Xml node observer for observing objects in the document + */ +class ObjectsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + /** + * Creates a new object watcher + * @param pnl The panel to which the object watcher belongs + * @param obj The object to watch + */ + ObjectWatcher(ObjectsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _highlightAttr(g_quark_from_string("inkscape:highlight-color")), + _lockedAttr(g_quark_from_string("sodipodi:insensitive")), + _labelAttr(g_quark_from_string("inkscape:label")), + _groupAttr(g_quark_from_string("inkscape:groupmode")), + _styleAttr(g_quark_from_string("style")), + _clipAttr(g_quark_from_string("clip-path")), + _maskAttr(g_quark_from_string("mask")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _lockedAttr || name == _labelAttr || name == _highlightAttr || name == _groupAttr || name == _styleAttr || name == _clipAttr || name == _maskAttr ) { + _pnl->_updateObject(_obj, name == _highlightAttr); + if ( name == _styleAttr ) { + _pnl->_updateComposite(); + } + } + } + } + + /** + * Objects panel to which this watcher belongs + */ + ObjectsPanel* _pnl; + + /** + * The object that is being observed + */ + SPObject* _obj; + + /** + * The xml representation of the object that is being observed + */ + Inkscape::XML::Node* _repr; + + /* These are quarks which define the attributes that we are observing */ + GQuark _highlightAttr; + GQuark _lockedAttr; + GQuark _labelAttr; + GQuark _groupAttr; + GQuark _styleAttr; + GQuark _clipAttr; + GQuark _maskAttr; +}; + +class ObjectsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +class ObjectsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colObject); + add(_colVisible); + add(_colLocked); + add(_colLabel); + add(_colType); + add(_colHighlight); + add(_colClipMask); + add(_colInsertOrder); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colVisible; + Gtk::TreeModelColumn _colLocked; + Gtk::TreeModelColumn _colType; + Gtk::TreeModelColumn _colHighlight; + Gtk::TreeModelColumn _colClipMask; + Gtk::TreeModelColumn _colInsertOrder; +}; + +/** + * Stylizes a button using the given icon name and tooltip + */ +void ObjectsPanel::_styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip ) +{ + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *Gtk::manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + + btn.set_tooltip_text (tooltip); + +} + +/** + * Adds an item to the pop-up (right-click) menu + * @param desktop The active destktop + * @param code Action code + * @param iconName Icon name + * @param fallback Fallback text + * @param id Button id for callback function + * @return The generated menu item + */ +Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = Gtk::manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +/** + * Callback function for when an object changes. Essentially refreshes the entire tree + * @param obj Object which was changed (currently not used as the entire tree is recreated) + */ +void ObjectsPanel::_objectsChanged(SPObject */*obj*/) +{ + //First, unattach the watchers + while (!_objectWatchers.empty()) + { + ObjectsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + //Get the current document's root and use that to enumerate the tree + SPDocument* document = _desktop->doc(); + SPRoot* root = document->getRoot(); + if ( root ) { + _selectedConnection.block(); + //Clear the tree store + _store->clear(); + //Add all items recursively + _addObject( root, 0 ); + _selectedConnection.unblock(); + //Set the tree selection + _objectsSelected(_desktop->selection); + //Handle button sensitivity + _checkTreeSelection(); + } + } +} + +/** + * Recursively adds the children of the given item to the tree + * @param obj Root object to add to the tree + * @param parentRow Parent tree row (or NULL if adding to tree root) + */ +void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + + if (SP_IS_ITEM(child)) + { + SPItem * item = SP_ITEM(child); + SPGroup * group = SP_IS_GROUP(child) ? SP_GROUP(child) : 0; + + //Add the item to the tree and set the column information + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = item; + row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + row[_model->_colVisible] = !item->isHidden(); + row[_model->_colLocked] = !item->isSensitive(); + row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; + row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00; + row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0); + row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + + //If our parent object is a group and it's expanded, expand the tree + if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded()) + { + _tree.expand_to_path( _store->get_path(iter) ); + } + + //Add an object watcher to the item + ObjectsPanel::ObjectWatcher *w = new ObjectsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + + //If the item is a group, recursively add its children + if (group) + { + _addObject( child, &row ); + } + } + } + } +} + +/** + * Updates an item in the tree and optionally recursively updates the item's children + * @param obj The item to update in the tree + * @param recurse Whether to recurse through the item's children + */ +void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) { + //Find the object in the tree store and update it + _store->foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) ); + if (recurse) + { + for (SPObject * iter = obj->children; iter != NULL; iter = iter->next) + { + _updateObject(iter, recurse); + } + } +} + +/** + * Checks items in the tree store and updates the given item + * @param iter Current item being looked at in the tree + * @param obj Object to update + * @return + */ +bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + //We found our item in the tree!! Update it! + SPItem * item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0; + SPGroup * group = SP_IS_GROUP(obj) ? SP_GROUP(obj) : 0; + + row[_model->_colLabel] = obj->label() ? obj->label() : obj->getId(); + row[_model->_colVisible] = item ? !item->isHidden() : false; + row[_model->_colLocked] = item ? !item->isSensitive() : false; + row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; + row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; + row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? (item->clip_ref->getObject()->inverse ? 3 : 1) : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; + row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + + return true; + } + + return false; +} + +/** + * Updates the composite controls for the selected item + */ +void ObjectsPanel::_updateComposite() { + if (!_blockCompositeUpdate) + { + //Set the default values + bool setValues = true; + + //Get/set the values + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_compositingChanged), &setValues)); + } +} + +/** + * Sets the compositing values for the first selected item in the tree + * @param iter Current tree item + * @param setValues Whether to set the compositing values + * @param blur Blur value to use + */ +void ObjectsPanel::_compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (*setValues) + { + _setCompositingValues(item); + *setValues = false; + } + } +} + +/** + * Occurs when the current desktop selection changes + * @param sel The current selection + */ +void ObjectsPanel::_objectsSelected( Selection *sel ) { + + bool setOpacity = true; + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + SPItem *item = NULL; + for (const GSList * iter = sel->itemList(); iter != NULL; iter = iter->next) + { + item = reinterpret_cast(iter->data); + if (setOpacity) + { + _setCompositingValues(item); + setOpacity = false; + } + _store->foreach(sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, iter->next == NULL)); + } + if (!item) { + if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) { + item = SP_ITEM(_desktop->currentLayer()); + _setCompositingValues(item); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, true)); + } + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +/** + * Helper function for setting the compositing values + * @param item Item to use for setting the compositing values + */ +void ObjectsPanel::_setCompositingValues(SPItem *item) +{ + //Block the connections to avoid interference + _opacityConnection.block(); + _blendConnection.block(); + _blurConnection.block(); + + //Set the opacity + _opacity_adjustment.set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment.get_upper()); + SPFeBlend *spblend = NULL; + SPGaussianBlur *spblur = NULL; + if (item->style->getFilter()) + { + for(SPObject *primitive_obj = item->style->getFilter()->children; primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); primitive_obj = primitive_obj->next) { + if(SP_IS_FEBLEND(primitive_obj) && !spblend) { + //Get the blend mode + spblend = SP_FEBLEND(primitive_obj); + } + + if(SP_IS_GAUSSIANBLUR(primitive_obj) && !spblur) { + //Get the blur value + spblur = SP_GAUSSIANBLUR(primitive_obj); + } + } + } + + //Set the blend mode + _fe_cb.set_blend_mode(spblend ? spblend->blend_mode : Inkscape::Filters::BLEND_NORMAL); + + //Set the blur value + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + if (bbox && spblur) { + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct? + _fe_blur.set_blur_value(spblur->stdDeviation.getNumber() * 400 / perimeter); + } else { + _fe_blur.set_blur_value(0); + } + + //Unblock connections + _blurConnection.unblock(); + _blendConnection.unblock(); + _opacityConnection.unblock(); +} + +/** + * Checks the tree and selects the specified item, optionally scrolling to the item + * @param path Current tree path + * @param iter Current tree item + * @param item Item to select in the tree + * @param scrollto Whether to scroll to the item + * @return Whether to continue searching the tree + */ +bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto) +{ + bool stopGoing = false; + + Gtk::TreeModel::Row row = *iter; + if ( item == row[_model->_colObject] ) + { + //We found the item! Expand to the path and select it in the tree. + _tree.expand_to_path( path ); + + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + if (scrollto) { + //Scroll to the item in the tree + _tree.scroll_to_row(path); + } + + stopGoing = true; + } + + return stopGoing; +} + +/** + * Pushes the current tree selection to the canvas + */ +void ObjectsPanel::_pushTreeSelectionToCurrent() +{ + if ( _desktop && _desktop->currentRoot() ) { + //block connections for selection and compositing values to prevent interference + _selectionChangedConnection.block(); + + //Clear the selection and then iterate over the tree selection, pushing each item to the desktop + _desktop->selection->clear(); + bool setOpacity = true; + _tree.get_selection()->selected_foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_selected_row_callback), &setOpacity)); + //unblock connections + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); + } +} + +/** + * Helper function for pushing the current tree selection to the current desktop + * @param iter Current tree item + * @param setCompositingValues Whether to set the compositing values + * @param blur + */ +void ObjectsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setCompositingValues ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER) + { + //If the item is not a layer, then select it and set the current layer to its parent (if it's the first item) + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + else + { + //If the item is a layer, set the current layer + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item); + } + if (*setCompositingValues) + { + //Only set the compositing values for the first item + _setCompositingValues(item); + *setCompositingValues = false; + } + } +} + +/** + * Handles button sensitivity + */ +void ObjectsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + //TODO: top/bottom sensitivity + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +/** + * Sets visibility of items in the tree + * @param iter Current item in the tree + * @param visible Whether the item should be visible or not + */ +void ObjectsPanel::_setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible ) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->setHidden( !visible ); + row[_model->_colVisible] = visible; + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Sets sensitivity of items in the tree + * @param iter Current item in the tree + * @param locked Whether the item should be locked + */ +void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked ) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->setLocked( locked ); + row[_model->_colLocked] = locked; + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Handles keyboard events + * @param event Keyboard event passed in from GDK + * @return Whether the event should be eaten (om nom nom) + */ +bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: + { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + //Rename item + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + break; + case GDK_Home: + { + //Move item(s) to top of containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT ); + } + return true; + } + case GDK_End: + { + //Move item(s) to bottom of containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK ); + } + return true; + } + case GDK_KEY_Page_Up: + { + //Move item(s) up in containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + if (event->state & GDK_SHIFT_MASK) { + _fireAction( SP_VERB_LAYER_MOVE_TO_NEXT ); + } else { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + return true; + } + case GDK_KEY_Page_Down: + { + //Move item(s) down in containing group/layer + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + if (event->state & GDK_SHIFT_MASK) { + _fireAction( SP_VERB_LAYER_MOVE_TO_PREV ); + } else { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + return true; + } + //TODO: Handle Ctrl-A, etc. + } + return false; +} + +/** + * Handles mouse events + * @param event Mouse event from GDK + * @return whether to eat the event (om nom nom) + */ +bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + static bool overVisible = false; + + //Right mouse button was clicked, launch the pop-up menu + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + //Left mouse button was pressed! In order to handle multiple item drag & drop, + //we need to defer selection by setting the select function so that the tree doesn't + //automatically select anything. In order to handle multiple item icon clicking, + //we need to eat the event. There might be a better way to do both of these... + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + overVisible = false; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_VISIBLE-1)) { + //Click on visible column, eat this event to keep row selection + overVisible = true; + return true; + } else if (col == _tree.get_column(COL_LOCKED-1) || + col == _tree.get_column(COL_TYPE-1) || + col == _tree.get_column(COL_INSERTORDER - 1) || + col == _tree.get_column(COL_HIGHLIGHT-1)) { + //Click on an icon column, eat this event to keep row selection + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + //Click on a selected item with no modifiers, defer selection to the mouse-up by + //setting the select function to _noSelection + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_noSelection)); + _defer_target = path; + } + } + } + + //Restore the selection function to allow tree selection on mouse button release + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction)); + } + + //CellRenderers do not have good support for dealing with multiple items, so + //we handle all events on them here + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + //We had deferred a selection target, select it here (assuming no drag & drop) + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } + else { + if (event->state & GDK_SHIFT_MASK) { + // Shift left click on the visible/lock columns toggles "solo" mode + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _takeAction(BUTTON_SOLO); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _takeAction(BUTTON_LOCK_OTHERS); + } + } else if (event->state & GDK_MOD1_MASK) { + // Alt+left click on the visible/lock columns toggles "solo" mode and preserves selection + Gtk::TreeModel::iterator iter = _store->get_iter(path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPItem *item = row[_model->_colObject]; + if (col == _tree.get_column(COL_VISIBLE - 1)) { + _desktop->toggleLayerSolo( item ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:solo", SP_VERB_LAYER_SOLO, _("Toggle layer solo")); + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + _desktop->toggleLockOtherLayers( item ); + DocumentUndo::maybeDone(_desktop->doc(), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers")); + } + } + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPItem* item = row[_model->_colObject]; + + if (col == _tree.get_column(COL_VISIBLE - 1)) { + if (overVisible) { + //Toggle visibility + bool newValue = !row[_model->_colVisible]; + if (_tree.get_selection()->is_selected(path)) + { + //If the current row is selected, toggle the visibility + //for all selected items + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setVisibleIter), newValue)); + } + else + { + //If the current row is not selected, toggle just its visibility + row[_model->_colVisible] = newValue; + item->setHidden(!newValue); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Unhide objects") : _("Hide objects")); + overVisible = false; + } + } else if (col == _tree.get_column(COL_LOCKED - 1)) { + //Toggle locking + bool newValue = !row[_model->_colLocked]; + if (_tree.get_selection()->is_selected(path)) + { + //If the current row is selected, toggle the sensitivity for + //all selected items + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setLockedIter), newValue)); + } + else + { + //If the current row is not selected, toggle just its sensitivity + row[_model->_colLocked] = newValue; + item->setLocked( newValue ); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Lock objects") : _("Unlock objects")); + + } else if (col == _tree.get_column(COL_TYPE - 1)) { + if (SP_IS_GROUP(item)) + { + //Toggle the current item between a group and a layer + SPGroup * g = SP_GROUP(item); + bool newValue = g->layerMode() == SPGroup::LAYER; + row[_model->_colType] = newValue ? 1: 2; + g->setLayerMode(newValue ? SPGroup::GROUP : SPGroup::LAYER); + g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Layer to group") : _("Group to layer")); + } + } else if (col == _tree.get_column(COL_INSERTORDER - 1)) { + if (SP_IS_GROUP(item)) + { + //Toggle the current item's insert order + SPGroup * g = SP_GROUP(item); + bool newValue = !g->insertBottom(); + row[_model->_colInsertOrder] = newValue ? 2: 1; + g->setInsertBottom(newValue); + g->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, + newValue? _("Set insert mode bottom") : _("Set insert mode top")); + } + } else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { + //Clear the highlight targets + _highlight_target.clear(); + if (_tree.get_selection()->is_selected(path)) + { + //If the current item is selected, store all selected items + //in the highlight source + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeHighlightTarget)); + } else { + //If the current item is not selected, store only it in the highlight source + _storeHighlightTarget(iter); + } + if (_colorSelector) + { + //Set up the color selector + SPColor color; + color.set( row[_model->_colHighlight] ); + _colorSelector->base->setColorAlpha(color, SP_RGBA32_A_F(row[_model->_colHighlight])); + } + //Show the color selector dialog + _colorSelectorDialog.show(); + } + } + } + } + } + + //Second mouse button press, set double click status for when the mouse is released + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + //Double click on mouse button release, if we're over the label column, edit + //the item name + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + + return false; +} + +/** + * Stores items in the highlight target vector to manipulate with the color selector + * @param iter Current tree item to store + */ +void ObjectsPanel::_storeHighlightTarget(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + _highlight_target.push_back(item); + } +} + +/* + * Drap and drop within the tree + */ +bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + //Set up our defaults and clear the source vector + _dnd_into = false; + _dnd_target = NULL; + _dnd_source.clear(); + + //Add all selected items to the source vector + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeDragSource)); + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/4) && cell_y <= (int)(cell_height * 3/4)); + if (cell_y > (int)(cell_height * 3/4)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = NULL; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + //Set the drop target. If we're not dropping into a group, we cannot + //drop into it, so set _dnd_into false. + _dnd_target = row[_model->_colObject]; + if (!(SP_IS_GROUP(_dnd_target))) _dnd_into = false; + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/** + * Stores all selected items as the drag source + * @param iter Current tree item + */ +void ObjectsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Move a layer in response to a drag & drop action + */ +void ObjectsPanel::_doTreeMove( ) +{ + g_assert(_desktop != NULL); + g_assert(_document != NULL); + + std::vector idvector; + + //Clear the desktop selection + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPItem *obj = _dnd_source.back(); + _dnd_source.pop_back(); + + if (obj != _dnd_target) { + //Store the object id (for selection later) and move the object + idvector.push_back(g_strdup(obj->getId())); + obj->moveTo(_dnd_target, _dnd_into); + } + } + + //Select items + while (!idvector.empty()) { + //Grab the id from the vector, get the item in the document and select it + gchar * id = idvector.back(); + idvector.pop_back(); + SPObject *obj = _document->getObjectById(id); + g_free(id); + if (obj && SP_IS_ITEM(obj)) { + SPItem *item = SP_ITEM(obj); + if (!SP_IS_GROUP(item) || SP_GROUP(item)->layerMode() != SPGroup::LAYER) + { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + else + { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item); + } + } + } + + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Moved objects")); +} + +/** + * Fires the action verb + */ +void ObjectsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +/** + * Executes the given button action during the idle time + */ +void ObjectsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &ObjectsPanel::_executeAction), 0 ); + } +} + +/** + * Executes the pending button action + */ +bool ObjectsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _document && _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_LAYER_NEW ); + } + break; + case BUTTON_RENAME: + { + _fireAction( SP_VERB_LAYER_RENAME ); + } + break; + case BUTTON_TOP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT); + } + } + break; + case BUTTON_BOTTOM: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK); + } + } + break; + case BUTTON_UP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + break; + case BUTTON_DOWN: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + break; + case BUTTON_DUPLICATE: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_DUPLICATE ); + } + else + { + _fireAction( SP_VERB_EDIT_DUPLICATE ); + } + } + break; + case BUTTON_DELETE: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_DELETE ); + } + else + { + _fireAction( SP_VERB_EDIT_DELETE ); + } + } + break; + case BUTTON_SOLO: + { + _fireAction( SP_VERB_LAYER_SOLO ); + } + break; + case BUTTON_SHOW_ALL: + { + _fireAction( SP_VERB_LAYER_SHOW_ALL ); + } + break; + case BUTTON_HIDE_ALL: + { + _fireAction( SP_VERB_LAYER_HIDE_ALL ); + } + break; + case BUTTON_LOCK_OTHERS: + { + _fireAction( SP_VERB_LAYER_LOCK_OTHERS ); + } + break; + case BUTTON_LOCK_ALL: + { + _fireAction( SP_VERB_LAYER_LOCK_ALL ); + } + break; + case BUTTON_UNLOCK_ALL: + { + _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); + } + break; + case BUTTON_SETCLIP: + { + _fireAction( SP_VERB_OBJECT_SET_CLIPPATH ); + } + break; + case BUTTON_UNSETCLIP: + { + _fireAction( SP_VERB_OBJECT_UNSET_CLIPPATH ); + } + break; + case BUTTON_SETMASK: + { + _fireAction( SP_VERB_OBJECT_SET_MASK ); + } + break; + case BUTTON_UNSETMASK: + { + _fireAction( SP_VERB_OBJECT_UNSET_MASK ); + } + break; + case BUTTON_GROUP: + { + _fireAction( SP_VERB_SELECTION_GROUP ); + } + break; + case BUTTON_UNGROUP: + { + _fireAction( SP_VERB_SELECTION_UNGROUP ); + } + break; + case BUTTON_COLLAPSE_ALL: + { + for (SPObject* obj = _document->getRoot()->firstChild(); obj != NULL; obj = obj->next) { + if (SP_IS_GROUP(obj)) { + _setCollapsed(SP_GROUP(obj)); + } + } + _objectsChanged(_document->getRoot()); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + +/** + * Handles an unsuccessful item label edit (escape pressed, etc.) + */ +void ObjectsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +/** + * Handle a successful item label edit + * @param path Tree path of the item currently being edited + * @param new_text New label text + */ +void ObjectsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +/** + * Renames an item in the tree + * @param row Tree row + * @param name New label to give to the item + */ +void ObjectsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPItem* item = row[_model->_colObject]; + if ( item ) { + gchar const* oldLabel = item->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + item->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } +} + +/** + * A row selection function used by the tree that doesn't allow any new items to be selected. + * Currently, this is used to allow multi-item drag & drop. + */ +bool ObjectsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ ) +{ + return false; +} + +/** + * Default row selection function taken from the layers dialog + */ +bool ObjectsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +/** + * Sets a group to be collapsed and recursively collapses its children + * @param group The group to collapse + */ +void ObjectsPanel::_setCollapsed(SPGroup * group) +{ + group->setExpanded(false); + group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + for (SPObject *iter = group->children; iter != NULL; iter = iter->next) + { + if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + } +} + +/** + * Sets a group to be expanded or collapsed + * @param iter Current tree item + * @param isexpanded Whether to expand or collapse + */ +void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPItem* item = row[_model->_colObject]; + if (item && SP_IS_GROUP(item)) + { + if (isexpanded) + { + //If we're expanding, simply perform the expansion + SP_GROUP(item)->setExpanded(isexpanded); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + else + { + //If we're collapsing, we need to recursively collapse, so call our helper function + _setCollapsed(SP_GROUP(item)); + } + } +} + +/** + * Callback for when the highlight color is changed + * @param csel Color selector + * @param cp Objects panel + */ +void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) +{ + SPColor color; + float alpha = 0; + csel->base->getColorAlpha(color, alpha); + guint32 rgba = color.toRGBA32( alpha ); + + ObjectsPanel *ptr = reinterpret_cast(cp); + + //Set the highlight color for all items in the _highlight_target (all selected items) + for (std::vector::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter) + { + SPItem * target = *iter; + target->setHighlightColor(rgba); + target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); +} + +/** + * Callback for when the opacity value is changed + */ +void ObjectsPanel::_opacityValueChanged() +{ + _blockCompositeUpdate = true; + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_opacityChangedIter)); + DocumentUndo::maybeDone(_document, "opacity", SP_VERB_DIALOG_OBJECTS, _("Set object opacity")); + _blockCompositeUpdate = false; +} + +/** + * Change the opacity of the selected items in the tree + * @param iter Current tree item + */ +void ObjectsPanel::_opacityChangedIter(const Gtk::TreeIter& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + item->style->opacity.set = TRUE; + item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment.get_value() / _opacity_adjustment.get_upper()); + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Callback for when the blend mode is changed + */ +void ObjectsPanel::_blendValueChanged() +{ + _blockCompositeUpdate = true; + const Glib::ustring blendmode = _fe_cb.get_blend_mode(); + + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter), blendmode)); + DocumentUndo::done(_document, SP_VERB_DIALOG_OBJECTS, _("Set object blend mode")); + _blockCompositeUpdate = false; +} + +/** + * Sets the blend mode of the selected tree items + * @param iter Current tree item + * @param blendmode Blend mode to set + */ +void ObjectsPanel::_blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + //Since blur and blend are both filters, we need to set both at the same time + SPStyle *style = item->style; + g_assert(style != NULL); + + if (blendmode != "normal") { + gdouble radius = 0; + if (item->style->getFilter()) { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_GAUSSIANBLUR(primitive)) { + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + if (bbox) { + radius = SP_GAUSSIANBLUR(primitive)->stdDeviation.getNumber(); + } + } + } + } + SPFilter *filter = new_filter_simple_from_item(_document, item, blendmode.c_str(), radius); + sp_style_set_property_url(item, "filter", filter, false); + } else { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_FEBLEND(primitive)) { + primitive->deleteObject(); + break; + } + } + if (!item->style->getFilter()->children) { + remove_filter(item, false); + } + } + + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Callback for when the blur value has changed + */ +void ObjectsPanel::_blurValueChanged() +{ + _blockCompositeUpdate = true; + _tree.get_selection()->selected_foreach_iter(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_blurChangedIter), _fe_blur.get_blur_value())); + DocumentUndo::maybeDone(_document, "blur", SP_VERB_DIALOG_OBJECTS, _("Set object blur")); + _blockCompositeUpdate = false; +} + +/** + * Sets the blur value for the selected items in the tree + * @param iter Current tree item + * @param blur Blur value to set + */ +void ObjectsPanel::_blurChangedIter(const Gtk::TreeIter& iter, double blur) +{ + Gtk::TreeModel::Row row = *iter; + SPItem* item = row[_model->_colObject]; + if (item) + { + //Since blur and blend are both filters, we need to set both at the same time + SPStyle *style = item->style; + if (style) { + Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX); + double radius; + if (bbox) { + double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct? + radius = blur * perimeter / 400; + } else { + radius = 0; + } + + if (radius != 0) { + SPFilter *filter = modify_filter_gaussian_blur_from_item(_document, item, radius); + sp_style_set_property_url(item, "filter", filter, false); + } else if (item->style->filter.set && item->style->getFilter()) { + for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) { + if (SP_IS_GAUSSIANBLUR(primitive)) { + primitive->deleteObject(); + break; + } + } + if (!item->style->getFilter()->children) { + remove_filter(item, false); + } + } + item->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + } +} + +/** + * Constructor + */ +ObjectsPanel::ObjectsPanel() : + UI::Widget::Panel("", "/dialogs/objects", SP_VERB_DIALOG_OBJECTS), + _rootWatcher(0), + _deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + _composite_vbox(false, 0), + _opacity_vbox(false, 0), + _opacity_label(_("Opacity:")), + _opacity_label_unit(_("%")), +#if WITH_GTKMM_3_0 + _opacity_adjustment(Gtk::Adjustment::create(100.0, 0.0, 100.0, 1.0, 1.0, 0.0)), +#else + _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), +#endif + _opacity_hscale(_opacity_adjustment), + _opacity_spin_button(_opacity_adjustment, 0.01, 1), + _fe_cb(UI::Widget::SimpleFilterModifier::BLEND), + _fe_vbox(false, 0), + _fe_alignment(1, 1, 1, 1), + _fe_blur(UI::Widget::SimpleFilterModifier::BLUR), + _blur_vbox(false, 0), + _blur_alignment(1, 1, 1, 1), + _colorSelectorDialog("dialogs.colorpickerwindow") +{ + //Create the tree model and store + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + //Set up the tree + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + //Create the column CellRenderers + //Visible + Inkscape::UI::Widget::ImageToggler *eyeRenderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-visible"), INKSCAPE_ICON("object-hidden")) ); + int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1; + eyeRenderer->property_activatable() = true; + Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum); + if ( col ) { + col->add_attribute( eyeRenderer->property_active(), _model->_colVisible ); + } + + //Locked + Inkscape::UI::Widget::ImageToggler * renderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler( + INKSCAPE_ICON("object-locked"), INKSCAPE_ICON("object-unlocked")) ); + int lockedColNum = _tree.append_column("lock", *renderer) - 1; + renderer->property_activatable() = true; + col = _tree.get_column(lockedColNum); + if ( col ) { + col->add_attribute( renderer->property_active(), _model->_colLocked ); + } + + //Type + Inkscape::UI::Widget::LayerTypeIcon * typeRenderer = Gtk::manage( new Inkscape::UI::Widget::LayerTypeIcon()); + int typeColNum = _tree.append_column("type", *typeRenderer) - 1; + typeRenderer->property_activatable() = true; + col = _tree.get_column(typeColNum); + if ( col ) { + col->add_attribute( typeRenderer->property_active(), _model->_colType ); + } + + //Insert order + Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); + int insertColNum = _tree.append_column("type", *insertRenderer) - 1; + col = _tree.get_column(insertColNum); + if ( col ) { + col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder ); + } + + //Clip/mask + Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon()); + int clipColNum = _tree.append_column("clipmask", *clipRenderer) - 1; + col = _tree.get_column(clipColNum); + if ( col ) { + col->add_attribute( clipRenderer->property_active(), _model->_colClipMask ); + } + + //Highlight + Inkscape::UI::Widget::HighlightPicker * highlightRenderer = Gtk::manage( new Inkscape::UI::Widget::HighlightPicker()); + int highlightColNum = _tree.append_column("highlight", *highlightRenderer) - 1; + col = _tree.get_column(highlightColNum); + if ( col ) { + col->add_attribute( highlightRenderer->property_active(), _model->_colHighlight ); + } + + //Label + _text_renderer = Gtk::manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + //Set the expander and search columns + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + _tree.set_search_column(_model->_colLabel); + + //Set up the tree selection + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &ObjectsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &ObjectsPanel::_rowSelectFunction) ); + + //Set up tree signals + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleKeyEvent), false ); + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleDragDrop), false); + _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), false)); + _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), true)); + + //Set up the label editing signals + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEditingCancelled) ); + + //Set up the scroller window and pack the page + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _page.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + //Set up the compositing items + //Blend mode filter effect + _composite_vbox.pack_start(_fe_vbox, false, false, 2); + _fe_alignment.set_padding(0, 0, 4, 0); + _fe_alignment.add(_fe_cb); + _fe_vbox.pack_start(_fe_alignment, false, false, 0); + _blendConnection = _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blendValueChanged)); + + //Blur filter effect + _composite_vbox.pack_start(_blur_vbox, false, false, 2); + _blur_alignment.set_padding(0, 0, 4, 0); + _blur_alignment.add(_fe_blur); + _blur_vbox.pack_start(_blur_alignment, false, false, 0); + _blurConnection = _fe_blur.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blurValueChanged)); + + //Opacity + _composite_vbox.pack_start(_opacity_vbox, false, false, 2); + _opacity_label.set_alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER); + _opacity_hbox.pack_start(_opacity_label, false, false, 3); + _opacity_vbox.pack_start(_opacity_hbox, false, false, 0); + _opacity_hbox.pack_start(_opacity_hscale, true, true, 0); + _opacity_hbox.pack_start(_opacity_spin_button, false, false, 0); + _opacity_hbox.pack_start(_opacity_label_unit, false, false, 3); + _opacity_hscale.set_draw_value(false); +#if WITH_GTKMM_3_0 + _opacityConnection = _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); + _opacity_label.set_mnemonic_widget(_opacity_hscale); +#else + _opacityConnection = _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged)); + _opacity_label.set_mnemonic_widget(_opacity_hscale); +#endif + + //Keep the labels aligned + GtkSizeGroup *labels = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL); + gtk_size_group_add_widget(labels, GTK_WIDGET(_opacity_label.gobj())); + gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_cb.get_blur_label()->gobj())); + gtk_size_group_add_widget(labels, GTK_WIDGET(_fe_blur.get_blur_label()->gobj())); + + //Pack the compositing functions and the button row + _page.pack_end(_composite_vbox, Gtk::PACK_SHRINK); + _page.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + //Pack into the panel contents + _getContents()->pack_start(_page, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + //Set up the button row + Gtk::Button* btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_ADD, _("New Layer") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_REMOVE, _("Remove") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GOTO_BOTTOM, _("Move To Bottom") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GO_DOWN, _("Move Down") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GO_UP, _("Move Up") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_GOTO_TOP, _("Move To Top") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) ); + _watchingNonTop.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + btn = Gtk::manage( new Gtk::Button() ); + _styleButton( *btn, GTK_STOCK_UNINDENT, _("Collapse All") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) ); + _watchingNonBottom.push_back( btn ); + _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + _watching.push_back(&_composite_vbox); + + //Set up the pop-up menu + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_EDIT_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SHOW_ALL, 0, "Show All", (int)BUTTON_SHOW_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_HIDE_ALL, 0, "Hide All", (int)BUTTON_HIDE_ALL ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_OTHERS, 0, "Lock Others", (int)BUTTON_LOCK_OTHERS ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOCK_ALL, 0, "Lock All", (int)BUTTON_LOCK_ALL ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_UNLOCK_ALL, 0, "Unlock All", (int)BUTTON_UNLOCK_ALL ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) ); + _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_GROUP, 0, "Group", (int)BUTTON_GROUP ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_SELECTION_UNGROUP, 0, "Ungroup", (int)BUTTON_UNGROUP ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) ); + //not implemented + //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); + + //will never be implemented + //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_CLIPPATH, 0, "Unset Clip", (int)BUTTON_UNSETCLIP ) ); + + _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_MASK, 0, "Set Mask", (int)BUTTON_SETMASK ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_UNSET_MASK, 0, "Unset Mask", (int)BUTTON_UNSETMASK ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + //Set initial sensitivity of buttons + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + //Set up the color selection dialog + GtkWidget *dlg = GTK_WIDGET(_colorSelectorDialog.gobj()); + sp_transientize(dlg); + + _colorSelectorDialog.hide(); + _colorSelectorDialog.set_title (_("Select Highlight Color")); + _colorSelectorDialog.set_border_width (4); + _colorSelectorDialog.property_modal() = true; + _colorSelector = SP_COLOR_SELECTOR(sp_color_selector_new(SP_TYPE_COLOR_NOTEBOOK)); + _colorSelectorDialog.get_vbox()->pack_start ( + *Glib::wrap(&_colorSelector->vbox), true, true, 0); + + g_signal_connect(G_OBJECT(_colorSelector), "dragged", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + g_signal_connect(G_OBJECT(_colorSelector), "released", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + g_signal_connect(G_OBJECT(_colorSelector), "changed", + G_CALLBACK(sp_highlight_picker_color_mod), (void *)this); + + gtk_widget_show(GTK_WIDGET(_colorSelector)); + + setDesktop( targetDesktop ); + + show_all_children(); + + //Connect the desktop changed connection + desktopChangeConn = _deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &ObjectsPanel::setDesktop) ); + _deskTrack.connect(GTK_WIDGET(gobj())); +} + +/** + * Destructor + */ +ObjectsPanel::~ObjectsPanel() +{ + //Close the highlight selection dialog + _colorSelectorDialog.hide(); + _colorSelector = NULL; + + //Set the desktop to null, which will disconnect all object watchers + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + _deskTrack.disconnect(); +} + +/** + * Sets the current document + */ +void ObjectsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + //Clear all object watchers + while (!_objectWatchers.empty()) + { + ObjectsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + //Delete the root watcher + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getRoot() && document->getRoot()->getRepr()) + { + //Create a new root watcher for the document and then call _objectsChanged to fill the tree + _rootWatcher = new ObjectsPanel::ObjectWatcher(this, document->getRoot()); + document->getRoot()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getRoot()); + } +} + +/** + * Set the current panel desktop + */ +void ObjectsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //Connect desktop signals + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &ObjectsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } else { + setDocument(NULL, NULL); + } + } + _deskTrack.setBase(desktop); +} +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/objects.h b/src/ui/dialog/objects.h new file mode 100644 index 000000000..7b07afd63 --- /dev/null +++ b/src/ui/dialog/objects.h @@ -0,0 +1,255 @@ +/* + * A simple dialog for objects UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_OBJECTS_PANEL_H +#define SEEN_OBJECTS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPGroup; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays objects. + */ +class ObjectsPanel : public UI::Widget::Panel +{ +public: + ObjectsPanel(); + virtual ~ObjectsPanel(); + + static ObjectsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +private: + //Internal Classes: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + //Connections, Watchers, Trackers: + + //Document root watcher + ObjectsPanel::ObjectWatcher* _rootWatcher; + + //All object watchers + std::vector _objectWatchers; + + //Connection for when the desktop changes + sigc::connection desktopChangeConn; + + //Connection for when the document changes + sigc::connection _documentChangedConnection; + + //Connection for when the active selection in the document changes + sigc::connection _selectionChangedConnection; + + //Connection for when the selection in the dialog changes + sigc::connection _selectedConnection; + + //Connections for when the opacity/blend/blur of the active selection in the document changes + sigc::connection _opacityConnection; + sigc::connection _blendConnection; + sigc::connection _blurConnection; + + //Desktop tracker for grabbing the desktop changed connection + DesktopTracker _deskTrack; + + //Members: + + //The current desktop + SPDesktop* _desktop; + + //The current document + SPDocument* _document; + + //Tree data model + ModelColumns* _model; + + //Prevents the composite controls from updating + bool _blockCompositeUpdate; + + // + InternalUIBounce* _pending; + + //Whether the drag & drop was dragged into an item + gboolean _dnd_into; + + //List of drag & drop source items + std::vector _dnd_source; + + //Drag & drop target item + SPItem* _dnd_target; + + //List of items to change the highlight on + std::vector _highlight_target; + + //GUI Members: + + GdkEvent* _toggleEvent; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _page; + + /* Composite Settings */ + Gtk::VBox _composite_vbox; + Gtk::VBox _opacity_vbox; + Gtk::HBox _opacity_hbox; + Gtk::Label _opacity_label; + Gtk::Label _opacity_label_unit; +#if WITH_GTKMM_3_0 + Glib::RefPtr _opacity_adjustment; +#else + Gtk::Adjustment _opacity_adjustment; +#endif + Gtk::HScale _opacity_hscale; + Inkscape::UI::Widget::SpinButton _opacity_spin_button; + + Inkscape::UI::Widget::SimpleFilterModifier _fe_cb; + Gtk::VBox _fe_vbox; + Gtk::Alignment _fe_alignment; + Inkscape::UI::Widget::SimpleFilterModifier _fe_blur; + Gtk::VBox _blur_vbox; + Gtk::Alignment _blur_alignment; + + Gtk::Dialog _colorSelectorDialog; + SPColorSelector *_colorSelector; + + + //Methods: + + ObjectsPanel(ObjectsPanel const &); // no copy + ObjectsPanel &operator=(ObjectsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + void _setVisibleIter( const Gtk::TreeModel::iterator& iter, const bool visible ); + void _setLockedIter( const Gtk::TreeModel::iterator& iter, const bool locked ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeHighlightTarget(const Gtk::TreeModel::iterator& iter); + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setOpacity ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + void _setCollapsed(SPGroup * group); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues ); + void _updateComposite(); + void _setCompositingValues(SPItem *item); + + void _updateObject(SPObject *obj, bool recurse); + bool _checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto); + + void _objectsChanged(SPObject *obj); + void _addObject( SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _opacityChangedIter(const Gtk::TreeIter& iter); + void _opacityValueChanged(); + + void _blendChangedIter(const Gtk::TreeIter& iter, Glib::ustring blendmode); + void _blendValueChanged(); + + void _blurChangedIter(const Gtk::TreeIter& iter, double blur); + void _blurValueChanged(); + + + void setupDialog(const Glib::ustring &title); + + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp new file mode 100644 index 000000000..f994b571f --- /dev/null +++ b/src/ui/dialog/tags.cpp @@ -0,0 +1,1182 @@ +/* + * A simple panel for tags + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "tags.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "layer-fns.h" +#include "layer-manager.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/addtoicon.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +#include "event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "sp-tag.h" +#include "sp-defs.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +TagsPanel& TagsPanel::getInstance() +{ + return *new TagsPanel(); +} + +enum { + COL_ADD = 1 +}; + +enum { + BUTTON_NEW = 0, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DELETE, + DRAGNDROP +}; + +class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : + _pnl(pnl), + _obj(obj), + _repr(repr), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + ObjectWatcher(TagsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _labelAttr ) { + _pnl->_updateObject( _obj); + } + } + } + + TagsPanel* _pnl; + SPObject* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; +}; + +class TagsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) +{ + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } + } + } + + btn.set_tooltip_text (tooltip); +} + + +Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +void TagsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +void TagsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); + } +} + +bool TagsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_TAG_NEW ); + } + break; + case BUTTON_TOP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_TOP ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_FRONT); + } + } + break; + case BUTTON_BOTTOM: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_TO_BOTTOM ); + } + else + { + _fireAction( SP_VERB_SELECTION_TO_BACK); + } + } + break; + case BUTTON_UP: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_RAISE ); + } + else + { + _fireAction( SP_VERB_SELECTION_RAISE ); + } + } + break; + case BUTTON_DOWN: + { + if (_desktop->selection->isEmpty()) + { + _fireAction( SP_VERB_LAYER_LOWER ); + } + else + { + _fireAction( SP_VERB_SELECTION_LOWER ); + } + } + break; + case BUTTON_DELETE: + { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + + +class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colParentObject); + add(_colObject); + add(_colLabel); + add(_colAddRemove); + add(_colAllowAddRemove); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colParentObject; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colAddRemove; + Gtk::TreeModelColumn _colAllowAddRemove; +}; + +void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) +{ + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && obj->parent) { + todelete->push_back(obj); + } +} + +void TagsPanel::_updateObject( SPObject *obj ) { + _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); +} + +bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + /* + * We get notified of layer update here (from layer->setLabel()) before layer->label() is set + * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which + * has the correct value (bug #168351) + */ + //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); + gchar const *label; + SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; + if (use && use->ref->isAttached()) { + label = use->ref->getObject()->getAttribute("inkscape:label"); + } else { + label = obj->getAttribute("inkscape:label"); + } + row[_model->_colLabel] = label ? label : obj->getId(); + row[_model->_colAddRemove] = SP_IS_TAG(obj); + } + + return false; +} + +void TagsPanel::_objectsSelected( Selection *sel ) { + + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) + { + SPObject *obj = reinterpret_cast(iter->data); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + SPObject * it = row[_model->_colObject]; + if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) + { + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + } + return false; +} + +void TagsPanel::_objectsChanged(SPObject* root) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + SPDocument* document = _desktop->doc(); + SPDefs* root = document->getDefs(); + if ( root ) { + _selectedConnection.block(); + _store->clear(); + _addObject( document, root, 0 ); + _selectedConnection.unblock(); + _objectsSelected(_desktop->selection); + _checkTreeSelection(); + } + } +} + +void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG(child)) + { + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colAddRemove] = true; + row[_model->_colAllowAddRemove] = true; + + _tree.expand_to_path( _store->get_path(iter) ); + + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + _addObject( doc, child, &row ); + } + } + if (SP_IS_TAG(obj) && obj->children) + { + Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row rowitems = *iteritems; + rowitems[_model->_colObject] = NULL; + rowitems[_model->_colParentObject] = obj; + rowitems[_model->_colLabel] = _("Items"); + rowitems[_model->_colAddRemove] = false; + rowitems[_model->_colAllowAddRemove] = false; + + _tree.expand_to_path( _store->get_path(iteritems) ); + + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child)) + { + SPItem *item = SP_TAG_USE(child)->ref->getObject(); + Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; + row[_model->_colAddRemove] = false; + row[_model->_colAllowAddRemove] = true; + + if (SP_TAG(obj)->expanded()) { + _tree.expand_to_path( _store->get_path(iter) ); + } + + if (item) { + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); + item->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + } + } + } + } + } +} + +void TagsPanel::_select_tag( SPTag * tag ) +{ + for (SPObject * child = tag->children; child != NULL; child = child->next) + { + if (SP_IS_TAG(child)) { + _select_tag(SP_TAG(child)); + } else if (SP_IS_TAG_USE(child)) { + SPObject * obj = SP_TAG_USE(child)->ref->getObject(); + if (obj) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); + _desktop->selection->add(obj); + } + } + } +} + +void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _select_tag(SP_TAG(obj)); + } else if (SP_IS_TAG_USE(obj)) { + SPObject * item = SP_TAG_USE(obj)->ref->getObject(); + if (item) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + } + } + } +} + +void TagsPanel::_pushTreeSelectionToCurrent() +{ + _selectionChangedConnection.block(); + // TODO hunt down the possible API abuse in getting NULL + if ( _desktop && _desktop->currentRoot() ) { + _desktop->selection->clear(); + _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); + } + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); +} + +void TagsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; +// if ( _tree.get_selection()->count_selected_rows() > 0 ) { +// sensitive = true; +// +// SPObject* inTree = _selectedLayer(); +// if ( inTree ) { +// +// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); +// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); +// +// } +// } + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +bool TagsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && SP_IS_TAG(obj)) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + } + case GDK_KEY_Delete: { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + return true; + } + break; + } + return false; +} + +bool TagsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + // Alt left click on the visible/lock columns - eat this event to keep row selection + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_ADD-1)) { + down_at_add = true; + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); + _defer_target = path; + } else { + down_at_add = false; + } + } else { + down_at_add = false; + } + } + + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); + } + + // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + + if (obj) { + if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { + if (SP_IS_TAG(obj)) { + bool wasadded = false; + for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) + { + SPObject *newobj = reinterpret_cast(iter->data); + bool addchild = true; + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { + addchild = false; + } + } + if (addchild) { + Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); + obj->appendChild(clone); + wasadded = true; + } + } + if (wasadded) { + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to tag")); + } + } else { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * tobj = *iter; + if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { + tobj->parent->getRepr()->removeChild(tobj->getRepr()); + } + } + } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); + } + } + } + } + } + } + + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + } + + return false; +} + +void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + _dnd_into = true; + _dnd_target = _document->getDefs(); + _dnd_source.clear(); + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); + + if (_dnd_source.empty()) { + return true; + } + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y > (int)(cell_height * 2/3)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = _document->getDefs(); + _dnd_into = true; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + SPObject *pobj = row[_model->_colParentObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _dnd_target = SP_TAG(obj); + } else if (SP_IS_TAG(obj->parent)) { + _dnd_target = SP_TAG(obj->parent); + _dnd_into = true; + } + } else if (pobj && SP_IS_TAG(pobj)) { + _dnd_target = SP_TAG(pobj); + _dnd_into = true; + } else { + return true; + } + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/* + * Move a layer in response to a drag & drop action + */ +void TagsPanel::_doTreeMove( ) +{ + if (_dnd_target) { + for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) + { + SPTag *src = *iter; + if (src != _dnd_target) { + src->moveTo(_dnd_target, _dnd_into); + } + } + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPTag *src = _dnd_source.back(); + _select_tag(src); + _dnd_source.pop_back(); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, + _("Moved tags")); + } +} + + +void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +void TagsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + if (SP_IS_TAG(obj)) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } + } +} + +bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + return false; +} + +bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colParentObject]; + if (obj && SP_IS_TAG(obj)) + { + SP_TAG(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Constructor + */ +TagsPanel::TagsPanel() : + UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), + _rootWatcher(0), + deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + desktopChangeConn() +{ + //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); + int addColNum = _tree.append_column("type", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _tree.get_column(addColNum); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); + col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); + } + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); + + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); + _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); + _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); + + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); + + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new tag") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button("Dup") ); +// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); +// _buttonsRow.add( *btn ); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Tag") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + setDesktop( targetDesktop ); + + show_all_children(); + + // restorePanelPrefs(); + + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +TagsPanel::~TagsPanel() +{ + + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + deskTrack.disconnect(); +} + +void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getDefs() && document->getDefs()->getRepr()) + { + _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); + document->getDefs()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getDefs()); + } +} + +void TagsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //setLabel( _desktop->doc()->name ); + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } + } +/* + GSList const *layers = _desktop->doc()->getResourceList( "layer" ); + g_message( "layers list starts at %p", layers ); + for ( GSList const *iter=layers ; iter ; iter = iter->next ) { + SPObject *layer=static_cast(iter->data); + g_message(" {%s} [%s]", layer->id, layer->label() ); + } +*/ + deskTrack.setBase(desktop); +} + + + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h new file mode 100644 index 000000000..d35dfba01 --- /dev/null +++ b/src/ui/dialog/tags.h @@ -0,0 +1,181 @@ +/* + * A simple dialog for tags UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_TAGS_PANEL_H +#define SEEN_TAGS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPTag; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays layers. + */ +class TagsPanel : public UI::Widget::Panel +{ +public: + TagsPanel(); + virtual ~TagsPanel(); + + //virtual void setOrientation( Gtk::AnchorType how ); + + static TagsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +protected: + //virtual void _handleAction( int setId, int itemId ); + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); +private: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + TagsPanel(TagsPanel const &); // no copy + TagsPanel &operator=(TagsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); + void _select_tag( SPTag * tag ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _updateObject(SPObject *obj); + bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); + + void _objectsChanged(SPObject *root); + void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); + +// std::vector groupConnections; + TagsPanel::ObjectWatcher* _rootWatcher; + std::vector _objectWatchers; + + // Hooked to the layer manager: + sigc::connection _documentChangedConnection; + sigc::connection _selectionChangedConnection; + + sigc::connection _changedConnection; + sigc::connection _addedConnection; + sigc::connection _removedConnection; + + // Internal + sigc::connection _selectedConnection; + sigc::connection _expandedConnection; + sigc::connection _collapsedConnection; + + DesktopTracker deskTrack; + SPDesktop* _desktop; + SPDocument* _document; + ModelColumns* _model; + InternalUIBounce* _pending; + gboolean _dnd_into; + std::vector _dnd_source; + SPObject* _dnd_target; + + GdkEvent* _toggleEvent; + bool down_at_add; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _layersPage; + + sigc::connection desktopChangeConn; + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 9bfba5c24a89f0d2ae75fc78a0aa21743a29e978 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 11:56:51 -0500 Subject: Experimental merge of Ponyscape features into trunk (will not compile) (bzr r13090.1.2) --- src/ui/dialog/objects.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 31e73db29..5023a8813 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -57,6 +57,8 @@ //#define DUMP_LAYERS 1 +guint get_group0_keyval(GdkEventKey *event); + namespace Inkscape { namespace UI { namespace Dialog { @@ -414,7 +416,7 @@ bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) row[_model->_colLocked] = item ? !item->isSensitive() : false; row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; - row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? (item->clip_ref->getObject()->inverse ? 3 : 1) : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; + row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; return true; @@ -2035,6 +2037,14 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) } //namespace UI } //namespace Inkscape +guint get_group0_keyval(GdkEventKey *event) { + guint keyval = 0; + gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( + gdk_display_get_default()), event->hardware_keycode, + (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, + NULL, NULL, NULL); + return keyval; +} /* Local Variables: -- cgit v1.2.3 From 8830d1ad5ab0693313d760cc99e2df0f35c9f6d9 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 16:29:52 -0500 Subject: Updated to include (non-functional) Objects dialogue (bzr r13090.1.6) --- src/ui/dialog/objects.cpp | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 5023a8813..ebfa16f02 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -37,6 +37,7 @@ #include "ui/widget/insertordericon.h" #include "ui/widget/clipmaskicon.h" #include "ui/widget/highlight-picker.h" +#include "ui/tools/node-tool.h" #include "verbs.h" #include "widgets/icon.h" #include "xml/node.h" @@ -54,6 +55,7 @@ #include "sp-clippath.h" #include "sp-mask.h" #include "layer-manager.h" +#include "tools-switch.h" //#define DUMP_LAYERS 1 @@ -2037,6 +2039,9 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) } //namespace UI } //namespace Inkscape +//should be okay to put these here because they are never referenced anywhere else +using namespace Inkscape::UI::Tools; + guint get_group0_keyval(GdkEventKey *event) { guint keyval = 0; gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( @@ -2046,6 +2051,42 @@ guint get_group0_keyval(GdkEventKey *event) { return keyval; } +void SPItem::setHighlightColor(guint32 const color) +{ + g_free(_highlightColor); + if (color & 0x000000ff) + { + _highlightColor = g_strdup_printf("%u", color); + } + else + { + _highlightColor = NULL; + } + + NodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + tools_switch(tool->desktop, TOOLS_NODES); + } + } +} + +void SPItem::unsetHighlightColor() +{ + g_free(_highlightColor); + _highlightColor = NULL; + NodeTool *tool = 0; + if (SP_ACTIVE_DESKTOP ) { + ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + if (INK_IS_NODE_TOOL(ec)) { + tool = static_cast(ec); + tools_switch(tool->desktop, TOOLS_NODES); + } + } +} + /* Local Variables: mode:c++ -- cgit v1.2.3 From fc643d9de8b5b3faf6d43559a43308fbce56e592 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 2 Mar 2014 17:39:47 -0500 Subject: Fix objects dialogue (bzr r13090.1.9) --- src/ui/dialog/dialog-manager.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 6d32e3aa8..bbb55ceee 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -54,6 +54,7 @@ #include "ui/dialog/xml-tree.h" #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" +#include "ui/dialog/objects.h" namespace Inkscape { namespace UI { @@ -108,6 +109,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); + registerFactory("ObjectsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -142,6 +144,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); + registerFactory("ObjectsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); -- cgit v1.2.3 From dc1f7ce719d703d8dd4d7747d1967a3e8a1bfb18 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 16:53:56 -0500 Subject: Remove tag dialog temporarily (bzr r13090.1.13) --- src/ui/dialog/Makefile_insert | 2 -- src/ui/dialog/dialog-manager.cpp | 6 +++--- src/ui/dialog/swatches.cpp | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index bdb1abcda..1cf667f2a 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -113,6 +113,4 @@ ink_common_sources += \ ui/dialog/lpe-powerstroke-properties.h \ ui/dialog/objects.cpp \ ui/dialog/objects.h \ - ui/dialog/tags.cpp \ - ui/dialog/tags.h \ $(inkboard_dialogs) diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index bbfea8cf0..1fddbf007 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -55,7 +55,7 @@ #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" #include "ui/dialog/objects.h" -#include "ui/dialog/tags.h" +//#include "ui/dialog/tags.h" namespace Inkscape { namespace UI { @@ -111,7 +111,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - registerFactory("TagsPanel", &create); + //registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -147,7 +147,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - registerFactory("TagsPanel", &create); + //registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 5e77a28ab..711bcfe2d 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -20,6 +20,7 @@ #include "swatches.h" #include +#include #include #include @@ -57,6 +58,22 @@ #include "gradient-chemistry.h" #include "helper/action.h" #include "helper/action-context.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-pattern.h" +#include "icon-size.h" +#include "widgets/icon.h" +#include "filedialog.h" +#include "sp-stop.h" +#include "svg/svg-color.h" +#include "sp-radial-gradient.h" +#include "color-rgba.h" +#include "event-context.h" +#include +//sorry! +#ifdef WIN32 +#include +#endif namespace Inkscape { namespace UI { @@ -64,6 +81,7 @@ namespace Dialogs { #define VBLOCK 16 #define PREVIEW_PIXBUF_WIDTH 128 +#define SWATCHES_FILE_NAME "swatches.svg" void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); -- cgit v1.2.3 From 12971e975dae83c23e89cdbff99e990d3916b6ff Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 18:05:52 -0500 Subject: Added some basic swatch stuff (does not compile) (bzr r13090.1.14) --- src/ui/dialog/swatches.cpp | 2940 ++++++++++++++++++++++++++++++-------------- src/ui/dialog/swatches.h | 155 ++- 2 files changed, 2157 insertions(+), 938 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 711bcfe2d..a0c79b8ac 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -43,10 +43,10 @@ #include "path-prefix.h" #include "preferences.h" #include "sp-item.h" +#include "sp-gradient-fns.h" #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" -#include "ui/previewholder.h" #include "widgets/desktop-widget.h" #include "widgets/gradient-vector.h" #include "widgets/eek-preview.h" @@ -57,7 +57,6 @@ #include "verbs.h" #include "gradient-chemistry.h" #include "helper/action.h" -#include "helper/action-context.h" #include "xml/node-observer.h" #include "xml/repr.h" #include "sp-pattern.h" @@ -68,1172 +67,2255 @@ #include "svg/svg-color.h" #include "sp-radial-gradient.h" #include "color-rgba.h" -#include "event-context.h" +#include "svg/css-ostringstream.h" +//#include "event-context.h" //no longer exists #include -//sorry! #ifdef WIN32 #include #endif +guint get_group0_keyval(GdkEventKey *event); +void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); + namespace Inkscape { namespace UI { namespace Dialogs { -#define VBLOCK 16 -#define PREVIEW_PIXBUF_WIDTH 128 #define SWATCHES_FILE_NAME "swatches.svg" -void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); - -std::list userSwatchPages; -std::list systemSwatchPages; -static std::map docPalettes; -static std::vector docTrackings; -static std::map docPerPanel; - - -class SwatchesPanelHook : public SwatchesPanel -{ -public: - static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); - static void deleteGradient( GtkMenuItem *menuitem, gpointer userData ); -}; +static char* trim( char* str ) { + char* ret = str; + while ( *str && (*str == ' ' || *str == '\t') ) { + str++; + } + ret = str; + while ( *str ) { + str++; + } + str--; + while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { + *str-- = 0; + } + return ret; +} -static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(false); +static void skipWhitespace( char*& str ) { + while ( *str == ' ' || *str == '\t' ) { + str++; } } -static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(true); +static bool parseNum( char*& str, int& val ) { + val = 0; + while ( '0' <= *str && *str <= '9' ) { + val = val * 10 + (*str - '0'); + str++; } + bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); + return retval; } -static GtkWidget* popupMenu = 0; -static GtkWidget *popupSubHolder = 0; -static GtkWidget *popupSub = 0; -static std::vector popupItems; -static std::vector popupExtras; -static ColorItem* bounceTarget = 0; -static SwatchesPanel* bouncePanel = 0; +static char * SwatchFile; +static SPDocument * SwatchDocument; +static unsigned int page_suffix; -static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) +static void loadPalletFile() { - if ( bounceTarget ) { - handleClick( GTK_WIDGET(menuitem), bounceTarget ); + if (!SwatchDocument) { + SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL); + SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE); + if (!SwatchDocument) { + SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } } } -static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) +static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset ) { - if ( bounceTarget ) { - handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget ); +#ifdef SP_GR_VERBOSE + g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset); +#endif + Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); + { + gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) ); + stop->setAttribute( "style", tmp ); + g_free(tmp); } + + stop->setAttribute( "offset", offset ); + + parent->appendChild(stop); + Inkscape::GC::release(stop); } -static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) +static SPGroup* importGPL(SPDocument* doc, const gchar* full) { - if ( gr ) { - bool shown = false; - if ( desktop && desktop->doc() ) { - Inkscape::Selection *selection = sp_desktop_selection( desktop ); - GSList const *items = selection->itemList(); - if (items) { - SPStyle *query = sp_style_new( desktop->doc() ); - int result = objects_query_fillstroke(const_cast(items), query, true); - if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) { - // could be pertinent - if (query->fill.isPaintserver()) { - SPPaintServer* server = query->getFillPaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* grad = SP_GRADIENT(server); - if ( grad->isSwatch() && grad->getId() == gr->getId()) { - desktop->_dlg_mgr->showDialog("FillAndStroke"); - shown = true; + SPGroup* ret = NULL; + if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { + + /*Load the pallet file here*/ + char block[1024]; + FILE *f = Inkscape::IO::fopen_utf8name( full, "r" ); + if ( f ) { + char* result = fgets( block, sizeof(block), f ); + if ( result ) { + if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { + bool inHeader = true; + bool hasErr = false; + + Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (doc->getObjectById(id)); + + page->setAttribute("id", id); + + do { + result = fgets( block, sizeof(block), f ); + block[sizeof(block) - 1] = 0; + if ( result ) { + if ( block[0] == '#' ) { + // ignore comment + } else { + char *ptr = block; + // very simple check for header versus entry + while ( *ptr == ' ' || *ptr == '\t' ) { + ptr++; + } + if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { + // blank line. skip it. + } else if ( '0' <= *ptr && *ptr <= '9' ) { + // should be an entry link + inHeader = false; + ptr = block; + Glib::ustring name(""); + skipWhitespace(ptr); + if ( *ptr ) { + int r = 0; + int g = 0; + int b = 0; + hasErr = parseNum(ptr, r); + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, g); + } + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, b); + } + if ( !hasErr && *ptr ) { + char* n = trim(ptr); + if (n != NULL) { + name = g_dpgettext2(NULL, "Palette", n); + } + } + if ( !hasErr ) { + // Add the entry now + + Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute("inkscape:label", name.c_str()); + grad->setAttribute( "osb:paint", "solid", 0 ); + SPColor color((float)r / 255, (float)g / 255, (float)b / 255); + addStop(grad, color.toString(), 1, "0"); + page->appendChild(grad); + Inkscape::GC::release(grad); + } + } else { + hasErr = true; + } + } else { + if ( !inHeader ) { + // Hmmm... probably bad. Not quite the format we want? + hasErr = true; + } else { + char* sep = strchr(result, ':'); + if ( sep ) { + *sep = 0; + char* val = trim(sep + 1); + char* name = trim(result); + if ( *name ) { + if ( strcmp( "Name", name ) == 0 ) + { + page->setAttribute("inkscape:label", val); + } + } else { + // error + hasErr = true; + } + } else { + // error + hasErr = true; + } + } + } } } + } while ( result && !hasErr ); + if ( !hasErr ) { + doc->getDefs()->appendChild(page); + Inkscape::GC::release(page); + SPObject* obj = doc->getObjectByRepr(page); + if (SP_IS_GROUP(obj)) { + ret = SP_GROUP(obj); + } + #if ENABLE_MAGIC_COLORS + ColorItem::_wireMagicColors( onceMore ); + #endif // ENABLE_MAGIC_COLORS + } else { + delete page; } } - sp_style_unref(query); } - } - if (!shown) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) { - // Legacy gradient dialog - GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); - gtk_widget_show( dialog ); - } else { - // Invoke the gradient tool - Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); - if ( verb ) { - SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); - if ( action ) { - sp_action_perform( action, NULL ); - } - } - } + fclose(f); } + /* end loading the pallet file*/ } + return ret; } -static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) +SwatchesPanel& SwatchesPanel::getInstance() { - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - SPDocument *doc = desktop ? desktop->doc() : 0; - if (doc) { - std::string targetName(bounceTarget->def.descr); - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - editGradientImpl( desktop, grad ); - break; + return *new SwatchesPanel(); +} + +class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver { +public: + StopWatcher(SwatchesPanel* pnl, SPStop* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()) + { + _repr->addObserver(*this); + } + + ~StopWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){} + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj) { + _pnl->_defsChanged( ); + } + } + + SwatchesPanel* _pnl; + SPStop* _obj; + Inkscape::XML::Node* _repr; +}; + +class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver { +public: + GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")), + _swatchAttr(g_quark_from_string("osb:paint")) + { + _repr->addObserver(*this); + } + + ~GradientWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch()) { + _pnl->_defsChanged( ); + } + } + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch() ) { + _pnl->_defsChanged( ); + } + } + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) + { + if ( _pnl && _obj && _obj->isSwatch() ) { + _pnl->_defsChanged( ); + } + } + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) { + _pnl->_defsChanged( ); + } + } + + SwatchesPanel* _pnl; + SPGradient* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; + GQuark _swatchAttr; +}; + +class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver { +public: + SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) : + _pnl(pnl), + _obj(obj), + _builtIn(builtIn), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")), + _swatchAttr(g_quark_from_string("osb:paint")) + { + _repr->addObserver(*this); + } + + ~SwatchWatcher() { + _repr->removeObserver(*this); + } + + virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj) { + SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); + if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); } } } } -} - -void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) -{ - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - SPDocument *doc = desktop ? desktop->doc() : 0; - gint index = GPOINTER_TO_INT(userData); - if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { - Glib::ustring targetName = popupItems[index]; - - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( targetName == grad->getId() ) { - grad->setSwatch(); - DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, - _("Add gradient stop")); - break; + virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) + { + if ( _pnl && _obj) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); + } + } + } + virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) + { + if ( _pnl && _obj) { + SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); + if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); } } } } -} + virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if (_pnl && _obj && name == _labelAttr) { + if (_builtIn) { + _pnl->_swatchesChanged( ); + } else { + _pnl->_defsChanged( ); + } + } + } -void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ ) + SwatchesPanel* _pnl; + SPObject* _obj; + bool _builtIn; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; + GQuark _swatchAttr; +}; + +class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord { - if ( bounceTarget ) { - SwatchesPanel* swp = bouncePanel; - SPDesktop* desktop = swp ? swp->getDesktop() : 0; - sp_gradient_unset_swatch(desktop, bounceTarget->def.descr); +public: + + ModelColumns() + { + add(_colObject); + add(_colLabel); } -} + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; +}; -static SwatchesPanel* findContainingPanel( GtkWidget *widget ) +class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord { - SwatchesPanel *swp = 0; +public: - std::map rawObjects; - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - rawObjects[GTK_WIDGET(it->first->gobj())] = it->first; + ModelColumnsDoc() + { + add(_colObject); + add(_colLabel); + add(_colPixbuf); } + virtual ~ModelColumnsDoc() {} - for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) { - if (rawObjects.find(curr) != rawObjects.end()) { - swp = rawObjects[curr]; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn > _colPixbuf; +}; + +static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo) +{ + for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) { + if (!strcmp(it->name(), "svg:g")) { + Inkscape::XML::Node * todel = it; + it = it->next(); + node->removeChild(todel); + } else { + it = it->next(); } } - - return swp; + addTo->appendChildRepr(node); } -static void removeit( GtkWidget *widget, gpointer data ) +static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo) { - gtk_container_remove( GTK_CONTAINER(data), widget ); + std::queue groups; + for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) { + if (!strcmp(it->name(), "svg:g")) { + groups.push(it->duplicate(addTo->document->getReprDoc())); + Inkscape::XML::Node * todel = it; + it = it->next(); + node->removeChild(todel); + } else { + it = it->next(); + } + } + addTo->appendChildRepr(node); + while (!groups.empty()) { + Inkscape::XML::Node * it = groups.front(); + groups.pop(); + BubbleChildGroups(it, addTo); + Inkscape::GC::release(it); + } } -/* extern'ed from colot-item.cpp */ -gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ); +void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse) +{ + if (_currentDocument) { + if (swatch && SP_IS_GROUP(swatch) ) { + Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); + if (recurse) { + BubbleChildGroups(copy, _currentDocument->getDefs()); + } else { + StripChildGroups(copy, _currentDocument->getDefs()); + } + Inkscape::GC::release(copy); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); + } + } +} -gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) +void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI) { - gboolean handled = FALSE; - - if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) { - SwatchesPanel* swp = findContainingPanel( widget ); - - if ( !popupMenu ) { - popupMenu = gtk_menu_new(); - GtkWidget* child = 0; - - //TRANSLATORS: An item in context menu on a colour in the swatches - child = gtk_menu_item_new_with_label(_("Set fill")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(redirClick), - user_data); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - - //TRANSLATORS: An item in context menu on a colour in the swatches - child = gtk_menu_item_new_with_label(_("Set stroke")); - - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(redirSecondaryClick), - user_data); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - - child = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_menu_item_new_with_label(_("Delete")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(SwatchesPanelHook::deleteGradient), - user_data ); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - gtk_widget_set_sensitive( child, FALSE ); - - child = gtk_menu_item_new_with_label(_("Edit...")); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(editGradient), - user_data ); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_separator_menu_item_new(); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - popupExtras.push_back(child); - - child = gtk_menu_item_new_with_label(_("Convert")); - gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); - //popupExtras.push_back(child); - //gtk_widget_set_sensitive( child, FALSE ); + if (addToDoc || addToBI) { + //# Get the current directory for finding files + static Glib::ustring open_path; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + if(open_path.empty()) + { + Glib::ustring attr = prefs->getString("/dialogs/open/path"); + if (!attr.empty()) open_path = attr; + } + + //# Test if the open_path directory exists + if (!Inkscape::IO::file_test(open_path.c_str(), + (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) + open_path = ""; + + #ifdef WIN32 + //# If no open path, default to our win32 documents folder + if (open_path.empty()) + { + // The path to the My Documents folder is read from the + // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal" + HKEY key = NULL; + if(RegOpenKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) { - popupSubHolder = child; - popupSub = gtk_menu_new(); - gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub ); + WCHAR utf16path[_MAX_PATH]; + DWORD value_type; + DWORD data_size = sizeof(utf16path); + if(RegQueryValueExW(key, L"Personal", NULL, &value_type, + (BYTE*)utf16path, &data_size) == ERROR_SUCCESS) + { + g_assert(value_type == REG_SZ); + gchar *utf8path = g_utf16_to_utf8( + (const gunichar2*)utf16path, -1, NULL, NULL, NULL); + if(utf8path) + { + open_path = Glib::ustring(utf8path); + g_free(utf8path); + } + } } + } + #endif - gtk_widget_show_all(popupMenu); + //# If no open path, default to our home directory + if (open_path.empty()) + { + open_path = g_get_home_dir(); + open_path.append(G_DIR_SEPARATOR_S); } - if ( user_data ) { - ColorItem* item = reinterpret_cast(user_data); - bool show = swp && (swp->getSelectedIndex() == 0); - for ( std::vector::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) { - gtk_widget_set_sensitive(*it, show); - } + Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel(); + //# Create a dialog + Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance = + Inkscape::UI::Dialog::FileOpenDialog::create( + *parent, open_path, + Inkscape::UI::Dialog::SWATCH_TYPES, + _("Select file to open")); - bounceTarget = item; - bouncePanel = swp; - popupItems.clear(); - if ( popupMenu ) { - gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub); - bool processed = false; - GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); - if ( wdgt ) { - SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); - if ( dtw && dtw->desktop ) { - // Pick up all gradients with vectors - const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient"); - gint index = 0; - for (const GSList *curr = gradients; curr; curr = curr->next) { - SPGradient* grad = SP_GRADIENT(curr->data); - if ( grad->hasStops() && !grad->isSwatch() ) { - //gl = g_slist_prepend(gl, curr->data); - processed = true; - GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); - gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child); - - popupItems.push_back(grad->getId()); - g_signal_connect( G_OBJECT(child), - "activate", - G_CALLBACK(SwatchesPanelHook::convertGradient), - GINT_TO_POINTER(index) ); - index++; - } - } + //# Show the dialog + bool const success = openDialogInstance->show(); - gtk_widget_show_all(popupSub); - } - } - gtk_widget_set_sensitive( popupSubHolder, processed ); + //# Save the folder the user selected for later + open_path = openDialogInstance->getCurrentDirectory(); - gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time); - handled = TRUE; - } + if (!success) + { + delete openDialogInstance; + return; } - } - return handled; -} + //# User selected something. Get name and type + Glib::ustring fileName = openDialogInstance->getFilename(); + //# We no longer need the file dialog object - delete it + delete openDialogInstance; + openDialogInstance = NULL; -static char* trim( char* str ) { - char* ret = str; - while ( *str && (*str == ' ' || *str == '\t') ) { - str++; - } - ret = str; - while ( *str ) { - str++; - } - str--; - while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { - *str-- = 0; - } - return ret; -} -static void skipWhitespace( char*& str ) { - while ( *str == ' ' || *str == '\t' ) { - str++; + if (!fileName.empty()) + { + Glib::ustring newFileName = Glib::filename_to_utf8(fileName); + + if ( newFileName.size() > 0) + fileName = newFileName; + else + g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); + + open_path = Glib::path_get_dirname (fileName); + open_path.append(G_DIR_SEPARATOR_S); + prefs->setString("/dialogs/open/path", open_path); + + SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true); + Inkscape::XML::Node * page = NULL; + if (importdoc && importdoc->getDefs()) { + if (addToBI) { + page = SwatchDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (SwatchDocument->getObjectById(id)); + + page->setAttribute("id", id); + gchar* name = g_path_get_basename(importdoc->getName()); + page->setAttribute("inkscape:label", name); + g_free(name); + } + + for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GROUP(it)) { + if (page) { + Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc()); + page->appendChild(copy); + } + if (addToDoc) { + _addSwatchButtonClicked(SP_GROUP(it), false); + } + } + } + if (page) { + SwatchDocument->getDefs()->appendChildRepr(page); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } + + importdoc->doUnref(); + } else { + SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str()); + if (addToBI) { + if (addToDoc) { + _addSwatchButtonClicked(g, false); + } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } else { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); + } + } + } } } -static bool parseNum( char*& str, int& val ) { - val = 0; - while ( '0' <= *str && *str <= '9' ) { - val = val * 10 + (*str - '0'); - str++; +void SwatchesPanel::SetSelectedFill(SPGradient* swatch) +{ + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->fill.isSet()) { + if (it->style->fill.isPaintserver()) { + SPPaintServer * server = it->style->getFillPaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = swatch->getRepr(); + if (repr != drepr && grad != swatch) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { + Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); + swatch->appendChildRepr(clone); + Inkscape::GC::release(clone); + } + swatch->setSwatch(); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); + } + } + } else if (it->style->fill.isColor()) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); + swatch->setSwatch(); + if (!_noLink.get_active()) { + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + } + } + } } - bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); - return retval; } - -void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ ) +void SwatchesPanel::SetSelectedStroke(SPGradient* swatch) { - char block[1024]; - FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" ); - if ( f ) { - char* result = fgets( block, sizeof(block), f ); - if ( result ) { - if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { - bool inHeader = true; - bool hasErr = false; - - SwatchPage *onceMore = new SwatchPage(); - - do { - result = fgets( block, sizeof(block), f ); - block[sizeof(block) - 1] = 0; - if ( result ) { - if ( block[0] == '#' ) { - // ignore comment - } else { - char *ptr = block; - // very simple check for header versus entry - while ( *ptr == ' ' || *ptr == '\t' ) { - ptr++; + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->stroke.isSet()) { + if (it->style->stroke.isPaintserver()) { + SPPaintServer * server = it->style->getStrokePaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = swatch->getRepr(); + if (repr != drepr && grad != swatch) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); } - if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { - // blank line. skip it. - } else if ( '0' <= *ptr && *ptr <= '9' ) { - // should be an entry link - inHeader = false; - ptr = block; - Glib::ustring name(""); - skipWhitespace(ptr); - if ( *ptr ) { - int r = 0; - int g = 0; - int b = 0; - hasErr = parseNum(ptr, r); - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, g); - } - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, b); - } - if ( !hasErr && *ptr ) { - char* n = trim(ptr); - if (n != NULL) { - name = g_dpgettext2(NULL, "Palette", n); - } - } - if ( !hasErr ) { - // Add the entry now - Glib::ustring nameStr(name); - ColorItem* item = new ColorItem( r, g, b, nameStr ); - onceMore->_colors.push_back(item); - } - } else { - hasErr = true; - } - } else { - if ( !inHeader ) { - // Hmmm... probably bad. Not quite the format we want? - hasErr = true; - } else { - char* sep = strchr(result, ':'); - if ( sep ) { - *sep = 0; - char* val = trim(sep + 1); - char* name = trim(result); - if ( *name ) { - if ( strcmp( "Name", name ) == 0 ) - { - onceMore->_name = val; - } - else if ( strcmp( "Columns", name ) == 0 ) - { - gchar* endPtr = 0; - guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 ); - if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { - // overflow - } else if ( (numVal == 0) && (endPtr == val) ) { - // failed conversion - } else { - onceMore->_prefWidth = numVal; - } - } - } else { - // error - hasErr = true; - } - } else { - // error - hasErr = true; - } - } + for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { + Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); + swatch->appendChildRepr(clone); + Inkscape::GC::release(clone); + } + swatch->setSwatch(); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); } } - } while ( result && !hasErr ); - if ( !hasErr ) { - if (user) - userSwatchPages.push_back(onceMore); - else - systemSwatchPages.push_back(onceMore); -#if ENABLE_MAGIC_COLORS - ColorItem::_wireMagicColors( onceMore ); -#endif // ENABLE_MAGIC_COLORS - } else { - delete onceMore; + } else if (it->style->stroke.isColor()) { + while (SPStop* olds = swatch->getFirstStop()) { + olds->deleteObject(); + } + addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); + swatch->setSwatch(); + if (!_noLink.get_active()) { + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); } } } + } +} - fclose(f); +void SwatchesPanel::MoveSwatchDown(SPGradient* swatch) +{ + if (_currentDocument && swatch) { + SPObject* next = swatch->next; + while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) { + next = next->next; + } + if (next) { + Inkscape::XML::Node* repr = swatch->getRepr(); + repr->parent()->changeOrder(repr, next->getRepr()); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right")); + } } } -static bool -compare_swatch_names(SwatchPage const *a, SwatchPage const *b) { +void SwatchesPanel::MoveSwatchUp(SPGradient* swatch) +{ + if (_currentDocument && swatch) { + SPObject* g = NULL; + SPObject* next = swatch->parent->firstChild(); + while (next && next != swatch) { + if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) { + g = next; + } + next = next->next; + } + if (g) { + g = g->getPrev(); + Inkscape::XML::Node* repr = swatch->getRepr(); + repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left")); + } + } +} - return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0; +void SwatchesPanel::RemoveSwatch(SPGradient* swatch) +{ + if (_currentDocument) { + if (swatch->isReferenced()) { + Inkscape::XML::Node * repr = swatch->getRepr(); + repr->parent()->removeChild(repr); + _currentDocument->getDefs()->getRepr()->appendChild(repr); + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); + } else { + swatch->deleteObject(false); + } + } } -static void loadEmUp() +void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke) { - static bool beenHere = false; - gboolean userPalete = true; - if ( !beenHere ) { - beenHere = true; - - std::list sources; - sources.push_back( profile_path("palettes") ); - sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) ); - sources.push_back( g_strdup(CREATE_PALETTESDIR) ); - - // Use this loop to iterate through a list of possible document locations. - while (!sources.empty()) { - gchar *dirname = sources.front(); - if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS ) - && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) { - GError *err = 0; - GDir *directory = g_dir_open(dirname, 0, &err); - if (!directory) { - gchar *safeDir = Inkscape::IO::sanitizeString(dirname); - g_warning(_("Palettes directory (%s) is unavailable."), safeDir); - g_free(safeDir); + if (_currentDocument) { + if (swatch) { + if (_noLink.get_active()) { + if (swatch->isSolid()) { + ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity)); + sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke); } else { - gchar *filename = 0; - while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) { - gchar* lower = g_ascii_strdown( filename, -1 ); -// if ( g_str_has_suffix(lower, ".gpl") ) { - if ( !g_str_has_suffix(lower, "~") ) { - gchar* full = g_build_filename(dirname, filename, NULL); - if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { - _loadPaletteFile(full, userPalete); - } - g_free(full); - } -// } - g_free(lower); - } - g_dir_close(directory); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); + + Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); + _currentDocument->getDefs()->appendChildRepr(clone); + SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + Inkscape::GC::release(clone); + grad->setSwatch(false); + SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad); +// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { +// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); +// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); +// } + sp_desktop_set_style(_currentDesktop, css); + sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); + sp_repr_css_attr_unref (css); } + } else { + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); + + SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); +// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { +// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); +// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); +// } + sp_desktop_set_style(_currentDesktop, css); + sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); + sp_repr_css_attr_unref (css); } - - // toss the dirname - g_free(dirname); - sources.pop_front(); - userPalete = false; + } else { + SPCSSAttr *css = sp_repr_css_attr_new (); + sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none"); + sp_desktop_set_style(_currentDesktop, css); + } + if (isStroke) { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch")); + } else { + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch")); } } +} - // Sort the list of swatches by name, grouped by user/system - userSwatchPages.sort(compare_swatch_names); - systemSwatchPages.sort(compare_swatch_names); +void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch) +{ + if (_currentDesktop) { + if (event->button == 3) { + Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi; + + Glib::ustring us = Glib::ustring::compose("%1", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")); + mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"))); + Gtk::Label* namelbl = dynamic_cast(mi->get_child()); + if (namelbl) { + namelbl->set_markup(us); + } + mi->show(); + mi->set_sensitive(false); + menu->append(*mi); + + Gtk::SeparatorMenuItem* sep; + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false)); + mi->show(); + mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true)); + mi->show(); + mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); + menu->append(*mi); + + if (swatch) { + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Left"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Right"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch)); + mi->show(); + menu->append(*mi); + } + menu->popup(event->button, event->time); + } else if (!_currentDesktop->selection->isEmpty()) { + _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK); + } + } } +void SwatchesPanel::MoveDown(SPGroup* page) +{ + if (_currentDocument && page) { + SPObject* next = page->next; + while (next && !SP_IS_GROUP(next)) { + next = next->next; + } + if (next) { + Inkscape::XML::Node* repr = page->getRepr(); + repr->parent()->changeOrder(repr, next->getRepr()); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down")); + } + } +} - -SwatchesPanel& SwatchesPanel::getInstance() +void SwatchesPanel::MoveUp(SPGroup* page) { - return *new SwatchesPanel(); + if (_currentDocument && page) { + SPObject* g = NULL; + SPObject* next = page->parent->firstChild(); + while (next && next != page) { + if (SP_IS_GROUP(next)) { + g = next; + } + next = next->next; + } + if (g) { + g = g->getPrev(); + Inkscape::XML::Node* repr = page->getRepr(); + repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up")); + } + } } +void SwatchesPanel::Remove(SPGroup* page) +{ + if (_currentDocument && page) { + std::vector toMove; + for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) { + if (SP_IS_GRADIENT(obj)) { + SPGradient* grad = SP_GRADIENT(obj); + if (grad->isReferenced()) { + toMove.push_back(grad->getRepr()); + } + } + } + while (!toMove.empty()) { + Inkscape::XML::Node * repr = toMove.back(); + toMove.pop_back(); + repr->parent()->removeChild(repr); + _currentDocument->getDefs()->getRepr()->appendChild(repr); + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); + } + page->deleteObject(false); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group")); + } +} -/** - * Constructor - */ -SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : - Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true), - _holder(0), - _clear(0), - _remove(0), - _currentIndex(0), - _currentDesktop(0), - _currentDocument(0) +void SwatchesPanel::AddSelectedFill(SPGroup* page) { - Gtk::RadioMenuItem* hotItem = 0; - _holder = new PreviewHolder(); - _clear = new ColorItem( ege::PaintDef::CLEAR ); - _remove = new ColorItem( ege::PaintDef::NONE ); - if (docPalettes.empty()) { - SwatchPage *docPalette = new SwatchPage(); - - docPalette->_name = "Auto"; - docPalettes[0] = docPalette; - } - - loadEmUp(); - if ( !systemSwatchPages.empty() ) { - SwatchPage* first = 0; - int index = 0; - Glib::ustring targetName; - if ( !_prefs_path.empty() ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - targetName = prefs->getString(_prefs_path + "/palette"); - if (!targetName.empty()) { - if (targetName == "Auto") { - first = docPalettes[0]; - } else { - //index++; - std::vector pages = _getSwatchSets(); - for ( std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter ) { - if ( (*iter)->_name == targetName ) { - first = *iter; - break; + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->fill.isSet()) { + if (it->style->fill.isPaintserver()) { + SPPaintServer * server = it->style->getFillPaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + if (_noLink.get_active()) { + Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + clone->setAttribute( "osb:paint", "gradient", 0 ); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else if (grad->isSwatch()) { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); + if (repr->parent() != drepr) { + repr->parent()->removeChild(repr); + drepr->appendChild(repr); + } + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); } - index++; } + } else if (it->style->fill.isColor()) { + Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute( "osb:paint", "solid", 0 ); + addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); + if (page) { + page->appendChild(grad); + } else { + _currentDocument->getDefs()->appendChild(grad); + } + SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); + Inkscape::GC::release(grad); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); } } } + } +} - if ( !first ) { - first = docPalettes[0]; - _currentIndex = 0; - } else { - _currentIndex = index; - } - - _rebuild(); - - Gtk::RadioMenuItem::Group groupOne; - - int i = 0; - std::vector swatchSets = _getSwatchSets(); - for ( std::vector::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) { - SwatchPage* curr = *it; - Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name)); - if ( curr == first ) { - hotItem = single; +void SwatchesPanel::AddSelectedStroke(SPGroup* page) +{ + if (_currentDesktop && _currentDocument) { + SPItem* it = _currentDesktop->selection->singleItem(); + if (it) { + if (it->style->stroke.isSet()) { + if (it->style->stroke.isPaintserver()) { + SPPaintServer * server = it->style->getStrokePaintServer(); + if (SP_IS_GRADIENT(server)) { + SPGradient *grad = SP_GRADIENT(server)->getVector(); + if (_noLink.get_active()) { + Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + clone->setAttribute( "osb:paint", "gradient", 0 ); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else if (grad->isSwatch()) { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); + if (page) { + page->appendChildRepr(clone); + } else { + _currentDocument->getDefs()->appendChildRepr(clone); + } + SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); + + sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + Inkscape::GC::release(clone); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } else { + Inkscape::XML::Node * repr = grad->getRepr(); + Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); + if (repr->parent() != drepr) { + repr->parent()->removeChild(repr); + drepr->appendChild(repr); + } + SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); + } + } + } else if (it->style->stroke.isColor()) { + Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); + grad->setAttribute( "osb:paint", "solid", 0 ); + addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); + if (page) { + page->appendChild(grad); + } else { + _currentDocument->getDefs()->appendChild(grad); + } + SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); + Inkscape::GC::release(grad); + if (!_noLink.get_active()) { + sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); + } + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); + } } - _regItem( single, 3, i ); - - i++; } } +} - if (Glib::ustring(prefsPath) == "/dialogs/swatches") { - Gtk::Requisition sreq; -#if WITH_GTKMM_3_0 - Gtk::Requisition sreq_natural; - get_preferred_size(sreq_natural, sreq); -#else - sreq = size_request(); -#endif - int minHeight = 60; - if (sreq.height < minHeight) { - set_size_request(70, minHeight); - } +void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event) +{ + if (popUpImportMenu) { + popUpImportMenu->popup(event->button, event->time); } +} - _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET); - _setTargetFillable(_holder); - - show_all_children(); - - restorePanelPrefs(); - if ( hotItem ) { - hotItem->set_active(); +void SwatchesPanel::NewGroupBI() +{ + if (_currentDocument) { + Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (SwatchDocument->getObjectById(id)); + + page->setAttribute("id", id); + + SwatchDocument->getDefs()->appendChild(page); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } -SwatchesPanel::~SwatchesPanel() +void SwatchesPanel::NewGroup() { - _trackDocument( this, 0 ); - - _documentConnection.disconnect(); - _selChanged.disconnect(); - - if ( _clear ) { - delete _clear; - } - if ( _remove ) { - delete _remove; - } - if ( _holder ) { - delete _holder; + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group")); } } -void SwatchesPanel::setOrientation(SPAnchorType how) +void SwatchesPanel::SaveAs() { - // Must call the parent class or bad things might happen - Inkscape::UI::Widget::Panel::setOrientation( how ); - - if ( _holder ) - { - _holder->setOrientation(SP_ANCHOR_SOUTH); + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + + std::vector toMove; + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->isSwatch()) { + toMove.push_back(grad->getRepr()); + } + } + } + while (!toMove.empty()) { + Inkscape::XML::Node* repr = toMove.back(); + toMove.pop_back(); + repr->parent()->removeChild(repr); + page->appendChild(repr); + } + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group")); } } -void SwatchesPanel::setDesktop( SPDesktop* desktop ) +void SwatchesPanel::Duplicate(SPGroup* oldpage) { - if ( desktop != _currentDesktop ) { - if ( _currentDesktop ) { - _documentConnection.disconnect(); - _selChanged.disconnect(); + if (_currentDocument) { + Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); + gchar *id=NULL; + do { + g_free(id); + id = g_strdup_printf("page%d", page_suffix++); + } while (_currentDocument->getObjectById(id)); + + page->setAttribute("id", id); + if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label()); + + for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->isSwatch()) { + Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); + page->appendChild(copy); + Inkscape::GC::release(copy); + } + } } + _currentDocument->getDefs()->appendChild(page); + DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group")); + } +} - _currentDesktop = desktop; +void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page) +{ + Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi; + Glib::ustring us = Glib::ustring::compose("%1", page ? (page->label() ? page->label() : page->getId()) : _("[Base]")); + mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]"))); + Gtk::Label* namelbl = dynamic_cast(mi->get_child()); + if (namelbl) { + namelbl->set_markup(us); + } + mi->show(); + mi->set_sensitive(false); + menu->append(*mi); + + Gtk::SeparatorMenuItem* sep; + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page)); + mi->show(); + mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + if (page) { + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Up"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Move Down"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page)); + mi->show(); + menu->append(*mi); + + sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + menu->append(*sep); + + mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Remove), page)); + mi->show(); + menu->append(*mi); + } else { + mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group"))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); + mi->show(); + menu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group"))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs)); + mi->show(); + menu->append(*mi); + } + + menu->popup(event->button, event->time); +} - if ( desktop ) { - _currentDesktop->selection->connectChanged( - sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); +void SwatchesPanel::_defsChanged() +{ + if (_storeDoc) { + _storeDoc->clear(); + } + + while (!docWatchers.empty()) { + Inkscape::XML::NodeObserver* w = docWatchers.back(); + docWatchers.pop_back(); + delete w; + } + + std::vector tableChildren = _insideTable.get_children(); + for (std::vector::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) { + _insideTable.remove(**c); + } + + if (_currentDocument) { + Gtk::EventBox* eb; + Gtk::Label* lbl; + if (_showlabels) { + eb = Gtk::manage(new Gtk::EventBox()); + eb->add_events(Gdk::BUTTON_PRESS_MASK); + eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL)); + + lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); + eb->add(*lbl); + _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + } + Glib::ustring str1 = Glib::ustring(_("[None]")); + ColorItem* item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str1)); + //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); + item->setName(_("[None]")); + _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + + unsigned int i = 1; + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GRADIENT(it)) { + SPGradient* grad = SP_GRADIENT(it); + if (grad->hasStops()) { + + GradientWatcher* w = new GradientWatcher(this, grad); + docWatchers.push_back(w); + + if (grad->isSwatch()) { + + for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { + StopWatcher* sw = new StopWatcher(this, s); + docWatchers.push_back(sw); + } - _currentDesktop->selection->connectModified( - sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)))); + if (_storeDoc) { + Gtk::TreeModel::iterator iter = _storeDoc->append(); + Gtk::TreeModel::Row row = *iter; + row[_modelDoc->_colObject] = grad; + row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); + GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); + row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); + } + Glib::ustring str2 = Glib::ustring(it->label() ? it->label() : it->getId()); + item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str2)); + item->setGradient(grad); + //item->colorItemHandleButtonPress().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->setName(it->label() ? it->label() : it->getId()); + if (_showlabels) { + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } else { + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } - _currentDesktop->connectToolSubselectionChanged( - sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + i++; + } + } + } + } + + for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { + if (SP_IS_GROUP(it)) { + SwatchWatcher* w = new SwatchWatcher(this, it, false); + docWatchers.push_back(w); + + if (_showlabels) { + i += 20 - (i % 20); + eb = Gtk::manage(new Gtk::EventBox()); + eb->add_events(Gdk::BUTTON_PRESS_MASK); + eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); + lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); + eb->add(*lbl); + _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + } + + Gtk::TreeModel::iterator rowiter; + + if (_storeDoc) { + rowiter = _storeDoc->append(); + Gtk::TreeModel::Row row = *rowiter; + row[_modelDoc->_colObject] = it; + row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId(); + } + + for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) { + if (SP_IS_GRADIENT(cit)) { + SPGradient* grad = SP_GRADIENT(cit); + + if (grad->hasStops()) { + + GradientWatcher* w = new GradientWatcher(this, grad); + docWatchers.push_back(w); + + if (grad->isSwatch()) { + + for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { + StopWatcher* sw = new StopWatcher(this, s); + docWatchers.push_back(sw); + } - sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument); - sigc::slot base2 = first; - sigc::slot slot2 = sigc::hide<0>( base2 ); - _documentConnection = desktop->connectDocumentReplaced( slot2 ); + if (_storeDoc && rowiter) { + Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children()); + Gtk::TreeModel::Row row = *iter; + row[_modelDoc->_colObject] = grad; + row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); + GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); + row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - _setDocument( desktop->doc() ); - } else { - _setDocument(0); + _editDoc.expand_to_path(_storeDoc->get_path(iter)); + } + Glib::ustring str3= Glib::ustring(cit->label() ? cit->label() : cit->getId()); + item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str3)); + item->setGradient(grad); + //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->setName(cit->label() ? cit->label() : cit->getId()); + if (_showlabels) { + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } else { + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + } + i++; + } + } + } + } + } } } + + _scroller.show_all_children(); + _scroller.queue_draw(); } - -class DocTrack +Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) { -public: - DocTrack(SPDocument *doc, sigc::connection &docDestroy, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) : - doc(doc), - updatePending(false), - lastGradientUpdate(0.0), - docDestroy(docDestroy), - gradientRsrcChanged(gradientRsrcChanged), - defsChanged(defsChanged), - defsModified(defsModified) - { - if ( !timer ) { - timer = new Glib::Timer(); - refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 ); + Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1)); + Gtk::Menu* m = NULL; + + Gtk::TreeModel::Row* r; + if (_store) { + Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = group; + row[_model->_colLabel] = group->label() ? group->label() : group->getId(); + + if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) { + _editBI.expand_to_path(_store->get_path(iter)); } - timerRefCount++; + r = &row; + } else { + r = NULL; } - - ~DocTrack() + + bool hasswatches = false; + for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next) { - timerRefCount--; - if ( timerRefCount <= 0 ) { - refreshTimer.disconnect(); - timerRefCount = 0; - if ( timer ) { - timer->stop(); - delete timer; - timer = 0; + if (SP_IS_GROUP(obj)) { + if (!m) { + m = manage(new Gtk::Menu()); + m->show_all(); + mi->set_submenu(*m); + + Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]"))); + basemi->show(); + Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); + if (namelbl) { + namelbl->set_markup(_("[All]")); + } + basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true)); + m->append(*basemi); + + Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + m->append(*sep); } + SwatchWatcher* w = new SwatchWatcher(this, obj, true); + rootWatchers.push_back(w); + m->append(*_addSwatchGroup(SP_GROUP(obj), r)); + } else if (SP_IS_GRADIENT(obj)) { + hasswatches = true; } - if (doc) { - docDestroy.disconnect(); - gradientRsrcChanged.disconnect(); - defsChanged.disconnect(); - defsModified.disconnect(); - doc = NULL; + } + if (!m) { + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); + } else if (hasswatches) { + Glib::ustring us = Glib::ustring::compose("%1", group->label() ? group->label() : group->getId()); + Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId())); + basemi->show(); + Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); + if (namelbl) { + namelbl->set_markup(us); } + basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); + m->prepend(*basemi); } + mi->show(); + return mi; +} - static bool handleTimerCB(); - - /** - * Checks if update should be queued or executed immediately. - * - * @return true if the update was queued and should not be immediately executed. - */ - static bool queueUpdateIfNeeded(SPDocument *doc); - - static Glib::Timer *timer; - static int timerRefCount; - static sigc::connection refreshTimer; - - SPDocument *doc; - bool updatePending; - double lastGradientUpdate; - sigc::connection docDestroy; - sigc::connection gradientRsrcChanged; - sigc::connection defsChanged; - sigc::connection defsModified; - -private: - DocTrack(DocTrack const &); // no copy - DocTrack &operator=(DocTrack const &); // no assign -}; - -Glib::Timer *DocTrack::timer = 0; -int DocTrack::timerRefCount = 0; -sigc::connection DocTrack::refreshTimer; +void SwatchesPanel::_swatchesChanged() +{ + while (!rootWatchers.empty()) { + Inkscape::XML::NodeObserver* w = rootWatchers.back(); + rootWatchers.pop_back(); + delete w; + } -static const double DOC_UPDATE_THREASHOLD = 0.090; + std::vector menuChildren = popUpMenu->get_children(); + for (std::vector::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) { + popUpMenu->remove(**c); + } + + if (_store) { + _store->clear(); + } + + Gtk::MenuItem* mi; + + for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next) + { + if (SP_IS_GROUP(obj)) { + SwatchWatcher* w = new SwatchWatcher(this, obj, true); + rootWatchers.push_back(w); + popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL)); + + } + } + Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); + sep->show(); + popUpMenu->append(*sep); + + mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1)); + mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); + mi->show(); + popUpMenu->append(*mi); + + mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1)); + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false)); + mi->show(); + popUpMenu->append(*mi); + + mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1)); + mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true)); + mi->show(); + popUpMenu->append(*mi); +} -bool DocTrack::handleTimerCB() +void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ) { - double now = timer->elapsed(); + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } - std::vector needCallback; - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { - DocTrack *track = *it; - if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) { - needCallback.push_back(track); + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } } } + + btn.set_tooltip_text (fallback); + + if ( !set ) { + btn.set_label( fallback ); + } +} - for (std::vector::iterator it = needCallback.begin(); it != needCallback.end(); ++it) { - DocTrack *track = *it; - if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping - // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag. - SwatchesPanel::handleDefsModified(track->doc); +void SwatchesPanel::_addButtonClicked(GdkEventButton* event) { + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) { + if (popUpMenu) { + popUpMenu->popup(event->button, event->time); } } +} - return true; +void SwatchesPanel::NoLinkToggled() { + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path); + prefs->setBool(nolink, _noLink.get_active()); } -bool DocTrack::queueUpdateIfNeeded( SPDocument *doc ) +bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) { - bool deferProcessing = false; - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { - DocTrack *track = *it; - if ( track->doc == doc ) { - double now = timer->elapsed(); - double elapsed = now - track->lastGradientUpdate; - - if ( elapsed < DOC_UPDATE_THREASHOLD ) { - deferProcessing = true; - track->updatePending = true; - } else { - track->lastGradientUpdate = now; - track->updatePending = false; - } + static unsigned doubleclick = 0; + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } - break; + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) { + // Double click on the Layer name, enable editing + _text_rendererBI->property_editable() = true; + _editBI.set_cursor (path, *_name_columnBI, true); + grab_focus(); } } - return deferProcessing; + + return false; } -void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document ) +bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) { - SPDocument *oldDoc = NULL; - if (docPerPanel.find(panel) != docPerPanel.end()) { - oldDoc = docPerPanel[panel]; - if (!oldDoc) { - docPerPanel.erase(panel); // Should not be needed, but clean up just in case. - } - } - if (oldDoc != document) { - if (oldDoc) { - docPerPanel[panel] = NULL; - bool found = false; - for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { - found = (it->second == document); - } - if (!found) { - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ - if ((*it)->doc == oldDoc) { - delete *it; - docTrackings.erase(it); - break; - } + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter && !_text_rendererBI->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_rendererBI->property_editable() = true; + _editBI.set_cursor(*path, *_name_columnBI, true); + grab_focus(); + return true; } } } - - if (document) { - bool found = false; - for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { - found = (it->second == document); - } - docPerPanel[panel] = document; - if (!found) { - sigc::connection conn0 = document->connectDestroy(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDocumentDestroy), document)); - sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) ); - sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) ); - sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) ); - - DocTrack *dt = new DocTrack(document, conn0, conn1, conn2, conn3); - docTrackings.push_back(dt); - - if (docPalettes.find(document) == docPalettes.end()) { - SwatchPage *docPalette = new SwatchPage(); - docPalette->_name = "Auto"; - docPalettes[document] = docPalette; + case GDK_KEY_Delete: { + + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj) { + obj->deleteObject(false); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } + return true; } + break; } + return false; } -void SwatchesPanel::_setDocument( SPDocument *document ) +void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) { - if ( document != _currentDocument ) { - _trackDocument(this, document); - _currentDocument = document; - handleGradientsChange( document ); - } + Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_rendererBI->property_editable() = false; } -static void recalcSwatchContents(SPDocument* doc, - boost::ptr_vector &tmpColors, - std::map &previewMappings, - std::map &gradMappings) +void SwatchesPanel::_handleEditingCancelled() { - std::vector newList; - - if (doc) { - const GSList *gradients = doc->getResourceList("gradient"); - for (const GSList *item = gradients; item; item = item->next) { - SPGradient* grad = SP_GRADIENT(item->data); - if ( grad->isSwatch() ) { - newList.push_back(SP_GRADIENT(item->data)); + _text_rendererBI->property_editable() = false; +} + +void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && SwatchDocument) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } } } +} - if ( !newList.empty() ) { - std::reverse(newList.begin(), newList.end()); - for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) - { - SPGradient* grad = *it; - - cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, - PREVIEW_PIXBUF_WIDTH, VBLOCK); - cairo_t *ct = cairo_create(preview); - - Glib::ustring name( grad->getId() ); - ColorItem* item = new ColorItem( 0, 0, 0, name ); - - cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); - cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH); - cairo_set_source(ct, check); - cairo_paint(ct); - cairo_set_source(ct, gradient); - cairo_paint(ct); - - cairo_destroy(ct); - cairo_pattern_destroy(gradient); - cairo_pattern_destroy(check); - - cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview); - cairo_surface_destroy(preview); +void SwatchesPanel::_setCollapsed(SPGroup * group) +{ + group->setExpanded(false); + group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + for (SPObject *iter = group->children; iter != NULL; iter = iter->next) + { + if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + } +} - previewMappings[item] = prevpat; +void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; - tmpColors.push_back(item); - gradMappings[item] = grad; + SPObject* obj = row[_model->_colObject]; + if (obj && SP_IS_GROUP(obj)) + { + if (isexpanded) + { + SP_GROUP(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } + else + { + _setCollapsed(SP_GROUP(obj)); } } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } -void SwatchesPanel::handleDocumentDestroy(SPDocument *document) +void SwatchesPanel::_deleteButtonClicked() { - if (document) { - for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ - if ((*it)->doc == document) { - delete *it; - docTrackings.erase(it); - break; - } + Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + if (obj) { + obj->deleteObject(false); + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } + } +} - if (docPalettes.find(document) != docPalettes.end()) { - docPalettes.erase(document); +bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _editDoc.get_path_at_pos( x, y, path ) ) { + Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_modelDoc->_colObject]; + if (SP_IS_GRADIENT(obj)) { + _swatchClicked(event, SP_GRADIENT(obj)); + } else if (SP_IS_GROUP(obj)) { + _lblClick(event, SP_GROUP(obj)); + } else { + _lblClick(event, NULL); + } + } else { + _lblClick(event, NULL); } + } + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - if (it->second == document) { - SwatchesPanel* swp = it->first; - std::vector pages = swp->_getSwatchSets(); - if ((swp->_currentIndex >= static_cast(pages.size())) && (pages.size() > 0)) - { - swp->_setSelectedIndex(swp->_getSwatchSets().size() - 1); - } - swp->_rebuild(); - docPerPanel.erase(it); - break; - } + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) { + // Double click on the Layer name, enable editing + _text_rendererDoc->property_editable() = true; + _editDoc.set_cursor (path, *_name_columnDoc, true); + grab_focus(); } } + + return false; } -void SwatchesPanel::handleGradientsChange(SPDocument *document) +void SwatchesPanel::_deleteButtonClickedDoc() { - SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; - if (docPalette) { - boost::ptr_vector tmpColors; - std::map tmpPrevs; - std::map tmpGrads; - recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - - for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { - it->first->setPattern(it->second); - cairo_pattern_destroy(it->second); + Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); + if (iter) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_modelDoc->_colObject]; + if (SP_IS_GRADIENT(obj)) { + RemoveSwatch(SP_GRADIENT(obj)); + } else if (SP_IS_GROUP(obj)) { + Remove(SP_GROUP(obj)); } + } +} - for (std::map::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) { - it->first->setGradient(it->second); - } - - docPalette->_colors.swap(tmpColors); - - // Figure out which SwatchesPanel instances are affected and update them. - - for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { - if (it->second == document) { - SwatchesPanel* swp = it->first; - std::vector pages = swp->_getSwatchSets(); - SwatchPage* curr = pages[swp->_currentIndex]; - if (curr == docPalette) { - swp->_rebuild(); +bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) +{ + switch (get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); + if (iter && !_text_rendererDoc->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_modelDoc->_colObject]; + if (obj) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_rendererDoc->property_editable() = true; + _editDoc.set_cursor(*path, *_name_columnDoc, true); + grab_focus(); + return true; } } } + case GDK_KEY_Delete: { + + _deleteButtonClickedDoc(); + return true; + } + break; } + return false; } -void SwatchesPanel::handleDefsModified(SPDocument *document) +void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name) { - SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; - if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) { - boost::ptr_vector tmpColors; - std::map tmpPrevs; - std::map tmpGrads; - recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - - if ( tmpColors.size() != docPalette->_colors.size() ) { - handleGradientsChange(document); - } else { - int cap = std::min(docPalette->_colors.size(), tmpColors.size()); - for (int i = 0; i < cap; i++) { - ColorItem *newColor = &tmpColors[i]; - ColorItem *oldColor = &docPalette->_colors[i]; - if ( (newColor->def.getType() != oldColor->def.getType()) || - (newColor->def.getR() != oldColor->def.getR()) || - (newColor->def.getG() != oldColor->def.getG()) || - (newColor->def.getB() != oldColor->def.getB()) ) { - oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); - } - if (tmpGrads.find(newColor) != tmpGrads.end()) { - oldColor->setGradient(tmpGrads[newColor]); - } - if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { - oldColor->setPattern(tmpPrevs[newColor]); - } + if ( row && SwatchDocument) { + SPObject* obj = row[_modelDoc->_colObject]; + if ( obj ) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); } } - - for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { - cairo_pattern_destroy(it->second); - } } } +void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObjectDoc(row, new_text); + _text_rendererDoc->property_editable() = false; +} + +void SwatchesPanel::_handleEditingCancelledDoc() +{ + _text_rendererDoc->property_editable() = false; +} -std::vector SwatchesPanel::_getSwatchSets() const +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) { - std::vector tmp; - if (docPalettes.find(_currentDocument) != docPalettes.end()) { - tmp.push_back(docPalettes[_currentDocument]); + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + bool _dnd_top = false; + _dnd_into = false; + _dnd_target = SwatchDocument->getDefs()->lastChild(); + Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected(); + if (!itersel) { + return true; } + Gtk::TreeModel::Row rowsel = *itersel; + _dnd_source = rowsel[_model->_colObject]; - tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end()); - tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end()); + if (!_dnd_source) { + return true; + } + + if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _editBI.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y < (int)(cell_height * 1/3)) { + Gtk::TreeModel::Path next_path = target_path; + if (next_path.prev()) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + _dnd_top = true; + // Drop into the top level + _dnd_target = NULL; + } + } + } + if (!_dnd_top) { + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + _dnd_target = obj; + } + } + } + } + + if (_dnd_source != _dnd_target) { + + Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; + Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); + + if (target_ref != our_ref) { + if (!target_ref) { + target_ref = SwatchDocument->getDefs()->getRepr(); + if (target_ref != our_ref->parent()) { + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else { + our_ref->parent()->changeOrder(our_ref, NULL); + } + } else if (_dnd_into) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } + } + sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + } - return tmp; + return true; } -void SwatchesPanel::_updateFromSelection() +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time) { - SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0; - if ( docPalette ) { - Glib::ustring fillId; - Glib::ustring strokeId; - - SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) ); - int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL ); - switch (result) { - case QUERY_STYLE_SINGLE: - case QUERY_STYLE_MULTIPLE_AVERAGED: - case QUERY_STYLE_MULTIPLE_SAME: - { - if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) { - SPPaintServer* server = tmpStyle->getFillPaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* target = 0; - SPGradient* grad = SP_GRADIENT(server); - - if ( grad->isSwatch() ) { - target = grad; - } else if ( grad->ref ) { - SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->isSwatch() ) { - target = tmp; - } - } - if ( target ) { - //XML Tree being used directly here while it shouldn't be - gchar const* id = target->getRepr()->attribute("id"); - if ( id ) { - fillId = id; - } - } - } + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + bool _dnd_top = false; + _dnd_into = false; + _dnd_target = _currentDocument->getDefs()->lastChild(); + Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected(); + if (!itersel) { + return true; + } + Gtk::TreeModel::Row rowsel = *itersel; + _dnd_source = rowsel[_modelDoc->_colObject]; + + if (!_dnd_source) { + return true; + } + + if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _editDoc.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y < (int)(cell_height * 1/3)) { + Gtk::TreeModel::Path next_path = target_path; + if (next_path.prev()) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + _dnd_top = true; + // Drop into the top level + _dnd_target = NULL; } - break; } } - - result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE ); - switch (result) { - case QUERY_STYLE_SINGLE: - case QUERY_STYLE_MULTIPLE_AVERAGED: - case QUERY_STYLE_MULTIPLE_SAME: - { - if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) { - SPPaintServer* server = tmpStyle->getStrokePaintServer(); - if ( SP_IS_GRADIENT(server) ) { - SPGradient* target = 0; - SPGradient* grad = SP_GRADIENT(server); - if ( grad->isSwatch() ) { - target = grad; - } else if ( grad->ref ) { - SPGradient *tmp = grad->ref->getObject(); - if ( tmp && tmp->isSwatch() ) { - target = tmp; - } - } - if ( target ) { - //XML Tree being used directly here while it shouldn't be - gchar const* id = target->getRepr()->attribute("id"); - if ( id ) { - strokeId = id; - } + if (!_dnd_top) { + Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path); + if (_storeDoc->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_modelDoc->_colObject]; + if (obj) { + _dnd_target = obj; + if (SP_IS_GRADIENT(obj)) { + _dnd_into = false; + if (SP_IS_GROUP(_dnd_source)) { + _dnd_target = obj->parent; } + } else if (SP_IS_GROUP(_dnd_source)) { + _dnd_into = false; } } - break; } } - sp_style_unref(tmpStyle); - - for ( boost::ptr_vector::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) { - ColorItem* item = &*it; - bool isFill = (fillId == item->def.descr); - bool isStroke = (strokeId == item->def.descr); - item->setState( isFill, isStroke ); + } + + if (_dnd_source != _dnd_target) { + + Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; + Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); + + if (target_ref != our_ref) { + if (!target_ref) { + target_ref = _currentDocument->getDefs()->getRepr(); + if (target_ref != our_ref->parent()) { + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else { + our_ref->parent()->changeOrder(our_ref, NULL); + } + } else if (_dnd_into) { + // Move this inside of the target at the end + our_ref->parent()->removeChild(our_ref); + target_ref->addChild(our_ref, NULL); + } else if (target_ref->parent() != our_ref->parent()) { + // Change in parent, need to remove and add + our_ref->parent()->removeChild(our_ref); + target_ref->parent()->addChild(our_ref, target_ref); + } else { + // Same parent, just move + our_ref->parent()->changeOrder(our_ref, target_ref); + } } + DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES, + _("Moved Swatches")); } + + return true; } -void SwatchesPanel::_handleAction( int setId, int itemId ) + +/** + * Constructor + */ +SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), + _scroller(), + _insideTable(1, 2), + _insideV(), + _insideH(), + _buttonsRow(), + _outsideV(), + _noLink(_("Don't Link")), + _showlabels(showLabels), + _store(0), + _scrollerBI(), + _editBI(), + _buttonsRowBI(), + _editBIV(), + _storeDoc(0), + _scrollerDoc(), + _editDoc(), + _buttonsRowDoc(), + _editDocV(), + _notebook(), + rootWatcher(0), + docWatcher(0), + _currentDesktop(0), + _currentDocument(0) { - switch( setId ) { - case 3: + _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK); + if (_showlabels) { + _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); + _scroller.add(_insideV); + } else { + _scroller.property_height_request() = 45; + _scroller.add(_insideH); + } + + popUpMenu = manage( new Gtk::Menu() ); + popUpMenu->show_all_children(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) ); + _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button() ); +// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") ); +// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK); + + static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath); + _noLink.set_tooltip_text(_("Don't link swatches")); + _noLink.set_active(prefs->getBool(nolink, false)); + _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled)); + _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK); + + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_NONE); + + if (_showlabels) { + _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); + + _notebook.append_page(_outsideV, "Use"); + + { + ModelColumnsDoc *zoop = new ModelColumnsDoc(); + _modelDoc = zoop; + + _storeDoc = Gtk::TreeStore::create( *zoop ); + + _editDoc.set_model( _storeDoc ); + _editDoc.set_headers_visible(false); + _editDoc.set_reorderable(true); + _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked)); + _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc))); + _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + + _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf()); + int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1; + _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum); + _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf); + + _text_rendererDoc = manage(new Gtk::CellRendererText()); + int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1; + _name_columnDoc = _editDoc.get_column(nameColNum); + _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel); + + _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) ); + _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) ); + + _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) ); + + _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); + _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); + _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false ); + + _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false); + + _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN); + _scrollerDoc.add(_editDoc); + + _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET); + _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK); + + _notebook.append_page(_editDocV, "Edit"); + } + { - _setSelectedIndex(itemId); + popUpImportMenu = Gtk::manage(new Gtk::Menu()); + + Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group..."))); + mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI)); + mi->show(); + popUpImportMenu->append(*mi); + + mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File..."))); + mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true)); + mi->show(); + popUpImportMenu->append(*mi); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _editBI.set_model( _store ); + _editBI.set_headers_visible(false); + _editBI.set_reorderable(true); + _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); + btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked)); + _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); + btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked))); + _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); + + _text_rendererBI = manage(new Gtk::CellRendererText()); + int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1; + _name_columnBI = _editBI.get_column(nameColNum); + _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel); + + _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) ); + _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) ); + + _editBI.set_expander_column( *_editBI.get_column(nameColNum) ); + + _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); + _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); + _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false ); + + _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false); + _editBI.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false)); + _editBI.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true)); + + _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scrollerBI.set_shadow_type(Gtk::SHADOW_IN); + _scrollerBI.add(_editBI); + + _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET); + _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK); + + _notebook.append_page(_editBIV, "Edit Built-In"); } - break; + + _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET); + } else { + //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK); + _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); + //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK); + _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK); } + + loadPalletFile(); + + rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); + SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); + _swatchesChanged(); } -void SwatchesPanel::_setSelectedIndex( int index ) +SwatchesPanel::~SwatchesPanel() { - std::vector pages = _getSwatchSets(); - if ( index >= 0 && index < static_cast(pages.size()) ) { - _currentIndex = index; + if (rootWatcher) { + rootWatcher->_repr->removeObserver(*rootWatcher); + delete rootWatcher; + } + + if (docWatcher) { + docWatcher->_repr->removeObserver(*docWatcher); + delete docWatcher; + } + + _documentConnection.disconnect(); + _selChanged.disconnect(); +} - if ( !_prefs_path.empty() ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name); +void SwatchesPanel::setDesktop( SPDesktop* desktop ) +{ + Inkscape::UI::Widget::Panel::setDesktop(desktop); + if ( desktop != _currentDesktop ) { + if ( _currentDesktop ) { + _documentConnection.disconnect(); + _selChanged.disconnect(); } - _rebuild(); + _currentDesktop = desktop; + + if ( desktop ) { + //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument)); + + _setDocument( desktop, desktop->doc() ); + } else { + _setDocument(0, 0); + } } } -void SwatchesPanel::_rebuild() +void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) { - std::vector pages = _getSwatchSets(); - if (_currentIndex < static_cast(pages.size())) { - SwatchPage* curr = pages[_currentIndex]; - _holder->clear(); - - if ( curr->_prefWidth > 0 ) { - _holder->setColumnPref( curr->_prefWidth ); + if ( document != _currentDocument ) { + if (docWatcher) { + docWatcher->_repr->removeObserver(*docWatcher); + delete docWatcher; + docWatcher = NULL; } - _holder->freezeUpdates(); - // TODO restore once 'clear' works _holder->addPreview(_clear); - _holder->addPreview(_remove); - for ( boost::ptr_vector::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) { - _holder->addPreview(&*it); + _currentDocument = document; + + if (_currentDocument) { + docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false); + _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher); } - _holder->thawUpdates(); + _defsChanged(); } } @@ -1241,6 +2323,48 @@ void SwatchesPanel::_rebuild() } //namespace UI } //namespace Inkscape +//should be okay to add this here +guint get_group0_keyval(GdkEventKey *event) { + guint keyval = 0; + gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( + gdk_display_get_default()), event->hardware_keycode, + (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, + NULL, NULL, NULL); + return keyval; +} + +void +sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) +{ + + bool intercepted = false; + + if (gradient->isSolid()) { + ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity)); + guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]); + gchar b[64]; + sp_svg_write_color(b, sizeof(b), rgba); + SPCSSAttr *css = sp_repr_css_attr_new(); + if (fill) { + sp_repr_css_set_property(css, "fill", b); + Inkscape::CSSOStringStream osalpha; + osalpha << color[3]; + sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str()); + } else { + sp_repr_css_set_property(css, "stroke", b); + Inkscape::CSSOStringStream osalpha; + osalpha << color[3]; + sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str()); + } + intercepted = desktop->_set_style_signal.emit(css); + } + + if (!intercepted) { + for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) { + sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); + } + } +} /* Local Variables: diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index 3abb81d98..cb8f87962 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -12,66 +12,161 @@ #include "ui/widget/panel.h" #include "enums.h" +#include "sp-object.h" +#include "sp-item-group.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sp-gradient.h" +#include "xml/node-observer.h" namespace Inkscape { namespace UI { -class PreviewHolder; - namespace Dialogs { -class ColorItem; -class SwatchPage; -class DocTrack; - /** * A panel that displays paint swatches. */ class SwatchesPanel : public Inkscape::UI::Widget::Panel { public: - SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches"); + SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true); virtual ~SwatchesPanel(); - + static SwatchesPanel& getInstance(); - virtual void setOrientation(SPAnchorType how); - virtual void setDesktop( SPDesktop* desktop ); virtual SPDesktop* getDesktop() {return _currentDesktop;} - virtual int getSelectedIndex() {return _currentIndex;} // temporary - protected: - static void handleDocumentDestroy(SPDocument *document); - static void handleGradientsChange(SPDocument *document); - - virtual void _updateFromSelection(); - virtual void _handleAction( int setId, int itemId ); - virtual void _setDocument( SPDocument *document ); - virtual void _setSelectedIndex( int index ); - virtual void _rebuild(); - virtual std::vector _getSwatchSets() const; + virtual void _setDocument( SPDesktop* desktop, SPDocument *document ); private: + class ModelColumns; + class ModelColumnsDoc; + + class StopWatcher; + class GradientWatcher; + class SwatchWatcher; + SwatchesPanel(SwatchesPanel const &); // no copy SwatchesPanel &operator=(SwatchesPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ); + + void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke); + + void NoLinkToggled(); + void NewGroup(); + void NewGroupBI(); + void _addBIButtonClicked(GdkEventButton* event); + void Duplicate(SPGroup* page); + void SaveAs(); + void AddSelectedFill(SPGroup* page); + void AddSelectedStroke(SPGroup* page); + void MoveUp(SPGroup* page); + void MoveDown(SPGroup* page); + void Remove(SPGroup* page); + + void SetSelectedFill(SPGradient* swatch); + void SetSelectedStroke(SPGradient* swatch); + void MoveSwatchUp(SPGradient* swatch); + void MoveSwatchDown(SPGradient* swatch); + void RemoveSwatch(SPGradient* swatch); + + void _lblClick(GdkEventButton* event, SPGroup* page); + void _addSwatchButtonClicked(SPGroup* swatch, bool recurse); + void _defsChanged(); + void _importButtonClicked(bool addToDoc, bool addToBI); + void _deleteButtonClicked(); + void _addButtonClicked(GdkEventButton* event); + void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem); + + Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow); + void _swatchesChanged(); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _setCollapsed(SPGroup * group); + void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded); + + void _deleteButtonClickedDoc(); + bool _handleButtonEventDoc(GdkEventButton* event); + bool _handleKeyEventDoc(GdkEventKey *event); + + void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelledDoc(); + void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name); + + bool _handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + + Gtk::Menu *popUpMenu; + Gtk::Menu *popUpImportMenu; + + Gtk::ScrolledWindow _scroller; + Gtk::Table _insideTable; + Gtk::VBox _insideV; + Gtk::HBox _insideH; + Gtk::HBox _buttonsRow; + Gtk::VBox _outsideV; + Gtk::CheckButton _noLink; + bool _showlabels; + + SwatchesPanel::ModelColumns* _model; + Glib::RefPtr _store; + + Gtk::CellRendererText *_text_rendererBI; + Gtk::TreeView::Column *_name_columnBI; + Gtk::ScrolledWindow _scrollerBI; + Gtk::TreeView _editBI; + Gtk::HBox _buttonsRowBI; + Gtk::VBox _editBIV; + + SwatchesPanel::ModelColumnsDoc* _modelDoc; + Glib::RefPtr _storeDoc; + + Gtk::CellRendererText *_text_rendererDoc; + Gtk::CellRendererPixbuf *_pixbuf_rendererDoc; + Gtk::TreeView::Column *_name_columnDoc; + Gtk::TreeView::Column *_pixbuf_columnDoc; + Gtk::ScrolledWindow _scrollerDoc; + Gtk::TreeView _editDoc; + Gtk::HBox _buttonsRowDoc; + Gtk::VBox _editDocV; + + Gtk::Notebook _notebook; + + SwatchWatcher* rootWatcher; + std::vector rootWatchers; + + std::vector docWatchers; + SwatchWatcher* docWatcher; - static void _trackDocument( SwatchesPanel *panel, SPDocument *document ); - static void handleDefsModified(SPDocument *document); - - PreviewHolder* _holder; - ColorItem* _clear; - ColorItem* _remove; - int _currentIndex; SPDesktop* _currentDesktop; SPDocument* _currentDocument; + + bool _dnd_into; + SPObject* _dnd_source; + SPObject* _dnd_target; sigc::connection _documentConnection; sigc::connection _selChanged; - - friend class DocTrack; }; } //namespace Dialogs -- cgit v1.2.3 From 3093434e177d4bb7ccc57c1339fad00d47431c17 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 4 Mar 2014 21:24:03 -0500 Subject: Added a few swatch related functions (does not compile) (bzr r13090.1.15) --- src/ui/dialog/swatches.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index a0c79b8ac..2956c6d17 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -68,7 +68,7 @@ #include "sp-radial-gradient.h" #include "color-rgba.h" #include "svg/css-ostringstream.h" -//#include "event-context.h" //no longer exists +#include "ui/tools/tool-base.h" //event-context.h #include #ifdef WIN32 #include -- cgit v1.2.3 From fcffbecabedd7c6bca1312918c918d57fee3cf8c Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 15:24:04 -0500 Subject: Added new swatches dialog (bzr r13090.1.16) --- src/ui/dialog/color-item.cpp | 860 ++++++++----------------------------------- src/ui/dialog/color-item.h | 108 ++---- src/ui/dialog/filedialog.h | 1 + src/ui/dialog/swatches.cpp | 48 +-- 4 files changed, 203 insertions(+), 814 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 7940c28ae..6eece0c17 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -11,18 +11,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - #include - -#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -#include -#endif - -#include #include +#include #include #include @@ -45,6 +36,7 @@ #include "xml/repr.h" #include "verbs.h" #include "widgets/gradient-vector.h" +#include "sp-paint-server.h" #include "color.h" // for SP_RGBA32_U_COMPOSE @@ -53,756 +45,206 @@ namespace Inkscape { namespace UI { namespace Dialogs { -static std::vector mimeStrings; -static std::map mimeToInt; - -#if ENABLE_MAGIC_COLORS -// TODO remove this soon: -extern std::vector possible; -#endif // ENABLE_MAGIC_COLORS - - -#if ENABLE_MAGIC_COLORS -static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b ) +bool ColorItem::on_enter_notify_event(GdkEventCrossing* event) { - bool changed = false; - - if ( node ) { - gchar const * val = node->attribute("inkscape:x-fill-tag"); - if ( val && (match == val) ) { - SPObject *obj = document->getObjectByRepr( node ); - - gchar c[64] = {0}; - sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, "fill", c ); - - sp_desktop_apply_css_recursive( obj, css, true ); - static_cast(obj)->updateRepr(); - - changed = true; - } - - val = node->attribute("inkscape:x-stroke-tag"); - if ( val && (match == val) ) { - SPObject *obj = document->getObjectByRepr( node ); - - gchar c[64] = {0}; - sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property( css, "stroke", c ); - - sp_desktop_apply_css_recursive( (SPItem*)obj, css, true ); - ((SPItem*)obj)->updateRepr(); - - changed = true; - } - - Inkscape::XML::Node* first = node->firstChild(); - changed |= bruteForce( document, first, match, r, g, b ); - - changed |= bruteForce( document, node->next(), match, r, g, b ); - } - - return changed; -} -#endif // ENABLE_MAGIC_COLORS - -static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(false); - } -} - -static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - item->buttonClicked(true); - } -} - -static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"), - item->def.descr.c_str()); - desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); - g_free(msg); - } - } - return FALSE; -} - -static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { - ColorItem* item = reinterpret_cast(callback_data); - if ( item ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - desktop->tipsMessageContext()->clear(); - } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"),def); + desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); + g_free(msg); } - return FALSE; + return Gtk::Widget::on_enter_notify_event(event); } -static void dieDieDie( GObject *obj, gpointer user_data ) +bool ColorItem::on_leave_notify_event(GdkEventCrossing* event) { - g_message("die die die %p %p", obj, user_data ); -} - -static bool getBlock( std::string& dst, guchar ch, std::string const & str ) -{ - bool good = false; - std::string::size_type pos = str.find(ch); - if ( pos != std::string::npos ) - { - std::string::size_type pos2 = str.find( '(', pos ); - if ( pos2 != std::string::npos ) { - std::string::size_type endPos = str.find( ')', pos2 ); - if ( endPos != std::string::npos ) { - dst = str.substr( pos2 + 1, (endPos - pos2 - 1) ); - good = true; - } - } + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + desktop->tipsMessageContext()->clear(); } - return good; + return Gtk::Widget::on_leave_notify_event(event); } -static bool popVal( guint64& numVal, std::string& str ) +void ColorItem::selection_modified(Selection* selection, guint flags) { - bool good = false; - std::string::size_type endPos = str.find(','); - if ( endPos == std::string::npos ) { - endPos = str.length(); - } - - if ( endPos != std::string::npos && endPos > 0 ) { - std::string xxx = str.substr( 0, endPos ); - const gchar* ptr = xxx.c_str(); - gchar* endPtr = 0; - numVal = g_ascii_strtoull( ptr, &endPtr, 10 ); - if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { - // overflow - } else if ( (numVal == 0) && (endPtr == ptr) ) { - // failed conversion - } else { - good = true; - str.erase( 0, endPos + 1 ); - } - } - - return good; + selection_changed(selection); } -// TODO resolve this more cleanly: -extern gboolean colorItemHandleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data); - -static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data ) +void ColorItem::selection_changed(Selection* selection) { - ColorItem* item = reinterpret_cast(data); - if ( item ) + SPItem* item = selection->singleItem(); + SPPaintServer* grad; + if (item && + ( + (item->style->fill.isPaintserver() && + SP_IS_GRADIENT( (grad = item->style->getFillPaintServer()) ) + && SP_GRADIENT(grad)->getVector() == gradient) || + + (item->style->stroke.isPaintserver() && + SP_IS_GRADIENT( (grad = item->style->getStrokePaintServer()) ) && + SP_GRADIENT(grad)->getVector() == gradient) + ) + ) { - using Inkscape::IO::Resource::get_path; - using Inkscape::IO::Resource::ICONS; - using Inkscape::IO::Resource::SYSTEM; - int width = 32; - int height = 24; - - if (item->def.getType() != ege::PaintDef::RGB){ - GError *error = NULL; - gsize bytesRead = 0; - gsize bytesWritten = 0; - gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), - -1, - &bytesRead, - &bytesWritten, - &error); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error); - g_free(localFilename); - gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); - } else { - GdkPixbuf* pixbuf = 0; - if ( item->getGradient() ){ - cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); - cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width); - cairo_t *ct = cairo_create(s); - cairo_set_source(ct, gradient); - cairo_paint(ct); - cairo_destroy(ct); - cairo_pattern_destroy(gradient); - cairo_surface_flush(s); - - pixbuf = ink_pixbuf_create_from_cairo_surface(s); - } else { - Glib::RefPtr thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height ); - guint32 fillWith = (0xff000000 & (item->def.getR() << 24)) - | (0x00ff0000 & (item->def.getG() << 16)) - | (0x0000ff00 & (item->def.getB() << 8)); - thumb->fill( fillWith ); - pixbuf = thumb->gobj(); - g_object_ref(G_OBJECT(pixbuf)); - } - gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); + if (!_isSelected) { + _isSelected = true; + queue_draw(); } + } else if (_isSelected) { + _isSelected = false; + queue_draw(); } - -} - -//"drag-drop" -// gboolean dragDropColorData( GtkWidget *widget, -// GdkDragContext *drag_context, -// gint x, -// gint y, -// guint time, -// gpointer user_data) -// { -// // TODO finish - -// return TRUE; -// } - - -SwatchPage::SwatchPage() - : _prefWidth(0) -{ -} - -SwatchPage::~SwatchPage() -{ -} - - -ColorItem::ColorItem(ege::PaintDef::ColorType type) : - def(type), - _isFill(false), - _isStroke(false), - _isLive(false), - _linkIsTone(false), - _linkPercent(0), - _linkGray(0), - _linkSrc(0), - _grad(0), - _pattern(0) -{ -} - -ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) : - def( r, g, b, name ), - _isFill(false), - _isStroke(false), - _isLive(false), - _linkIsTone(false), - _linkPercent(0), - _linkGray(0), - _linkSrc(0), - _grad(0), - _pattern(0) -{ -} - -ColorItem::~ColorItem() -{ - if (_pattern != NULL) { - cairo_pattern_destroy(_pattern); - } -} - -ColorItem::ColorItem(ColorItem const &other) : - Inkscape::UI::Previewable() -{ - if ( this != &other ) { - *this = other; - } -} - -ColorItem &ColorItem::operator=(ColorItem const &other) -{ - if ( this != &other ) { - def = other.def; - - // TODO - correct linkage - _linkSrc = other._linkSrc; - g_message("Erk!"); - } - return *this; } -void ColorItem::setState( bool fill, bool stroke ) +ColorItem::ColorItem( SPGradient* grad, const gchar* name, SPDesktop* desktop ) : + Glib::ObjectBase("coloritem"), + Gtk::Widget(), + def( name ), + gradient(grad), + _isSelected(false) { - if ( (_isFill != fill) || (_isStroke != stroke) ) { - _isFill = fill; - _isStroke = stroke; - - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - EekPreview * preview = EEK_PREVIEW(widget->gobj()); - - int val = eek_preview_get_linked( preview ); - val &= ~(PREVIEW_FILL | PREVIEW_STROKE); - if ( _isFill ) { - val |= PREVIEW_FILL; - } - if ( _isStroke ) { - val |= PREVIEW_STROKE; - } - eek_preview_set_linked( preview, static_cast(val) ); - } - } - } + set_has_window(true); + add_events(Gdk::BUTTON_PRESS_MASK); + add_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); + sel_connection = desktop->selection->connectChanged(sigc::mem_fun(*this, &ColorItem::selection_changed)); + mod_connection = desktop->selection->connectModified(sigc::mem_fun(*this, &ColorItem::selection_modified)); + selection_changed(desktop->selection); } -void ColorItem::setGradient(SPGradient *grad) +void ColorItem::on_size_request(Gtk::Requisition* requisition) { - if (_grad != grad) { - _grad = grad; - // TODO regen and push to listeners - } - - setName( gr_prepare_label(_grad) ); + requisition->height = 20; + requisition->width = 20; } -void ColorItem::setName(const Glib::ustring name) +void ColorItem::on_size_allocate(Gtk::Allocation& allocation) { - //def.descr = name; - - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str()); - } - else if ( GTK_IS_LABEL(widget->gobj()) ) { - gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str()); - } + set_allocation(allocation); + if (m_refGdkWindow) + { + m_refGdkWindow->move_resize( allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height() ); } } -void ColorItem::setPattern(cairo_pattern_t *pattern) +void ColorItem::on_map() { - if (pattern) { - cairo_pattern_reference(pattern); - } - if (_pattern) { - cairo_pattern_destroy(_pattern); - } - _pattern = pattern; - - _updatePreviews(); + Gtk::Widget::on_map(); } -void ColorItem::_dragGetColorData( GtkWidget */*widget*/, - GdkDragContext */*drag_context*/, - GtkSelectionData *data, - guint info, - guint /*time*/, - gpointer user_data) +void ColorItem::on_unmap() { - ColorItem* item = reinterpret_cast(user_data); - std::string key; - if ( info < mimeStrings.size() ) { - key = mimeStrings[info]; - } else { - g_warning("ERROR: unknown value (%d)", info); - } - - if ( !key.empty() ) { - char* tmp = 0; - int len = 0; - int format = 0; - item->def.getMIMEData(key, tmp, len, format); - if ( tmp ) { - GdkAtom dataAtom = gdk_atom_intern( key.c_str(), FALSE ); - gtk_selection_data_set( data, dataAtom, format, (guchar*)tmp, len ); - delete[] tmp; - } - } + Gtk::Widget::on_unmap(); } -void ColorItem::_dropDataIn( GtkWidget */*widget*/, - GdkDragContext */*drag_context*/, - gint /*x*/, gint /*y*/, - GtkSelectionData */*data*/, - guint /*info*/, - guint /*event_time*/, - gpointer /*user_data*/) +void ColorItem::on_realize() { + set_realized(); + ensure_style(); + + if(!m_refGdkWindow) + { + //Create the GdkWindow: + + GdkWindowAttr attributes; + memset(&attributes, 0, sizeof(attributes)); + + Gtk::Allocation allocation = get_allocation(); + + //Set initial position and size of the Gdk::Window: + attributes.x = allocation.get_x(); + attributes.y = allocation.get_y(); + attributes.width = allocation.get_width(); + attributes.height = allocation.get_height(); + + attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + + m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes, + GDK_WA_X | GDK_WA_Y); + set_window(m_refGdkWindow); + + //Attach this widget's style to its Gdk::Window. + style_attach(); + + //make the widget receive expose events + m_refGdkWindow->set_user_data(gobj()); + } } -void ColorItem::_colorDefChanged(void* data) +void ColorItem::on_unrealize() { - ColorItem* item = reinterpret_cast(data); - if ( item ) { - item->_updatePreviews(); - } + m_refGdkWindow.reset(); + + Gtk::Widget::on_unrealize(); } -void ColorItem::_updatePreviews() +bool ColorItem::on_expose_event(GdkEventExpose* event) { - for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { - Gtk::Widget* widget = *it; - if ( IS_EEK_PREVIEW(widget->gobj()) ) { - EekPreview * preview = EEK_PREVIEW(widget->gobj()); - - _regenPreview(preview); - - widget->queue_draw(); - } - } - - for ( std::vector::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) { - guint r = def.getR(); - guint g = def.getG(); - guint b = def.getB(); - - if ( (*it)->_linkIsTone ) { - r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100; - g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100; - b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100; - } else { - r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100; - g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100; - b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100; - } - - (*it)->def.setRGB( r, g, b ); - } - - -#if ENABLE_MAGIC_COLORS - // Look for objects using this color + if(m_refGdkWindow) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - SPDocument* document = sp_desktop_document( desktop ); - Inkscape::XML::Node *rroot = document->getReprRoot(); - if ( rroot ) { - - // Find where this thing came from - Glib::ustring paletteName; - bool found = false; - int index = 0; - for ( std::vector::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) { - SwatchPage* curr = *it2; - index = 0; - for ( boost::ptr_vector::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) { - if ( this == &*zz ) { - found = true; - paletteName = curr->_name; - break; - } else { - index++; - } - } - } - - if ( !paletteName.empty() ) { - gchar* str = g_strdup_printf("%d|", index); - paletteName.insert( 0, str ); - g_free(str); - str = 0; - - if ( bruteForce( document, rroot, paletteName, def.getR(), def.getG(), def.getB() ) ) { - SPDocumentUndo::done( document , SP_VERB_DIALOG_SWATCHES, - _("Change color definition")); - } - } - } - } - } -#endif // ENABLE_MAGIC_COLORS - -} - -void ColorItem::_regenPreview(EekPreview * preview) -{ - if ( def.getType() != ege::PaintDef::RGB ) { - using Inkscape::IO::Resource::get_path; - using Inkscape::IO::Resource::ICONS; - using Inkscape::IO::Resource::SYSTEM; - GError *error = NULL; - gsize bytesRead = 0; - gsize bytesWritten = 0; - gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), - -1, - &bytesRead, - &bytesWritten, - &error); - GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error); - if (!pixbuf) { - g_warning("Null pixbuf for %p [%s]", localFilename, localFilename ); - } - g_free(localFilename); - - eek_preview_set_pixbuf( preview, pixbuf ); - } - else if ( !_pattern ){ - eek_preview_set_color( preview, - (def.getR() << 8) | def.getR(), - (def.getG() << 8) | def.getG(), - (def.getB() << 8) | def.getB() ); - } else { - // These correspond to PREVIEW_PIXBUF_WIDTH and VBLOCK from swatches.cpp - // TODO: the pattern to draw should be in the widget that draws the preview, - // so the preview can be scalable - int w = 128; - int h = 16; - - cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); - cairo_t *ct = cairo_create(s); - cairo_set_source(ct, _pattern); - cairo_paint(ct); - cairo_destroy(ct); - cairo_surface_flush(s); - - GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); - eek_preview_set_pixbuf( preview, pixbuf ); - } - - eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0) - | (_listeners.empty() ? 0:PREVIEW_LINK_OUT) - | (_isLive ? PREVIEW_LINK_OTHER:0)) ); -} - -Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) -{ - Gtk::Widget* widget = 0; - if ( style == PREVIEW_STYLE_BLURB) { - Gtk::Label *lbl = new Gtk::Label(def.descr); - lbl->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); - widget = lbl; - } else { - GtkWidget* eekWidget = eek_preview_new(); - EekPreview * preview = EEK_PREVIEW(eekWidget); - Gtk::Widget* newBlot = Glib::wrap(eekWidget); - _regenPreview(preview); - - eek_preview_set_details( preview, - (::ViewType)view, - (::PreviewSize)size, - ratio, - border ); - - def.addCallback( _colorDefChanged, this ); - eek_preview_set_focus_on_click(preview, FALSE); - newBlot->set_tooltip_text(def.descr); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "clicked", - G_CALLBACK(handleClick), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "alt-clicked", - G_CALLBACK(handleSecondaryClick), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "button-press-event", - G_CALLBACK(colorItemHandleButtonPress), - this); - + Cairo::RefPtr cr = m_refGdkWindow->create_cairo_context(); + if(event) { - std::vector listing = def.getMIMETypes(); - int entryCount = listing.size(); - GtkTargetEntry* entries = new GtkTargetEntry[entryCount]; - GtkTargetEntry* curr = entries; - for ( std::vector::iterator it = listing.begin(); it != listing.end(); ++it ) { - curr->target = g_strdup(it->c_str()); - curr->flags = 0; - if ( mimeToInt.find(*it) == mimeToInt.end() ){ - // these next lines are order-dependent: - mimeToInt[*it] = mimeStrings.size(); - mimeStrings.push_back(*it); - } - curr->info = mimeToInt[curr->target]; - curr++; - } - gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()), - GDK_BUTTON1_MASK, - entries, entryCount, - GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) ); - for ( int i = 0; i < entryCount; i++ ) { - g_free(entries[i].target); - } - delete[] entries; + // clip to the area that needs to be re-exposed so we don't draw any + // more than we need to. + cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); + cr->clip(); } - g_signal_connect( G_OBJECT(newBlot->gobj()), - "drag-data-get", - G_CALLBACK(ColorItem::_dragGetColorData), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "drag-begin", - G_CALLBACK(colorItemDragBegin), - this ); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "enter-notify-event", - G_CALLBACK(handleEnterNotify), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "leave-notify-event", - G_CALLBACK(handleLeaveNotify), - this); - - g_signal_connect( G_OBJECT(newBlot->gobj()), - "destroy", - G_CALLBACK(dieDieDie), - this); - - - widget = newBlot; - } - - _previews.push_back( widget ); - - return widget; -} - -void ColorItem::buttonClicked(bool secondary) -{ - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (desktop) { - char const * attrName = secondary ? "stroke" : "fill"; - - SPCSSAttr *css = sp_repr_css_attr_new(); - Glib::ustring descr; - switch (def.getType()) { - case ege::PaintDef::CLEAR: { - // TODO actually make this clear - sp_repr_css_set_property( css, attrName, "none" ); - descr = secondary? _("Remove stroke color") : _("Remove fill color"); - break; - } - case ege::PaintDef::NONE: { - sp_repr_css_set_property( css, attrName, "none" ); - descr = secondary? _("Set stroke color to none") : _("Set fill color to none"); - break; - } - case ege::PaintDef::RGB: { - Glib::ustring colorspec; - if ( _grad ){ - colorspec = "url(#"; - colorspec += _grad->getId(); - colorspec += ")"; - } else { - gchar c[64]; - guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff; - sp_svg_write_color(c, sizeof(c), rgba); - colorspec = c; - } - sp_repr_css_set_property( css, attrName, colorspec.c_str() ); - descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"); - break; - } - } - sp_desktop_set_style(desktop, css); - sp_repr_css_attr_unref(css); - - DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_SWATCHES, descr.c_str() ); - } -} - -void ColorItem::_wireMagicColors( SwatchPage *colorSet ) -{ - if ( colorSet ) - { - for ( boost::ptr_vector::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it ) - { - std::string::size_type pos = it->def.descr.find("*{"); - if ( pos != std::string::npos ) - { - std::string subby = it->def.descr.substr( pos + 2 ); - std::string::size_type endPos = subby.find("}*"); - if ( endPos != std::string::npos ) - { - subby.erase( endPos ); - //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str()); - //g_message(" '%s'", subby.c_str()); - - if ( subby.find('E') != std::string::npos ) - { - it->def.setEditable( true ); - } - - if ( subby.find('L') != std::string::npos ) - { - it->_isLive = true; - } - - std::string part; - // Tint. index + 1 more val. - if ( getBlock( part, 'T', subby ) ) { - guint64 colorIndex = 0; - if ( popVal( colorIndex, part ) ) { - guint64 percent = 0; - if ( popVal( percent, part ) ) { - it->_linkTint( colorSet->_colors[colorIndex], percent ); - } - } - } - - // Shade/tone. index + 1 or 2 more val. - if ( getBlock( part, 'S', subby ) ) { - guint64 colorIndex = 0; - if ( popVal( colorIndex, part ) ) { - guint64 percent = 0; - if ( popVal( percent, part ) ) { - guint64 grayLevel = 0; - if ( !popVal( grayLevel, part ) ) { - grayLevel = 0; - } - it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel ); - } - } - } - - } + if (gradient) { + cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); + + Cairo::RefPtr checkpat(new Cairo::Pattern(check)); + + cr->set_source(checkpat); + cr->paint(); + + cairo_pattern_t *g = sp_gradient_create_preview_pattern(gradient, get_allocation().get_width()); + Cairo::RefPtr gpat(new Cairo::Pattern(g)); + cr->set_source(gpat); + cr->paint(); + gpat.clear(); + cairo_pattern_destroy(g); + + checkpat.clear(); + + cairo_pattern_destroy(check); + + if (_isSelected) { + cr->set_source_rgb(0, 0, 0); + cr->set_line_width(3); + cr->move_to(0, get_allocation().get_height()); + cr->line_to(0,0); + cr->line_to(get_allocation().get_width(), 0); + cr->stroke(); + cr->move_to(get_allocation().get_width(), 0); + cr->set_source_rgb(1, 1, 1); + cr->line_to(get_allocation().get_width(), get_allocation().get_height()); + cr->line_to(0, get_allocation().get_height()); + //cr->rectangle(0, 0, get_allocation().get_width(), get_allocation().get_height()); + cr->stroke(); } + } else { + cr->set_source_rgb(1, 1, 1); + cr->paint(); + cr->set_source_rgb(1, 0, 0); + cr->set_line_width(3); + cr->move_to(0,0); + cr->line_to(get_allocation().get_width(), get_allocation().get_height()); + cr->move_to(get_allocation().get_width(), 0); + cr->line_to(0, get_allocation().get_height()); + cr->stroke(); } } + return true; } - -void ColorItem::_linkTint( ColorItem& other, int percent ) -{ - if ( !_linkSrc ) - { - other._listeners.push_back(this); - _linkIsTone = false; - _linkPercent = percent; - if ( _linkPercent > 100 ) - _linkPercent = 100; - if ( _linkPercent < 0 ) - _linkPercent = 0; - _linkGray = 0; - _linkSrc = &other; - - ColorItem::_colorDefChanged(&other); - } -} - -void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel ) +ColorItem::~ColorItem() { - if ( !_linkSrc ) - { - other._listeners.push_back(this); - _linkIsTone = true; - _linkPercent = percent; - if ( _linkPercent > 100 ) - _linkPercent = 100; - if ( _linkPercent < 0 ) - _linkPercent = 0; - _linkGray = grayLevel; - _linkSrc = &other; - - ColorItem::_colorDefChanged(&other); - } + sel_connection.disconnect(); + mod_connection.disconnect(); } } // namespace Dialogs diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h index 3a0b33193..5d97d8803 100644 --- a/src/ui/dialog/color-item.h +++ b/src/ui/dialog/color-item.h @@ -15,7 +15,11 @@ #include #include "widgets/ege-paint-def.h" -#include "ui/previewable.h" +#include "widgets/eek-preview.h" +#include +#include +#include "desktop.h" +#include "selection.h" class SPGradient; @@ -23,89 +27,43 @@ namespace Inkscape { namespace UI { namespace Dialogs { -class ColorItem; - -class SwatchPage -{ -public: - SwatchPage(); - ~SwatchPage(); - - Glib::ustring _name; - int _prefWidth; - boost::ptr_vector _colors; -}; - /** * The color swatch you see on screen as a clickable box. */ -class ColorItem : public Inkscape::UI::Previewable +class ColorItem : public Gtk::Widget { - friend void _loadPaletteFile( gchar const *filename ); public: - ColorItem( ege::PaintDef::ColorType type ); - ColorItem( unsigned int r, unsigned int g, unsigned int b, - Glib::ustring& name ); + ColorItem( SPGradient * grad, const gchar* name, SPDesktop* desktop ); virtual ~ColorItem(); - ColorItem(ColorItem const &other); - virtual ColorItem &operator=(ColorItem const &other); - virtual Gtk::Widget* getPreview(PreviewStyle style, - ViewType view, - ::PreviewSize size, - guint ratio, - guint border); - void buttonClicked(bool secondary = false); - - void setGradient(SPGradient *grad); - SPGradient * getGradient() const { return _grad; } - void setPattern(cairo_pattern_t *pattern); - void setName(const Glib::ustring name); - - void setState( bool fill, bool stroke ); - bool isFill() { return _isFill; } - bool isStroke() { return _isStroke; } - - ege::PaintDef def; - + + SPGradient * getGradient() { return gradient; } + +protected: + + const gchar* def; + SPGradient * gradient; + virtual bool on_enter_notify_event(GdkEventCrossing* event); + virtual bool on_leave_notify_event(GdkEventCrossing* event); + + virtual void on_size_request(Gtk::Requisition* requisition); + virtual void on_size_allocate(Gtk::Allocation& allocation); + virtual void on_map(); + virtual void on_unmap(); + virtual void on_realize(); + virtual void on_unrealize(); + virtual bool on_expose_event(GdkEventExpose* event); + + Glib::RefPtr m_refGdkWindow; + + private: + void selection_changed(Selection* selection); + void selection_modified(Selection* selection, guint flags); - static void _dropDataIn( GtkWidget *widget, - GdkDragContext *drag_context, - gint x, gint y, - GtkSelectionData *data, - guint info, - guint event_time, - gpointer user_data); - - static void _dragGetColorData( GtkWidget *widget, - GdkDragContext *drag_context, - GtkSelectionData *data, - guint info, - guint time, - gpointer user_data); - - static void _wireMagicColors( SwatchPage *colorSet ); - static void _colorDefChanged(void* data); - - void _updatePreviews(); - void _regenPreview(EekPreview * preview); - - void _linkTint( ColorItem& other, int percent ); - void _linkTone( ColorItem& other, int percent, int grayLevel ); - - std::vector _previews; - - bool _isFill; - bool _isStroke; - bool _isLive; - bool _linkIsTone; - int _linkPercent; - int _linkGray; - ColorItem* _linkSrc; - SPGradient* _grad; - cairo_pattern_t *_pattern; - std::vector _listeners; + sigc::connection sel_connection; + sigc::connection mod_connection; + bool _isSelected; }; } // namespace Dialogs diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h index 8dfcf5dce..175031bcf 100644 --- a/src/ui/dialog/filedialog.h +++ b/src/ui/dialog/filedialog.h @@ -48,6 +48,7 @@ typedef enum { IMPORT_TYPES, EXPORT_TYPES, EXE_TYPES, + SWATCH_TYPES, CUSTOM_TYPE } FileDialogType; diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 2956c6d17..efea4b869 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -67,14 +67,14 @@ #include "svg/svg-color.h" #include "sp-radial-gradient.h" #include "color-rgba.h" +#include "ui/tools/tool-base.h" #include "svg/css-ostringstream.h" -#include "ui/tools/tool-base.h" //event-context.h #include #ifdef WIN32 #include #endif -guint get_group0_keyval(GdkEventKey *event); +//lazy! void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); namespace Inkscape { @@ -1335,10 +1335,10 @@ void SwatchesPanel::_defsChanged() eb->add(*lbl); _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); } - Glib::ustring str1 = Glib::ustring(_("[None]")); - ColorItem* item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str1)); - //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); - item->setName(_("[None]")); + + ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); + item->set_tooltip_text(_("[None]")); _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); unsigned int i = 1; @@ -1365,11 +1365,10 @@ void SwatchesPanel::_defsChanged() GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); } - Glib::ustring str2 = Glib::ustring(it->label() ? it->label() : it->getId()); - item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str2)); - item->setGradient(grad); - //item->colorItemHandleButtonPress().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->setName(it->label() ? it->label() : it->getId()); + + item = Gtk::manage(new ColorItem(grad, it->label() ? it->label() : it->getId(), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->set_tooltip_text(it->label() ? it->label() : it->getId()); if (_showlabels) { _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); } else { @@ -1432,11 +1431,10 @@ void SwatchesPanel::_defsChanged() _editDoc.expand_to_path(_storeDoc->get_path(iter)); } - Glib::ustring str3= Glib::ustring(cit->label() ? cit->label() : cit->getId()); - item = Gtk::manage(new ColorItem(NULL, NULL, NULL, str3)); - item->setGradient(grad); - //item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->setName(cit->label() ? cit->label() : cit->getId()); + + item = Gtk::manage(new ColorItem(grad, cit->label() ? cit->label() : cit->getId(), _currentDesktop)); + item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); + item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); if (_showlabels) { _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); } else { @@ -1643,7 +1641,7 @@ bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -1815,7 +1813,7 @@ void SwatchesPanel::_deleteButtonClickedDoc() bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: { @@ -2323,18 +2321,8 @@ void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) } //namespace UI } //namespace Inkscape -//should be okay to add this here -guint get_group0_keyval(GdkEventKey *event) { - guint keyval = 0; - gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( - gdk_display_get_default()), event->hardware_keycode, - (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, - NULL, NULL, NULL); - return keyval; -} - -void -sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) +//really lazy! +void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) { bool intercepted = false; -- cgit v1.2.3 From a13fdaaa6335ad69b59750a3a9c6b978b921881b Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 16:21:29 -0500 Subject: Fixed some swatch sizes (what about the table?) (bzr r13090.1.17) --- src/ui/dialog/swatches.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index efea4b869..91d859f90 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -1333,13 +1333,13 @@ void SwatchesPanel::_defsChanged() lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); } ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); item->set_tooltip_text(_("[None]")); - _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); unsigned int i = 1; for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { @@ -1370,9 +1370,9 @@ void SwatchesPanel::_defsChanged() item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); item->set_tooltip_text(it->label() ? it->label() : it->getId()); if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } i++; @@ -1393,7 +1393,7 @@ void SwatchesPanel::_defsChanged() eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND , 5, 0); + _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); } Gtk::TreeModel::iterator rowiter; @@ -1436,9 +1436,9 @@ void SwatchesPanel::_defsChanged() item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND ); + _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); } i++; } @@ -2072,7 +2072,7 @@ bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& con SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), _scroller(), - _insideTable(1, 2), + _insideTable(1, 1), _insideV(), _insideH(), _buttonsRow(), -- cgit v1.2.3 From 8db893813e5974793db85bad0eb6b32468d29c45 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 19:31:15 -0500 Subject: Makefile fix (bzr r13090.1.18) --- src/ui/dialog/swatches.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 91d859f90..ceda27885 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -1448,9 +1448,11 @@ void SwatchesPanel::_defsChanged() } } } - + //_scroller.resize(1,1); + _insideTable.resize(1,1); _scroller.show_all_children(); _scroller.queue_draw(); + } Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) @@ -2258,6 +2260,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); _swatchesChanged(); + _insideTable.resize(1,1); } SwatchesPanel::~SwatchesPanel() -- cgit v1.2.3 From 50a5b62b327c55b8038b5031d35bf6ae48705485 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 5 Mar 2014 21:08:09 -0500 Subject: Fixed size of swatches widget (bzr r13090.1.19) --- src/ui/dialog/swatches.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index ceda27885..c3889db46 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -2102,7 +2102,7 @@ SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); _scroller.add(_insideV); } else { - _scroller.property_height_request() = 45; + _scroller.property_height_request() = 20; _scroller.add(_insideH); } -- cgit v1.2.3 From c3edf2beebfdf0cbb505d2accbddc4fec17dff7d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 6 Mar 2014 21:05:19 -0500 Subject: Start cleanup for merge into trunk (bzr r13090.1.20) --- src/ui/dialog/color-item.cpp | 2 +- src/ui/dialog/dialog-manager.cpp | 4 +- src/ui/dialog/lpe-powerstroke-properties.cpp | 8 + src/ui/dialog/swatches.cpp | 1 - src/ui/dialog/tags.cpp | 1182 -------------------------- src/ui/dialog/tags.h | 181 ---- 6 files changed, 11 insertions(+), 1367 deletions(-) delete mode 100644 src/ui/dialog/tags.cpp delete mode 100644 src/ui/dialog/tags.h (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index 6eece0c17..a1951ec48 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -12,7 +12,6 @@ */ #include -#include #include #include #include @@ -40,6 +39,7 @@ #include "color.h" // for SP_RGBA32_U_COMPOSE +#include namespace Inkscape { namespace UI { diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 1fddbf007..ddf41e0c8 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -111,7 +111,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - //registerFactory("TagsPanel", &create); +// registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -147,7 +147,7 @@ DialogManager::DialogManager() { registerFactory("InkscapePreferences", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); - //registerFactory("TagsPanel", &create); +// registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/lpe-powerstroke-properties.cpp b/src/ui/dialog/lpe-powerstroke-properties.cpp index cef6f494e..c34351511 100644 --- a/src/ui/dialog/lpe-powerstroke-properties.cpp +++ b/src/ui/dialog/lpe-powerstroke-properties.cpp @@ -13,6 +13,14 @@ * Released under GNU GPL. Read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include "lpe-powerstroke-properties.h" #include #include diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index c3889db46..34885a971 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -43,7 +43,6 @@ #include "path-prefix.h" #include "preferences.h" #include "sp-item.h" -#include "sp-gradient-fns.h" #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp deleted file mode 100644 index 116f9eb0b..000000000 --- a/src/ui/dialog/tags.cpp +++ /dev/null @@ -1,1182 +0,0 @@ -/* - * A simple panel for tags - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "tags.h" -#include -#include -#include -#include - -#include - -#include "desktop.h" -#include "desktop-style.h" -#include "document.h" -#include "document-undo.h" -#include "helper/action.h" -#include "inkscape.h" -#include "layer-fns.h" -#include "layer-manager.h" -#include "preferences.h" -#include "sp-item.h" -#include "sp-object.h" -#include "sp-shape.h" -#include "svg/css-ostringstream.h" -#include "ui/icon-names.h" -#include "ui/widget/layertypeicon.h" -#include "ui/widget/addtoicon.h" -#include "verbs.h" -#include "widgets/icon.h" -#include "xml/node.h" -#include "xml/node-observer.h" -#include "xml/repr.h" -#include "sp-root.h" -//#include "event-context.h" -#include "selection.h" -#include "dialogs/dialog-events.h" -#include "widgets/sp-color-notebook.h" -#include "style.h" -#include "filter-chemistry.h" -#include "filters/blend.h" -#include "filters/gaussian-blur.h" -#include "sp-clippath.h" -#include "sp-mask.h" -#include "sp-tag.h" -#include "sp-defs.h" -#include "sp-tag-use.h" -#include "sp-tag-use-reference.h" - -//#define DUMP_LAYERS 1 - -namespace Inkscape { -namespace UI { -namespace Dialog { - -using Inkscape::XML::Node; - -TagsPanel& TagsPanel::getInstance() -{ - return *new TagsPanel(); -} - -enum { - COL_ADD = 1 -}; - -enum { - BUTTON_NEW = 0, - BUTTON_TOP, - BUTTON_BOTTOM, - BUTTON_UP, - BUTTON_DOWN, - BUTTON_DELETE, - DRAGNDROP -}; - -class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { -public: - ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : - _pnl(pnl), - _obj(obj), - _repr(repr), - _labelAttr(g_quark_from_string("inkscape:label")) - {} - - ObjectWatcher(TagsPanel* pnl, SPObject* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")) - {} - - virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) - { - if ( _pnl && _obj ) { - _pnl->_objectsChanged( _obj ); - } - } - virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if ( _pnl && _obj ) { - if ( name == _labelAttr ) { - _pnl->_updateObject( _obj); - } - } - } - - TagsPanel* _pnl; - SPObject* _obj; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; -}; - -class TagsPanel::InternalUIBounce -{ -public: - int _actionCode; -}; - -void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) -{ - bool set = false; - - if ( iconName ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - btn.set_relief(Gtk::RELIEF_NONE); - set = true; - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !set && action && action->image ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - set = true; - } - } - } - - btn.set_tooltip_text (tooltip); -} - - -Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) -{ - GtkWidget* iconWidget = 0; - const char* label = 0; - - if ( iconName ) { - iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !iconWidget && action && action->image ) { - iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); - } - - if ( action ) { - label = action->name; - } - } - } - - if ( !label && fallback ) { - label = fallback; - } - - Gtk::Widget* wrapped = 0; - if ( iconWidget ) { - wrapped = manage(Glib::wrap(iconWidget)); - wrapped->show(); - } - - - Gtk::MenuItem* item = 0; - - if (wrapped) { - item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); - } else { - item = Gtk::manage(new Gtk::MenuItem(label, true)); - } - - item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); - _popupMenu.append(*item); - - return *item; -} - -void TagsPanel::_fireAction( unsigned int code ) -{ - if ( _desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(_desktop); - if ( action ) { - sp_action_perform( action, NULL ); - } - } - } -} - -void TagsPanel::_takeAction( int val ) -{ - if ( !_pending ) { - _pending = new InternalUIBounce(); - _pending->_actionCode = val; - Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); - } -} - -bool TagsPanel::_executeAction() -{ - // Make sure selected layer hasn't changed since the action was triggered - if ( _pending) - { - int val = _pending->_actionCode; -// SPObject* target = _pending->_target; - - switch ( val ) { - case BUTTON_NEW: - { - _fireAction( SP_VERB_TAG_NEW ); - } - break; - case BUTTON_TOP: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_TOP ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_FRONT); - } - } - break; - case BUTTON_BOTTOM: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_BOTTOM ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_BACK); - } - } - break; - case BUTTON_UP: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_RAISE ); - } - else - { - _fireAction( SP_VERB_SELECTION_RAISE ); - } - } - break; - case BUTTON_DOWN: - { - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_LOWER ); - } - else - { - _fireAction( SP_VERB_SELECTION_LOWER ); - } - } - break; - case BUTTON_DELETE: - { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * obj = *iter; - if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - break; - case DRAGNDROP: - { - _doTreeMove( ); - } - break; - } - - delete _pending; - _pending = 0; - } - - return false; -} - - -class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord -{ -public: - - ModelColumns() - { - add(_colParentObject); - add(_colObject); - add(_colLabel); - add(_colAddRemove); - add(_colAllowAddRemove); - } - virtual ~ModelColumns() {} - - Gtk::TreeModelColumn _colParentObject; - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; - Gtk::TreeModelColumn _colAddRemove; - Gtk::TreeModelColumn _colAllowAddRemove; -}; - -void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) -{ - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj && obj->parent) { - todelete->push_back(obj); - } -} - -void TagsPanel::_updateObject( SPObject *obj ) { - _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); -} - -bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) -{ - Gtk::TreeModel::Row row = *iter; - if ( obj == row[_model->_colObject] ) - { - /* - * We get notified of layer update here (from layer->setLabel()) before layer->label() is set - * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which - * has the correct value (bug #168351) - */ - //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); - gchar const *label; - SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; - if (use && use->ref->isAttached()) { - label = use->ref->getObject()->getAttribute("inkscape:label"); - } else { - label = obj->getAttribute("inkscape:label"); - } - row[_model->_colLabel] = label ? label : obj->getId(); - row[_model->_colAddRemove] = SP_IS_TAG(obj); - } - - return false; -} - -void TagsPanel::_objectsSelected( Selection *sel ) { - - _selectedConnection.block(); - _tree.get_selection()->unselect_all(); - for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) - { - SPObject *obj = reinterpret_cast(iter->data); - _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); - } - _selectedConnection.unblock(); - _checkTreeSelection(); -} - -bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) -{ - Gtk::TreeModel::Row row = *iter; - SPObject * it = row[_model->_colObject]; - if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) - { - Glib::RefPtr select = _tree.get_selection(); - - select->select(iter); - } - return false; -} - -void TagsPanel::_objectsChanged(SPObject* root) -{ - while (!_objectWatchers.empty()) - { - TagsPanel::ObjectWatcher *w = _objectWatchers.back(); - w->_repr->removeObserver(*w); - _objectWatchers.pop_back(); - delete w; - } - - if (_desktop) { - SPDocument* document = _desktop->doc(); - SPDefs* root = document->getDefs(); - if ( root ) { - _selectedConnection.block(); - _store->clear(); - _addObject( document, root, 0 ); - _selectedConnection.unblock(); - _objectsSelected(_desktop->selection); - _checkTreeSelection(); - } - } -} - -void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) -{ - if ( _desktop && obj ) { - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG(child)) - { - Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = child; - row[_model->_colParentObject] = NULL; - row[_model->_colLabel] = child->label() ? child->label() : child->getId(); - row[_model->_colAddRemove] = true; - row[_model->_colAllowAddRemove] = true; - - _tree.expand_to_path( _store->get_path(iter) ); - - TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); - child->getRepr()->addObserver(*w); - _objectWatchers.push_back(w); - _addObject( doc, child, &row ); - } - } - if (SP_IS_TAG(obj) && obj->children) - { - Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); - Gtk::TreeModel::Row rowitems = *iteritems; - rowitems[_model->_colObject] = NULL; - rowitems[_model->_colParentObject] = obj; - rowitems[_model->_colLabel] = _("Items"); - rowitems[_model->_colAddRemove] = false; - rowitems[_model->_colAllowAddRemove] = false; - - _tree.expand_to_path( _store->get_path(iteritems) ); - - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG_USE(child)) - { - SPItem *item = SP_TAG_USE(child)->ref->getObject(); - Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = child; - row[_model->_colParentObject] = NULL; - row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; - row[_model->_colAddRemove] = false; - row[_model->_colAllowAddRemove] = true; - - if (SP_TAG(obj)->expanded()) { - _tree.expand_to_path( _store->get_path(iter) ); - } - - if (item) { - TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); - item->getRepr()->addObserver(*w); - _objectWatchers.push_back(w); - } - } - } - } - } -} - -void TagsPanel::_select_tag( SPTag * tag ) -{ - for (SPObject * child = tag->children; child != NULL; child = child->next) - { - if (SP_IS_TAG(child)) { - _select_tag(SP_TAG(child)); - } else if (SP_IS_TAG_USE(child)) { - SPObject * obj = SP_TAG_USE(child)->ref->getObject(); - if (obj) { - if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); - _desktop->selection->add(obj); - } - } - } -} - -void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) -{ - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - if (obj) { - if (SP_IS_TAG(obj)) { - _select_tag(SP_TAG(obj)); - } else if (SP_IS_TAG_USE(obj)) { - SPObject * item = SP_TAG_USE(obj)->ref->getObject(); - if (item) { - if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); - _desktop->selection->add(item); - } - } - } - } -} - -void TagsPanel::_pushTreeSelectionToCurrent() -{ - _selectionChangedConnection.block(); - // TODO hunt down the possible API abuse in getting NULL - if ( _desktop && _desktop->currentRoot() ) { - _desktop->selection->clear(); - _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); - } - _selectionChangedConnection.unblock(); - - _checkTreeSelection(); -} - -void TagsPanel::_checkTreeSelection() -{ - bool sensitive = _tree.get_selection()->count_selected_rows() > 0; - bool sensitiveNonTop = true; - bool sensitiveNonBottom = true; -// if ( _tree.get_selection()->count_selected_rows() > 0 ) { -// sensitive = true; -// -// SPObject* inTree = _selectedLayer(); -// if ( inTree ) { -// -// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); -// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); -// -// } -// } - - - for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { - (*it)->set_sensitive( sensitive ); - } - for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { - (*it)->set_sensitive( sensitiveNonTop ); - } - for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { - (*it)->set_sensitive( sensitiveNonBottom ); - } -} - -bool TagsPanel::_handleKeyEvent(GdkEventKey *event) -{ - - switch (get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); - if (iter && !_text_renderer->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj && SP_IS_TAG(obj)) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_renderer->property_editable() = true; - _tree.set_cursor(*path, *_name_column, true); - grab_focus(); - return true; - } - } - } - case GDK_KEY_Delete: { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - if (!todelete.empty()) { - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * obj = *iter; - if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - return true; - } - break; - } - return false; -} - -bool TagsPanel::_handleButtonEvent(GdkEventButton* event) -{ - static unsigned doubleclick = 0; - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { - // TODO - fix to a better is-popup function - Gtk::TreeModel::Path path; - int x = static_cast(event->x); - int y = static_cast(event->y); - if ( _tree.get_path_at_pos( x, y, path ) ) { - _checkTreeSelection(); - _popupMenu.popup(event->button, event->time); - if (_tree.get_selection()->is_selected(path)) { - return true; - } - } - } - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { - // Alt left click on the visible/lock columns - eat this event to keep row selection - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { - if (col == _tree.get_column(COL_ADD-1)) { - down_at_add = true; - return true; - } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { - _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); - _defer_target = path; - } else { - down_at_add = false; - } - } else { - down_at_add = false; - } - } - - if ( event->type == GDK_BUTTON_RELEASE) { - _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); - } - - // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. - if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { - - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { - if (_defer_target) { - if (_defer_target == path && !(event->x == 0 && event->y == 0)) - { - _tree.set_cursor(path, *col, false); - } - _defer_target = Gtk::TreeModel::Path(); - } else { - Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colObject]; - - if (obj) { - if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { - if (SP_IS_TAG(obj)) { - bool wasadded = false; - for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) - { - SPObject *newobj = reinterpret_cast(iter->data); - bool addchild = true; - for ( SPObject *child = obj->children; child != NULL; child = child->next) { - if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { - addchild = false; - } - } - if (addchild) { - Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); - clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); - obj->appendChild(clone); - wasadded = true; - } - } - if (wasadded) { - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to tag")); - } - } else { - std::vector todelete; - _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); - if (!todelete.empty()) { - for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { - SPObject * tobj = *iter; - if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { - tobj->parent->getRepr()->removeChild(tobj->getRepr()); - } - } - } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); - } - DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from tags")); - } - } - } - } - } - } - - - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } - - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { - Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colObject]; - if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { - // Double click on the Layer name, enable editing - _text_renderer->property_editable() = true; - _tree.set_cursor (path, *_name_column, true); - grab_focus(); - } - } - } - - return false; -} - -void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) -{ - Gtk::TreeModel::Row row = *iter; - SPObject* obj = row[_model->_colObject]; - SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; - if (item) - { - _dnd_source.push_back(item); - } -} - -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) -{ - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - _dnd_into = true; - _dnd_target = _document->getDefs(); - _dnd_source.clear(); - _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); - - if (_dnd_source.empty()) { - return true; - } - - if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _tree.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y > (int)(cell_height * 2/3)) { - Gtk::TreeModel::Path next_path = target_path; - next_path.next(); - if (_store->iter_is_valid(_store->get_iter(next_path))) { - target_path = next_path; - } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_store->iter_is_valid(_store->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - // Drop into the top level - _dnd_target = _document->getDefs(); - _dnd_into = true; - } - } - } - Gtk::TreeModel::iterator iter = _store->get_iter(target_path); - if (_store->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - SPObject *pobj = row[_model->_colParentObject]; - if (obj) { - if (SP_IS_TAG(obj)) { - _dnd_target = SP_TAG(obj); - } else if (SP_IS_TAG(obj->parent)) { - _dnd_target = SP_TAG(obj->parent); - _dnd_into = true; - } - } else if (pobj && SP_IS_TAG(pobj)) { - _dnd_target = SP_TAG(pobj); - _dnd_into = true; - } else { - return true; - } - } - } - - _takeAction(DRAGNDROP); - - return false; -} - -/* - * Move a layer in response to a drag & drop action - */ -void TagsPanel::_doTreeMove( ) -{ - if (_dnd_target) { - for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) - { - SPTag *src = *iter; - if (src != _dnd_target) { - src->moveTo(_dnd_target, _dnd_into); - } - } - _desktop->selection->clear(); - while (!_dnd_source.empty()) - { - SPTag *src = _dnd_source.back(); - _select_tag(src); - _dnd_source.pop_back(); - } - DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, - _("Moved tags")); - } -} - - -void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - _renameObject(row, new_text); - _text_renderer->property_editable() = false; -} - -void TagsPanel::_handleEditingCancelled() -{ - _text_renderer->property_editable() = false; -} - -void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && _desktop) { - SPObject* obj = row[_model->_colObject]; - if ( obj ) { - if (SP_IS_TAG(obj)) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, - _("Rename object")); - } - } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, - _("Rename object")); - } - } - } - } -} - -bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) -{ - return false; -} - -bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) -{ - bool val = true; - if ( !currentlySelected && _toggleEvent ) - { - GdkEvent* event = gtk_get_current_event(); - if ( event ) { - // (keep these checks separate, so we know when to call gdk_event_free() - if ( event->type == GDK_BUTTON_PRESS ) { - GdkEventButton const* target = reinterpret_cast(_toggleEvent); - GdkEventButton const* evtb = reinterpret_cast(event); - - if ( (evtb->window == target->window) - && (evtb->send_event == target->send_event) - && (evtb->time == target->time) - && (evtb->state == target->state) - ) - { - // Ooooh! It's a magic one - val = false; - } - } - gdk_event_free(event); - } - } - return val; -} - -void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) -{ - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_model->_colParentObject]; - if (obj && SP_IS_TAG(obj)) - { - SP_TAG(obj)->setExpanded(isexpanded); - obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - } -} - -/** - * Constructor - */ -TagsPanel::TagsPanel() : - UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), - _rootWatcher(0), - deskTrack(), - _desktop(0), - _document(0), - _model(0), - _pending(0), - _toggleEvent(0), - _defer_target(), - desktopChangeConn() -{ - //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - ModelColumns *zoop = new ModelColumns(); - _model = zoop; - - _store = Gtk::TreeStore::create( *zoop ); - - _tree.set_model( _store ); - _tree.set_headers_visible(false); - _tree.set_reorderable(true); - _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); - - Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); - int addColNum = _tree.append_column("type", *addRenderer) - 1; - Gtk::TreeViewColumn *col = _tree.get_column(addColNum); - if ( col ) { - col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); - col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); - } - - _text_renderer = manage(new Gtk::CellRendererText()); - int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; - _name_column = _tree.get_column(nameColNum); - _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); - - _tree.set_expander_column( *_tree.get_column(nameColNum) ); - - _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); - _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); - _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); - - _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); - _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); - _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); - - _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); - _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); - - _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); - _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); - _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); - - _scroller.add( _tree ); - _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scroller.set_shadow_type(Gtk::SHADOW_IN); - Gtk::Requisition sreq; -#if WITH_GTKMM_3_0 - Gtk::Requisition sreq_natural; - _scroller.get_preferred_size(sreq_natural, sreq); -#else - sreq = _scroller.size_request(); -#endif - int minHeight = 70; - if (sreq.height < minHeight) { - // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar - _scroller.set_size_request(sreq.width, minHeight); - } - - _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); - - _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); - - _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); - - SPDesktop* targetDesktop = getDesktop(); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new tag") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); - _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); - -// btn = manage( new Gtk::Button("Dup") ); -// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); -// _buttonsRow.add( *btn ); - - btn = manage( new Gtk::Button() ); - _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Tag") ); - btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); - _watching.push_back( btn ); - _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); - - _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); - _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); - - // ------------------------------------------------------- - { - _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); - - _popupMenu.show_all_children(); - } - // ------------------------------------------------------- - - - - for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { - (*it)->set_sensitive( false ); - } - for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { - (*it)->set_sensitive( false ); - } - for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { - (*it)->set_sensitive( false ); - } - - setDesktop( targetDesktop ); - - show_all_children(); - - // restorePanelPrefs(); - - // Connect this up last - desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); - deskTrack.connect(GTK_WIDGET(gobj())); -} - -TagsPanel::~TagsPanel() -{ - - setDesktop(NULL); - - if ( _model ) - { - delete _model; - _model = 0; - } - - if (_pending) { - delete _pending; - _pending = 0; - } - - if ( _toggleEvent ) - { - gdk_event_free( _toggleEvent ); - _toggleEvent = 0; - } - - desktopChangeConn.disconnect(); - deskTrack.disconnect(); -} - -void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) -{ - while (!_objectWatchers.empty()) - { - TagsPanel::ObjectWatcher *w = _objectWatchers.back(); - w->_repr->removeObserver(*w); - _objectWatchers.pop_back(); - delete w; - } - - if (_rootWatcher) - { - _rootWatcher->_repr->removeObserver(*_rootWatcher); - delete _rootWatcher; - _rootWatcher = NULL; - } - - _document = document; - - if (document && document->getDefs() && document->getDefs()->getRepr()) - { - _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); - document->getDefs()->getRepr()->addObserver(*_rootWatcher); - _objectsChanged(document->getDefs()); - } -} - -void TagsPanel::setDesktop( SPDesktop* desktop ) -{ - Panel::setDesktop(desktop); - - if ( desktop != _desktop ) { - _documentChangedConnection.disconnect(); - _selectionChangedConnection.disconnect(); - if ( _desktop ) { - _desktop = 0; - } - - _desktop = Panel::getDesktop(); - if ( _desktop ) { - //setLabel( _desktop->doc()->name ); - _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); - _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); - - setDocument(_desktop, _desktop->doc()); - } - } -/* - GSList const *layers = _desktop->doc()->getResourceList( "layer" ); - g_message( "layers list starts at %p", layers ); - for ( GSList const *iter=layers ; iter ; iter = iter->next ) { - SPObject *layer=static_cast(iter->data); - g_message(" {%s} [%s]", layer->id, layer->label() ); - } -*/ - deskTrack.setBase(desktop); -} - - - - - -} //namespace Dialogs -} //namespace UI -} //namespace Inkscape - - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h deleted file mode 100644 index d35dfba01..000000000 --- a/src/ui/dialog/tags.h +++ /dev/null @@ -1,181 +0,0 @@ -/* - * A simple dialog for tags UI. - * - * Authors: - * Theodore Janeczko - * - * Copyright (C) Theodore Janeczko 2012 - * - * Released under GNU GPL, read the file 'COPYING' for more information - */ - -#ifndef SEEN_TAGS_PANEL_H -#define SEEN_TAGS_PANEL_H - -#include -#include -#include -#include -#include -#include "ui/widget/spinbutton.h" -#include "ui/widget/panel.h" -#include "ui/widget/object-composite-settings.h" -#include "desktop-tracker.h" -#include "ui/widget/style-subject.h" -#include "selection.h" -#include "ui/widget/filter-effect-chooser.h" - -class SPObject; -class SPTag; -struct SPColorSelector; - -namespace Inkscape { - -namespace UI { -namespace Dialog { - - -/** - * A panel that displays layers. - */ -class TagsPanel : public UI::Widget::Panel -{ -public: - TagsPanel(); - virtual ~TagsPanel(); - - //virtual void setOrientation( Gtk::AnchorType how ); - - static TagsPanel& getInstance(); - - void setDesktop( SPDesktop* desktop ); - void setDocument( SPDesktop* desktop, SPDocument* document); - -protected: - //virtual void _handleAction( int setId, int itemId ); - friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); -private: - class ModelColumns; - class InternalUIBounce; - class ObjectWatcher; - - TagsPanel(TagsPanel const &); // no copy - TagsPanel &operator=(TagsPanel const &); // no assign - - void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); - void _fireAction( unsigned int code ); - Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); - - bool _handleButtonEvent(GdkEventButton *event); - bool _handleKeyEvent(GdkEventKey *event); - - void _storeDragSource(const Gtk::TreeModel::iterator& iter); - bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); - void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelled(); - - void _doTreeMove(); - void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); - - void _pushTreeSelectionToCurrent(); - void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); - void _select_tag( SPTag * tag ); - - void _checkTreeSelection(); - - void _takeAction( int val ); - bool _executeAction(); - - void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); - - bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); - bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); - - void _updateObject(SPObject *obj); - bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); - - void _objectsSelected(Selection *sel); - bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); - - void _objectsChanged(SPObject *root); - void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); - - void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); - -// std::vector groupConnections; - TagsPanel::ObjectWatcher* _rootWatcher; - std::vector _objectWatchers; - - // Hooked to the layer manager: - sigc::connection _documentChangedConnection; - sigc::connection _selectionChangedConnection; - - sigc::connection _changedConnection; - sigc::connection _addedConnection; - sigc::connection _removedConnection; - - // Internal - sigc::connection _selectedConnection; - sigc::connection _expandedConnection; - sigc::connection _collapsedConnection; - - DesktopTracker deskTrack; - SPDesktop* _desktop; - SPDocument* _document; - ModelColumns* _model; - InternalUIBounce* _pending; - gboolean _dnd_into; - std::vector _dnd_source; - SPObject* _dnd_target; - - GdkEvent* _toggleEvent; - bool down_at_add; - - Gtk::TreeModel::Path _defer_target; - - Glib::RefPtr _store; - std::vector _watching; - std::vector _watchingNonTop; - std::vector _watchingNonBottom; - - Gtk::TreeView _tree; - Gtk::CellRendererText *_text_renderer; - Gtk::TreeView::Column *_name_column; -#if WITH_GTKMM_3_0 - Gtk::Box _buttonsRow; - Gtk::Box _buttonsPrimary; - Gtk::Box _buttonsSecondary; -#else - Gtk::HBox _buttonsRow; - Gtk::HBox _buttonsPrimary; - Gtk::HBox _buttonsSecondary; -#endif - Gtk::ScrolledWindow _scroller; - Gtk::Menu _popupMenu; - Inkscape::UI::Widget::SpinButton _spinBtn; - Gtk::VBox _layersPage; - - sigc::connection desktopChangeConn; - -}; - - - -} //namespace Dialogs -} //namespace UI -} //namespace Inkscape - - - -#endif // SEEN_OBJECTS_PANEL_H - -/* - Local Variables: - mode:c++ - c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) - indent-tabs-mode:nil - fill-column:99 - End: -*/ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From fd36e8d406b5ca3bfdc575a949351c6ae4a45c57 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 8 Mar 2014 20:52:27 -0500 Subject: Remove all trace of the Tags dialog Fixed Attach Path and Fill Between Many LPEs Enabled Gradient Meshes (bzr r13090.1.21) --- src/ui/dialog/swatches.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 34885a971..2a8471b55 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -6,6 +6,7 @@ * Jon A. Cruz * John Bintz * Abhishek Sharma + * Theodore Janezcko * * Copyright (C) 2005 Jon A. Cruz * Copyright (C) 2008 John Bintz -- cgit v1.2.3 From 13c192e2fa564c0a743e13e30b1cf6de9b1a39a6 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Wed, 12 Mar 2014 08:56:04 -0400 Subject: Reverted swatches Removed a toy effect (not ready yet) Fixed a bug with Livarot General cleanup (bzr r13090.1.23) --- src/ui/dialog/color-item.cpp | 862 ++++++++-- src/ui/dialog/color-item.h | 108 +- src/ui/dialog/object-properties.cpp | 1 + src/ui/dialog/objects.cpp | 227 +-- src/ui/dialog/swatches.cpp | 2944 +++++++++++------------------------ src/ui/dialog/swatches.h | 153 +- 6 files changed, 1825 insertions(+), 2470 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/color-item.cpp b/src/ui/dialog/color-item.cpp index a1951ec48..bab7e18e1 100644 --- a/src/ui/dialog/color-item.cpp +++ b/src/ui/dialog/color-item.cpp @@ -11,8 +11,18 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + #include + +#if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H +#include +#endif + #include +#include #include #include @@ -35,216 +45,766 @@ #include "xml/repr.h" #include "verbs.h" #include "widgets/gradient-vector.h" -#include "sp-paint-server.h" #include "color.h" // for SP_RGBA32_U_COMPOSE -#include namespace Inkscape { namespace UI { namespace Dialogs { +static std::vector mimeStrings; +static std::map mimeToInt; + -bool ColorItem::on_enter_notify_event(GdkEventCrossing* event) +#if ENABLE_MAGIC_COLORS +// TODO remove this soon: +extern std::vector possible; +#endif // ENABLE_MAGIC_COLORS + + +#if ENABLE_MAGIC_COLORS +static bool bruteForce( SPDocument* document, Inkscape::XML::Node* node, Glib::ustring const& match, int r, int g, int b ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"),def); - desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); - g_free(msg); + bool changed = false; + + if ( node ) { + gchar const * val = node->attribute("inkscape:x-fill-tag"); + if ( val && (match == val) ) { + SPObject *obj = document->getObjectByRepr( node ); + + gchar c[64] = {0}; + sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property( css, "fill", c ); + + sp_desktop_apply_css_recursive( obj, css, true ); + static_cast(obj)->updateRepr(); + + changed = true; + } + + val = node->attribute("inkscape:x-stroke-tag"); + if ( val && (match == val) ) { + SPObject *obj = document->getObjectByRepr( node ); + + gchar c[64] = {0}; + sp_svg_write_color( c, sizeof(c), SP_RGBA32_U_COMPOSE( r, g, b, 0xff ) ); + SPCSSAttr *css = sp_repr_css_attr_new(); + sp_repr_css_set_property( css, "stroke", c ); + + sp_desktop_apply_css_recursive( (SPItem*)obj, css, true ); + ((SPItem*)obj)->updateRepr(); + + changed = true; + } + + Inkscape::XML::Node* first = node->firstChild(); + changed |= bruteForce( document, first, match, r, g, b ); + + changed |= bruteForce( document, node->next(), match, r, g, b ); } - return Gtk::Widget::on_enter_notify_event(event); + + return changed; +} +#endif // ENABLE_MAGIC_COLORS + +static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(false); + } +} + +static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(true); + } +} + +static gboolean handleEnterNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + gchar* msg = g_strdup_printf(_("Color: %s; Click to set fill, Shift+click to set stroke"), + item->def.descr.c_str()); + desktop->tipsMessageContext()->set(Inkscape::INFORMATION_MESSAGE, msg); + g_free(msg); + } + } + return FALSE; +} + +static gboolean handleLeaveNotify( GtkWidget* /*widget*/, GdkEventCrossing* /*event*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + desktop->tipsMessageContext()->clear(); + } + } + return FALSE; } -bool ColorItem::on_leave_notify_event(GdkEventCrossing* event) +static void dieDieDie( GObject *obj, gpointer user_data ) { - SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if ( desktop ) { - desktop->tipsMessageContext()->clear(); + g_message("die die die %p %p", obj, user_data ); +} + +static bool getBlock( std::string& dst, guchar ch, std::string const & str ) +{ + bool good = false; + std::string::size_type pos = str.find(ch); + if ( pos != std::string::npos ) + { + std::string::size_type pos2 = str.find( '(', pos ); + if ( pos2 != std::string::npos ) { + std::string::size_type endPos = str.find( ')', pos2 ); + if ( endPos != std::string::npos ) { + dst = str.substr( pos2 + 1, (endPos - pos2 - 1) ); + good = true; + } + } } - return Gtk::Widget::on_leave_notify_event(event); + return good; } -void ColorItem::selection_modified(Selection* selection, guint flags) +static bool popVal( guint64& numVal, std::string& str ) { - selection_changed(selection); + bool good = false; + std::string::size_type endPos = str.find(','); + if ( endPos == std::string::npos ) { + endPos = str.length(); + } + + if ( endPos != std::string::npos && endPos > 0 ) { + std::string xxx = str.substr( 0, endPos ); + const gchar* ptr = xxx.c_str(); + gchar* endPtr = 0; + numVal = g_ascii_strtoull( ptr, &endPtr, 10 ); + if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { + // overflow + } else if ( (numVal == 0) && (endPtr == ptr) ) { + // failed conversion + } else { + good = true; + str.erase( 0, endPos + 1 ); + } + } + + return good; } -void ColorItem::selection_changed(Selection* selection) +// TODO resolve this more cleanly: +extern gboolean colorItemHandleButtonPress( GtkWidget* /*widget*/, GdkEventButton* event, gpointer user_data); + +static void colorItemDragBegin( GtkWidget */*widget*/, GdkDragContext* dc, gpointer data ) { - SPItem* item = selection->singleItem(); - SPPaintServer* grad; - if (item && - ( - (item->style->fill.isPaintserver() && - SP_IS_GRADIENT( (grad = item->style->getFillPaintServer()) ) - && SP_GRADIENT(grad)->getVector() == gradient) || - - (item->style->stroke.isPaintserver() && - SP_IS_GRADIENT( (grad = item->style->getStrokePaintServer()) ) && - SP_GRADIENT(grad)->getVector() == gradient) - ) - ) + ColorItem* item = reinterpret_cast(data); + if ( item ) { - if (!_isSelected) { - _isSelected = true; - queue_draw(); + using Inkscape::IO::Resource::get_path; + using Inkscape::IO::Resource::ICONS; + using Inkscape::IO::Resource::SYSTEM; + int width = 32; + int height = 24; + + if (item->def.getType() != ege::PaintDef::RGB){ + GError *error = NULL; + gsize bytesRead = 0; + gsize bytesWritten = 0; + gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), + -1, + &bytesRead, + &bytesWritten, + &error); + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file_at_scale(localFilename, width, height, FALSE, &error); + g_free(localFilename); + gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); + } else { + GdkPixbuf* pixbuf = 0; + if ( item->getGradient() ){ + cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); + cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(item->getGradient(), width); + cairo_t *ct = cairo_create(s); + cairo_set_source(ct, gradient); + cairo_paint(ct); + cairo_destroy(ct); + cairo_pattern_destroy(gradient); + cairo_surface_flush(s); + + pixbuf = ink_pixbuf_create_from_cairo_surface(s); + } else { + Glib::RefPtr thumb = Gdk::Pixbuf::create( Gdk::COLORSPACE_RGB, false, 8, width, height ); + guint32 fillWith = (0xff000000 & (item->def.getR() << 24)) + | (0x00ff0000 & (item->def.getG() << 16)) + | (0x0000ff00 & (item->def.getB() << 8)); + thumb->fill( fillWith ); + pixbuf = thumb->gobj(); + g_object_ref(G_OBJECT(pixbuf)); + } + gtk_drag_set_icon_pixbuf( dc, pixbuf, 0, 0 ); } - } else if (_isSelected) { - _isSelected = false; - queue_draw(); } + +} + +//"drag-drop" +// gboolean dragDropColorData( GtkWidget *widget, +// GdkDragContext *drag_context, +// gint x, +// gint y, +// guint time, +// gpointer user_data) +// { +// // TODO finish + +// return TRUE; +// } + + +SwatchPage::SwatchPage() + : _prefWidth(0) +{ } -ColorItem::ColorItem( SPGradient* grad, const gchar* name, SPDesktop* desktop ) : - Glib::ObjectBase("coloritem"), - Gtk::Widget(), - def( name ), - gradient(grad), - _isSelected(false) +SwatchPage::~SwatchPage() { - set_has_window(true); - add_events(Gdk::BUTTON_PRESS_MASK); - add_events(Gdk::ENTER_NOTIFY_MASK | Gdk::LEAVE_NOTIFY_MASK); - sel_connection = desktop->selection->connectChanged(sigc::mem_fun(*this, &ColorItem::selection_changed)); - mod_connection = desktop->selection->connectModified(sigc::mem_fun(*this, &ColorItem::selection_modified)); - selection_changed(desktop->selection); } -void ColorItem::on_size_request(Gtk::Requisition* requisition) + +ColorItem::ColorItem(ege::PaintDef::ColorType type) : + def(type), + _isFill(false), + _isStroke(false), + _isLive(false), + _linkIsTone(false), + _linkPercent(0), + _linkGray(0), + _linkSrc(0), + _grad(0), + _pattern(0) { - requisition->height = 20; - requisition->width = 20; } -void ColorItem::on_size_allocate(Gtk::Allocation& allocation) +ColorItem::ColorItem( unsigned int r, unsigned int g, unsigned int b, Glib::ustring& name ) : + def( r, g, b, name ), + _isFill(false), + _isStroke(false), + _isLive(false), + _linkIsTone(false), + _linkPercent(0), + _linkGray(0), + _linkSrc(0), + _grad(0), + _pattern(0) { - set_allocation(allocation); - if (m_refGdkWindow) - { - m_refGdkWindow->move_resize( allocation.get_x(), allocation.get_y(), allocation.get_width(), allocation.get_height() ); +} + +ColorItem::~ColorItem() +{ + if (_pattern != NULL) { + cairo_pattern_destroy(_pattern); + } +} + +ColorItem::ColorItem(ColorItem const &other) : + Inkscape::UI::Previewable() +{ + if ( this != &other ) { + *this = other; + } +} + +ColorItem &ColorItem::operator=(ColorItem const &other) +{ + if ( this != &other ) { + def = other.def; + + // TODO - correct linkage + _linkSrc = other._linkSrc; + g_message("Erk!"); + } + return *this; +} + +void ColorItem::setState( bool fill, bool stroke ) +{ + if ( (_isFill != fill) || (_isStroke != stroke) ) { + _isFill = fill; + _isStroke = stroke; + + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + EekPreview * preview = EEK_PREVIEW(widget->gobj()); + + int val = eek_preview_get_linked( preview ); + val &= ~(PREVIEW_FILL | PREVIEW_STROKE); + if ( _isFill ) { + val |= PREVIEW_FILL; + } + if ( _isStroke ) { + val |= PREVIEW_STROKE; + } + eek_preview_set_linked( preview, static_cast(val) ); + } + } + } +} + +void ColorItem::setGradient(SPGradient *grad) +{ + if (_grad != grad) { + _grad = grad; + // TODO regen and push to listeners } + + setName( gr_prepare_label(_grad) ); } -void ColorItem::on_map() +void ColorItem::setName(const Glib::ustring name) { - Gtk::Widget::on_map(); + //def.descr = name; + + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + gtk_widget_set_tooltip_text(GTK_WIDGET(widget->gobj()), name.c_str()); + } + else if ( GTK_IS_LABEL(widget->gobj()) ) { + gtk_label_set_text(GTK_LABEL(widget->gobj()), name.c_str()); + } + } } -void ColorItem::on_unmap() +void ColorItem::setPattern(cairo_pattern_t *pattern) { - Gtk::Widget::on_unmap(); + if (pattern) { + cairo_pattern_reference(pattern); + } + if (_pattern) { + cairo_pattern_destroy(_pattern); + } + _pattern = pattern; + + _updatePreviews(); } -void ColorItem::on_realize() +void ColorItem::_dragGetColorData( GtkWidget */*widget*/, + GdkDragContext */*drag_context*/, + GtkSelectionData *data, + guint info, + guint /*time*/, + gpointer user_data) +{ + ColorItem* item = reinterpret_cast(user_data); + std::string key; + if ( info < mimeStrings.size() ) { + key = mimeStrings[info]; + } else { + g_warning("ERROR: unknown value (%d)", info); + } + + if ( !key.empty() ) { + char* tmp = 0; + int len = 0; + int format = 0; + item->def.getMIMEData(key, tmp, len, format); + if ( tmp ) { + GdkAtom dataAtom = gdk_atom_intern( key.c_str(), FALSE ); + gtk_selection_data_set( data, dataAtom, format, (guchar*)tmp, len ); + delete[] tmp; + } + } +} + +void ColorItem::_dropDataIn( GtkWidget */*widget*/, + GdkDragContext */*drag_context*/, + gint /*x*/, gint /*y*/, + GtkSelectionData */*data*/, + guint /*info*/, + guint /*event_time*/, + gpointer /*user_data*/) { - set_realized(); - ensure_style(); - - if(!m_refGdkWindow) - { - //Create the GdkWindow: - - GdkWindowAttr attributes; - memset(&attributes, 0, sizeof(attributes)); - - Gtk::Allocation allocation = get_allocation(); - - //Set initial position and size of the Gdk::Window: - attributes.x = allocation.get_x(); - attributes.y = allocation.get_y(); - attributes.width = allocation.get_width(); - attributes.height = allocation.get_height(); - - attributes.event_mask = get_events () | Gdk::EXPOSURE_MASK; - attributes.window_type = GDK_WINDOW_CHILD; - attributes.wclass = GDK_INPUT_OUTPUT; - - m_refGdkWindow = Gdk::Window::create(get_parent_window(), &attributes, - GDK_WA_X | GDK_WA_Y); - set_window(m_refGdkWindow); - - //Attach this widget's style to its Gdk::Window. - style_attach(); - - //make the widget receive expose events - m_refGdkWindow->set_user_data(gobj()); - } } -void ColorItem::on_unrealize() +void ColorItem::_colorDefChanged(void* data) { - m_refGdkWindow.reset(); - - Gtk::Widget::on_unrealize(); + ColorItem* item = reinterpret_cast(data); + if ( item ) { + item->_updatePreviews(); + } } -bool ColorItem::on_expose_event(GdkEventExpose* event) +void ColorItem::_updatePreviews() { - if(m_refGdkWindow) + for ( std::vector::iterator it = _previews.begin(); it != _previews.end(); ++it ) { + Gtk::Widget* widget = *it; + if ( IS_EEK_PREVIEW(widget->gobj()) ) { + EekPreview * preview = EEK_PREVIEW(widget->gobj()); + + _regenPreview(preview); + + widget->queue_draw(); + } + } + + for ( std::vector::iterator it = _listeners.begin(); it != _listeners.end(); ++it ) { + guint r = def.getR(); + guint g = def.getG(); + guint b = def.getB(); + + if ( (*it)->_linkIsTone ) { + r = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * r) ) / 100; + g = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * g) ) / 100; + b = ( ((*it)->_linkPercent * (*it)->_linkGray) + ((100 - (*it)->_linkPercent) * b) ) / 100; + } else { + r = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * r) ) / 100; + g = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * g) ) / 100; + b = ( ((*it)->_linkPercent * 255) + ((100 - (*it)->_linkPercent) * b) ) / 100; + } + + (*it)->def.setRGB( r, g, b ); + } + + +#if ENABLE_MAGIC_COLORS + // Look for objects using this color { - Cairo::RefPtr cr = m_refGdkWindow->create_cairo_context(); - if(event) + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if ( desktop ) { + SPDocument* document = sp_desktop_document( desktop ); + Inkscape::XML::Node *rroot = document->getReprRoot(); + if ( rroot ) { + + // Find where this thing came from + Glib::ustring paletteName; + bool found = false; + int index = 0; + for ( std::vector::iterator it2 = possible.begin(); it2 != possible.end() && !found; ++it2 ) { + SwatchPage* curr = *it2; + index = 0; + for ( boost::ptr_vector::iterator zz = curr->_colors.begin(); zz != curr->_colors.end(); ++zz ) { + if ( this == &*zz ) { + found = true; + paletteName = curr->_name; + break; + } else { + index++; + } + } + } + + if ( !paletteName.empty() ) { + gchar* str = g_strdup_printf("%d|", index); + paletteName.insert( 0, str ); + g_free(str); + str = 0; + + if ( bruteForce( document, rroot, paletteName, def.getR(), def.getG(), def.getB() ) ) { + SPDocumentUndo::done( document , SP_VERB_DIALOG_SWATCHES, + _("Change color definition")); + } + } + } + } + } +#endif // ENABLE_MAGIC_COLORS + +} + +void ColorItem::_regenPreview(EekPreview * preview) +{ + if ( def.getType() != ege::PaintDef::RGB ) { + using Inkscape::IO::Resource::get_path; + using Inkscape::IO::Resource::ICONS; + using Inkscape::IO::Resource::SYSTEM; + GError *error = NULL; + gsize bytesRead = 0; + gsize bytesWritten = 0; + gchar *localFilename = g_filename_from_utf8( get_path(SYSTEM, ICONS, "remove-color.png"), + -1, + &bytesRead, + &bytesWritten, + &error); + GdkPixbuf* pixbuf = gdk_pixbuf_new_from_file(localFilename, &error); + if (!pixbuf) { + g_warning("Null pixbuf for %p [%s]", localFilename, localFilename ); + } + g_free(localFilename); + + eek_preview_set_pixbuf( preview, pixbuf ); + } + else if ( !_pattern ){ + eek_preview_set_color( preview, + (def.getR() << 8) | def.getR(), + (def.getG() << 8) | def.getG(), + (def.getB() << 8) | def.getB() ); + } else { + // These correspond to PREVIEW_PIXBUF_WIDTH and VBLOCK from swatches.cpp + // TODO: the pattern to draw should be in the widget that draws the preview, + // so the preview can be scalable + int w = 128; + int h = 16; + + cairo_surface_t *s = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, w, h); + cairo_t *ct = cairo_create(s); + cairo_set_source(ct, _pattern); + cairo_paint(ct); + cairo_destroy(ct); + cairo_surface_flush(s); + + GdkPixbuf* pixbuf = ink_pixbuf_create_from_cairo_surface(s); + eek_preview_set_pixbuf( preview, pixbuf ); + } + + eek_preview_set_linked( preview, (LinkType)((_linkSrc ? PREVIEW_LINK_IN:0) + | (_listeners.empty() ? 0:PREVIEW_LINK_OUT) + | (_isLive ? PREVIEW_LINK_OTHER:0)) ); +} + +Gtk::Widget* ColorItem::getPreview(PreviewStyle style, ViewType view, ::PreviewSize size, guint ratio, guint border) +{ + Gtk::Widget* widget = 0; + if ( style == PREVIEW_STYLE_BLURB) { + Gtk::Label *lbl = new Gtk::Label(def.descr); + lbl->set_alignment(Gtk::ALIGN_START, Gtk::ALIGN_CENTER); + widget = lbl; + } else { + GtkWidget* eekWidget = eek_preview_new(); + EekPreview * preview = EEK_PREVIEW(eekWidget); + Gtk::Widget* newBlot = Glib::wrap(eekWidget); + _regenPreview(preview); + + eek_preview_set_details( preview, + (::ViewType)view, + (::PreviewSize)size, + ratio, + border ); + + def.addCallback( _colorDefChanged, this ); + eek_preview_set_focus_on_click(preview, FALSE); + newBlot->set_tooltip_text(def.descr); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "clicked", + G_CALLBACK(handleClick), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "alt-clicked", + G_CALLBACK(handleSecondaryClick), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "button-press-event", + G_CALLBACK(colorItemHandleButtonPress), + this); + { - // clip to the area that needs to be re-exposed so we don't draw any - // more than we need to. - cr->rectangle(event->area.x, event->area.y, event->area.width, event->area.height); - cr->clip(); + std::vector listing = def.getMIMETypes(); + int entryCount = listing.size(); + GtkTargetEntry* entries = new GtkTargetEntry[entryCount]; + GtkTargetEntry* curr = entries; + for ( std::vector::iterator it = listing.begin(); it != listing.end(); ++it ) { + curr->target = g_strdup(it->c_str()); + curr->flags = 0; + if ( mimeToInt.find(*it) == mimeToInt.end() ){ + // these next lines are order-dependent: + mimeToInt[*it] = mimeStrings.size(); + mimeStrings.push_back(*it); + } + curr->info = mimeToInt[curr->target]; + curr++; + } + gtk_drag_source_set( GTK_WIDGET(newBlot->gobj()), + GDK_BUTTON1_MASK, + entries, entryCount, + GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY) ); + for ( int i = 0; i < entryCount; i++ ) { + g_free(entries[i].target); + } + delete[] entries; } - if (gradient) { - cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); - - Cairo::RefPtr checkpat(new Cairo::Pattern(check)); - - cr->set_source(checkpat); - cr->paint(); - - cairo_pattern_t *g = sp_gradient_create_preview_pattern(gradient, get_allocation().get_width()); - Cairo::RefPtr gpat(new Cairo::Pattern(g)); - cr->set_source(gpat); - cr->paint(); - gpat.clear(); - cairo_pattern_destroy(g); - - checkpat.clear(); - - cairo_pattern_destroy(check); - - if (_isSelected) { - cr->set_source_rgb(0, 0, 0); - cr->set_line_width(3); - cr->move_to(0, get_allocation().get_height()); - cr->line_to(0,0); - cr->line_to(get_allocation().get_width(), 0); - cr->stroke(); - cr->move_to(get_allocation().get_width(), 0); - cr->set_source_rgb(1, 1, 1); - cr->line_to(get_allocation().get_width(), get_allocation().get_height()); - cr->line_to(0, get_allocation().get_height()); - //cr->rectangle(0, 0, get_allocation().get_width(), get_allocation().get_height()); - cr->stroke(); + g_signal_connect( G_OBJECT(newBlot->gobj()), + "drag-data-get", + G_CALLBACK(ColorItem::_dragGetColorData), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "drag-begin", + G_CALLBACK(colorItemDragBegin), + this ); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "enter-notify-event", + G_CALLBACK(handleEnterNotify), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "leave-notify-event", + G_CALLBACK(handleLeaveNotify), + this); + + g_signal_connect( G_OBJECT(newBlot->gobj()), + "destroy", + G_CALLBACK(dieDieDie), + this); + + + widget = newBlot; + } + + _previews.push_back( widget ); + + return widget; +} + +void ColorItem::buttonClicked(bool secondary) +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (desktop) { + char const * attrName = secondary ? "stroke" : "fill"; + + SPCSSAttr *css = sp_repr_css_attr_new(); + Glib::ustring descr; + switch (def.getType()) { + case ege::PaintDef::CLEAR: { + // TODO actually make this clear + sp_repr_css_set_property( css, attrName, "none" ); + descr = secondary? _("Remove stroke color") : _("Remove fill color"); + break; + } + case ege::PaintDef::NONE: { + sp_repr_css_set_property( css, attrName, "none" ); + descr = secondary? _("Set stroke color to none") : _("Set fill color to none"); + break; + } +//mark + case ege::PaintDef::RGB: { + Glib::ustring colorspec; + if ( _grad ){ + colorspec = "url(#"; + colorspec += _grad->getId(); + colorspec += ")"; + } else { + gchar c[64]; + guint32 rgba = (def.getR() << 24) | (def.getG() << 16) | (def.getB() << 8) | 0xff; + sp_svg_write_color(c, sizeof(c), rgba); + colorspec = c; + } +//end mark + sp_repr_css_set_property( css, attrName, colorspec.c_str() ); + descr = secondary? _("Set stroke color from swatch") : _("Set fill color from swatch"); + break; } - } else { - cr->set_source_rgb(1, 1, 1); - cr->paint(); - cr->set_source_rgb(1, 0, 0); - cr->set_line_width(3); - cr->move_to(0,0); - cr->line_to(get_allocation().get_width(), get_allocation().get_height()); - cr->move_to(get_allocation().get_width(), 0); - cr->line_to(0, get_allocation().get_height()); - cr->stroke(); } + sp_desktop_set_style(desktop, css); + sp_repr_css_attr_unref(css); + + DocumentUndo::done( sp_desktop_document(desktop), SP_VERB_DIALOG_SWATCHES, descr.c_str() ); } - return true; } -ColorItem::~ColorItem() +void ColorItem::_wireMagicColors( SwatchPage *colorSet ) +{ + if ( colorSet ) + { + for ( boost::ptr_vector::iterator it = colorSet->_colors.begin(); it != colorSet->_colors.end(); ++it ) + { + std::string::size_type pos = it->def.descr.find("*{"); + if ( pos != std::string::npos ) + { + std::string subby = it->def.descr.substr( pos + 2 ); + std::string::size_type endPos = subby.find("}*"); + if ( endPos != std::string::npos ) + { + subby.erase( endPos ); + //g_message("FOUND MAGIC at '%s'", (*it)->def.descr.c_str()); + //g_message(" '%s'", subby.c_str()); + + if ( subby.find('E') != std::string::npos ) + { + it->def.setEditable( true ); + } + + if ( subby.find('L') != std::string::npos ) + { + it->_isLive = true; + } + + std::string part; + // Tint. index + 1 more val. + if ( getBlock( part, 'T', subby ) ) { + guint64 colorIndex = 0; + if ( popVal( colorIndex, part ) ) { + guint64 percent = 0; + if ( popVal( percent, part ) ) { + it->_linkTint( colorSet->_colors[colorIndex], percent ); + } + } + } + + // Shade/tone. index + 1 or 2 more val. + if ( getBlock( part, 'S', subby ) ) { + guint64 colorIndex = 0; + if ( popVal( colorIndex, part ) ) { + guint64 percent = 0; + if ( popVal( percent, part ) ) { + guint64 grayLevel = 0; + if ( !popVal( grayLevel, part ) ) { + grayLevel = 0; + } + it->_linkTone( colorSet->_colors[colorIndex], percent, grayLevel ); + } + } + } + + } + } + } + } +} + + +void ColorItem::_linkTint( ColorItem& other, int percent ) +{ + if ( !_linkSrc ) + { + other._listeners.push_back(this); + _linkIsTone = false; + _linkPercent = percent; + if ( _linkPercent > 100 ) + _linkPercent = 100; + if ( _linkPercent < 0 ) + _linkPercent = 0; + _linkGray = 0; + _linkSrc = &other; + + ColorItem::_colorDefChanged(&other); + } +} + +void ColorItem::_linkTone( ColorItem& other, int percent, int grayLevel ) { - sel_connection.disconnect(); - mod_connection.disconnect(); + if ( !_linkSrc ) + { + other._listeners.push_back(this); + _linkIsTone = true; + _linkPercent = percent; + if ( _linkPercent > 100 ) + _linkPercent = 100; + if ( _linkPercent < 0 ) + _linkPercent = 0; + _linkGray = grayLevel; + _linkSrc = &other; + + ColorItem::_colorDefChanged(&other); + } } } // namespace Dialogs diff --git a/src/ui/dialog/color-item.h b/src/ui/dialog/color-item.h index 5d97d8803..3a0b33193 100644 --- a/src/ui/dialog/color-item.h +++ b/src/ui/dialog/color-item.h @@ -15,11 +15,7 @@ #include #include "widgets/ege-paint-def.h" -#include "widgets/eek-preview.h" -#include -#include -#include "desktop.h" -#include "selection.h" +#include "ui/previewable.h" class SPGradient; @@ -27,43 +23,89 @@ namespace Inkscape { namespace UI { namespace Dialogs { +class ColorItem; + +class SwatchPage +{ +public: + SwatchPage(); + ~SwatchPage(); + + Glib::ustring _name; + int _prefWidth; + boost::ptr_vector _colors; +}; + /** * The color swatch you see on screen as a clickable box. */ -class ColorItem : public Gtk::Widget +class ColorItem : public Inkscape::UI::Previewable { + friend void _loadPaletteFile( gchar const *filename ); public: - ColorItem( SPGradient * grad, const gchar* name, SPDesktop* desktop ); + ColorItem( ege::PaintDef::ColorType type ); + ColorItem( unsigned int r, unsigned int g, unsigned int b, + Glib::ustring& name ); virtual ~ColorItem(); - - SPGradient * getGradient() { return gradient; } - -protected: - - const gchar* def; - SPGradient * gradient; - virtual bool on_enter_notify_event(GdkEventCrossing* event); - virtual bool on_leave_notify_event(GdkEventCrossing* event); - - virtual void on_size_request(Gtk::Requisition* requisition); - virtual void on_size_allocate(Gtk::Allocation& allocation); - virtual void on_map(); - virtual void on_unmap(); - virtual void on_realize(); - virtual void on_unrealize(); - virtual bool on_expose_event(GdkEventExpose* event); - - Glib::RefPtr m_refGdkWindow; - - + ColorItem(ColorItem const &other); + virtual ColorItem &operator=(ColorItem const &other); + virtual Gtk::Widget* getPreview(PreviewStyle style, + ViewType view, + ::PreviewSize size, + guint ratio, + guint border); + void buttonClicked(bool secondary = false); + + void setGradient(SPGradient *grad); + SPGradient * getGradient() const { return _grad; } + void setPattern(cairo_pattern_t *pattern); + void setName(const Glib::ustring name); + + void setState( bool fill, bool stroke ); + bool isFill() { return _isFill; } + bool isStroke() { return _isStroke; } + + ege::PaintDef def; + private: - void selection_changed(Selection* selection); - void selection_modified(Selection* selection, guint flags); - sigc::connection sel_connection; - sigc::connection mod_connection; - bool _isSelected; + static void _dropDataIn( GtkWidget *widget, + GdkDragContext *drag_context, + gint x, gint y, + GtkSelectionData *data, + guint info, + guint event_time, + gpointer user_data); + + static void _dragGetColorData( GtkWidget *widget, + GdkDragContext *drag_context, + GtkSelectionData *data, + guint info, + guint time, + gpointer user_data); + + static void _wireMagicColors( SwatchPage *colorSet ); + static void _colorDefChanged(void* data); + + void _updatePreviews(); + void _regenPreview(EekPreview * preview); + + void _linkTint( ColorItem& other, int percent ); + void _linkTone( ColorItem& other, int percent, int grayLevel ); + + std::vector _previews; + + bool _isFill; + bool _isStroke; + bool _isLive; + bool _linkIsTone; + int _linkPercent; + int _linkGray; + ColorItem* _linkSrc; + SPGradient* _grad; + cairo_pattern_t *_pattern; + std::vector _listeners; }; } // namespace Dialogs diff --git a/src/ui/dialog/object-properties.cpp b/src/ui/dialog/object-properties.cpp index 82b2cf6b1..8f36cba43 100644 --- a/src/ui/dialog/object-properties.cpp +++ b/src/ui/dialog/object-properties.cpp @@ -467,6 +467,7 @@ void ObjectProperties::label_changed(void) blocked = true; /* Retrieve the label widget for the object's id */ + //bug 1290573: getId() crashes after undo (cannot create string from NULL ptr) gchar *id = g_strdup(EntryID.get_text().c_str()); g_strcanon (id, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.:", '_'); if (!strcmp (id, item->getId())) { diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index ebfa16f02..2095546fb 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -3,6 +3,7 @@ * * Authors: * Theodore Janeczko + * Tweaked by Liam P White for use in Inkscape * * Copyright (C) Theodore Janeczko 2012 * @@ -17,20 +18,31 @@ #include #include #include +#include #include #include "desktop.h" #include "desktop-style.h" +#include "dialogs/dialog-events.h" #include "document.h" #include "document-undo.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" #include "helper/action.h" #include "inkscape.h" +#include "layer-manager.h" #include "preferences.h" +#include "selection.h" +#include "sp-clippath.h" +#include "sp-mask.h" #include "sp-item.h" #include "sp-object.h" +#include "sp-root.h" #include "sp-shape.h" -#include "svg/css-ostringstream.h" +#include "style.h" +#include "tools-switch.h" #include "ui/icon-names.h" #include "ui/widget/imagetoggler.h" #include "ui/widget/layertypeicon.h" @@ -38,29 +50,16 @@ #include "ui/widget/clipmaskicon.h" #include "ui/widget/highlight-picker.h" #include "ui/tools/node-tool.h" +#include "ui/tools/tool-base.h" #include "verbs.h" +#include "widgets/sp-color-notebook.h" #include "widgets/icon.h" #include "xml/node.h" #include "xml/node-observer.h" #include "xml/repr.h" -#include "sp-root.h" -//#include "event-context.h" -#include "selection.h" -#include "dialogs/dialog-events.h" -#include "widgets/sp-color-notebook.h" -#include "style.h" -#include "filter-chemistry.h" -#include "filters/blend.h" -#include "filters/gaussian-blur.h" -#include "sp-clippath.h" -#include "sp-mask.h" -#include "layer-manager.h" -#include "tools-switch.h" //#define DUMP_LAYERS 1 -guint get_group0_keyval(GdkEventKey *event); - namespace Inkscape { namespace UI { namespace Dialog { @@ -82,7 +81,7 @@ enum { COL_VISIBLE = 1, COL_LOCKED, COL_TYPE, - COL_INSERTORDER, +// COL_INSERTORDER, COL_CLIPMASK, COL_HIGHLIGHT }; @@ -106,8 +105,8 @@ enum { BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, BUTTON_SETCLIP, - BUTTON_CLIPGROUP, - BUTTON_SETINVCLIP, +// BUTTON_CLIPGROUP, +// BUTTON_SETINVCLIP, BUTTON_UNSETCLIP, BUTTON_SETMASK, BUTTON_UNSETMASK, @@ -214,7 +213,7 @@ public: add(_colType); add(_colHighlight); add(_colClipMask); - add(_colInsertOrder); + //add(_colInsertOrder); } virtual ~ModelColumns() {} @@ -225,7 +224,7 @@ public: Gtk::TreeModelColumn _colType; Gtk::TreeModelColumn _colHighlight; Gtk::TreeModelColumn _colClipMask; - Gtk::TreeModelColumn _colInsertOrder; + //Gtk::TreeModelColumn _colInsertOrder; }; /** @@ -352,13 +351,19 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); Gtk::TreeModel::Row row = *iter; row[_model->_colObject] = item; - row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + //this seems to crash on convert stroke to path then undo (probably no ID?) + try { + row[_model->_colLabel] = item->label() ? item->label() : item->getId(); + } catch (...) { + row[_model->_colLabel] = Glib::ustring("getId_failure"); + g_critical("item->getId() failed, using \"getId_failure\""); + } row[_model->_colVisible] = !item->isHidden(); row[_model->_colLocked] = !item->isSensitive(); row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00; row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0); - row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; //If our parent object is a group and it's expanded, expand the tree if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded()) @@ -388,7 +393,10 @@ void ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow) */ void ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) { //Find the object in the tree store and update it + + //mark _store->foreach_iter( sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) ); + //end mark if (recurse) { for (SPObject * iter = obj->children; iter != NULL; iter = iter->next) @@ -419,7 +427,7 @@ bool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj) row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0; row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0; row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0; - row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; + //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0; return true; } @@ -685,7 +693,9 @@ void ObjectsPanel::_setLockedIter( const Gtk::TreeModel::iterator& iter, const b bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) { - switch (get_group0_keyval(event)) { + bool empty = _desktop->selection->isEmpty(); + + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { case GDK_KEY_Return: case GDK_KEY_KP_Enter: case GDK_KEY_F2: @@ -702,68 +712,33 @@ bool ObjectsPanel::_handleKeyEvent(GdkEventKey *event) } break; case GDK_Home: - { //Move item(s) to top of containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_TOP ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_FRONT ); - } - return true; - } + _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT ); + break; case GDK_End: - { //Move item(s) to bottom of containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_TO_BOTTOM ); - } - else - { - _fireAction( SP_VERB_SELECTION_TO_BACK ); - } - return true; - } + _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK ); + break; case GDK_KEY_Page_Up: { //Move item(s) up in containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_RAISE ); - } - else - { - if (event->state & GDK_SHIFT_MASK) { - _fireAction( SP_VERB_LAYER_MOVE_TO_NEXT ); - } else { - _fireAction( SP_VERB_SELECTION_RAISE ); - } - } - return true; + int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_NEXT : SP_VERB_SELECTION_RAISE; + _fireAction( empty ? SP_VERB_LAYER_RAISE : ch ); + break; } case GDK_KEY_Page_Down: { //Move item(s) down in containing group/layer - if (_desktop->selection->isEmpty()) - { - _fireAction( SP_VERB_LAYER_LOWER ); - } - else - { - if (event->state & GDK_SHIFT_MASK) { - _fireAction( SP_VERB_LAYER_MOVE_TO_PREV ); - } else { - _fireAction( SP_VERB_SELECTION_LOWER ); - } - } - return true; + int ch = event->state & GDK_SHIFT_MASK ? SP_VERB_LAYER_MOVE_TO_PREV : SP_VERB_SELECTION_LOWER; + _fireAction( empty ? SP_VERB_LAYER_LOWER : ch ); + break; } + //TODO: Handle Ctrl-A, etc. + default: + return false; } - return false; + return true; } /** @@ -809,7 +784,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) return true; } else if (col == _tree.get_column(COL_LOCKED-1) || col == _tree.get_column(COL_TYPE-1) || - col == _tree.get_column(COL_INSERTORDER - 1) || + //col == _tree.get_column(COL_INSERTORDER - 1) || col == _tree.get_column(COL_HIGHLIGHT-1)) { //Click on an icon column, eat this event to keep row selection return true; @@ -926,7 +901,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, newValue? _("Layer to group") : _("Group to layer")); } - } else if (col == _tree.get_column(COL_INSERTORDER - 1)) { + } /*else if (col == _tree.get_column(COL_INSERTORDER - 1)) { if (SP_IS_GROUP(item)) { //Toggle the current item's insert order @@ -938,7 +913,7 @@ bool ObjectsPanel::_handleButtonEvent(GdkEventButton* event) DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_OBJECTS, newValue? _("Set insert mode bottom") : _("Set insert mode top")); } - } else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { + }*/ else if (col == _tree.get_column(COL_HIGHLIGHT - 1)) { //Clear the highlight targets _highlight_target.clear(); if (_tree.get_selection()->is_selected(path)) @@ -1474,7 +1449,7 @@ void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) target->setHighlightColor(rgba); target->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); } - DocumentUndo::done(SP_ACTIVE_DOCUMENT, SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); + DocumentUndo::maybeDone(SP_ACTIVE_DOCUMENT, "highlight", SP_VERB_DIALOG_OBJECTS, _("Set object highlight color")); } /** @@ -1689,13 +1664,13 @@ ObjectsPanel::ObjectsPanel() : col->add_attribute( typeRenderer->property_active(), _model->_colType ); } - //Insert order - Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); + //Insert order (LiamW: unused) + /*Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon()); int insertColNum = _tree.append_column("type", *insertRenderer) - 1; col = _tree.get_column(insertColNum); if ( col ) { col->add_attribute( insertRenderer->property_active(), _model->_colInsertOrder ); - } + }*/ //Clip/mask Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon()); @@ -1807,43 +1782,102 @@ ObjectsPanel::ObjectsPanel() : SPDesktop* targetDesktop = getDesktop(); //Set up the button row + + + //Add object/layer Gtk::Button* btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_ADD, _("New Layer") ); + btn->set_tooltip_text(_("Add layer...")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + Gtk::Image *image_add = Gtk::manage(new Gtk::Image()); + image_add->set_from_icon_name(INKSCAPE_ICON("list-add"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_add); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) ); _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + //Remove object btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_REMOVE, _("Remove") ); + btn->set_tooltip_text(_("Remove object")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + Gtk::Image *image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("list-remove"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) ); _watching.push_back( btn ); _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + //Move to bottom btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GOTO_BOTTOM, _("Move To Bottom") ); + btn->set_tooltip_text(_("Move To Bottom")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-bottom"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); - + + //Move down btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GO_DOWN, _("Move Down") ); + btn->set_tooltip_text(_("Move Down")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-down"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + //Move up btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GO_UP, _("Move Up") ); + btn->set_tooltip_text(_("Move Up")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-up"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) ); _watchingNonTop.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); + //Move to top btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_GOTO_TOP, _("Move To Top") ); + btn->set_tooltip_text(_("Move To Top")); +#if GTK_CHECK_VERSION(3,10,0) + btn->set_image_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR); +#else + image_remove = Gtk::manage(new Gtk::Image()); + image_remove->set_from_icon_name(INKSCAPE_ICON("go-top"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image(*image_remove); +#endif + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) ); _watchingNonTop.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); - btn = Gtk::manage( new Gtk::Button() ); - _styleButton( *btn, GTK_STOCK_UNINDENT, _("Collapse All") ); + //Collapse all + btn = Gtk::manage( new Gtk::Button(Gtk::Stock::UNINDENT) ); + btn->set_tooltip_text(_("Collapse All")); + btn->set_relief(Gtk::RELIEF_NONE); btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) ); _watchingNonBottom.push_back( btn ); _buttonsPrimary.pack_end(*btn, Gtk::PACK_SHRINK); @@ -2042,15 +2076,6 @@ void ObjectsPanel::setDesktop( SPDesktop* desktop ) //should be okay to put these here because they are never referenced anywhere else using namespace Inkscape::UI::Tools; -guint get_group0_keyval(GdkEventKey *event) { - guint keyval = 0; - gdk_keymap_translate_keyboard_state(gdk_keymap_get_for_display( - gdk_display_get_default()), event->hardware_keycode, - (GdkModifierType) event->state, 0 /*event->key.group*/, &keyval, - NULL, NULL, NULL); - return keyval; -} - void SPItem::setHighlightColor(guint32 const color) { g_free(_highlightColor); @@ -2065,7 +2090,7 @@ void SPItem::setHighlightColor(guint32 const color) NodeTool *tool = 0; if (SP_ACTIVE_DESKTOP ) { - ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; if (INK_IS_NODE_TOOL(ec)) { tool = static_cast(ec); tools_switch(tool->desktop, TOOLS_NODES); @@ -2079,7 +2104,7 @@ void SPItem::unsetHighlightColor() _highlightColor = NULL; NodeTool *tool = 0; if (SP_ACTIVE_DESKTOP ) { - ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; + Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context; if (INK_IS_NODE_TOOL(ec)) { tool = static_cast(ec); tools_switch(tool->desktop, TOOLS_NODES); diff --git a/src/ui/dialog/swatches.cpp b/src/ui/dialog/swatches.cpp index 2a8471b55..807618b4d 100644 --- a/src/ui/dialog/swatches.cpp +++ b/src/ui/dialog/swatches.cpp @@ -6,7 +6,6 @@ * Jon A. Cruz * John Bintz * Abhishek Sharma - * Theodore Janezcko * * Copyright (C) 2005 Jon A. Cruz * Copyright (C) 2008 John Bintz @@ -21,7 +20,6 @@ #include "swatches.h" #include -#include #include #include @@ -47,6 +45,7 @@ #include "sp-gradient.h" #include "sp-gradient-vector.h" #include "style.h" +#include "ui/previewholder.h" #include "widgets/desktop-widget.h" #include "widgets/gradient-vector.h" #include "widgets/eek-preview.h" @@ -57,2305 +56,1130 @@ #include "verbs.h" #include "gradient-chemistry.h" #include "helper/action.h" -#include "xml/node-observer.h" -#include "xml/repr.h" -#include "sp-pattern.h" -#include "icon-size.h" -#include "widgets/icon.h" -#include "filedialog.h" -#include "sp-stop.h" -#include "svg/svg-color.h" -#include "sp-radial-gradient.h" -#include "color-rgba.h" -#include "ui/tools/tool-base.h" -#include "svg/css-ostringstream.h" -#include -#ifdef WIN32 -#include -#endif - -//lazy! -void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill); +#include "helper/action-context.h" namespace Inkscape { namespace UI { namespace Dialogs { -#define SWATCHES_FILE_NAME "swatches.svg" - -static char* trim( char* str ) { - char* ret = str; - while ( *str && (*str == ' ' || *str == '\t') ) { - str++; - } - ret = str; - while ( *str ) { - str++; - } - str--; - while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { - *str-- = 0; - } - return ret; -} - -static void skipWhitespace( char*& str ) { - while ( *str == ' ' || *str == '\t' ) { - str++; - } -} - -static bool parseNum( char*& str, int& val ) { - val = 0; - while ( '0' <= *str && *str <= '9' ) { - val = val * 10 + (*str - '0'); - str++; - } - bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); - return retval; -} - -static char * SwatchFile; -static SPDocument * SwatchDocument; -static unsigned int page_suffix; - -static void loadPalletFile() -{ - if (!SwatchDocument) { - SwatchFile=g_build_filename(INKSCAPE_PALETTESDIR, _("swatches.svg"), NULL); - SwatchDocument=SPDocument::createNewDoc (SwatchFile, TRUE); - if (!SwatchDocument) { - SwatchDocument = SPDocument::createNewDoc(NULL, TRUE, true); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - } -} - -static void addStop( Inkscape::XML::Node *parent, Glib::ustring const &color, gfloat opacity, gchar const *offset ) -{ -#ifdef SP_GR_VERBOSE - g_message("addStop(%p, %s, %d, %s)", parent, color.c_str(), opacity, offset); -#endif - Inkscape::XML::Node *stop = parent->document()->createElement("svg:stop"); - { - gchar *tmp = g_strdup_printf( "stop-color:%s;stop-opacity:%f;", color.c_str(), opacity < 0.0 ? 0.0 : (opacity > 1.0 ? 1.0 : opacity) ); - stop->setAttribute( "style", tmp ); - g_free(tmp); - } - - stop->setAttribute( "offset", offset ); - - parent->appendChild(stop); - Inkscape::GC::release(stop); -} - -static SPGroup* importGPL(SPDocument* doc, const gchar* full) -{ - SPGroup* ret = NULL; - if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { - - /*Load the pallet file here*/ - char block[1024]; - FILE *f = Inkscape::IO::fopen_utf8name( full, "r" ); - if ( f ) { - char* result = fgets( block, sizeof(block), f ); - if ( result ) { - if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { - bool inHeader = true; - bool hasErr = false; - - Inkscape::XML::Node * page = doc->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (doc->getObjectById(id)); - - page->setAttribute("id", id); - - do { - result = fgets( block, sizeof(block), f ); - block[sizeof(block) - 1] = 0; - if ( result ) { - if ( block[0] == '#' ) { - // ignore comment - } else { - char *ptr = block; - // very simple check for header versus entry - while ( *ptr == ' ' || *ptr == '\t' ) { - ptr++; - } - if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { - // blank line. skip it. - } else if ( '0' <= *ptr && *ptr <= '9' ) { - // should be an entry link - inHeader = false; - ptr = block; - Glib::ustring name(""); - skipWhitespace(ptr); - if ( *ptr ) { - int r = 0; - int g = 0; - int b = 0; - hasErr = parseNum(ptr, r); - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, g); - } - if ( !hasErr ) { - skipWhitespace(ptr); - hasErr = parseNum(ptr, b); - } - if ( !hasErr && *ptr ) { - char* n = trim(ptr); - if (n != NULL) { - name = g_dpgettext2(NULL, "Palette", n); - } - } - if ( !hasErr ) { - // Add the entry now - - Inkscape::XML::Node *grad = doc->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute("inkscape:label", name.c_str()); - grad->setAttribute( "osb:paint", "solid", 0 ); - SPColor color((float)r / 255, (float)g / 255, (float)b / 255); - addStop(grad, color.toString(), 1, "0"); - page->appendChild(grad); - Inkscape::GC::release(grad); - } - } else { - hasErr = true; - } - } else { - if ( !inHeader ) { - // Hmmm... probably bad. Not quite the format we want? - hasErr = true; - } else { - char* sep = strchr(result, ':'); - if ( sep ) { - *sep = 0; - char* val = trim(sep + 1); - char* name = trim(result); - if ( *name ) { - if ( strcmp( "Name", name ) == 0 ) - { - page->setAttribute("inkscape:label", val); - } - } else { - // error - hasErr = true; - } - } else { - // error - hasErr = true; - } - } - } - } - } - } while ( result && !hasErr ); - if ( !hasErr ) { - doc->getDefs()->appendChild(page); - Inkscape::GC::release(page); - SPObject* obj = doc->getObjectByRepr(page); - if (SP_IS_GROUP(obj)) { - ret = SP_GROUP(obj); - } - #if ENABLE_MAGIC_COLORS - ColorItem::_wireMagicColors( onceMore ); - #endif // ENABLE_MAGIC_COLORS - } else { - delete page; - } - } - } - - fclose(f); - } - /* end loading the pallet file*/ - } - return ret; -} - -SwatchesPanel& SwatchesPanel::getInstance() -{ - return *new SwatchesPanel(); -} - -class SwatchesPanel::StopWatcher : public Inkscape::XML::NodeObserver { -public: - StopWatcher(SwatchesPanel* pnl, SPStop* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()) - { - _repr->addObserver(*this); - } - - ~StopWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ){} - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ){} - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj) { - _pnl->_defsChanged( ); - } - } +#define VBLOCK 16 +#define PREVIEW_PIXBUF_WIDTH 128 - SwatchesPanel* _pnl; - SPStop* _obj; - Inkscape::XML::Node* _repr; -}; +void _loadPaletteFile( gchar const *filename, gboolean user=FALSE ); -class SwatchesPanel::GradientWatcher : public Inkscape::XML::NodeObserver { -public: - GradientWatcher(SwatchesPanel* pnl, SPGradient* obj) : - _pnl(pnl), - _obj(obj), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")), - _swatchAttr(g_quark_from_string("osb:paint")) - { - _repr->addObserver(*this); - } - - ~GradientWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch()) { - _pnl->_defsChanged( ); - } - } - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch() ) { - _pnl->_defsChanged( ); - } - } - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &/*child*/, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) - { - if ( _pnl && _obj && _obj->isSwatch() ) { - _pnl->_defsChanged( ); - } - } - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj && ((_obj->isSwatch() && name == _labelAttr) || name == _swatchAttr)) { - _pnl->_defsChanged( ); - } - } - - SwatchesPanel* _pnl; - SPGradient* _obj; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; - GQuark _swatchAttr; -}; - -class SwatchesPanel::SwatchWatcher : public Inkscape::XML::NodeObserver { -public: - SwatchWatcher(SwatchesPanel* pnl, SPObject* obj, bool builtIn) : - _pnl(pnl), - _obj(obj), - _builtIn(builtIn), - _repr(obj->getRepr()), - _labelAttr(g_quark_from_string("inkscape:label")), - _swatchAttr(g_quark_from_string("osb:paint")) - { - _repr->addObserver(*this); - } - - ~SwatchWatcher() { - _repr->removeObserver(*this); - } - - virtual void notifyChildAdded( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj) { - SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); - if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - } - virtual void notifyChildRemoved( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*prev*/ ) - { - if ( _pnl && _obj) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - virtual void notifyChildOrderChanged( Inkscape::XML::Node &/*node*/, Inkscape::XML::Node &child, Inkscape::XML::Node */*old_prev*/, Inkscape::XML::Node */*new_prev*/ ) - { - if ( _pnl && _obj) { - SPObject *childobj = _builtIn ? SwatchDocument->getObjectByRepr(&child) : (_pnl->_currentDocument ? _pnl->_currentDocument->getObjectByRepr(&child) : 0); - if (childobj && ((SP_IS_GRADIENT(childobj) && SP_GRADIENT(childobj)->hasStops()) || SP_IS_GROUP(childobj))) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } - } - virtual void notifyContentChanged( Inkscape::XML::Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} - virtual void notifyAttributeChanged( Inkscape::XML::Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { - if (_pnl && _obj && name == _labelAttr) { - if (_builtIn) { - _pnl->_swatchesChanged( ); - } else { - _pnl->_defsChanged( ); - } - } - } +std::list userSwatchPages; +std::list systemSwatchPages; +static std::map docPalettes; +static std::vector docTrackings; +static std::map docPerPanel; - SwatchesPanel* _pnl; - SPObject* _obj; - bool _builtIn; - Inkscape::XML::Node* _repr; - GQuark _labelAttr; - GQuark _swatchAttr; -}; -class SwatchesPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +class SwatchesPanelHook : public SwatchesPanel { public: - - ModelColumns() - { - add(_colObject); - add(_colLabel); - } - virtual ~ModelColumns() {} - - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; + static void convertGradient( GtkMenuItem *menuitem, gpointer userData ); + static void deleteGradient( GtkMenuItem *menuitem, gpointer userData ); }; -class SwatchesPanel::ModelColumnsDoc : public Gtk::TreeModel::ColumnRecord -{ -public: - - ModelColumnsDoc() - { - add(_colObject); - add(_colLabel); - add(_colPixbuf); +static void handleClick( GtkWidget* /*widget*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(false); } - virtual ~ModelColumnsDoc() {} - - Gtk::TreeModelColumn _colObject; - Gtk::TreeModelColumn _colLabel; - Gtk::TreeModelColumn > _colPixbuf; -}; +} -static void StripChildGroups(Inkscape::XML::Node * node, SPObject* addTo) -{ - for (Inkscape::XML::Node * it = node->firstChild(); it != NULL;) { - if (!strcmp(it->name(), "svg:g")) { - Inkscape::XML::Node * todel = it; - it = it->next(); - node->removeChild(todel); - } else { - it = it->next(); - } +static void handleSecondaryClick( GtkWidget* /*widget*/, gint /*arg1*/, gpointer callback_data ) { + ColorItem* item = reinterpret_cast(callback_data); + if ( item ) { + item->buttonClicked(true); } - addTo->appendChildRepr(node); } -static void BubbleChildGroups(Inkscape::XML::Node * node, SPObject* addTo) +static GtkWidget* popupMenu = 0; +static GtkWidget *popupSubHolder = 0; +static GtkWidget *popupSub = 0; +static std::vector popupItems; +static std::vector popupExtras; +static ColorItem* bounceTarget = 0; +static SwatchesPanel* bouncePanel = 0; + +static void redirClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) { - std::queue groups; - for (Inkscape::XML::Node * it = node->firstChild(); it != NULL; ) { - if (!strcmp(it->name(), "svg:g")) { - groups.push(it->duplicate(addTo->document->getReprDoc())); - Inkscape::XML::Node * todel = it; - it = it->next(); - node->removeChild(todel); - } else { - it = it->next(); - } - } - addTo->appendChildRepr(node); - while (!groups.empty()) { - Inkscape::XML::Node * it = groups.front(); - groups.pop(); - BubbleChildGroups(it, addTo); - Inkscape::GC::release(it); + if ( bounceTarget ) { + handleClick( GTK_WIDGET(menuitem), bounceTarget ); } } -void SwatchesPanel::_addSwatchButtonClicked(SPGroup* swatch, bool recurse) +static void redirSecondaryClick( GtkMenuItem *menuitem, gpointer /*user_data*/ ) { - if (_currentDocument) { - if (swatch && SP_IS_GROUP(swatch) ) { - Inkscape::XML::Node * copy = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); - if (recurse) { - BubbleChildGroups(copy, _currentDocument->getDefs()); - } else { - StripChildGroups(copy, _currentDocument->getDefs()); - } - Inkscape::GC::release(copy); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); - } + if ( bounceTarget ) { + handleSecondaryClick( GTK_WIDGET(menuitem), 0, bounceTarget ); } } -void SwatchesPanel::_importButtonClicked(bool addToDoc, bool addToBI) +static void editGradientImpl( SPDesktop* desktop, SPGradient* gr ) { - if (addToDoc || addToBI) { - //# Get the current directory for finding files - static Glib::ustring open_path; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - - if(open_path.empty()) - { - Glib::ustring attr = prefs->getString("/dialogs/open/path"); - if (!attr.empty()) open_path = attr; - } - - //# Test if the open_path directory exists - if (!Inkscape::IO::file_test(open_path.c_str(), - (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) - open_path = ""; - - #ifdef WIN32 - //# If no open path, default to our win32 documents folder - if (open_path.empty()) - { - // The path to the My Documents folder is read from the - // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal" - HKEY key = NULL; - if(RegOpenKeyExA(HKEY_CURRENT_USER, - "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", - 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) - { - WCHAR utf16path[_MAX_PATH]; - DWORD value_type; - DWORD data_size = sizeof(utf16path); - if(RegQueryValueExW(key, L"Personal", NULL, &value_type, - (BYTE*)utf16path, &data_size) == ERROR_SUCCESS) - { - g_assert(value_type == REG_SZ); - gchar *utf8path = g_utf16_to_utf8( - (const gunichar2*)utf16path, -1, NULL, NULL, NULL); - if(utf8path) - { - open_path = Glib::ustring(utf8path); - g_free(utf8path); + if ( gr ) { + bool shown = false; + if ( desktop && desktop->doc() ) { + Inkscape::Selection *selection = sp_desktop_selection( desktop ); + GSList const *items = selection->itemList(); + if (items) { + SPStyle *query = sp_style_new( desktop->doc() ); + int result = objects_query_fillstroke(const_cast(items), query, true); + if ( (result == QUERY_STYLE_MULTIPLE_SAME) || (result == QUERY_STYLE_SINGLE) ) { + // could be pertinent + if (query->fill.isPaintserver()) { + SPPaintServer* server = query->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* grad = SP_GRADIENT(server); + if ( grad->isSwatch() && grad->getId() == gr->getId()) { + desktop->_dlg_mgr->showDialog("FillAndStroke"); + shown = true; + } + } } } + sp_style_unref(query); } } - #endif - - //# If no open path, default to our home directory - if (open_path.empty()) - { - open_path = g_get_home_dir(); - open_path.append(G_DIR_SEPARATOR_S); - } - Gtk::Window * parent = SP_ACTIVE_DESKTOP->getToplevel(); - //# Create a dialog - Inkscape::UI::Dialog::FileOpenDialog *openDialogInstance = - Inkscape::UI::Dialog::FileOpenDialog::create( - *parent, open_path, - Inkscape::UI::Dialog::SWATCH_TYPES, - _("Select file to open")); - - //# Show the dialog - bool const success = openDialogInstance->show(); - - //# Save the folder the user selected for later - open_path = openDialogInstance->getCurrentDirectory(); - - if (!success) - { - delete openDialogInstance; - return; - } - - //# User selected something. Get name and type - Glib::ustring fileName = openDialogInstance->getFilename(); - - //# We no longer need the file dialog object - delete it - delete openDialogInstance; - openDialogInstance = NULL; - - - if (!fileName.empty()) - { - Glib::ustring newFileName = Glib::filename_to_utf8(fileName); - - if ( newFileName.size() > 0) - fileName = newFileName; - else - g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); - - open_path = Glib::path_get_dirname (fileName); - open_path.append(G_DIR_SEPARATOR_S); - prefs->setString("/dialogs/open/path", open_path); - - SPDocument* importdoc = SPDocument::createNewDoc(fileName.c_str(), true); - Inkscape::XML::Node * page = NULL; - if (importdoc && importdoc->getDefs()) { - if (addToBI) { - page = SwatchDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (SwatchDocument->getObjectById(id)); - - page->setAttribute("id", id); - gchar* name = g_path_get_basename(importdoc->getName()); - page->setAttribute("inkscape:label", name); - g_free(name); - } - - for (SPObject* it = importdoc->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GROUP(it)) { - if (page) { - Inkscape::XML::Node * copy = it->getRepr()->duplicate(SwatchDocument->getReprDoc()); - page->appendChild(copy); - } - if (addToDoc) { - _addSwatchButtonClicked(SP_GROUP(it), false); - } - } - } - if (page) { - SwatchDocument->getDefs()->appendChildRepr(page); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - - importdoc->doUnref(); + if (!shown) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/dialogs/gradienteditor/showlegacy", false)) { + // Legacy gradient dialog + GtkWidget *dialog = sp_gradient_vector_editor_new( gr ); + gtk_widget_show( dialog ); } else { - SPGroup* g = importGPL(addToBI ? SwatchDocument : _currentDocument, fileName.c_str()); - if (addToBI) { - if (addToDoc) { - _addSwatchButtonClicked(g, false); + // Invoke the gradient tool + Inkscape::Verb *verb = Inkscape::Verb::get( SP_VERB_CONTEXT_GRADIENT ); + if ( verb ) { + SPAction *action = verb->get_action( Inkscape::ActionContext( ( Inkscape::UI::View::View * ) SP_ACTIVE_DESKTOP ) ); + if ( action ) { + sp_action_perform( action, NULL ); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } else { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add swatches to document")); } } } } } -void SwatchesPanel::SetSelectedFill(SPGradient* swatch) +static void editGradient( GtkMenuItem */*menuitem*/, gpointer /*user_data*/ ) { - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->fill.isSet()) { - if (it->style->fill.isPaintserver()) { - SPPaintServer * server = it->style->getFillPaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = swatch->getRepr(); - if (repr != drepr && grad != swatch) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { - Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); - swatch->appendChildRepr(clone); - Inkscape::GC::release(clone); - } - swatch->setSwatch(); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); - } - } - } else if (it->style->fill.isColor()) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - addStop(swatch->getRepr(), it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); - swatch->setSwatch(); - if (!_noLink.get_active()) { - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + SPDocument *doc = desktop ? desktop->doc() : 0; + if (doc) { + std::string targetName(bounceTarget->def.descr); + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + editGradientImpl( desktop, grad ); + break; } } } } } -void SwatchesPanel::SetSelectedStroke(SPGradient* swatch) +void SwatchesPanelHook::convertGradient( GtkMenuItem * /*menuitem*/, gpointer userData ) { - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->stroke.isSet()) { - if (it->style->stroke.isPaintserver()) { - SPPaintServer * server = it->style->getStrokePaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = swatch->getRepr(); - if (repr != drepr && grad != swatch) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - for (SPStop* news = grad->getVector()->getFirstStop(); news != NULL; news = news->getNextStop()) { - Inkscape::XML::Node* clone = news->getRepr()->duplicate(_currentDocument->getReprDoc()); - swatch->appendChildRepr(clone); - Inkscape::GC::release(clone); - } - swatch->setSwatch(); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(swatch), SP_IS_RADIALGRADIENT(swatch) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Gradient Swatch")); - } - } - } else if (it->style->stroke.isColor()) { - while (SPStop* olds = swatch->getFirstStop()) { - olds->deleteObject(); - } - addStop(swatch->getRepr(), it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); - swatch->setSwatch(); - if (!_noLink.get_active()) { - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set Color Swatch")); + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + SPDocument *doc = desktop ? desktop->doc() : 0; + gint index = GPOINTER_TO_INT(userData); + if ( doc && (index >= 0) && (static_cast(index) < popupItems.size()) ) { + Glib::ustring targetName = popupItems[index]; + + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( targetName == grad->getId() ) { + grad->setSwatch(); + DocumentUndo::done(doc, SP_VERB_CONTEXT_GRADIENT, + _("Add gradient stop")); + break; } } } } } -void SwatchesPanel::MoveSwatchDown(SPGradient* swatch) +void SwatchesPanelHook::deleteGradient( GtkMenuItem */*menuitem*/, gpointer /*userData*/ ) { - if (_currentDocument && swatch) { - SPObject* next = swatch->next; - while (next && (!SP_IS_GRADIENT(next) || !(SP_GRADIENT(next)->isSwatch()))) { - next = next->next; - } - if (next) { - Inkscape::XML::Node* repr = swatch->getRepr(); - repr->parent()->changeOrder(repr, next->getRepr()); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Right")); - } + if ( bounceTarget ) { + SwatchesPanel* swp = bouncePanel; + SPDesktop* desktop = swp ? swp->getDesktop() : 0; + sp_gradient_unset_swatch(desktop, bounceTarget->def.descr); } } -void SwatchesPanel::MoveSwatchUp(SPGradient* swatch) +static SwatchesPanel* findContainingPanel( GtkWidget *widget ) { - if (_currentDocument && swatch) { - SPObject* g = NULL; - SPObject* next = swatch->parent->firstChild(); - while (next && next != swatch) { - if (SP_IS_GRADIENT(next) && SP_GRADIENT(next)->isSwatch()) { - g = next; - } - next = next->next; - } - if (g) { - g = g->getPrev(); - Inkscape::XML::Node* repr = swatch->getRepr(); - repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Left")); - } - } -} + SwatchesPanel *swp = 0; -void SwatchesPanel::RemoveSwatch(SPGradient* swatch) -{ - if (_currentDocument) { - if (swatch->isReferenced()) { - Inkscape::XML::Node * repr = swatch->getRepr(); - repr->parent()->removeChild(repr); - _currentDocument->getDefs()->getRepr()->appendChild(repr); - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); - } else { - swatch->deleteObject(false); - } + std::map rawObjects; + for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { + rawObjects[GTK_WIDGET(it->first->gobj())] = it->first; } -} -void SwatchesPanel::_setSelectionSwatch(SPGradient* swatch, bool isStroke) -{ - if (_currentDocument) { - if (swatch) { - if (_noLink.get_active()) { - if (swatch->isSolid()) { - ColorRGBA rgba(swatch->getFirstStop()->getEffectiveColor().toRGBA32(swatch->getFirstStop()->opacity)); - sp_desktop_set_color(_currentDesktop, rgba, false, !isStroke); - } else { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); - - Inkscape::XML::Node * clone = swatch->getRepr()->duplicate(_currentDocument->getReprDoc()); - _currentDocument->getDefs()->appendChildRepr(clone); - SPGradient* grad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - Inkscape::GC::release(clone); - grad->setSwatch(false); - SPGradient* normalized = sp_gradient_ensure_vector_normalized(grad); -// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { -// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); -// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); -// } - sp_desktop_set_style(_currentDesktop, css); - sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); - sp_repr_css_attr_unref (css); - } - } else { - SPCSSAttr *css = sp_repr_css_attr_new(); - sp_repr_css_set_property(css, isStroke ? "stroke-opacity" : "fill-opacity", "1.0"); - - SPGradient* normalized = sp_gradient_ensure_vector_normalized(swatch); -// for (GSList const * it = _currentDesktop->selection->itemList(); it != NULL; it = it->next) { -// sp_desktop_apply_css_recursive(SP_ITEM(it->data), css, true); -// sp_item_set_gradient(SP_ITEM(it->data), normalized, SP_IS_RADIALGRADIENT(normalized) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, isStroke ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); -// } - sp_desktop_set_style(_currentDesktop, css); - sp_desktop_set_gradient(_currentDesktop, normalized, !isStroke); - sp_repr_css_attr_unref (css); - } - } else { - SPCSSAttr *css = sp_repr_css_attr_new (); - sp_repr_css_set_property (css, isStroke ? "stroke" : "fill", "none"); - sp_desktop_set_style(_currentDesktop, css); - } - if (isStroke) { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item stroke swatch")); - } else { - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Set item fill swatch")); + for (GtkWidget* curr = widget; curr && !swp; curr = gtk_widget_get_parent(curr)) { + if (rawObjects.find(curr) != rawObjects.end()) { + swp = rawObjects[curr]; } } -} - -void SwatchesPanel::_swatchClicked(GdkEventButton* event, SPGradient* swatch) -{ - if (_currentDesktop) { - if (event->button == 3) { - Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi; - - Glib::ustring us = Glib::ustring::compose("%1", swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]")); - mi = Gtk::manage(new Gtk::MenuItem(swatch ? (swatch->label() ? swatch->label() : swatch->getId()) : _("[None]"))); - Gtk::Label* namelbl = dynamic_cast(mi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - mi->show(); - mi->set_sensitive(false); - menu->append(*mi); - - Gtk::SeparatorMenuItem* sep; - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, false)); - mi->show(); - mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setSelectionSwatch), swatch, true)); - mi->show(); - mi->set_sensitive(_currentDesktop && !_currentDesktop->selection->isEmpty()); - menu->append(*mi); - - if (swatch) { - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedFill), swatch)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Set to Selected Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::SetSelectedStroke), swatch)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Left"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchUp), swatch)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Right"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveSwatchDown), swatch)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::RemoveSwatch), swatch)); - mi->show(); - menu->append(*mi); - } - menu->popup(event->button, event->time); - } else if (!_currentDesktop->selection->isEmpty()) { - _setSelectionSwatch(swatch, event->state & GDK_SHIFT_MASK); - } - } + return swp; } -void SwatchesPanel::MoveDown(SPGroup* page) +static void removeit( GtkWidget *widget, gpointer data ) { - if (_currentDocument && page) { - SPObject* next = page->next; - while (next && !SP_IS_GROUP(next)) { - next = next->next; - } - if (next) { - Inkscape::XML::Node* repr = page->getRepr(); - repr->parent()->changeOrder(repr, next->getRepr()); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Down")); - } - } + gtk_container_remove( GTK_CONTAINER(data), widget ); } -void SwatchesPanel::MoveUp(SPGroup* page) -{ - if (_currentDocument && page) { - SPObject* g = NULL; - SPObject* next = page->parent->firstChild(); - while (next && next != page) { - if (SP_IS_GROUP(next)) { - g = next; - } - next = next->next; - } - if (g) { - g = g->getPrev(); - Inkscape::XML::Node* repr = page->getRepr(); - repr->parent()->changeOrder(repr, g ? g->getRepr() : NULL); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Move Swatch Up")); - } - } -} +/* extern'ed from colot-item.cpp */ +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ); -void SwatchesPanel::Remove(SPGroup* page) +gboolean colorItemHandleButtonPress( GtkWidget* widget, GdkEventButton* event, gpointer user_data ) { - if (_currentDocument && page) { - std::vector toMove; - for(SPObject* obj = page->firstChild(); obj != NULL; obj = obj->next) { - if (SP_IS_GRADIENT(obj)) { - SPGradient* grad = SP_GRADIENT(obj); - if (grad->isReferenced()) { - toMove.push_back(grad->getRepr()); - } + gboolean handled = FALSE; + + if ( event && (event->button == 3) && (event->type == GDK_BUTTON_PRESS) ) { + SwatchesPanel* swp = findContainingPanel( widget ); + + if ( !popupMenu ) { + popupMenu = gtk_menu_new(); + GtkWidget* child = 0; + + //TRANSLATORS: An item in context menu on a colour in the swatches + child = gtk_menu_item_new_with_label(_("Set fill")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(redirClick), + user_data); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + + //TRANSLATORS: An item in context menu on a colour in the swatches + child = gtk_menu_item_new_with_label(_("Set stroke")); + + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(redirSecondaryClick), + user_data); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + + child = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_menu_item_new_with_label(_("Delete")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(SwatchesPanelHook::deleteGradient), + user_data ); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + gtk_widget_set_sensitive( child, FALSE ); + + child = gtk_menu_item_new_with_label(_("Edit...")); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(editGradient), + user_data ); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_separator_menu_item_new(); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + popupExtras.push_back(child); + + child = gtk_menu_item_new_with_label(_("Convert")); + gtk_menu_shell_append(GTK_MENU_SHELL(popupMenu), child); + //popupExtras.push_back(child); + //gtk_widget_set_sensitive( child, FALSE ); + { + popupSubHolder = child; + popupSub = gtk_menu_new(); + gtk_menu_item_set_submenu( GTK_MENU_ITEM(child), popupSub ); } + + gtk_widget_show_all(popupMenu); } - while (!toMove.empty()) { - Inkscape::XML::Node * repr = toMove.back(); - toMove.pop_back(); - repr->parent()->removeChild(repr); - _currentDocument->getDefs()->getRepr()->appendChild(repr); - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(false); - } - page->deleteObject(false); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Remove Swatch Group")); - } -} -void SwatchesPanel::AddSelectedFill(SPGroup* page) -{ - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->fill.isSet()) { - if (it->style->fill.isPaintserver()) { - SPPaintServer * server = it->style->getFillPaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - if (_noLink.get_active()) { - Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - clone->setAttribute( "osb:paint", "gradient", 0 ); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else if (grad->isSwatch()) { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); - if (repr->parent() != drepr) { - repr->parent()->removeChild(repr); - drepr->appendChild(repr); - } - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } - } - } else if (it->style->fill.isColor()) { - Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute( "osb:paint", "solid", 0 ); - addStop(grad, it->style->fill.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->fill_opacity.value), "0"); - if (page) { - page->appendChild(grad); - } else { - _currentDocument->getDefs()->appendChild(grad); - } - SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); - Inkscape::GC::release(grad); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_FILL); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); - } + if ( user_data ) { + ColorItem* item = reinterpret_cast(user_data); + bool show = swp && (swp->getSelectedIndex() == 0); + for ( std::vector::iterator it = popupExtras.begin(); it != popupExtras.end(); ++ it) { + gtk_widget_set_sensitive(*it, show); } - } - } -} -void SwatchesPanel::AddSelectedStroke(SPGroup* page) -{ - if (_currentDesktop && _currentDocument) { - SPItem* it = _currentDesktop->selection->singleItem(); - if (it) { - if (it->style->stroke.isSet()) { - if (it->style->stroke.isPaintserver()) { - SPPaintServer * server = it->style->getStrokePaintServer(); - if (SP_IS_GRADIENT(server)) { - SPGradient *grad = SP_GRADIENT(server)->getVector(); - if (_noLink.get_active()) { - Inkscape::XML::Node * clone = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - clone->setAttribute( "osb:paint", "gradient", 0 ); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); + bounceTarget = item; + bouncePanel = swp; + popupItems.clear(); + if ( popupMenu ) { + gtk_container_foreach(GTK_CONTAINER(popupSub), removeit, popupSub); + bool processed = false; + GtkWidget *wdgt = gtk_widget_get_ancestor(widget, SP_TYPE_DESKTOP_WIDGET); + if ( wdgt ) { + SPDesktopWidget *dtw = SP_DESKTOP_WIDGET(wdgt); + if ( dtw && dtw->desktop ) { + // Pick up all gradients with vectors + const GSList *gradients = (dtw->desktop->doc())->getResourceList("gradient"); + gint index = 0; + for (const GSList *curr = gradients; curr; curr = curr->next) { + SPGradient* grad = SP_GRADIENT(curr->data); + if ( grad->hasStops() && !grad->isSwatch() ) { + //gl = g_slist_prepend(gl, curr->data); + processed = true; + GtkWidget *child = gtk_menu_item_new_with_label(grad->getId()); + gtk_menu_shell_append(GTK_MENU_SHELL(popupSub), child); + + popupItems.push_back(grad->getId()); + g_signal_connect( G_OBJECT(child), + "activate", + G_CALLBACK(SwatchesPanelHook::convertGradient), + GINT_TO_POINTER(index) ); + index++; } - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else if (grad->isSwatch()) { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * clone = repr->duplicate(_currentDocument->getReprDoc()); - if (page) { - page->appendChildRepr(clone); - } else { - _currentDocument->getDefs()->appendChildRepr(clone); - } - SPGradient *newgrad = SP_GRADIENT(_currentDocument->getObjectByRepr(clone)); - - sp_item_set_gradient(it, sp_gradient_ensure_vector_normalized(newgrad), SP_IS_RADIALGRADIENT(newgrad) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - Inkscape::GC::release(clone); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); - } else { - Inkscape::XML::Node * repr = grad->getRepr(); - Inkscape::XML::Node * drepr = page ? page->getRepr() : _currentDocument->getDefs()->getRepr(); - if (repr->parent() != drepr) { - repr->parent()->removeChild(repr); - drepr->appendChild(repr); - } - SP_GRADIENT(_currentDocument->getObjectByRepr(repr))->setSwatch(); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Gradient Swatch")); } + + gtk_widget_show_all(popupSub); } - } else if (it->style->stroke.isColor()) { - Inkscape::XML::Node *grad = _currentDocument->getReprDoc()->createElement("svg:linearGradient"); - grad->setAttribute( "osb:paint", "solid", 0 ); - addStop(grad, it->style->stroke.value.color.toString(), SP_SCALE24_TO_FLOAT(it->style->stroke_opacity.value), "0"); - if (page) { - page->appendChild(grad); - } else { - _currentDocument->getDefs()->appendChild(grad); - } - SPGradient* normalized = sp_gradient_ensure_vector_normalized(SP_GRADIENT(_currentDocument->getObjectByRepr(grad))); - Inkscape::GC::release(grad); - if (!_noLink.get_active()) { - sp_item_set_gradient(it, normalized, SP_GRADIENT_TYPE_LINEAR, Inkscape::FOR_STROKE); - } - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Add Color Swatch")); } + gtk_widget_set_sensitive( popupSubHolder, processed ); + + gtk_menu_popup(GTK_MENU(popupMenu), NULL, NULL, NULL, NULL, event->button, event->time); + handled = TRUE; } } } -} -void SwatchesPanel::_addBIButtonClicked(GdkEventButton* event) -{ - if (popUpImportMenu) { - popUpImportMenu->popup(event->button, event->time); - } + return handled; } -void SwatchesPanel::NewGroupBI() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = SwatchDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (SwatchDocument->getObjectById(id)); - - page->setAttribute("id", id); - - SwatchDocument->getDefs()->appendChild(page); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } -} -void SwatchesPanel::NewGroup() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("New Swatch Group")); +static char* trim( char* str ) { + char* ret = str; + while ( *str && (*str == ' ' || *str == '\t') ) { + str++; } -} - -void SwatchesPanel::SaveAs() -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - - std::vector toMove; - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->isSwatch()) { - toMove.push_back(grad->getRepr()); - } - } - } - while (!toMove.empty()) { - Inkscape::XML::Node* repr = toMove.back(); - toMove.pop_back(); - repr->parent()->removeChild(repr); - page->appendChild(repr); - } - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Save Swatch Group")); + ret = str; + while ( *str ) { + str++; } -} - -void SwatchesPanel::Duplicate(SPGroup* oldpage) -{ - if (_currentDocument) { - Inkscape::XML::Node * page = _currentDocument->getReprDoc()->createElement("svg:g"); - gchar *id=NULL; - do { - g_free(id); - id = g_strdup_printf("page%d", page_suffix++); - } while (_currentDocument->getObjectById(id)); - - page->setAttribute("id", id); - if (oldpage->label()) page->setAttribute("inkscape:label", oldpage->label()); - - for (SPObject *it = oldpage->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->isSwatch()) { - Inkscape::XML::Node * copy = grad->getRepr()->duplicate(_currentDocument->getReprDoc()); - page->appendChild(copy); - Inkscape::GC::release(copy); - } - } - } - _currentDocument->getDefs()->appendChild(page); - DocumentUndo::done(_currentDocument, SP_VERB_DIALOG_SWATCHES, _("Duplicate Swatch Group")); + str--; + while ( str > ret && (( *str == ' ' || *str == '\t' ) || *str == '\r' || *str == '\n') ) { + *str-- = 0; } + return ret; } -void SwatchesPanel::_lblClick(GdkEventButton* event, SPGroup* page) -{ - Gtk::Menu * menu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi; - Glib::ustring us = Glib::ustring::compose("%1", page ? (page->label() ? page->label() : page->getId()) : _("[Base]")); - mi = Gtk::manage(new Gtk::MenuItem(page ? (page->label() ? page->label() : page->getId()) : _("[Base]"))); - Gtk::Label* namelbl = dynamic_cast(mi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - mi->show(); - mi->set_sensitive(false); - menu->append(*mi); - - Gtk::SeparatorMenuItem* sep; - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Fill"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedFill), page)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Add Selected Stroke"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::AddSelectedStroke), page)); - mi->show(); - mi->set_sensitive(_currentDesktop && _currentDesktop->selection->singleItem()); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - if (page) { - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Up"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveUp), page)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Move Down"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::MoveDown), page)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Duplicate"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Duplicate), page)); - mi->show(); - menu->append(*mi); - - sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - menu->append(*sep); - - mi = Gtk::manage(new Gtk::MenuItem(_("Remove"))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::Remove), page)); - mi->show(); - menu->append(*mi); - } else { - mi = Gtk::manage(new Gtk::MenuItem(_("Create New Group"))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); - mi->show(); - menu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Save As New Group"))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::SaveAs)); - mi->show(); - menu->append(*mi); +static void skipWhitespace( char*& str ) { + while ( *str == ' ' || *str == '\t' ) { + str++; } - - menu->popup(event->button, event->time); } -void SwatchesPanel::_defsChanged() -{ - if (_storeDoc) { - _storeDoc->clear(); - } - - while (!docWatchers.empty()) { - Inkscape::XML::NodeObserver* w = docWatchers.back(); - docWatchers.pop_back(); - delete w; - } - - std::vector tableChildren = _insideTable.get_children(); - for (std::vector::iterator c = tableChildren.begin(); c != tableChildren.end(); ++c) { - _insideTable.remove(**c); +static bool parseNum( char*& str, int& val ) { + val = 0; + while ( '0' <= *str && *str <= '9' ) { + val = val * 10 + (*str - '0'); + str++; } - - if (_currentDocument) { - Gtk::EventBox* eb; - Gtk::Label* lbl; - if (_showlabels) { - eb = Gtk::manage(new Gtk::EventBox()); - eb->add_events(Gdk::BUTTON_PRESS_MASK); - eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), NULL)); - - lbl = Gtk::manage(new Gtk::Label(_("[Base]"))); - eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); - } - - ColorItem* item = Gtk::manage(new ColorItem(NULL, _("[None]"), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), NULL)); - item->set_tooltip_text(_("[None]")); - _insideTable.attach( *item, _showlabels ? 1 : 0, _showlabels ? 2 : 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); - - unsigned int i = 1; - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GRADIENT(it)) { - SPGradient* grad = SP_GRADIENT(it); - if (grad->hasStops()) { - - GradientWatcher* w = new GradientWatcher(this, grad); - docWatchers.push_back(w); - - if (grad->isSwatch()) { - - for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { - StopWatcher* sw = new StopWatcher(this, s); - docWatchers.push_back(sw); - } + bool retval = !(*str == 0 || *str == ' ' || *str == '\t' || *str == '\r' || *str == '\n'); + return retval; +} - if (_storeDoc) { - Gtk::TreeModel::iterator iter = _storeDoc->append(); - Gtk::TreeModel::Row row = *iter; - row[_modelDoc->_colObject] = grad; - row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); - GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); - row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - } - item = Gtk::manage(new ColorItem(grad, it->label() ? it->label() : it->getId(), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->set_tooltip_text(it->label() ? it->label() : it->getId()); - if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); +void _loadPaletteFile( gchar const *filename, gboolean user/*=FALSE*/ ) +{ + char block[1024]; + FILE *f = Inkscape::IO::fopen_utf8name( filename, "r" ); + if ( f ) { + char* result = fgets( block, sizeof(block), f ); + if ( result ) { + if ( strncmp( "GIMP Palette", block, 12 ) == 0 ) { + bool inHeader = true; + bool hasErr = false; + + SwatchPage *onceMore = new SwatchPage(); + + do { + result = fgets( block, sizeof(block), f ); + block[sizeof(block) - 1] = 0; + if ( result ) { + if ( block[0] == '#' ) { + // ignore comment } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); - } - - i++; - } - } - } - } - - for (SPObject *it = _currentDocument->getDefs()->firstChild(); it != NULL; it = it->next) { - if (SP_IS_GROUP(it)) { - SwatchWatcher* w = new SwatchWatcher(this, it, false); - docWatchers.push_back(w); - - if (_showlabels) { - i += 20 - (i % 20); - eb = Gtk::manage(new Gtk::EventBox()); - eb->add_events(Gdk::BUTTON_PRESS_MASK); - eb->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_lblClick), SP_GROUP(it))); - lbl = Gtk::manage(new Gtk::Label(it->label() ? it->label() : it->getId())); - eb->add(*lbl); - _insideTable.attach( *eb, 0, 1, i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ , 5, 0); - } - - Gtk::TreeModel::iterator rowiter; - - if (_storeDoc) { - rowiter = _storeDoc->append(); - Gtk::TreeModel::Row row = *rowiter; - row[_modelDoc->_colObject] = it; - row[_modelDoc->_colLabel] = it->label() ? it->label() : it->getId(); - } - - for (SPObject *cit = it->firstChild(); cit != NULL; cit = cit->next) { - if (SP_IS_GRADIENT(cit)) { - SPGradient* grad = SP_GRADIENT(cit); - - if (grad->hasStops()) { - - GradientWatcher* w = new GradientWatcher(this, grad); - docWatchers.push_back(w); - - if (grad->isSwatch()) { - - for (SPStop* s = grad->getFirstStop(); s != NULL; s = s->getNextStop()) { - StopWatcher* sw = new StopWatcher(this, s); - docWatchers.push_back(sw); - } - - if (_storeDoc && rowiter) { - Gtk::TreeModel::iterator iter = _storeDoc->append(rowiter->children()); - Gtk::TreeModel::Row row = *iter; - row[_modelDoc->_colObject] = grad; - row[_modelDoc->_colLabel] = grad->label() ? grad->label() : grad->getId(); - GdkPixbuf* pixb = sp_gradient_to_pixbuf (grad, 64, 18); - row[_modelDoc->_colPixbuf] = Glib::wrap(pixb); - - _editDoc.expand_to_path(_storeDoc->get_path(iter)); + char *ptr = block; + // very simple check for header versus entry + while ( *ptr == ' ' || *ptr == '\t' ) { + ptr++; + } + if ( (*ptr == 0) || (*ptr == '\r') || (*ptr == '\n') ) { + // blank line. skip it. + } else if ( '0' <= *ptr && *ptr <= '9' ) { + // should be an entry link + inHeader = false; + ptr = block; + Glib::ustring name(""); + skipWhitespace(ptr); + if ( *ptr ) { + int r = 0; + int g = 0; + int b = 0; + hasErr = parseNum(ptr, r); + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, g); + } + if ( !hasErr ) { + skipWhitespace(ptr); + hasErr = parseNum(ptr, b); + } + if ( !hasErr && *ptr ) { + char* n = trim(ptr); + if (n != NULL) { + name = g_dpgettext2(NULL, "Palette", n); + } + } + if ( !hasErr ) { + // Add the entry now + Glib::ustring nameStr(name); + ColorItem* item = new ColorItem( r, g, b, nameStr ); + onceMore->_colors.push_back(item); + } + } else { + hasErr = true; } - - item = Gtk::manage(new ColorItem(grad, cit->label() ? cit->label() : cit->getId(), _currentDesktop)); - item->signal_button_press_event().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_swatchClicked), grad)); - item->set_tooltip_text(cit->label() ? cit->label() : cit->getId()); - if (_showlabels) { - _insideTable.attach( *item, 1 + (i % 20), 2 + (i % 20), i / 20, i / 20 + 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); + } else { + if ( !inHeader ) { + // Hmmm... probably bad. Not quite the format we want? + hasErr = true; } else { - _insideTable.attach( *item, i, i + 1, 0, 1, Gtk::FILL/*|Gtk::EXPAND*/, Gtk::FILL/*|Gtk::EXPAND*/ ); + char* sep = strchr(result, ':'); + if ( sep ) { + *sep = 0; + char* val = trim(sep + 1); + char* name = trim(result); + if ( *name ) { + if ( strcmp( "Name", name ) == 0 ) + { + onceMore->_name = val; + } + else if ( strcmp( "Columns", name ) == 0 ) + { + gchar* endPtr = 0; + guint64 numVal = g_ascii_strtoull( val, &endPtr, 10 ); + if ( (numVal == G_MAXUINT64) && (ERANGE == errno) ) { + // overflow + } else if ( (numVal == 0) && (endPtr == val) ) { + // failed conversion + } else { + onceMore->_prefWidth = numVal; + } + } + } else { + // error + hasErr = true; + } + } else { + // error + hasErr = true; + } } - i++; } } } + } while ( result && !hasErr ); + if ( !hasErr ) { + if (user) + userSwatchPages.push_back(onceMore); + else + systemSwatchPages.push_back(onceMore); +#if ENABLE_MAGIC_COLORS + ColorItem::_wireMagicColors( onceMore ); +#endif // ENABLE_MAGIC_COLORS + } else { + delete onceMore; } } } - } - //_scroller.resize(1,1); - _insideTable.resize(1,1); - _scroller.show_all_children(); - _scroller.queue_draw(); - -} -Gtk::MenuItem* SwatchesPanel::_addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow) -{ - Gtk::MenuItem* mi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId(),1)); - Gtk::Menu* m = NULL; - - Gtk::TreeModel::Row* r; - if (_store) { - Gtk::TreeModel::iterator iter = parentRow ? _store->append(parentRow->children()) : _store->append(); - Gtk::TreeModel::Row row = *iter; - row[_model->_colObject] = group; - row[_model->_colLabel] = group->label() ? group->label() : group->getId(); - - if (SP_IS_GROUP(group->parent) && SP_GROUP(group->parent)->expanded()) { - _editBI.expand_to_path(_store->get_path(iter)); - } - r = &row; - } else { - r = NULL; - } - - bool hasswatches = false; - for (SPObject * obj = group->firstChild(); obj != NULL; obj = obj->next) - { - if (SP_IS_GROUP(obj)) { - if (!m) { - m = manage(new Gtk::Menu()); - m->show_all(); - mi->set_submenu(*m); - - Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(_("[All]"))); - basemi->show(); - Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); - if (namelbl) { - namelbl->set_markup(_("[All]")); - } - basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, true)); - m->append(*basemi); - - Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - m->append(*sep); - } - SwatchWatcher* w = new SwatchWatcher(this, obj, true); - rootWatchers.push_back(w); - m->append(*_addSwatchGroup(SP_GROUP(obj), r)); - } else if (SP_IS_GRADIENT(obj)) { - hasswatches = true; - } + fclose(f); } - if (!m) { - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); - } else if (hasswatches) { - Glib::ustring us = Glib::ustring::compose("%1", group->label() ? group->label() : group->getId()); - Gtk::MenuItem* basemi = manage(new Gtk::MenuItem(group->label() ? group->label() : group->getId())); - basemi->show(); - Gtk::Label* namelbl = dynamic_cast(basemi->get_child()); - if (namelbl) { - namelbl->set_markup(us); - } - basemi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_addSwatchButtonClicked), group, false)); - m->prepend(*basemi); - } - mi->show(); - return mi; } -void SwatchesPanel::_swatchesChanged() -{ - while (!rootWatchers.empty()) { - Inkscape::XML::NodeObserver* w = rootWatchers.back(); - rootWatchers.pop_back(); - delete w; - } +static bool +compare_swatch_names(SwatchPage const *a, SwatchPage const *b) { - std::vector menuChildren = popUpMenu->get_children(); - for (std::vector::iterator c = menuChildren.begin(); c != menuChildren.end(); ++c) { - popUpMenu->remove(**c); - } - - if (_store) { - _store->clear(); - } - - Gtk::MenuItem* mi; - - for (SPObject * obj = SwatchDocument->getDefs()->firstChild(); obj != NULL; obj = obj->next) - { - if (SP_IS_GROUP(obj)) { - SwatchWatcher* w = new SwatchWatcher(this, obj, true); - rootWatchers.push_back(w); - popUpMenu->append(*_addSwatchGroup(SP_GROUP(obj), NULL)); - - } - } - Gtk::SeparatorMenuItem* sep = manage(new Gtk::SeparatorMenuItem()); - sep->show(); - popUpMenu->append(*sep); - - mi = manage(new Gtk::MenuItem(_("New Swatch Group..."),1)); - mi->signal_activate().connect(sigc::mem_fun(*this, &SwatchesPanel::NewGroup)); - mi->show(); - popUpMenu->append(*mi); - - mi = manage(new Gtk::MenuItem(_("Add Swatch File..."),1)); - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, false)); - mi->show(); - popUpMenu->append(*mi); - - mi = manage(new Gtk::MenuItem(_("Import Swatch File..."),1)); - mi->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), true, true)); - mi->show(); - popUpMenu->append(*mi); + return g_utf8_collate(a->_name.c_str(), b->_name.c_str()) < 0; } -void SwatchesPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ) +static void loadEmUp() { - bool set = false; - - if ( iconName ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - btn.set_relief(Gtk::RELIEF_NONE); - set = true; - } - - if ( desktop ) { - Verb *verb = Verb::get( code ); - if ( verb ) { - SPAction *action = verb->get_action(desktop); - if ( !set && action && action->image ) { - GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); - gtk_widget_show( child ); - btn.add( *manage(Glib::wrap(child)) ); - set = true; + static bool beenHere = false; + gboolean userPalete = true; + if ( !beenHere ) { + beenHere = true; + + std::list sources; + sources.push_back( profile_path("palettes") ); + sources.push_back( g_strdup(INKSCAPE_PALETTESDIR) ); + sources.push_back( g_strdup(CREATE_PALETTESDIR) ); + + // Use this loop to iterate through a list of possible document locations. + while (!sources.empty()) { + gchar *dirname = sources.front(); + if ( Inkscape::IO::file_test( dirname, G_FILE_TEST_EXISTS ) + && Inkscape::IO::file_test( dirname, G_FILE_TEST_IS_DIR )) { + GError *err = 0; + GDir *directory = g_dir_open(dirname, 0, &err); + if (!directory) { + gchar *safeDir = Inkscape::IO::sanitizeString(dirname); + g_warning(_("Palettes directory (%s) is unavailable."), safeDir); + g_free(safeDir); + } else { + gchar *filename = 0; + while ((filename = (gchar *)g_dir_read_name(directory)) != NULL) { + gchar* lower = g_ascii_strdown( filename, -1 ); +// if ( g_str_has_suffix(lower, ".gpl") ) { + if ( !g_str_has_suffix(lower, "~") ) { + gchar* full = g_build_filename(dirname, filename, NULL); + if ( !Inkscape::IO::file_test( full, G_FILE_TEST_IS_DIR ) ) { + _loadPaletteFile(full, userPalete); + } + g_free(full); + } +// } + g_free(lower); + } + g_dir_close(directory); + } } + + // toss the dirname + g_free(dirname); + sources.pop_front(); + userPalete = false; } } - - btn.set_tooltip_text (fallback); - if ( !set ) { - btn.set_label( fallback ); - } -} + // Sort the list of swatches by name, grouped by user/system + userSwatchPages.sort(compare_swatch_names); + systemSwatchPages.sort(compare_swatch_names); -void SwatchesPanel::_addButtonClicked(GdkEventButton* event) { - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) { - if (popUpMenu) { - popUpMenu->popup(event->button, event->time); - } - } } -void SwatchesPanel::NoLinkToggled() { - static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring nolink = Glib::ustring::compose("%1/nolink", _prefs_path); - prefs->setBool(nolink, _noLink.get_active()); -} -bool SwatchesPanel::_handleButtonEvent(GdkEventButton *event) -{ - static unsigned doubleclick = 0; - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _editBI.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnBI) { - // Double click on the Layer name, enable editing - _text_rendererBI->property_editable() = true; - _editBI.set_cursor (path, *_name_columnBI, true); - grab_focus(); - } - } - - return false; +SwatchesPanel& SwatchesPanel::getInstance() +{ + return *new SwatchesPanel(); } -bool SwatchesPanel::_handleKeyEvent(GdkEventKey *event) + +/** + * Constructor + */ +SwatchesPanel::SwatchesPanel(gchar const* prefsPath) : + Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, "", true), + _holder(0), + _clear(0), + _remove(0), + _currentIndex(0), + _currentDesktop(0), + _currentDocument(0) { - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter && !_text_rendererBI->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_rendererBI->property_editable() = true; - _editBI.set_cursor(*path, *_name_columnBI, true); - grab_focus(); - return true; + Gtk::RadioMenuItem* hotItem = 0; + _holder = new PreviewHolder(); + _clear = new ColorItem( ege::PaintDef::CLEAR ); + _remove = new ColorItem( ege::PaintDef::NONE ); + if (docPalettes.empty()) { + SwatchPage *docPalette = new SwatchPage(); + + docPalette->_name = "Auto"; + docPalettes[0] = docPalette; + } + + loadEmUp(); + if ( !systemSwatchPages.empty() ) { + SwatchPage* first = 0; + int index = 0; + Glib::ustring targetName; + if ( !_prefs_path.empty() ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + targetName = prefs->getString(_prefs_path + "/palette"); + if (!targetName.empty()) { + if (targetName == "Auto") { + first = docPalettes[0]; + } else { + //index++; + std::vector pages = _getSwatchSets(); + for ( std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter ) { + if ( (*iter)->_name == targetName ) { + first = *iter; + break; + } + index++; + } } } } - case GDK_KEY_Delete: { - - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_model->_colObject]; - if (obj) { - obj->deleteObject(false); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } + + if ( !first ) { + first = docPalettes[0]; + _currentIndex = 0; + } else { + _currentIndex = index; + } + + _rebuild(); + + Gtk::RadioMenuItem::Group groupOne; + + int i = 0; + std::vector swatchSets = _getSwatchSets(); + for ( std::vector::iterator it = swatchSets.begin(); it != swatchSets.end(); ++it) { + SwatchPage* curr = *it; + Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, curr->_name)); + if ( curr == first ) { + hotItem = single; } - return true; + _regItem( single, 3, i ); + + i++; } - break; } - return false; -} -void SwatchesPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _editBI.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; + if (Glib::ustring(prefsPath) == "/dialogs/swatches") { + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + get_preferred_size(sreq_natural, sreq); +#else + sreq = size_request(); +#endif + int minHeight = 60; + if (sreq.height < minHeight) { + set_size_request(70, minHeight); + } + } - _renameObject(row, new_text); - _text_rendererBI->property_editable() = false; -} + _getContents()->pack_start(*_holder, Gtk::PACK_EXPAND_WIDGET); + _setTargetFillable(_holder); -void SwatchesPanel::_handleEditingCancelled() -{ - _text_rendererBI->property_editable() = false; -} + show_all_children(); -void SwatchesPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && SwatchDocument) { - SPObject* obj = row[_model->_colObject]; - if ( obj ) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); - } - } + restorePanelPrefs(); + if ( hotItem ) { + hotItem->set_active(); } } -void SwatchesPanel::_setCollapsed(SPGroup * group) +SwatchesPanel::~SwatchesPanel() { - group->setExpanded(false); - group->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - for (SPObject *iter = group->children; iter != NULL; iter = iter->next) - { - if (SP_IS_GROUP(iter)) _setCollapsed(SP_GROUP(iter)); + _trackDocument( this, 0 ); + + _documentConnection.disconnect(); + _selChanged.disconnect(); + + if ( _clear ) { + delete _clear; + } + if ( _remove ) { + delete _remove; + } + if ( _holder ) { + delete _holder; } } -void SwatchesPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +void SwatchesPanel::setOrientation(SPAnchorType how) { - Gtk::TreeModel::Row row = *iter; + // Must call the parent class or bad things might happen + Inkscape::UI::Widget::Panel::setOrientation( how ); - SPObject* obj = row[_model->_colObject]; - if (obj && SP_IS_GROUP(obj)) + if ( _holder ) { - if (isexpanded) - { - SP_GROUP(obj)->setExpanded(isexpanded); - obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); - } - else - { - _setCollapsed(SP_GROUP(obj)); - } + _holder->setOrientation(SP_ANCHOR_SOUTH); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } -void SwatchesPanel::_deleteButtonClicked() +void SwatchesPanel::setDesktop( SPDesktop* desktop ) { - Gtk::TreeModel::iterator iter = _editBI.get_selection()->get_selected(); - if (iter) { - Gtk::TreeModel::Row row = *iter; - SPObject* obj = row[_model->_colObject]; - if (obj) { - obj->deleteObject(false); - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); + if ( desktop != _currentDesktop ) { + if ( _currentDesktop ) { + _documentConnection.disconnect(); + _selChanged.disconnect(); } - } -} -bool SwatchesPanel::_handleButtonEventDoc(GdkEventButton* event) -{ - static unsigned doubleclick = 0; - - if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { - // TODO - fix to a better is-popup function - Gtk::TreeModel::Path path; - int x = static_cast(event->x); - int y = static_cast(event->y); - if ( _editDoc.get_path_at_pos( x, y, path ) ) { - Gtk::TreeModel::Children::iterator iter = _editDoc.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; - - SPObject* obj = row[_modelDoc->_colObject]; - if (SP_IS_GRADIENT(obj)) { - _swatchClicked(event, SP_GRADIENT(obj)); - } else if (SP_IS_GROUP(obj)) { - _lblClick(event, SP_GROUP(obj)); - } else { - _lblClick(event, NULL); - } - } else { - _lblClick(event, NULL); - } - } - - if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { - doubleclick = 1; - } + _currentDesktop = desktop; - if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { - doubleclick = 0; - Gtk::TreeModel::Path path; - Gtk::TreeViewColumn* col = 0; - int x = static_cast(event->x); - int y = static_cast(event->y); - int x2 = 0; - int y2 = 0; - if ( _editDoc.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_columnDoc) { - // Double click on the Layer name, enable editing - _text_rendererDoc->property_editable() = true; - _editDoc.set_cursor (path, *_name_columnDoc, true); - grab_focus(); + if ( desktop ) { + _currentDesktop->selection->connectChanged( + sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + _currentDesktop->selection->connectModified( + sigc::hide(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection)))); + + _currentDesktop->connectToolSubselectionChanged( + sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + + sigc::bound_mem_functor1 first = sigc::mem_fun(*this, &SwatchesPanel::_setDocument); + sigc::slot base2 = first; + sigc::slot slot2 = sigc::hide<0>( base2 ); + _documentConnection = desktop->connectDocumentReplaced( slot2 ); + + _setDocument( desktop->doc() ); + } else { + _setDocument(0); } } - - return false; } -void SwatchesPanel::_deleteButtonClickedDoc() + +class DocTrack { - Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); - if (iter) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_modelDoc->_colObject]; - if (SP_IS_GRADIENT(obj)) { - RemoveSwatch(SP_GRADIENT(obj)); - } else if (SP_IS_GROUP(obj)) { - Remove(SP_GROUP(obj)); +public: + DocTrack(SPDocument *doc, sigc::connection &gradientRsrcChanged, sigc::connection &defsChanged, sigc::connection &defsModified) : + doc(doc->doRef()), + updatePending(false), + lastGradientUpdate(0.0), + gradientRsrcChanged(gradientRsrcChanged), + defsChanged(defsChanged), + defsModified(defsModified) + { + if ( !timer ) { + timer = new Glib::Timer(); + refreshTimer = Glib::signal_timeout().connect( sigc::ptr_fun(handleTimerCB), 33 ); } + timerRefCount++; } -} -bool SwatchesPanel::_handleKeyEventDoc(GdkEventKey *event) -{ - switch (Inkscape::UI::Tools::get_group0_keyval(event)) { - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_F2: { - Gtk::TreeModel::iterator iter = _editDoc.get_selection()->get_selected(); - if (iter && !_text_rendererDoc->property_editable()) { - Gtk::TreeRow row = *iter; - SPObject * obj = row[_modelDoc->_colObject]; - if (obj) { - Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); - // Edit the layer label - _text_rendererDoc->property_editable() = true; - _editDoc.set_cursor(*path, *_name_columnDoc, true); - grab_focus(); - return true; - } + ~DocTrack() + { + timerRefCount--; + if ( timerRefCount <= 0 ) { + refreshTimer.disconnect(); + timerRefCount = 0; + if ( timer ) { + timer->stop(); + delete timer; + timer = 0; } } - case GDK_KEY_Delete: { - - _deleteButtonClickedDoc(); - return true; + if (doc) { + gradientRsrcChanged.disconnect(); + defsChanged.disconnect(); + defsModified.disconnect(); + doc->doUnref(); + doc = NULL; } - break; } - return false; -} -void SwatchesPanel::_renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name) -{ - if ( row && SwatchDocument) { - SPObject* obj = row[_modelDoc->_colObject]; - if ( obj ) { - gchar const* oldLabel = obj->label(); - if ( !name.empty() && (!oldLabel || name != oldLabel) ) { - obj->setLabel(name.c_str()); - } - } - } -} + static bool handleTimerCB(); -void SwatchesPanel::_handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text) -{ - Gtk::TreeModel::iterator iter = _editDoc.get_model()->get_iter(path); - Gtk::TreeModel::Row row = *iter; + /** + * Checks if update should be queued or executed immediately. + * + * @return true if the update was queued and should not be immediately executed. + */ + static bool queueUpdateIfNeeded(SPDocument *doc); - _renameObjectDoc(row, new_text); - _text_rendererDoc->property_editable() = false; -} + static Glib::Timer *timer; + static int timerRefCount; + static sigc::connection refreshTimer; -void SwatchesPanel::_handleEditingCancelledDoc() -{ - _text_rendererDoc->property_editable() = false; -} + SPDocument *doc; + bool updatePending; + double lastGradientUpdate; + sigc::connection gradientRsrcChanged; + sigc::connection defsChanged; + sigc::connection defsModified; -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool SwatchesPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +private: + DocTrack(DocTrack const &); // no copy + DocTrack &operator=(DocTrack const &); // no assign +}; + +Glib::Timer *DocTrack::timer = 0; +int DocTrack::timerRefCount = 0; +sigc::connection DocTrack::refreshTimer; + +static const double DOC_UPDATE_THREASHOLD = 0.090; + +bool DocTrack::handleTimerCB() { - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - bool _dnd_top = false; - _dnd_into = false; - _dnd_target = SwatchDocument->getDefs()->lastChild(); - Gtk::TreeModel::iterator itersel = _editBI.get_selection()->get_selected(); - if (!itersel) { - return true; - } - Gtk::TreeModel::Row rowsel = *itersel; - _dnd_source = rowsel[_model->_colObject]; + double now = timer->elapsed(); - if (!_dnd_source) { - return true; - } - - if (_editBI.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _editBI.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y < (int)(cell_height * 1/3)) { - Gtk::TreeModel::Path next_path = target_path; - if (next_path.prev()) { - target_path = next_path; - } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_store->iter_is_valid(_store->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - _dnd_top = true; - // Drop into the top level - _dnd_target = NULL; - } - } - } - if (!_dnd_top) { - Gtk::TreeModel::iterator iter = _store->get_iter(target_path); - if (_store->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_model->_colObject]; - if (obj) { - _dnd_target = obj; - } - } + std::vector needCallback; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->updatePending && ( (now - track->lastGradientUpdate) >= DOC_UPDATE_THREASHOLD) ) { + needCallback.push_back(track); } } - - if (_dnd_source != _dnd_target) { - - Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; - Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); - - if (target_ref != our_ref) { - if (!target_ref) { - target_ref = SwatchDocument->getDefs()->getRepr(); - if (target_ref != our_ref->parent()) { - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else { - our_ref->parent()->changeOrder(our_ref, NULL); - } - } else if (_dnd_into) { - // Move this inside of the target at the end - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else if (target_ref->parent() != our_ref->parent()) { - // Change in parent, need to remove and add - our_ref->parent()->removeChild(our_ref); - target_ref->parent()->addChild(our_ref, target_ref); - } else { - // Same parent, just move - our_ref->parent()->changeOrder(our_ref, target_ref); - } + + for (std::vector::iterator it = needCallback.begin(); it != needCallback.end(); ++it) { + DocTrack *track = *it; + if ( std::find(docTrackings.begin(), docTrackings.end(), track) != docTrackings.end() ) { // Just in case one gets deleted while we are looping + // Note: calling handleDefsModified will call queueUpdateIfNeeded and thus update the time and flag. + SwatchesPanel::handleDefsModified(track->doc); } - sp_repr_save_file(SwatchDocument->getReprDoc(), SwatchFile, SP_SVG_NS_URI); } return true; } -/* - * Drap and drop within the tree - * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer - */ -bool SwatchesPanel::_handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time) +bool DocTrack::queueUpdateIfNeeded( SPDocument *doc ) { - int cell_x = 0, cell_y = 0; - Gtk::TreeModel::Path target_path; - Gtk::TreeView::Column *target_column; - - bool _dnd_top = false; - _dnd_into = false; - _dnd_target = _currentDocument->getDefs()->lastChild(); - Gtk::TreeModel::iterator itersel = _editDoc.get_selection()->get_selected(); - if (!itersel) { - return true; - } - Gtk::TreeModel::Row rowsel = *itersel; - _dnd_source = rowsel[_modelDoc->_colObject]; - - if (!_dnd_source) { - return true; - } - - if (_editDoc.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { - // Are we before, inside or after the drop layer - Gdk::Rectangle rect; - _editDoc.get_background_area (target_path, *target_column, rect); - int cell_height = rect.get_height(); - _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); - if (cell_y < (int)(cell_height * 1/3)) { - Gtk::TreeModel::Path next_path = target_path; - if (next_path.prev()) { - target_path = next_path; + bool deferProcessing = false; + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it) { + DocTrack *track = *it; + if ( track->doc == doc ) { + double now = timer->elapsed(); + double elapsed = now - track->lastGradientUpdate; + + if ( elapsed < DOC_UPDATE_THREASHOLD ) { + deferProcessing = true; + track->updatePending = true; } else { - // Dragging to the "end" - Gtk::TreeModel::Path up_path = target_path; - up_path.up(); - if (_storeDoc->iter_is_valid(_storeDoc->get_iter(up_path))) { - // Drop into parent - target_path = up_path; - _dnd_into = true; - } else { - _dnd_top = true; - // Drop into the top level - _dnd_target = NULL; - } + track->lastGradientUpdate = now; + track->updatePending = false; } + + break; } - if (!_dnd_top) { - Gtk::TreeModel::iterator iter = _storeDoc->get_iter(target_path); - if (_storeDoc->iter_is_valid(iter)) { - Gtk::TreeModel::Row row = *iter; - SPObject *obj = row[_modelDoc->_colObject]; - if (obj) { - _dnd_target = obj; - if (SP_IS_GRADIENT(obj)) { - _dnd_into = false; - if (SP_IS_GROUP(_dnd_source)) { - _dnd_target = obj->parent; - } - } else if (SP_IS_GROUP(_dnd_source)) { - _dnd_into = false; + } + return deferProcessing; +} + +void SwatchesPanel::_trackDocument( SwatchesPanel *panel, SPDocument *document ) +{ + SPDocument *oldDoc = NULL; + if (docPerPanel.find(panel) != docPerPanel.end()) { + oldDoc = docPerPanel[panel]; + if (!oldDoc) { + docPerPanel.erase(panel); // Should not be needed, but clean up just in case. + } + } + if (oldDoc != document) { + if (oldDoc) { + docPerPanel[panel] = NULL; + bool found = false; + for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { + found = (it->second == document); + } + if (!found) { + for (std::vector::iterator it = docTrackings.begin(); it != docTrackings.end(); ++it){ + if ((*it)->doc == oldDoc) { + delete *it; + docTrackings.erase(it); + break; } } } } - } - - if (_dnd_source != _dnd_target) { - - Inkscape::XML::Node *target_ref = _dnd_target ? _dnd_target->getRepr() : NULL; - Inkscape::XML::Node *our_ref = _dnd_source->getRepr(); - - if (target_ref != our_ref) { - if (!target_ref) { - target_ref = _currentDocument->getDefs()->getRepr(); - if (target_ref != our_ref->parent()) { - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else { - our_ref->parent()->changeOrder(our_ref, NULL); + + if (document) { + bool found = false; + for (std::map::iterator it = docPerPanel.begin(); (it != docPerPanel.end()) && !found; ++it) { + found = (it->second == document); + } + docPerPanel[panel] = document; + if (!found) { + sigc::connection conn1 = document->connectResourcesChanged( "gradient", sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleGradientsChange), document) ); + sigc::connection conn2 = document->getDefs()->connectRelease( sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document)) ); + sigc::connection conn3 = document->getDefs()->connectModified( sigc::hide(sigc::hide(sigc::bind(sigc::ptr_fun(&SwatchesPanel::handleDefsModified), document))) ); + + DocTrack *dt = new DocTrack(document, conn1, conn2, conn3); + docTrackings.push_back(dt); + + if (docPalettes.find(document) == docPalettes.end()) { + SwatchPage *docPalette = new SwatchPage(); + docPalette->_name = "Auto"; + docPalettes[document] = docPalette; } - } else if (_dnd_into) { - // Move this inside of the target at the end - our_ref->parent()->removeChild(our_ref); - target_ref->addChild(our_ref, NULL); - } else if (target_ref->parent() != our_ref->parent()) { - // Change in parent, need to remove and add - our_ref->parent()->removeChild(our_ref); - target_ref->parent()->addChild(our_ref, target_ref); - } else { - // Same parent, just move - our_ref->parent()->changeOrder(our_ref, target_ref); } } - DocumentUndo::done( _currentDocument , SP_VERB_DIALOG_SWATCHES, - _("Moved Swatches")); } - - return true; } +void SwatchesPanel::_setDocument( SPDocument *document ) +{ + if ( document != _currentDocument ) { + _trackDocument(this, document); + _currentDocument = document; + handleGradientsChange( document ); + } +} -/** - * Constructor - */ -SwatchesPanel::SwatchesPanel(gchar const* prefsPath, bool showLabels) : - Inkscape::UI::Widget::Panel("", prefsPath, SP_VERB_DIALOG_SWATCHES, ""), - _scroller(), - _insideTable(1, 1), - _insideV(), - _insideH(), - _buttonsRow(), - _outsideV(), - _noLink(_("Don't Link")), - _showlabels(showLabels), - _store(0), - _scrollerBI(), - _editBI(), - _buttonsRowBI(), - _editBIV(), - _storeDoc(0), - _scrollerDoc(), - _editDoc(), - _buttonsRowDoc(), - _editDocV(), - _notebook(), - rootWatcher(0), - docWatcher(0), - _currentDesktop(0), - _currentDocument(0) +static void recalcSwatchContents(SPDocument* doc, + boost::ptr_vector &tmpColors, + std::map &previewMappings, + std::map &gradMappings) { - _insideH.pack_start(_insideTable, Gtk::PACK_SHRINK); - if (_showlabels) { - _insideV.pack_start(_insideH, Gtk::PACK_SHRINK); - _scroller.add(_insideV); - } else { - _scroller.property_height_request() = 20; - _scroller.add(_insideH); + std::vector newList; + + const GSList *gradients = doc->getResourceList("gradient"); + for (const GSList *item = gradients; item; item = item->next) { + SPGradient* grad = SP_GRADIENT(item->data); + if ( grad->isSwatch() ) { + newList.push_back(SP_GRADIENT(item->data)); + } } - - popUpMenu = manage( new Gtk::Menu() ); - popUpMenu->show_all_children(); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Add Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked) ); - _buttonsRow.pack_start(*btn, Gtk::PACK_SHRINK); - -// btn = manage( new Gtk::Button() ); -// _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_DISCONNECT, C_("Unlink", "New") ); -// _buttonsRow.pack_end(*btn, Gtk::PACK_SHRINK); - - static Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring nolink = Glib::ustring::compose("%1/nolink", prefsPath); - _noLink.set_tooltip_text(_("Don't link swatches")); - _noLink.set_active(prefs->getBool(nolink, false)); - _noLink.signal_toggled().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NoLinkToggled)); - _buttonsRow.pack_end(_noLink, Gtk::PACK_SHRINK); - - _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scroller.set_shadow_type(Gtk::SHADOW_NONE); - - if (_showlabels) { - _outsideV.pack_end(_buttonsRow, Gtk::PACK_SHRINK); - _outsideV.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); - - _notebook.append_page(_outsideV, "Use"); - + + if ( !newList.empty() ) { + std::reverse(newList.begin(), newList.end()); + for ( std::vector::iterator it = newList.begin(); it != newList.end(); ++it ) { - ModelColumnsDoc *zoop = new ModelColumnsDoc(); - _modelDoc = zoop; + SPGradient* grad = *it; - _storeDoc = Gtk::TreeStore::create( *zoop ); + cairo_surface_t *preview = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, + PREVIEW_PIXBUF_WIDTH, VBLOCK); + cairo_t *ct = cairo_create(preview); - _editDoc.set_model( _storeDoc ); - _editDoc.set_headers_visible(false); - _editDoc.set_reorderable(true); - _editDoc.enable_model_drag_dest (Gdk::ACTION_MOVE); + Glib::ustring name( grad->getId() ); + ColorItem* item = new ColorItem( 0, 0, 0, name ); - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::mem_fun(*this, &SwatchesPanel::_addButtonClicked)); - _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + cairo_pattern_t *check = ink_cairo_pattern_create_checkerboard(); + cairo_pattern_t *gradient = sp_gradient_create_preview_pattern(grad, PREVIEW_PIXBUF_WIDTH); + cairo_set_source(ct, check); + cairo_paint(ct); + cairo_set_source(ct, gradient); + cairo_paint(ct); - btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClickedDoc))); - _buttonsRowDoc.pack_start(*btn, Gtk::PACK_SHRINK); + cairo_destroy(ct); + cairo_pattern_destroy(gradient); + cairo_pattern_destroy(check); - _pixbuf_rendererDoc = manage(new Gtk::CellRendererPixbuf()); - int pixbufColNum = _editDoc.append_column("Pixbuf", *_pixbuf_rendererDoc) - 1; - _pixbuf_columnDoc = _editDoc.get_column(pixbufColNum); - _pixbuf_columnDoc->add_attribute(_pixbuf_rendererDoc->property_pixbuf(), _modelDoc->_colPixbuf); - - _text_rendererDoc = manage(new Gtk::CellRendererText()); - int nameColNum = _editDoc.append_column("Name", *_text_rendererDoc) - 1; - _name_columnDoc = _editDoc.get_column(nameColNum); - _name_columnDoc->add_attribute(_text_rendererDoc->property_text(), _modelDoc->_colLabel); + cairo_pattern_t *prevpat = cairo_pattern_create_for_surface(preview); + cairo_surface_destroy(preview); - _text_rendererDoc->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditedDoc) ); - _text_rendererDoc->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelledDoc) ); + previewMappings[item] = prevpat; + + tmpColors.push_back(item); + gradMappings[item] = grad; + } + } +} - _editDoc.set_expander_column( *_editDoc.get_column(nameColNum) ); +void SwatchesPanel::handleGradientsChange(SPDocument *document) +{ + SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; + if (docPalette) { + boost::ptr_vector tmpColors; + std::map tmpPrevs; + std::map tmpGrads; + recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); - _editDoc.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); - _editDoc.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEventDoc), false ); - _editDoc.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEventDoc), false ); + for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { + it->first->setPattern(it->second); + cairo_pattern_destroy(it->second); + } - _editDoc.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDropDoc), false); + for (std::map::iterator it = tmpGrads.begin(); it != tmpGrads.end(); ++it) { + it->first->setGradient(it->second); + } - _scrollerDoc.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scrollerDoc.set_shadow_type(Gtk::SHADOW_IN); - _scrollerDoc.add(_editDoc); + docPalette->_colors.swap(tmpColors); - _editDocV.pack_start(_scrollerDoc, Gtk::PACK_EXPAND_WIDGET); - _editDocV.pack_end(_buttonsRowDoc, Gtk::PACK_SHRINK); + // Figure out which SwatchesPanel instances are affected and update them. - _notebook.append_page(_editDocV, "Edit"); - } - - { - popUpImportMenu = Gtk::manage(new Gtk::Menu()); - - Gtk::MenuItem* mi = Gtk::manage(new Gtk::MenuItem(_("New Swatch Group..."))); - mi->signal_activate().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::NewGroupBI)); - mi->show(); - popUpImportMenu->append(*mi); - - mi = Gtk::manage(new Gtk::MenuItem(_("Import Swatch File..."))); - mi->signal_activate().connect_notify(sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_importButtonClicked), false, true)); - mi->show(); - popUpImportMenu->append(*mi); - - ModelColumns *zoop = new ModelColumns(); - _model = zoop; - - _store = Gtk::TreeStore::create( *zoop ); - - _editBI.set_model( _store ); - _editBI.set_headers_visible(false); - _editBI.set_reorderable(true); - _editBI.enable_model_drag_dest (Gdk::ACTION_MOVE); - - Gtk::Button* btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("Import Swatch") ); - btn->signal_button_press_event().connect_notify(sigc::mem_fun(*this, &SwatchesPanel::_addBIButtonClicked)); - _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); - - btn = manage( new Gtk::Button() ); - _styleButton( *btn, SP_ACTIVE_DESKTOP, SP_VERB_LAYER_DELETE, GTK_STOCK_DELETE, _("Delete Swatch") ); - btn->signal_button_press_event().connect_notify( sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_deleteButtonClicked))); - _buttonsRowBI.pack_start(*btn, Gtk::PACK_SHRINK); - - _text_rendererBI = manage(new Gtk::CellRendererText()); - int nameColNum = _editBI.append_column("Name", *_text_rendererBI) - 1; - _name_columnBI = _editBI.get_column(nameColNum); - _name_columnBI->add_attribute(_text_rendererBI->property_text(), _model->_colLabel); - - _text_rendererBI->signal_edited().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEdited) ); - _text_rendererBI->signal_editing_canceled().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleEditingCancelled) ); - - _editBI.set_expander_column( *_editBI.get_column(nameColNum) ); - - _editBI.signal_button_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); - _editBI.signal_button_release_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleButtonEvent), false ); - _editBI.signal_key_press_event().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleKeyEvent), false ); - - _editBI.signal_drag_drop().connect( sigc::mem_fun(*this, &SwatchesPanel::_handleDragDrop), false); - _editBI.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), false)); - _editBI.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &SwatchesPanel::_setExpanded), true)); - - _scrollerBI.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); - _scrollerBI.set_shadow_type(Gtk::SHADOW_IN); - _scrollerBI.add(_editBI); - - _editBIV.pack_start(_scrollerBI, Gtk::PACK_EXPAND_WIDGET); - _editBIV.pack_end(_buttonsRowBI, Gtk::PACK_SHRINK); - - _notebook.append_page(_editBIV, "Edit Built-In"); + for (std::map::iterator it = docPerPanel.begin(); it != docPerPanel.end(); ++it) { + if (it->second == document) { + SwatchesPanel* swp = it->first; + std::vector pages = swp->_getSwatchSets(); + SwatchPage* curr = pages[swp->_currentIndex]; + if (curr == docPalette) { + swp->_rebuild(); + } + } } - - _getContents()->pack_end(_notebook, Gtk::PACK_EXPAND_WIDGET); - } else { - //_outsideV.pack_end(_scroller, Gtk::PACK_SHRINK); - _buttonsRow.pack_end(_scroller, Gtk::PACK_EXPAND_WIDGET); - //_getContents()->pack_end(_outsideV, Gtk::PACK_SHRINK); - _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK); } - - loadPalletFile(); - - rootWatcher = new SwatchWatcher(this, SwatchDocument->getDefs(), true); - SwatchDocument->getDefs()->getRepr()->addObserver(*rootWatcher); - _swatchesChanged(); - _insideTable.resize(1,1); } -SwatchesPanel::~SwatchesPanel() +void SwatchesPanel::handleDefsModified(SPDocument *document) { - if (rootWatcher) { - rootWatcher->_repr->removeObserver(*rootWatcher); - delete rootWatcher; + SwatchPage *docPalette = (docPalettes.find(document) != docPalettes.end()) ? docPalettes[document] : 0; + if (docPalette && !DocTrack::queueUpdateIfNeeded(document) ) { + boost::ptr_vector tmpColors; + std::map tmpPrevs; + std::map tmpGrads; + recalcSwatchContents(document, tmpColors, tmpPrevs, tmpGrads); + + if ( tmpColors.size() != docPalette->_colors.size() ) { + handleGradientsChange(document); + } else { + int cap = std::min(docPalette->_colors.size(), tmpColors.size()); + for (int i = 0; i < cap; i++) { + ColorItem *newColor = &tmpColors[i]; + ColorItem *oldColor = &docPalette->_colors[i]; + if ( (newColor->def.getType() != oldColor->def.getType()) || + (newColor->def.getR() != oldColor->def.getR()) || + (newColor->def.getG() != oldColor->def.getG()) || + (newColor->def.getB() != oldColor->def.getB()) ) { + oldColor->def.setRGB(newColor->def.getR(), newColor->def.getG(), newColor->def.getB()); + } + if (tmpGrads.find(newColor) != tmpGrads.end()) { + oldColor->setGradient(tmpGrads[newColor]); + } + if ( tmpPrevs.find(newColor) != tmpPrevs.end() ) { + oldColor->setPattern(tmpPrevs[newColor]); + } + } + } + + for (std::map::iterator it = tmpPrevs.begin(); it != tmpPrevs.end(); ++it) { + cairo_pattern_destroy(it->second); + } } - - if (docWatcher) { - docWatcher->_repr->removeObserver(*docWatcher); - delete docWatcher; +} + + +std::vector SwatchesPanel::_getSwatchSets() const +{ + std::vector tmp; + if (docPalettes.find(_currentDocument) != docPalettes.end()) { + tmp.push_back(docPalettes[_currentDocument]); } - _documentConnection.disconnect(); - _selChanged.disconnect(); + tmp.insert(tmp.end(), userSwatchPages.begin(), userSwatchPages.end()); + tmp.insert(tmp.end(), systemSwatchPages.begin(), systemSwatchPages.end()); + + return tmp; } -void SwatchesPanel::setDesktop( SPDesktop* desktop ) +void SwatchesPanel::_updateFromSelection() { - Inkscape::UI::Widget::Panel::setDesktop(desktop); - if ( desktop != _currentDesktop ) { - if ( _currentDesktop ) { - _documentConnection.disconnect(); - _selChanged.disconnect(); + SwatchPage *docPalette = (docPalettes.find(_currentDocument) != docPalettes.end()) ? docPalettes[_currentDocument] : 0; + if ( docPalette ) { + Glib::ustring fillId; + Glib::ustring strokeId; + + SPStyle *tmpStyle = sp_style_new( sp_desktop_document(_currentDesktop) ); + int result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_FILL ); + switch (result) { + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + { + if (tmpStyle->fill.set && tmpStyle->fill.isPaintserver()) { + SPPaintServer* server = tmpStyle->getFillPaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* target = 0; + SPGradient* grad = SP_GRADIENT(server); + + if ( grad->isSwatch() ) { + target = grad; + } else if ( grad->ref ) { + SPGradient *tmp = grad->ref->getObject(); + if ( tmp && tmp->isSwatch() ) { + target = tmp; + } + } + if ( target ) { + //XML Tree being used directly here while it shouldn't be + gchar const* id = target->getRepr()->attribute("id"); + if ( id ) { + fillId = id; + } + } + } + } + break; + } } - _currentDesktop = desktop; + result = sp_desktop_query_style( _currentDesktop, tmpStyle, QUERY_STYLE_PROPERTY_STROKE ); + switch (result) { + case QUERY_STYLE_SINGLE: + case QUERY_STYLE_MULTIPLE_AVERAGED: + case QUERY_STYLE_MULTIPLE_SAME: + { + if (tmpStyle->stroke.set && tmpStyle->stroke.isPaintserver()) { + SPPaintServer* server = tmpStyle->getStrokePaintServer(); + if ( SP_IS_GRADIENT(server) ) { + SPGradient* target = 0; + SPGradient* grad = SP_GRADIENT(server); + if ( grad->isSwatch() ) { + target = grad; + } else if ( grad->ref ) { + SPGradient *tmp = grad->ref->getObject(); + if ( tmp && tmp->isSwatch() ) { + target = tmp; + } + } + if ( target ) { + //XML Tree being used directly here while it shouldn't be + gchar const* id = target->getRepr()->attribute("id"); + if ( id ) { + strokeId = id; + } + } + } + } + break; + } + } + sp_style_unref(tmpStyle); - if ( desktop ) { - //_currentDesktop->selection->connectChanged(sigc::hide(sigc::mem_fun(*this, &SwatchesPanel::_updateFromSelection))); + for ( boost::ptr_vector::iterator it = docPalette->_colors.begin(); it != docPalette->_colors.end(); ++it ) { + ColorItem* item = &*it; + bool isFill = (fillId == item->def.descr); + bool isStroke = (strokeId == item->def.descr); + item->setState( isFill, isStroke ); + } + } +} - _documentConnection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &SwatchesPanel::_setDocument)); +void SwatchesPanel::_handleAction( int setId, int itemId ) +{ + switch( setId ) { + case 3: + { + std::vector pages = _getSwatchSets(); + if ( itemId >= 0 && itemId < static_cast(pages.size()) ) { + _currentIndex = itemId; - _setDocument( desktop, desktop->doc() ); - } else { - _setDocument(0, 0); + if ( !_prefs_path.empty() ) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString(_prefs_path + "/palette", pages[_currentIndex]->_name); + } + + _rebuild(); + } } + break; } } -void SwatchesPanel::_setDocument( SPDesktop* desktop, SPDocument *document ) +void SwatchesPanel::_rebuild() { - if ( document != _currentDocument ) { - if (docWatcher) { - docWatcher->_repr->removeObserver(*docWatcher); - delete docWatcher; - docWatcher = NULL; - } - _currentDocument = document; - - if (_currentDocument) { - docWatcher = new SwatchWatcher(this, _currentDocument->getDefs(), false); - _currentDocument->getDefs()->getRepr()->addObserver(*docWatcher); - } - _defsChanged(); + std::vector pages = _getSwatchSets(); + SwatchPage* curr = pages[_currentIndex]; + _holder->clear(); + + if ( curr->_prefWidth > 0 ) { + _holder->setColumnPref( curr->_prefWidth ); } + _holder->freezeUpdates(); + // TODO restore once 'clear' works _holder->addPreview(_clear); + _holder->addPreview(_remove); + for ( boost::ptr_vector::iterator it = curr->_colors.begin(); it != curr->_colors.end(); ++it) { + _holder->addPreview(&*it); + } + _holder->thawUpdates(); } } //namespace Dialogs } //namespace UI } //namespace Inkscape -//really lazy! -void sp_desktop_set_gradient(SPDesktop *desktop, SPGradient* gradient, bool fill) -{ - - bool intercepted = false; - - if (gradient->isSolid()) { - ColorRGBA color(gradient->getFirstStop()->getEffectiveColor().toRGBA32(gradient->getFirstStop()->opacity)); - guint32 rgba = SP_RGBA32_F_COMPOSE(color[0], color[1], color[2], color[3]); - gchar b[64]; - sp_svg_write_color(b, sizeof(b), rgba); - SPCSSAttr *css = sp_repr_css_attr_new(); - if (fill) { - sp_repr_css_set_property(css, "fill", b); - Inkscape::CSSOStringStream osalpha; - osalpha << color[3]; - sp_repr_css_set_property(css, "fill-opacity", osalpha.str().c_str()); - } else { - sp_repr_css_set_property(css, "stroke", b); - Inkscape::CSSOStringStream osalpha; - osalpha << color[3]; - sp_repr_css_set_property(css, "stroke-opacity", osalpha.str().c_str()); - } - intercepted = desktop->_set_style_signal.emit(css); - } - - if (!intercepted) { - for (const GSList *it = desktop->selection->itemList(); it != NULL; it = it->next) { - sp_item_set_gradient(SP_ITEM(it->data), gradient, SP_IS_RADIALGRADIENT(gradient) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, !fill ? Inkscape::FOR_STROKE : Inkscape::FOR_FILL); - } - } -} /* Local Variables: diff --git a/src/ui/dialog/swatches.h b/src/ui/dialog/swatches.h index cb8f87962..ca4c1687d 100644 --- a/src/ui/dialog/swatches.h +++ b/src/ui/dialog/swatches.h @@ -12,161 +12,64 @@ #include "ui/widget/panel.h" #include "enums.h" -#include "sp-object.h" -#include "sp-item-group.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sp-gradient.h" -#include "xml/node-observer.h" namespace Inkscape { namespace UI { +class PreviewHolder; + namespace Dialogs { +class ColorItem; +class SwatchPage; +class DocTrack; + /** * A panel that displays paint swatches. */ class SwatchesPanel : public Inkscape::UI::Widget::Panel { public: - SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches", bool showLabels = true); + SwatchesPanel(gchar const* prefsPath = "/dialogs/swatches"); virtual ~SwatchesPanel(); - + static SwatchesPanel& getInstance(); + virtual void setOrientation(SPAnchorType how); + virtual void setDesktop( SPDesktop* desktop ); virtual SPDesktop* getDesktop() {return _currentDesktop;} + virtual int getSelectedIndex() {return _currentIndex;} // temporary + protected: + static void handleGradientsChange(SPDocument *document); + + virtual void _updateFromSelection(); + virtual void _handleAction( int setId, int itemId ); + virtual void _setDocument( SPDocument *document ); + virtual void _rebuild(); - virtual void _setDocument( SPDesktop* desktop, SPDocument *document ); + virtual std::vector _getSwatchSets() const; private: - class ModelColumns; - class ModelColumnsDoc; - - class StopWatcher; - class GradientWatcher; - class SwatchWatcher; - SwatchesPanel(SwatchesPanel const &); // no copy SwatchesPanel &operator=(SwatchesPanel const &); // no assign - - void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback ); - - void _setSelectionSwatch(SPGradient* swatchItem, bool isStroke); - - void NoLinkToggled(); - void NewGroup(); - void NewGroupBI(); - void _addBIButtonClicked(GdkEventButton* event); - void Duplicate(SPGroup* page); - void SaveAs(); - void AddSelectedFill(SPGroup* page); - void AddSelectedStroke(SPGroup* page); - void MoveUp(SPGroup* page); - void MoveDown(SPGroup* page); - void Remove(SPGroup* page); - - void SetSelectedFill(SPGradient* swatch); - void SetSelectedStroke(SPGradient* swatch); - void MoveSwatchUp(SPGradient* swatch); - void MoveSwatchDown(SPGradient* swatch); - void RemoveSwatch(SPGradient* swatch); - - void _lblClick(GdkEventButton* event, SPGroup* page); - void _addSwatchButtonClicked(SPGroup* swatch, bool recurse); - void _defsChanged(); - void _importButtonClicked(bool addToDoc, bool addToBI); - void _deleteButtonClicked(); - void _addButtonClicked(GdkEventButton* event); - void _swatchClicked(GdkEventButton* event, SPGradient* swatchItem); - - Gtk::MenuItem* _addSwatchGroup(SPGroup* group, Gtk::TreeModel::Row* parentRow); - void _swatchesChanged(); - - bool _handleButtonEvent(GdkEventButton *event); - bool _handleKeyEvent(GdkEventKey *event); - - void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelled(); - void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); - - void _setCollapsed(SPGroup * group); - void _setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded); - - void _deleteButtonClickedDoc(); - bool _handleButtonEventDoc(GdkEventButton* event); - bool _handleKeyEventDoc(GdkEventKey *event); - - void _handleEditedDoc(const Glib::ustring& path, const Glib::ustring& new_text); - void _handleEditingCancelledDoc(); - void _renameObjectDoc(Gtk::TreeModel::Row row, const Glib::ustring& name); - - bool _handleDragDropDoc(const Glib::RefPtr& context, int x, int y, guint time); - bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); - - Gtk::Menu *popUpMenu; - Gtk::Menu *popUpImportMenu; - - Gtk::ScrolledWindow _scroller; - Gtk::Table _insideTable; - Gtk::VBox _insideV; - Gtk::HBox _insideH; - Gtk::HBox _buttonsRow; - Gtk::VBox _outsideV; - Gtk::CheckButton _noLink; - bool _showlabels; - - SwatchesPanel::ModelColumns* _model; - Glib::RefPtr _store; - - Gtk::CellRendererText *_text_rendererBI; - Gtk::TreeView::Column *_name_columnBI; - Gtk::ScrolledWindow _scrollerBI; - Gtk::TreeView _editBI; - Gtk::HBox _buttonsRowBI; - Gtk::VBox _editBIV; - - SwatchesPanel::ModelColumnsDoc* _modelDoc; - Glib::RefPtr _storeDoc; - - Gtk::CellRendererText *_text_rendererDoc; - Gtk::CellRendererPixbuf *_pixbuf_rendererDoc; - Gtk::TreeView::Column *_name_columnDoc; - Gtk::TreeView::Column *_pixbuf_columnDoc; - Gtk::ScrolledWindow _scrollerDoc; - Gtk::TreeView _editDoc; - Gtk::HBox _buttonsRowDoc; - Gtk::VBox _editDocV; - - Gtk::Notebook _notebook; - - SwatchWatcher* rootWatcher; - std::vector rootWatchers; - - std::vector docWatchers; - SwatchWatcher* docWatcher; + static void _trackDocument( SwatchesPanel *panel, SPDocument *document ); + static void handleDefsModified(SPDocument *document); + + PreviewHolder* _holder; + ColorItem* _clear; + ColorItem* _remove; + int _currentIndex; SPDesktop* _currentDesktop; SPDocument* _currentDocument; - - bool _dnd_into; - SPObject* _dnd_source; - SPObject* _dnd_target; sigc::connection _documentConnection; sigc::connection _selChanged; + + friend class DocTrack; }; } //namespace Dialogs -- cgit v1.2.3 From 9a04c985ec628dc749a8a82d94bcf47d482a4f63 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Thu, 20 Mar 2014 17:09:57 -0400 Subject: Fix a linker error ("static") (hopefully) Resolve compiler errors with GTK3+ (bzr r13090.1.28) --- src/ui/dialog/objects.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 338233042..85583a0e7 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -1887,8 +1887,9 @@ ObjectsPanel::ObjectsPanel() : btn = Gtk::manage( new Gtk::Button() ); btn->set_tooltip_text(_("Collapse All")); #if GTK_CHECK_VERSION(3,10,0) - btn->set_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); + btn->set_image_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); #else + image_remove = Gtk::manage(new Gtk::Image()); image_remove->set_from_icon_name(INKSCAPE_ICON("gtk-unindent-ltr"), Gtk::ICON_SIZE_SMALL_TOOLBAR); btn->set_image(*image_remove); #endif -- cgit v1.2.3 From 4038de8b4763974c97aa8fcb9d87b83c1a5daac7 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 10 May 2014 15:16:24 -0400 Subject: Add selection sets (bzr r13090.1.75) --- src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/dialog-manager.cpp | 6 +- src/ui/dialog/tags.cpp | 1155 ++++++++++++++++++++++++++++++++++++++ src/ui/dialog/tags.h | 181 ++++++ 4 files changed, 1341 insertions(+), 3 deletions(-) create mode 100644 src/ui/dialog/tags.cpp create mode 100644 src/ui/dialog/tags.h (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index 8a7a4a5dd..1aa73dc5b 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -100,6 +100,8 @@ ink_common_sources += \ ui/dialog/template-load-tab.h \ ui/dialog/template-widget.cpp \ ui/dialog/template-widget.h \ + ui/dialog/tags.cpp \ + ui/dialpg/tags.h \ ui/dialog/text-edit.cpp \ ui/dialog/text-edit.h \ ui/dialog/tile.cpp \ diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 22c41d75e..bd2f1eb12 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -55,7 +55,7 @@ #include "ui/dialog/clonetiler.h" #include "ui/dialog/svg-fonts-dialog.h" #include "ui/dialog/objects.h" -//#include "ui/dialog/tags.h" +#include "ui/dialog/tags.h" namespace Inkscape { namespace UI { @@ -113,7 +113,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); -// registerFactory("TagsPanel", &create); + registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); @@ -148,7 +148,7 @@ DialogManager::DialogManager() { registerFactory("IconPreviewPanel", &create); registerFactory("LayersPanel", &create); registerFactory("ObjectsPanel", &create); -// registerFactory("TagsPanel", &create); + registerFactory("TagsPanel", &create); registerFactory("LivePathEffect", &create); registerFactory("Memory", &create); registerFactory("Messages", &create); diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp new file mode 100644 index 000000000..7fdd2e906 --- /dev/null +++ b/src/ui/dialog/tags.cpp @@ -0,0 +1,1155 @@ +/* + * A simple panel for tags + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "tags.h" +#include +#include +#include +#include + +#include + +#include "desktop.h" +#include "desktop-style.h" +#include "document.h" +#include "document-undo.h" +#include "helper/action.h" +#include "inkscape.h" +#include "layer-fns.h" +#include "layer-manager.h" +#include "preferences.h" +#include "sp-item.h" +#include "sp-object.h" +#include "sp-shape.h" +#include "svg/css-ostringstream.h" +#include "ui/icon-names.h" +#include "ui/widget/layertypeicon.h" +#include "ui/widget/addtoicon.h" +#include "verbs.h" +#include "widgets/icon.h" +#include "xml/node.h" +#include "xml/node-observer.h" +#include "xml/repr.h" +#include "sp-root.h" +#include "ui/tools/tool-base.h" //"event-context.h" +#include "selection.h" +#include "dialogs/dialog-events.h" +#include "widgets/sp-color-notebook.h" +#include "style.h" +#include "filter-chemistry.h" +#include "filters/blend.h" +#include "filters/gaussian-blur.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "sp-tag.h" +#include "sp-defs.h" +#include "sp-tag-use.h" +#include "sp-tag-use-reference.h" + +//#define DUMP_LAYERS 1 + +namespace Inkscape { +namespace UI { +namespace Dialog { + +using Inkscape::XML::Node; + +TagsPanel& TagsPanel::getInstance() +{ + return *new TagsPanel(); +} + +enum { + COL_ADD = 1 +}; + +enum { + BUTTON_NEW = 0, + BUTTON_TOP, + BUTTON_BOTTOM, + BUTTON_UP, + BUTTON_DOWN, + BUTTON_DELETE, + DRAGNDROP +}; + +class TagsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver { +public: + ObjectWatcher(TagsPanel* pnl, SPObject* obj, Inkscape::XML::Node * repr) : + _pnl(pnl), + _obj(obj), + _repr(repr), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + ObjectWatcher(TagsPanel* pnl, SPObject* obj) : + _pnl(pnl), + _obj(obj), + _repr(obj->getRepr()), + _labelAttr(g_quark_from_string("inkscape:label")) + {} + + virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ ) + { + if ( _pnl && _obj ) { + _pnl->_objectsChanged( _obj ); + } + } + virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared /*old_content*/, Util::ptr_shared /*new_content*/ ) {} + virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared /*old_value*/, Util::ptr_shared /*new_value*/ ) { + if ( _pnl && _obj ) { + if ( name == _labelAttr ) { + _pnl->_updateObject( _obj); + } + } + } + + TagsPanel* _pnl; + SPObject* _obj; + Inkscape::XML::Node* _repr; + GQuark _labelAttr; +}; + +class TagsPanel::InternalUIBounce +{ +public: + int _actionCode; +}; + +void TagsPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ) +{ + bool set = false; + + if ( iconName ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + btn.set_relief(Gtk::RELIEF_NONE); + set = true; + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !set && action && action->image ) { + GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image ); + gtk_widget_show( child ); + btn.add( *manage(Glib::wrap(child)) ); + set = true; + } + } + } + + btn.set_tooltip_text (tooltip); +} + + +Gtk::MenuItem& TagsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ) +{ + GtkWidget* iconWidget = 0; + const char* label = 0; + + if ( iconName ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName ); + } + + if ( desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(desktop); + if ( !iconWidget && action && action->image ) { + iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image ); + } + + if ( action ) { + label = action->name; + } + } + } + + if ( !label && fallback ) { + label = fallback; + } + + Gtk::Widget* wrapped = 0; + if ( iconWidget ) { + wrapped = manage(Glib::wrap(iconWidget)); + wrapped->show(); + } + + + Gtk::MenuItem* item = 0; + + if (wrapped) { + item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true)); + } else { + item = Gtk::manage(new Gtk::MenuItem(label, true)); + } + + item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &TagsPanel::_takeAction), id)); + _popupMenu.append(*item); + + return *item; +} + +void TagsPanel::_fireAction( unsigned int code ) +{ + if ( _desktop ) { + Verb *verb = Verb::get( code ); + if ( verb ) { + SPAction *action = verb->get_action(_desktop); + if ( action ) { + sp_action_perform( action, NULL ); + } + } + } +} + +void TagsPanel::_takeAction( int val ) +{ + if ( !_pending ) { + _pending = new InternalUIBounce(); + _pending->_actionCode = val; + Glib::signal_timeout().connect( sigc::mem_fun(*this, &TagsPanel::_executeAction), 0 ); + } +} + +bool TagsPanel::_executeAction() +{ + // Make sure selected layer hasn't changed since the action was triggered + if ( _pending) + { + int val = _pending->_actionCode; +// SPObject* target = _pending->_target; + bool empty = _desktop->selection->isEmpty(); + + switch ( val ) { + case BUTTON_NEW: + { + _fireAction( SP_VERB_TAG_NEW ); + } + break; + case BUTTON_TOP: + { + _fireAction( empty ? SP_VERB_LAYER_TO_TOP : SP_VERB_SELECTION_TO_FRONT); + } + break; + case BUTTON_BOTTOM: + { + _fireAction( empty ? SP_VERB_LAYER_TO_BOTTOM : SP_VERB_SELECTION_TO_BACK ); + } + break; + case BUTTON_UP: + { + _fireAction( empty ? SP_VERB_LAYER_RAISE : SP_VERB_SELECTION_RAISE ); + } + break; + case BUTTON_DOWN: + { + _fireAction( empty ? SP_VERB_LAYER_LOWER : SP_VERB_SELECTION_LOWER ); + } + break; + case BUTTON_DELETE: + { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + break; + case DRAGNDROP: + { + _doTreeMove( ); + } + break; + } + + delete _pending; + _pending = 0; + } + + return false; +} + + +class TagsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord +{ +public: + + ModelColumns() + { + add(_colParentObject); + add(_colObject); + add(_colLabel); + add(_colAddRemove); + add(_colAllowAddRemove); + } + virtual ~ModelColumns() {} + + Gtk::TreeModelColumn _colParentObject; + Gtk::TreeModelColumn _colObject; + Gtk::TreeModelColumn _colLabel; + Gtk::TreeModelColumn _colAddRemove; + Gtk::TreeModelColumn _colAllowAddRemove; +}; + +void TagsPanel::_checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete) +{ + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && obj->parent) { + todelete->push_back(obj); + } +} + +void TagsPanel::_updateObject( SPObject *obj ) { + _store->foreach( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_checkForUpdated), obj) ); +} + +bool TagsPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + if ( obj == row[_model->_colObject] ) + { + /* + * We get notified of layer update here (from layer->setLabel()) before layer->label() is set + * with the correct value (sp-object bug?). So use the inkscape:label attribute instead which + * has the correct value (bug #168351) + */ + //row[_model->_colLabel] = layer->label() ? layer->label() : layer->getId(); + gchar const *label; + SPTagUse * use = SP_IS_TAG_USE(obj) ? SP_TAG_USE(obj) : 0; + if (use && use->ref->isAttached()) { + label = use->ref->getObject()->getAttribute("inkscape:label"); + } else { + label = obj->getAttribute("inkscape:label"); + } + row[_model->_colLabel] = label ? label : obj->getId(); + row[_model->_colAddRemove] = SP_IS_TAG(obj); + } + + return false; +} + +void TagsPanel::_objectsSelected( Selection *sel ) { + + _selectedConnection.block(); + _tree.get_selection()->unselect_all(); + for (const GSList * iter = sel->list(); iter != NULL; iter = iter->next) + { + SPObject *obj = reinterpret_cast(iter->data); + _store->foreach(sigc::bind( sigc::mem_fun(*this, &TagsPanel::_checkForSelected), obj)); + } + _selectedConnection.unblock(); + _checkTreeSelection(); +} + +bool TagsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj) +{ + Gtk::TreeModel::Row row = *iter; + SPObject * it = row[_model->_colObject]; + if ( it && SP_IS_TAG_USE(it) && SP_TAG_USE(it)->ref->getObject() == obj ) + { + Glib::RefPtr select = _tree.get_selection(); + + select->select(iter); + } + return false; +} + +void TagsPanel::_objectsChanged(SPObject* root) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_desktop) { + SPDocument* document = _desktop->doc(); + SPDefs* root = document->getDefs(); + if ( root ) { + _selectedConnection.block(); + _store->clear(); + _addObject( document, root, 0 ); + _selectedConnection.unblock(); + _objectsSelected(_desktop->selection); + _checkTreeSelection(); + } + } +} + +void TagsPanel::_addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ) +{ + if ( _desktop && obj ) { + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG(child)) + { + Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = child->label() ? child->label() : child->getId(); + row[_model->_colAddRemove] = true; + row[_model->_colAllowAddRemove] = true; + + _tree.expand_to_path( _store->get_path(iter) ); + + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child); + child->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + _addObject( doc, child, &row ); + } + } + if (SP_IS_TAG(obj) && obj->children) + { + Gtk::TreeModel::iterator iteritems = parentRow ? _store->append(parentRow->children()) : _store->prepend(); + Gtk::TreeModel::Row rowitems = *iteritems; + rowitems[_model->_colObject] = NULL; + rowitems[_model->_colParentObject] = obj; + rowitems[_model->_colLabel] = _("Items"); + rowitems[_model->_colAddRemove] = false; + rowitems[_model->_colAllowAddRemove] = false; + + _tree.expand_to_path( _store->get_path(iteritems) ); + + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child)) + { + SPItem *item = SP_TAG_USE(child)->ref->getObject(); + Gtk::TreeModel::iterator iter = _store->prepend(rowitems->children()); + Gtk::TreeModel::Row row = *iter; + row[_model->_colObject] = child; + row[_model->_colParentObject] = NULL; + row[_model->_colLabel] = item ? (item->label() ? item->label() : item->getId()) : SP_TAG_USE(child)->href; + row[_model->_colAddRemove] = false; + row[_model->_colAllowAddRemove] = true; + + if (SP_TAG(obj)->expanded()) { + _tree.expand_to_path( _store->get_path(iter) ); + } + + if (item) { + TagsPanel::ObjectWatcher *w = new TagsPanel::ObjectWatcher(this, child, item->getRepr()); + item->getRepr()->addObserver(*w); + _objectWatchers.push_back(w); + } + } + } + } + } +} + +void TagsPanel::_select_tag( SPTag * tag ) +{ + for (SPObject * child = tag->children; child != NULL; child = child->next) + { + if (SP_IS_TAG(child)) { + _select_tag(SP_TAG(child)); + } else if (SP_IS_TAG_USE(child)) { + SPObject * obj = SP_TAG_USE(child)->ref->getObject(); + if (obj) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(obj->parent); + _desktop->selection->add(obj); + } + } + } +} + +void TagsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter ) +{ + if (iter) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _select_tag(SP_TAG(obj)); + } else if (SP_IS_TAG_USE(obj)) { + SPObject * item = SP_TAG_USE(obj)->ref->getObject(); + if (item) { + if (_desktop->selection->isEmpty()) _desktop->setCurrentLayer(item->parent); + _desktop->selection->add(item); + } + } + } + } +} + +void TagsPanel::_pushTreeSelectionToCurrent() +{ + _selectionChangedConnection.block(); + // TODO hunt down the possible API abuse in getting NULL + if ( _desktop && _desktop->currentRoot() ) { + _desktop->selection->clear(); + _tree.get_selection()->selected_foreach_iter( sigc::mem_fun(*this, &TagsPanel::_selected_row_callback)); + } + _selectionChangedConnection.unblock(); + + _checkTreeSelection(); +} + +void TagsPanel::_checkTreeSelection() +{ + bool sensitive = _tree.get_selection()->count_selected_rows() > 0; + bool sensitiveNonTop = true; + bool sensitiveNonBottom = true; +// if ( _tree.get_selection()->count_selected_rows() > 0 ) { +// sensitive = true; +// +// SPObject* inTree = _selectedLayer(); +// if ( inTree ) { +// +// sensitiveNonTop = (Inkscape::Nex(inTree->parent, inTree) != 0); +// sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0); +// +// } +// } + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( sensitive ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonTop ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( sensitiveNonBottom ); + } +} + +bool TagsPanel::_handleKeyEvent(GdkEventKey *event) +{ + + switch (Inkscape::UI::Tools::get_group0_keyval(event)) { + case GDK_KEY_Return: + case GDK_KEY_KP_Enter: + case GDK_KEY_F2: { + Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected(); + if (iter && !_text_renderer->property_editable()) { + Gtk::TreeRow row = *iter; + SPObject * obj = row[_model->_colObject]; + if (obj && SP_IS_TAG(obj)) { + Gtk::TreeModel::Path *path = new Gtk::TreeModel::Path(iter); + // Edit the layer label + _text_renderer->property_editable() = true; + _tree.set_cursor(*path, *_name_column, true); + grab_focus(); + return true; + } + } + } + case GDK_KEY_Delete: { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * obj = *iter; + if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + return true; + } + break; + } + return false; +} + +bool TagsPanel::_handleButtonEvent(GdkEventButton* event) +{ + static unsigned doubleclick = 0; + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3) ) { + // TODO - fix to a better is-popup function + Gtk::TreeModel::Path path; + int x = static_cast(event->x); + int y = static_cast(event->y); + if ( _tree.get_path_at_pos( x, y, path ) ) { + _checkTreeSelection(); + _popupMenu.popup(event->button, event->time); + if (_tree.get_selection()->is_selected(path)) { + return true; + } + } + } + + if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 1)) { + // Alt left click on the visible/lock columns - eat this event to keep row selection + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (col == _tree.get_column(COL_ADD-1)) { + down_at_add = true; + return true; + } else if ( !(event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK)) & _tree.get_selection()->is_selected(path) ) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_noSelection)); + _defer_target = path; + } else { + down_at_add = false; + } + } else { + down_at_add = false; + } + } + + if ( event->type == GDK_BUTTON_RELEASE) { + _tree.get_selection()->set_select_function(sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction)); + } + + // TODO - ImageToggler doesn't seem to handle Shift/Alt clicks - so we deal with them here. + if ( (event->type == GDK_BUTTON_RELEASE) && (event->button == 1)) { + + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) ) { + if (_defer_target) { + if (_defer_target == path && !(event->x == 0 && event->y == 0)) + { + _tree.set_cursor(path, *col, false); + } + _defer_target = Gtk::TreeModel::Path(); + } else { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + + if (obj) { + if (col == _tree.get_column(COL_ADD - 1) && down_at_add) { + if (SP_IS_TAG(obj)) { + bool wasadded = false; + for (const GSList * iter = _desktop->selection->itemList(); iter != NULL; iter = iter->next) + { + SPObject *newobj = reinterpret_cast(iter->data); + bool addchild = true; + for ( SPObject *child = obj->children; child != NULL; child = child->next) { + if (SP_IS_TAG_USE(child) && SP_TAG_USE(child)->ref->getObject() == newobj) { + addchild = false; + } + } + if (addchild) { + Inkscape::XML::Node *clone = _document->getReprDoc()->createElement("inkscape:tagref"); + clone->setAttribute("xlink:href", g_strdup_printf("#%s", newobj->getRepr()->attribute("id")), false); + obj->appendChild(clone); + wasadded = true; + } + } + if (wasadded) { + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Add selection to set")); + } + } else { + std::vector todelete; + _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); + if (!todelete.empty()) { + for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { + SPObject * tobj = *iter; + if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { + tobj->parent->getRepr()->removeChild(tobj->getRepr()); + } + } + } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { + obj->parent->getRepr()->removeChild(obj->getRepr()); + } + DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); + } + } + } + } + } + } + + + if ( (event->type == GDK_2BUTTON_PRESS) && (event->button == 1) ) { + doubleclick = 1; + } + + if ( event->type == GDK_BUTTON_RELEASE && doubleclick) { + doubleclick = 0; + Gtk::TreeModel::Path path; + Gtk::TreeViewColumn* col = 0; + int x = static_cast(event->x); + int y = static_cast(event->y); + int x2 = 0; + int y2 = 0; + if ( _tree.get_path_at_pos( x, y, path, col, x2, y2 ) && col == _name_column) { + Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colObject]; + if (obj && (SP_IS_TAG(obj) || (SP_IS_TAG_USE(obj) && SP_TAG_USE(obj)->ref->getObject()))) { + // Double click on the Layer name, enable editing + _text_renderer->property_editable() = true; + _tree.set_cursor (path, *_name_column, true); + grab_focus(); + } + } + } + + return false; +} + +void TagsPanel::_storeDragSource(const Gtk::TreeModel::iterator& iter) +{ + Gtk::TreeModel::Row row = *iter; + SPObject* obj = row[_model->_colObject]; + SPTag* item = ( obj && SP_IS_TAG(obj) ) ? SP_TAG(obj) : 0; + if (item) + { + _dnd_source.push_back(item); + } +} + +/* + * Drap and drop within the tree + * Save the drag source and drop target SPObjects and if its a drag between layers or into (sublayer) a layer + */ +bool TagsPanel::_handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time) +{ + int cell_x = 0, cell_y = 0; + Gtk::TreeModel::Path target_path; + Gtk::TreeView::Column *target_column; + + _dnd_into = true; + _dnd_target = _document->getDefs(); + _dnd_source.clear(); + _tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &TagsPanel::_storeDragSource)); + + if (_dnd_source.empty()) { + return true; + } + + if (_tree.get_path_at_pos (x, y, target_path, target_column, cell_x, cell_y)) { + // Are we before, inside or after the drop layer + Gdk::Rectangle rect; + _tree.get_background_area (target_path, *target_column, rect); + int cell_height = rect.get_height(); + _dnd_into = (cell_y > (int)(cell_height * 1/3) && cell_y <= (int)(cell_height * 2/3)); + if (cell_y > (int)(cell_height * 2/3)) { + Gtk::TreeModel::Path next_path = target_path; + next_path.next(); + if (_store->iter_is_valid(_store->get_iter(next_path))) { + target_path = next_path; + } else { + // Dragging to the "end" + Gtk::TreeModel::Path up_path = target_path; + up_path.up(); + if (_store->iter_is_valid(_store->get_iter(up_path))) { + // Drop into parent + target_path = up_path; + _dnd_into = true; + } else { + // Drop into the top level + _dnd_target = _document->getDefs(); + _dnd_into = true; + } + } + } + Gtk::TreeModel::iterator iter = _store->get_iter(target_path); + if (_store->iter_is_valid(iter)) { + Gtk::TreeModel::Row row = *iter; + SPObject *obj = row[_model->_colObject]; + SPObject *pobj = row[_model->_colParentObject]; + if (obj) { + if (SP_IS_TAG(obj)) { + _dnd_target = SP_TAG(obj); + } else if (SP_IS_TAG(obj->parent)) { + _dnd_target = SP_TAG(obj->parent); + _dnd_into = true; + } + } else if (pobj && SP_IS_TAG(pobj)) { + _dnd_target = SP_TAG(pobj); + _dnd_into = true; + } else { + return true; + } + } + } + + _takeAction(DRAGNDROP); + + return false; +} + +/* + * Move a layer in response to a drag & drop action + */ +void TagsPanel::_doTreeMove( ) +{ + if (_dnd_target) { + for (std::vector::iterator iter = _dnd_source.begin(); iter != _dnd_source.end(); ++iter) + { + SPTag *src = *iter; + if (src != _dnd_target) { + src->moveTo(_dnd_target, _dnd_into); + } + } + _desktop->selection->clear(); + while (!_dnd_source.empty()) + { + SPTag *src = _dnd_source.back(); + _select_tag(src); + _dnd_source.pop_back(); + } + DocumentUndo::done( _desktop->doc() , SP_VERB_DIALOG_TAGS, + _("Moved sets")); + } +} + + +void TagsPanel::_handleEdited(const Glib::ustring& path, const Glib::ustring& new_text) +{ + Gtk::TreeModel::iterator iter = _tree.get_model()->get_iter(path); + Gtk::TreeModel::Row row = *iter; + + _renameObject(row, new_text); + _text_renderer->property_editable() = false; +} + +void TagsPanel::_handleEditingCancelled() +{ + _text_renderer->property_editable() = false; +} + +void TagsPanel::_renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name) +{ + if ( row && _desktop) { + SPObject* obj = row[_model->_colObject]; + if ( obj ) { + if (SP_IS_TAG(obj)) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } else if (SP_IS_TAG_USE(obj) && (obj = SP_TAG_USE(obj)->ref->getObject())) { + gchar const* oldLabel = obj->label(); + if ( !name.empty() && (!oldLabel || name != oldLabel) ) { + obj->setLabel(name.c_str()); + DocumentUndo::done( _desktop->doc() , SP_VERB_NONE, + _("Rename object")); + } + } + } + } +} + +bool TagsPanel::_noSelection( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + return false; +} + +bool TagsPanel::_rowSelectFunction( Glib::RefPtr const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected ) +{ + bool val = true; + if ( !currentlySelected && _toggleEvent ) + { + GdkEvent* event = gtk_get_current_event(); + if ( event ) { + // (keep these checks separate, so we know when to call gdk_event_free() + if ( event->type == GDK_BUTTON_PRESS ) { + GdkEventButton const* target = reinterpret_cast(_toggleEvent); + GdkEventButton const* evtb = reinterpret_cast(event); + + if ( (evtb->window == target->window) + && (evtb->send_event == target->send_event) + && (evtb->time == target->time) + && (evtb->state == target->state) + ) + { + // Ooooh! It's a magic one + val = false; + } + } + gdk_event_free(event); + } + } + return val; +} + +void TagsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded) +{ + Gtk::TreeModel::Row row = *iter; + + SPObject* obj = row[_model->_colParentObject]; + if (obj && SP_IS_TAG(obj)) + { + SP_TAG(obj)->setExpanded(isexpanded); + obj->updateRepr(SP_OBJECT_WRITE_NO_CHILDREN | SP_OBJECT_WRITE_EXT); + } +} + +/** + * Constructor + */ +TagsPanel::TagsPanel() : + UI::Widget::Panel("", "/dialogs/tags", SP_VERB_DIALOG_TAGS), + _rootWatcher(0), + deskTrack(), + _desktop(0), + _document(0), + _model(0), + _pending(0), + _toggleEvent(0), + _defer_target(), + desktopChangeConn() +{ + //Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + ModelColumns *zoop = new ModelColumns(); + _model = zoop; + + _store = Gtk::TreeStore::create( *zoop ); + + _tree.set_model( _store ); + _tree.set_headers_visible(false); + _tree.set_reorderable(true); + _tree.enable_model_drag_dest (Gdk::ACTION_MOVE); + + Inkscape::UI::Widget::AddToIcon * addRenderer = manage( new Inkscape::UI::Widget::AddToIcon()); + int addColNum = _tree.append_column("type", *addRenderer) - 1; + Gtk::TreeViewColumn *col = _tree.get_column(addColNum); + if ( col ) { + col->add_attribute( addRenderer->property_active(), _model->_colAddRemove ); + col->add_attribute( addRenderer->property_visible(), _model->_colAllowAddRemove ); + } + + _text_renderer = manage(new Gtk::CellRendererText()); + int nameColNum = _tree.append_column("Name", *_text_renderer) - 1; + _name_column = _tree.get_column(nameColNum); + _name_column->add_attribute(_text_renderer->property_text(), _model->_colLabel); + + _tree.set_expander_column( *_tree.get_column(nameColNum) ); + + _tree.get_selection()->set_mode(Gtk::SELECTION_MULTIPLE); + _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &TagsPanel::_pushTreeSelectionToCurrent) ); + _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &TagsPanel::_rowSelectFunction) ); + + _tree.signal_drag_drop().connect( sigc::mem_fun(*this, &TagsPanel::_handleDragDrop), false); + _collapsedConnection = _tree.signal_row_collapsed().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), false)); + _expandedConnection = _tree.signal_row_expanded().connect( sigc::bind(sigc::mem_fun(*this, &TagsPanel::_setExpanded), true)); + + _text_renderer->signal_edited().connect( sigc::mem_fun(*this, &TagsPanel::_handleEdited) ); + _text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &TagsPanel::_handleEditingCancelled) ); + + _tree.signal_button_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_button_release_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleButtonEvent), false ); + _tree.signal_key_press_event().connect( sigc::mem_fun(*this, &TagsPanel::_handleKeyEvent), false ); + + _scroller.add( _tree ); + _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC ); + _scroller.set_shadow_type(Gtk::SHADOW_IN); + Gtk::Requisition sreq; +#if WITH_GTKMM_3_0 + Gtk::Requisition sreq_natural; + _scroller.get_preferred_size(sreq_natural, sreq); +#else + sreq = _scroller.size_request(); +#endif + int minHeight = 70; + if (sreq.height < minHeight) { + // Set a min height to see the layers when used with Ubuntu liboverlay-scrollbar + _scroller.set_size_request(sreq.width, minHeight); + } + + _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET ); + + _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK); + + _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET); + + SPDesktop* targetDesktop = getDesktop(); + + Gtk::Button* btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_TAG_NEW, GTK_STOCK_ADD, _("Add a new selection set") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_NEW) ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + +// btn = manage( new Gtk::Button("Dup") ); +// btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) ); +// _buttonsRow.add( *btn ); + + btn = manage( new Gtk::Button() ); + _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("Remove Item/Set") ); + btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &TagsPanel::_takeAction), (int)BUTTON_DELETE) ); + _watching.push_back( btn ); + _buttonsSecondary.pack_start(*btn, Gtk::PACK_SHRINK); + + _buttonsRow.pack_start(_buttonsSecondary, Gtk::PACK_EXPAND_WIDGET); + _buttonsRow.pack_end(_buttonsPrimary, Gtk::PACK_EXPAND_WIDGET); + + // ------------------------------------------------------- + { + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + + _popupMenu.show_all_children(); + } + // ------------------------------------------------------- + + + + for ( std::vector::iterator it = _watching.begin(); it != _watching.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) { + (*it)->set_sensitive( false ); + } + for ( std::vector::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) { + (*it)->set_sensitive( false ); + } + + setDesktop( targetDesktop ); + + show_all_children(); + + // restorePanelPrefs(); + + // Connect this up last + desktopChangeConn = deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &TagsPanel::setDesktop) ); + deskTrack.connect(GTK_WIDGET(gobj())); +} + +TagsPanel::~TagsPanel() +{ + + setDesktop(NULL); + + if ( _model ) + { + delete _model; + _model = 0; + } + + if (_pending) { + delete _pending; + _pending = 0; + } + + if ( _toggleEvent ) + { + gdk_event_free( _toggleEvent ); + _toggleEvent = 0; + } + + desktopChangeConn.disconnect(); + deskTrack.disconnect(); +} + +void TagsPanel::setDocument(SPDesktop* /*desktop*/, SPDocument* document) +{ + while (!_objectWatchers.empty()) + { + TagsPanel::ObjectWatcher *w = _objectWatchers.back(); + w->_repr->removeObserver(*w); + _objectWatchers.pop_back(); + delete w; + } + + if (_rootWatcher) + { + _rootWatcher->_repr->removeObserver(*_rootWatcher); + delete _rootWatcher; + _rootWatcher = NULL; + } + + _document = document; + + if (document && document->getDefs() && document->getDefs()->getRepr()) + { + _rootWatcher = new TagsPanel::ObjectWatcher(this, document->getDefs()); + document->getDefs()->getRepr()->addObserver(*_rootWatcher); + _objectsChanged(document->getDefs()); + } +} + +void TagsPanel::setDesktop( SPDesktop* desktop ) +{ + Panel::setDesktop(desktop); + + if ( desktop != _desktop ) { + _documentChangedConnection.disconnect(); + _selectionChangedConnection.disconnect(); + if ( _desktop ) { + _desktop = 0; + } + + _desktop = Panel::getDesktop(); + if ( _desktop ) { + //setLabel( _desktop->doc()->name ); + _documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &TagsPanel::setDocument)); + _selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &TagsPanel::_objectsSelected)); + + setDocument(_desktop, _desktop->doc()); + } + } +/* + GSList const *layers = _desktop->doc()->getResourceList( "layer" ); + g_message( "layers list starts at %p", layers ); + for ( GSList const *iter=layers ; iter ; iter = iter->next ) { + SPObject *layer=static_cast(iter->data); + g_message(" {%s} [%s]", layer->id, layer->label() ); + } +*/ + deskTrack.setBase(desktop); +} + + + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/tags.h b/src/ui/dialog/tags.h new file mode 100644 index 000000000..d35dfba01 --- /dev/null +++ b/src/ui/dialog/tags.h @@ -0,0 +1,181 @@ +/* + * A simple dialog for tags UI. + * + * Authors: + * Theodore Janeczko + * + * Copyright (C) Theodore Janeczko 2012 + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifndef SEEN_TAGS_PANEL_H +#define SEEN_TAGS_PANEL_H + +#include +#include +#include +#include +#include +#include "ui/widget/spinbutton.h" +#include "ui/widget/panel.h" +#include "ui/widget/object-composite-settings.h" +#include "desktop-tracker.h" +#include "ui/widget/style-subject.h" +#include "selection.h" +#include "ui/widget/filter-effect-chooser.h" + +class SPObject; +class SPTag; +struct SPColorSelector; + +namespace Inkscape { + +namespace UI { +namespace Dialog { + + +/** + * A panel that displays layers. + */ +class TagsPanel : public UI::Widget::Panel +{ +public: + TagsPanel(); + virtual ~TagsPanel(); + + //virtual void setOrientation( Gtk::AnchorType how ); + + static TagsPanel& getInstance(); + + void setDesktop( SPDesktop* desktop ); + void setDocument( SPDesktop* desktop, SPDocument* document); + +protected: + //virtual void _handleAction( int setId, int itemId ); + friend void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject *cp); +private: + class ModelColumns; + class InternalUIBounce; + class ObjectWatcher; + + TagsPanel(TagsPanel const &); // no copy + TagsPanel &operator=(TagsPanel const &); // no assign + + void _styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* tooltip ); + void _fireAction( unsigned int code ); + Gtk::MenuItem& _addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id ); + + bool _handleButtonEvent(GdkEventButton *event); + bool _handleKeyEvent(GdkEventKey *event); + + void _storeDragSource(const Gtk::TreeModel::iterator& iter); + bool _handleDragDrop(const Glib::RefPtr& context, int x, int y, guint time); + void _handleEdited(const Glib::ustring& path, const Glib::ustring& new_text); + void _handleEditingCancelled(); + + void _doTreeMove(); + void _renameObject(Gtk::TreeModel::Row row, const Glib::ustring& name); + + void _pushTreeSelectionToCurrent(); + void _selected_row_callback( const Gtk::TreeModel::iterator& iter ); + void _select_tag( SPTag * tag ); + + void _checkTreeSelection(); + + void _takeAction( int val ); + bool _executeAction(); + + void _setExpanded( const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& path, bool isexpanded ); + + bool _noSelection( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + bool _rowSelectFunction( Glib::RefPtr const & model, Gtk::TreeModel::Path const & path, bool b ); + + void _updateObject(SPObject *obj); + bool _checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* obj); + + void _objectsSelected(Selection *sel); + bool _checkForSelected(const Gtk::TreePath& path, const Gtk::TreeIter& iter, SPObject* layer); + + void _objectsChanged(SPObject *root); + void _addObject( SPDocument* doc, SPObject* obj, Gtk::TreeModel::Row* parentRow ); + + void _checkForDeleted(const Gtk::TreeIter& iter, std::vector* todelete); + +// std::vector groupConnections; + TagsPanel::ObjectWatcher* _rootWatcher; + std::vector _objectWatchers; + + // Hooked to the layer manager: + sigc::connection _documentChangedConnection; + sigc::connection _selectionChangedConnection; + + sigc::connection _changedConnection; + sigc::connection _addedConnection; + sigc::connection _removedConnection; + + // Internal + sigc::connection _selectedConnection; + sigc::connection _expandedConnection; + sigc::connection _collapsedConnection; + + DesktopTracker deskTrack; + SPDesktop* _desktop; + SPDocument* _document; + ModelColumns* _model; + InternalUIBounce* _pending; + gboolean _dnd_into; + std::vector _dnd_source; + SPObject* _dnd_target; + + GdkEvent* _toggleEvent; + bool down_at_add; + + Gtk::TreeModel::Path _defer_target; + + Glib::RefPtr _store; + std::vector _watching; + std::vector _watchingNonTop; + std::vector _watchingNonBottom; + + Gtk::TreeView _tree; + Gtk::CellRendererText *_text_renderer; + Gtk::TreeView::Column *_name_column; +#if WITH_GTKMM_3_0 + Gtk::Box _buttonsRow; + Gtk::Box _buttonsPrimary; + Gtk::Box _buttonsSecondary; +#else + Gtk::HBox _buttonsRow; + Gtk::HBox _buttonsPrimary; + Gtk::HBox _buttonsSecondary; +#endif + Gtk::ScrolledWindow _scroller; + Gtk::Menu _popupMenu; + Inkscape::UI::Widget::SpinButton _spinBtn; + Gtk::VBox _layersPage; + + sigc::connection desktopChangeConn; + +}; + + + +} //namespace Dialogs +} //namespace UI +} //namespace Inkscape + + + +#endif // SEEN_OBJECTS_PANEL_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 1f1932ae4592c8f316e3a68ac86874bf87f321c4 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 11 May 2014 14:23:10 -0400 Subject: Stabilize the selection set system a bit (bzr r13090.1.76) --- src/ui/dialog/tags.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 7fdd2e906..14ad5b8cc 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -280,7 +280,8 @@ bool TagsPanel::_executeAction() for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * obj = *iter; if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); + //obj->parent->getRepr()->removeChild(obj->getRepr()); + obj->deleteObject(true, true); } } DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); @@ -576,7 +577,8 @@ bool TagsPanel::_handleKeyEvent(GdkEventKey *event) for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * obj = *iter; if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { - obj->parent->getRepr()->removeChild(obj->getRepr()); + //obj->parent->getRepr()->removeChild(obj->getRepr()); + obj->deleteObject(true, true); } } DocumentUndo::done(_document, SP_VERB_DIALOG_TAGS, _("Remove from selection set")); @@ -680,12 +682,14 @@ bool TagsPanel::_handleButtonEvent(GdkEventButton* event) } } else { std::vector todelete; + // FIXME unnecessary use of XML tree _tree.get_selection()->selected_foreach_iter(sigc::bind*>(sigc::mem_fun(*this, &TagsPanel::_checkForDeleted), &todelete)); if (!todelete.empty()) { for (std::vector::iterator iter = todelete.begin(); iter != todelete.end(); ++iter) { SPObject * tobj = *iter; if (tobj && tobj->parent && tobj->getRepr() && tobj->parent->getRepr()) { - tobj->parent->getRepr()->removeChild(tobj->getRepr()); + //tobj->parent->getRepr()->removeChild(tobj->getRepr()); + tobj->deleteObject(true, true); } } } else if (obj && obj->parent && obj->getRepr() && obj->parent->getRepr()) { -- cgit v1.2.3 From 0dc8b506fe92a6f4a57d6412db69c3fea420d67a Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 11 May 2014 15:08:59 -0400 Subject: Rename "Tags" to "Selection sets" to avoid confusion with a global tagging system (bzr r13090.1.77) --- src/ui/dialog/tags.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index 14ad5b8cc..1b5dd9400 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -1025,7 +1025,7 @@ TagsPanel::TagsPanel() : // ------------------------------------------------------- { - _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "New", (int)BUTTON_NEW ) ); + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_TAG_NEW, 0, "Add a new selection set", (int)BUTTON_NEW ) ); _popupMenu.show_all_children(); } -- cgit v1.2.3 From 41ab3bd526807e0a092466e7d4e979f12bab81ff Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Tue, 13 May 2014 21:17:06 +0200 Subject: fix windows 64bit build. (changes already committed to trunk) (bzr r13341.1.19) --- src/ui/dialog/filedialogimpl-win32.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index 29bcb9a45..a71ee1ad0 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -13,6 +13,8 @@ # include "config.h" #endif +#include + #ifdef WIN32 #if WITH_GLIBMM_2_32 #if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H -- cgit v1.2.3 From 16262c5a24e91309c4c762ffbb0e82b05026c9b6 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 15 May 2014 16:14:19 +0200 Subject: Fix Pango markup in Text and Font dialog. (bzr r13341.1.25) --- src/ui/dialog/text-edit.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 17c29c69f..c1ebb32e0 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -404,12 +404,12 @@ void TextEdit::setPreviewText (Glib::ustring font_spec, Glib::ustring phrase) double pt_size = Inkscape::Util::Quantity::convert(sp_style_css_size_units_to_px(sp_font_selector_get_size(fsel), unit), "px", "pt"); // Pango font size is in 1024ths of a point - // C++11: Glib::ustring size = std::to_string( pt_size * PANGO_SCALE ); + // C++11: Glib::ustring size = std::to_string( int(pt_size * PANGO_SCALE) ); std::ostringstream size_st; - size_st << pt_size * PANGO_SCALE; + size_st << int(pt_size * PANGO_SCALE); // Markup code expects integers - Glib::ustring markup = "" + phrase_escaped + ""; + Glib::ustring markup = "" + phrase_escaped + ""; preview_label.set_markup(markup.c_str()); } -- cgit v1.2.3 From 639540b57f19cce10e6b37df3475c252455a1b28 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Thu, 15 May 2014 23:08:12 +0200 Subject: make windows filedialog's code more portable for different mingw versions (failed on 64bit) (bzr r13341.1.26) --- src/ui/dialog/filedialogimpl-win32.cpp | 12 ++---------- src/ui/dialog/filedialogimpl-win32.h | 6 +++++- 2 files changed, 7 insertions(+), 11 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 9d91f5d56..06153a2d8 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -72,13 +72,6 @@ const unsigned long MaxPreviewFileSize = 10240; // kB #define IDC_SHOW_PREVIEW 1000 -// Windows 2000 version of OPENFILENAMEW -struct OPENFILENAMEEXW : public OPENFILENAMEW { - void * pvReserved; - DWORD dwReserved; - DWORD FlagsEx; -}; - struct Filter { gunichar2* name; @@ -483,7 +476,7 @@ void FileOpenDialogImplWin32::createFilterMenu() void FileOpenDialogImplWin32::GetOpenFileName_thread() { - OPENFILENAMEEXW ofn; + OPENFILENAMEW ofn; g_assert(this != NULL); g_assert(_mutex != NULL); @@ -1829,7 +1822,7 @@ void FileSaveDialogImplWin32::addFileType(Glib::ustring name, Glib::ustring patt void FileSaveDialogImplWin32::GetSaveFileName_thread() { - OPENFILENAMEEXW ofn; + OPENFILENAMEW ofn; g_assert(this != NULL); g_assert(_main_loop != NULL); @@ -1860,7 +1853,6 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() ofn.nFilterIndex = _filter_index; ofn.lpfnHook = GetSaveFileName_hookproc; ofn.lCustData = (LPARAM)this; - _result = GetSaveFileNameW(&ofn) != 0; g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index a71ee1ad0..c523f041d 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -20,9 +20,13 @@ #if GLIBMM_DISABLE_DEPRECATED && HAVE_GLIBMM_THREADS_H # include #endif - #endif + #include "gc-core.h" + // define WINVER high enough so we get the correct OPENFILENAMEW size +#ifndef WINVER +#define WINVER 0x0500 +#endif #include #include "filedialogimpl-gtkmm.h" -- cgit v1.2.3 From 95033e5a510be941172977dc948f9c914180e359 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sun, 1 Jun 2014 15:05:24 +0200 Subject: spellcheck.cpp: correct indenting. disable debug output. (bzr r13341.1.44) --- src/ui/dialog/spellcheck.cpp | 74 ++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index 8a4ddc57e..a887a7355 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -347,7 +347,7 @@ SpellCheck::init(SPDesktop *d) char *slashPos = strrchr(exeName, '\\'); if (slashPos) *slashPos = '\0'; - g_print ("%s\n", exeName); + //g_print ("Aspell prefix path: %s\n", exeName); #endif _stops = 0; @@ -356,54 +356,54 @@ SpellCheck::init(SPDesktop *d) #ifdef HAVE_ASPELL { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller = to_aspell_speller(ret); } if (_lang2 != "") { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang2.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller2 = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang2.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller2 = to_aspell_speller(ret); } if (_lang3 != "") { - AspellConfig *config = new_aspell_config(); + AspellConfig *config = new_aspell_config(); #ifdef WIN32 - aspell_config_replace(config, "prefix", exeName); + aspell_config_replace(config, "prefix", exeName); #endif - aspell_config_replace(config, "lang", _lang3.c_str()); - aspell_config_replace(config, "encoding", "UTF-8"); - AspellCanHaveError *ret = new_aspell_speller(config); - delete_aspell_config(config); - if (aspell_error(ret) != 0) { - g_warning("Error: %s\n", aspell_error_message(ret)); - delete_aspell_can_have_error(ret); - return false; - } - _speller3 = to_aspell_speller(ret); + aspell_config_replace(config, "lang", _lang3.c_str()); + aspell_config_replace(config, "encoding", "UTF-8"); + AspellCanHaveError *ret = new_aspell_speller(config); + delete_aspell_config(config); + if (aspell_error(ret) != 0) { + g_warning("Error: %s\n", aspell_error_message(ret)); + delete_aspell_can_have_error(ret); + return false; + } + _speller3 = to_aspell_speller(ret); } #endif /* HAVE_ASPELL */ -- cgit v1.2.3 From 5e1c70580e6d156716aba9e5dcc62a15a215da06 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 13 Jun 2014 09:34:58 +0200 Subject: Display symbols in document order. (bzr r13341.1.58) --- src/ui/dialog/symbols.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 8e0d085a4..0dfd915fe 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -613,6 +613,7 @@ GSList* SymbolsDialog::symbols_in_doc( SPDocument* symbolDocument ) { GSList *l = NULL; l = symbols_in_doc_recursive (symbolDocument->getRoot(), l ); + l = g_slist_reverse( l ); return l; } -- cgit v1.2.3 From 5390e245e922648d989bfa10e0613e2f588a9cc7 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Fri, 13 Jun 2014 18:11:54 +0200 Subject: Allow symbol zooming independent of icon screen size. (bzr r13341.1.60) --- src/ui/dialog/symbols.cpp | 72 +++++++++++++++++++++++++++++++++++++++-------- src/ui/dialog/symbols.h | 9 +++++- 2 files changed, 68 insertions(+), 13 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/symbols.cpp b/src/ui/dialog/symbols.cpp index 0dfd915fe..c58df864c 100644 --- a/src/ui/dialog/symbols.cpp +++ b/src/ui/dialog/symbols.cpp @@ -219,25 +219,27 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : Gtk::Label* spacer = Gtk::manage(new Gtk::Label("")); tools->pack_start(* Gtk::manage(spacer)); - in_sizes = 2; // Default 32px + // Pack size (controls display area) + pack_size = 2; // Default 32px button = Gtk::manage(new Gtk::Button()); button->add(*Gtk::manage(Glib::wrap( - sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-bigger")))) ); - button->set_tooltip_text(_("Make Icons bigger by zooming in.")); + sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("pack-more")))) ); + button->set_tooltip_text(_("Display more icons in row.")); button->set_relief( Gtk::RELIEF_NONE ); button->set_focus_on_click( false ); - button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomin)); + button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::packmore)); tools->pack_start(* button, Gtk::PACK_SHRINK); button = Gtk::manage(new Gtk::Button()); button->add(*Gtk::manage(Glib::wrap( - sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-smaller")))) ); - button->set_tooltip_text(_("Make Icons smaller by zooming out.")); + sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("pack-less")))) ); + button->set_tooltip_text(_("Display fewer icons in row.")); button->set_relief( Gtk::RELIEF_NONE ); button->set_focus_on_click( false ); - button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomout)); + button->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::packless)); tools->pack_start(* button, Gtk::PACK_SHRINK); + // Toggle scale to fit on/off fitSymbol = Gtk::manage(new Gtk::ToggleButton()); fitSymbol->add(*Gtk::manage(Glib::wrap( sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-fit")))) ); @@ -248,6 +250,28 @@ SymbolsDialog::SymbolsDialog( gchar const* prefsPath ) : fitSymbol->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::rebuild)); tools->pack_start(* fitSymbol, Gtk::PACK_SHRINK); + // Render size (scales symbols within display area) + scale_factor = 0; // Default 1:1 * pack_size/pack_size default + zoomOut = Gtk::manage(new Gtk::Button()); + zoomOut->add(*Gtk::manage(Glib::wrap( + sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-smaller")))) ); + zoomOut->set_tooltip_text(_("Make symbols smaller by zooming out.")); + zoomOut->set_relief( Gtk::RELIEF_NONE ); + zoomOut->set_focus_on_click( false ); + zoomOut->set_sensitive( false ); + zoomOut->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomout)); + tools->pack_start(* zoomOut, Gtk::PACK_SHRINK); + + zoomIn = Gtk::manage(new Gtk::Button()); + zoomIn->add(*Gtk::manage(Glib::wrap( + sp_icon_new (Inkscape::ICON_SIZE_SMALL_TOOLBAR, INKSCAPE_ICON("symbol-bigger")))) ); + zoomIn->set_tooltip_text(_("Make symbols bigger by zooming in.")); + zoomIn->set_relief( Gtk::RELIEF_NONE ); + zoomIn->set_focus_on_click( false ); + zoomIn->set_sensitive( false ); + zoomIn->signal_clicked().connect(sigc::mem_fun(*this, &SymbolsDialog::zoomin)); + tools->pack_start(* zoomIn, Gtk::PACK_SHRINK); + ++row; /**********************************************************/ @@ -298,22 +322,44 @@ SymbolsDialog& SymbolsDialog::getInstance() return *new SymbolsDialog(); } +void SymbolsDialog::packless() { + if(pack_size < 4) { + pack_size++; + rebuild(); + } +} + +void SymbolsDialog::packmore() { + if(pack_size > 0) { + pack_size--; + rebuild(); + } +} + void SymbolsDialog::zoomin() { - if(in_sizes < 4) { - in_sizes++; + if(scale_factor < 4) { + scale_factor++; rebuild(); } } void SymbolsDialog::zoomout() { - if(in_sizes > 0) { - in_sizes--; + if(scale_factor > -8) { + scale_factor--; rebuild(); } } void SymbolsDialog::rebuild() { + if( fitSymbol->get_active() ) { + zoomIn->set_sensitive( false ); + zoomOut->set_sensitive( false ); + } else { + zoomIn->set_sensitive( true); + zoomOut->set_sensitive( true ); + } + store->clear(); Glib::ustring symbolSetString = symbolSet->get_active_text(); @@ -757,7 +803,7 @@ SymbolsDialog::draw_symbol(SPObject *symbol) previewDocument->ensureUpToDate(); SPItem *item = SP_ITEM(object_temp); - unsigned psize = SYMBOL_ICON_SIZES[in_sizes]; + unsigned psize = SYMBOL_ICON_SIZES[pack_size]; Glib::RefPtr pixbuf(NULL); // We could use cache here, but it doesn't really work with the structure @@ -779,6 +825,8 @@ SymbolsDialog::draw_symbol(SPObject *symbol) if( fitSymbol->get_active() ) scale = psize / std::max(width, height); + else + scale = pow( 2.0, scale_factor/2.0 ) * psize / 32.0; pixbuf = Glib::wrap(render_pixbuf(renderDrawing, scale, *dbox, psize)); } diff --git a/src/ui/dialog/symbols.h b/src/ui/dialog/symbols.h index 8021fb0c1..5dc1e3cad 100644 --- a/src/ui/dialog/symbols.h +++ b/src/ui/dialog/symbols.h @@ -65,6 +65,8 @@ private: static SymbolColumns *getColumns(); + void packless(); + void packmore(); void zoomin(); void zoomout(); void rebuild(); @@ -95,13 +97,18 @@ private: std::map symbolSets; // Index into sizes which is selected - int in_sizes; + int pack_size; + + // Scale factor + int scale_factor; Glib::RefPtr store; Gtk::ComboBoxText* symbolSet; Gtk::IconView* iconView; Gtk::Button* addSymbol; Gtk::Button* removeSymbol; + Gtk::Button* zoomIn; + Gtk::Button* zoomOut; Gtk::ToggleButton* fitSymbol; void setTargetDesktop(SPDesktop *desktop); -- cgit v1.2.3 From eb4d7e1225a2e1e5a5d1da8d0ab784632bc77291 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 14 Jun 2014 14:51:11 -0400 Subject: Add clip group option from Ponyscape (bzr r13090.1.83) --- src/ui/dialog/objects.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 85583a0e7..2d558daae 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -106,7 +106,7 @@ enum { BUTTON_LOCK_ALL, BUTTON_UNLOCK_ALL, BUTTON_SETCLIP, -// BUTTON_CLIPGROUP, + BUTTON_CLIPGROUP, // BUTTON_SETINVCLIP, BUTTON_UNSETCLIP, BUTTON_SETMASK, @@ -269,7 +269,7 @@ Gtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int cod } if ( action ) { - label = action->name; + // label = action->name; } } } @@ -1257,6 +1257,10 @@ bool ObjectsPanel::_executeAction() _fireAction( SP_VERB_LAYER_UNLOCK_ALL ); } break; + case BUTTON_CLIPGROUP: + { + _fireAction ( SP_VERB_OBJECT_CREATE_CLIP_GROUP ); + } case BUTTON_SETCLIP: { _fireAction( SP_VERB_OBJECT_SET_CLIPPATH ); @@ -1935,8 +1939,8 @@ ObjectsPanel::ObjectsPanel() : _popupMenu.append(*Gtk::manage(new Gtk::SeparatorMenuItem())); _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, "Set Clip", (int)BUTTON_SETCLIP ) ); - //not implemented - //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); + + _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_CREATE_CLIP_GROUP, 0, "Create Clip Group", (int)BUTTON_CLIPGROUP ) ); //will never be implemented //_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_INVERSE_CLIPPATH, 0, "Set Inverse Clip", (int)BUTTON_SETINVCLIP ) ); -- cgit v1.2.3 From f1305982b84adfe04cdeb2686c3b1d7ed3a37bc7 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 25 Jun 2014 23:05:33 +0200 Subject: fix windows build (gtk3) partly. broken because of windows.h poluting namespace with "interface" struct name. (bzr r13341.1.68) --- src/ui/dialog/filedialogimpl-win32.h | 3 ++- src/ui/dialog/print.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index c523f041d..f77249abd 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -22,13 +22,14 @@ #endif #endif +#include "filedialogimpl-gtkmm.h" + #include "gc-core.h" // define WINVER high enough so we get the correct OPENFILENAMEW size #ifndef WINVER #define WINVER 0x0500 #endif #include -#include "filedialogimpl-gtkmm.h" namespace Inkscape diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index 03ac9dc64..459e64041 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -13,10 +13,6 @@ #ifdef HAVE_CONFIG_H # include #endif -#ifdef WIN32 -#include -#include -#endif #include "print.h" #include @@ -33,6 +29,11 @@ #include +#ifdef WIN32 +#include +#include +#endif + static void draw_page( #ifdef WIN32 -- cgit v1.2.3 From 371f45365a6b6ea42d17c8ea33cc0072f318967e Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Wed, 2 Jul 2014 13:14:35 +0200 Subject: Add LPE fillet-chamfer (bzr r13341.1.74) --- src/ui/dialog/Makefile_insert | 2 + src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 257 ++++++++++++++++++++++++ src/ui/dialog/lpe-fillet-chamfer-properties.h | 112 +++++++++++ 3 files changed, 371 insertions(+) create mode 100644 src/ui/dialog/lpe-fillet-chamfer-properties.cpp create mode 100644 src/ui/dialog/lpe-fillet-chamfer-properties.h (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index daa8aea22..1bd939707 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -114,4 +114,6 @@ ink_common_sources += \ ui/dialog/undo-history.h \ ui/dialog/xml-tree.cpp \ ui/dialog/xml-tree.h \ + ui/dialog/lpe-fillet-chamfer-properties.cpp \ + ui/dialog/lpe-fillet-chamfer-properties.h \ $(inkboard_dialogs) diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp new file mode 100644 index 000000000..a68c7ee08 --- /dev/null +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -0,0 +1,257 @@ +/** + * From the code of Liam P.White from his Power Stroke Knot dialog + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#if GLIBMM_DISABLE_DEPRECATED &&HAVE_GLIBMM_THREADS_H +#include +#endif + +#include "lpe-fillet-chamfer-properties.h" +#include +#include +#include +#include +#include "inkscape.h" +#include "desktop.h" +#include "document.h" +#include "document-undo.h" +#include "layer-manager.h" +#include "message-stack.h" +#include "desktop-handles.h" +#include "sp-object.h" +#include "sp-item.h" +#include "verbs.h" +#include "selection.h" +#include "selection-chemistry.h" +#include "ui/icon-names.h" +#include "ui/widget/imagetoggler.h" +#include +#include +#include "util/units.h" + +//#include "event-context.h" + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() + : _desktop(NULL), _knotpoint(NULL), _position_visible(false) +{ + Gtk::Box *mainVBox = get_vbox(); + mainVBox->set_homogeneous(false); + _layout_table.set_spacings(4); + _layout_table.resize(2, 2); + + // Layer name widgets + _fillet_chamfer_position_entry.set_activates_default(true); + _fillet_chamfer_position_label.set_label(_("Radius (pixels):")); + _fillet_chamfer_position_label.set_alignment(1.0, 0.5); + + _layout_table.attach(_fillet_chamfer_position_label, 0, 1, 0, 1, Gtk::FILL, + Gtk::FILL); + _layout_table.attach(_fillet_chamfer_position_entry, 1, 2, 0, 1, + Gtk::FILL | Gtk::EXPAND, Gtk::FILL); + _fillet_chamfer_type_fillet.set_label(_("Fillet")); + _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group); + _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet")); + _fillet_chamfer_type_inverse_fillet.set_group(_fillet_chamfer_type_group); + _fillet_chamfer_type_chamfer.set_label(_("Chamfer")); + _fillet_chamfer_type_chamfer.set_group(_fillet_chamfer_type_group); + _fillet_chamfer_type_double_chamfer.set_label(_("Double chamfer")); + _fillet_chamfer_type_double_chamfer.set_group(_fillet_chamfer_type_group); + + mainVBox->pack_start(_layout_table, true, true, 4); + mainVBox->pack_start(_fillet_chamfer_type_fillet, true, true, 4); + mainVBox->pack_start(_fillet_chamfer_type_inverse_fillet, true, true, 4); + mainVBox->pack_start(_fillet_chamfer_type_chamfer, true, true, 4); + mainVBox->pack_start(_fillet_chamfer_type_double_chamfer, true, true, 4); + + // Buttons + _close_button.set_use_stock(true); + _close_button.set_label(Gtk::Stock::CANCEL.id); + _close_button.set_can_default(); + + _apply_button.set_use_underline(true); + _apply_button.set_can_default(); + + _close_button.signal_clicked() + .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close)); + _apply_button.signal_clicked() + .connect(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_apply)); + + signal_delete_event().connect(sigc::bind_return( + sigc::hide(sigc::mem_fun(*this, &FilletChamferPropertiesDialog::_close)), + true)); + + add_action_widget(_close_button, Gtk::RESPONSE_CLOSE); + add_action_widget(_apply_button, Gtk::RESPONSE_APPLY); + + _apply_button.grab_default(); + + show_all_children(); + + set_focus(_fillet_chamfer_position_entry); +} + +FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog() +{ + + _setDesktop(NULL); +} + +void FilletChamferPropertiesDialog::showDialog( + SPDesktop *desktop, Geom::Point knotpoint, + const Inkscape::LivePathEffect:: + FilletChamferPointArrayParamKnotHolderEntity *pt, + const gchar *unit) +{ + FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); + + dialog->_setDesktop(desktop); + dialog->_setUnit(unit); + dialog->_setKnotPoint(knotpoint); + dialog->_setPt(pt); + + dialog->set_title(_("Modify Fillet-Chamfer")); + dialog->_apply_button.set_label(_("_Modify")); + + dialog->set_modal(true); + desktop->setWindowTransient(dialog->gobj()); + dialog->property_destroy_with_parent() = true; + + dialog->show(); + dialog->present(); +} + +void FilletChamferPropertiesDialog::_apply() +{ + std::istringstream i_pos(_fillet_chamfer_position_entry.get_text()); + double d_pos, d_width; + if (i_pos >> d_pos) { + if (_fillet_chamfer_type_fillet.get_active() == true) { + d_width = 1; + } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { + d_width = 2; + } else if (_fillet_chamfer_type_chamfer.get_active() == true) { + d_width = 3; + } else { + d_width = 4; + } + if (_flexible) { + if (d_pos > 99.99999 || d_pos < 0) { + d_pos = 0; + } + d_pos = _index + (d_pos / 100); + } else { + d_pos = Inkscape::Util::Quantity::convert(d_pos, unit, "px"); + d_pos = d_pos * -1; + } + _knotpoint->knot_set_offset(Geom::Point(d_pos, d_width)); + } + _close(); +} + +void FilletChamferPropertiesDialog::_close() +{ + _setDesktop(NULL); + destroy_(); + Glib::signal_idle().connect( + sigc::bind_return( + sigc::bind(sigc::ptr_fun(&::operator delete), this), + false + ) + ); +} + +bool FilletChamferPropertiesDialog::_handleKeyEvent(GdkEventKey *event) +{ + return false; +} + +void FilletChamferPropertiesDialog::_handleButtonEvent(GdkEventButton *event) +{ + if ((event->type == GDK_2BUTTON_PRESS) && (event->button == 1)) { + _apply(); + } +} + +void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) +{ + double position; + if (knotpoint.x() > 0) { + double intpart; + position = modf(knotpoint[Geom::X], &intpart) * 100; + _flexible = true; + _index = intpart; + _fillet_chamfer_position_label.set_label(_("Position (%):")); + } else { + _flexible = false; + std::string posConcat = + std::string(_("Position (")) + std::string(unit) + std::string(")"); + _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); + position = knotpoint[Geom::X] * -1; + position = Inkscape::Util::Quantity::convert(position, "px", unit); + } + std::ostringstream s; + s.imbue(std::locale::classic()); + s << position; + _fillet_chamfer_position_entry.set_text(s.str()); + if (knotpoint.y() == 1) { + _fillet_chamfer_type_fillet.set_active(true); + } else if (knotpoint.y() == 2) { + _fillet_chamfer_type_inverse_fillet.set_active(true); + } else if (knotpoint.y() == 3) { + _fillet_chamfer_type_chamfer.set_active(true); + } else if (knotpoint.y() == 1) { + _fillet_chamfer_type_double_chamfer.set_active(true); + } +} + +void FilletChamferPropertiesDialog::_setPt( + const Inkscape::LivePathEffect:: + FilletChamferPointArrayParamKnotHolderEntity *pt) +{ + _knotpoint = const_cast< + Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity *>( + pt); +} + +void FilletChamferPropertiesDialog::_setUnit(const gchar *abbr) +{ + unit = abbr; +} + +void FilletChamferPropertiesDialog::_setDesktop(SPDesktop *desktop) +{ + if (desktop) { + Inkscape::GC::anchor(desktop); + } + if (_desktop) { + Inkscape::GC::release(_desktop); + } + _desktop = desktop; +} + +} // namespace +} // namespace +} // namespace + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 +// : diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h new file mode 100644 index 000000000..a07b5ab66 --- /dev/null +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -0,0 +1,112 @@ +/** + * + * From the code of Liam P.White from his Power Stroke Knot dialog + * + * Released under GNU GPL. Read the file 'COPYING' for more information + */ + +#ifndef INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H +#define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H + +#include <2geom/point.h> +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "live_effects/parameter/filletchamferpointarray.h" + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Dialogs { + +class FilletChamferPropertiesDialog : public Gtk::Dialog { +public: + FilletChamferPropertiesDialog(); + virtual ~FilletChamferPropertiesDialog(); + + Glib::ustring getName() const { + return "LayerPropertiesDialog"; + } + + static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, + const Inkscape::LivePathEffect:: + FilletChamferPointArrayParamKnotHolderEntity *pt, + const gchar *unit); + +protected: + + SPDesktop *_desktop; + Inkscape::LivePathEffect::FilletChamferPointArrayParamKnotHolderEntity * + _knotpoint; + + Gtk::Label _fillet_chamfer_position_label; + Gtk::Entry _fillet_chamfer_position_entry; + Gtk::RadioButton::Group _fillet_chamfer_type_group; + Gtk::RadioButton _fillet_chamfer_type_fillet; + Gtk::RadioButton _fillet_chamfer_type_inverse_fillet; + Gtk::RadioButton _fillet_chamfer_type_chamfer; + Gtk::RadioButton _fillet_chamfer_type_double_chamfer; + + Gtk::Table _layout_table; + bool _position_visible; + double _index; + + Gtk::Button _close_button; + Gtk::Button _apply_button; + + sigc::connection _destroy_connection; + + static FilletChamferPropertiesDialog &_instance() { + static FilletChamferPropertiesDialog instance; + return instance; + } + + void _setDesktop(SPDesktop *desktop); + void _setPt(const Inkscape::LivePathEffect:: + FilletChamferPointArrayParamKnotHolderEntity *pt); + void _setUnit(const gchar *abbr); + void _apply(); + void _close(); + bool _flexible; + const gchar *unit; + void _setKnotPoint(Geom::Point knotpoint); + void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); + + bool _handleKeyEvent(GdkEventKey *event); + void _handleButtonEvent(GdkEventButton *event); + + friend class Inkscape::LivePathEffect:: + FilletChamferPointArrayParamKnotHolderEntity; + +private: + FilletChamferPropertiesDialog( + FilletChamferPropertiesDialog const &); // no copy + FilletChamferPropertiesDialog &operator=( + FilletChamferPropertiesDialog const &); // no assign +}; + +} // namespace +} // namespace +} // namespace + +#endif //INKSCAPE_DIALOG_LAYER_PROPERTIES_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: +// filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 +// : -- cgit v1.2.3 From 962ef8a02c2dbaf2049c1951ec8953ba885f9e19 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 5 Jul 2014 12:01:13 -0400 Subject: Fix FTBFS gtk3 & make check (bzr r13341.1.78) --- src/ui/dialog/lpe-fillet-chamfer-properties.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index a07b5ab66..d3e859bff 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -9,15 +9,7 @@ #define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H #include <2geom/point.h> -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include "live_effects/parameter/filletchamferpointarray.h" class SPDesktop; -- cgit v1.2.3 From 2a2db8af11c2e518bd7bfe520e2f88a7e439d939 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sat, 16 Aug 2014 22:47:53 -0400 Subject: Merge in font-speedup branch to improve launch times (bzr r13341.1.140) --- src/ui/dialog/text-edit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index c1ebb32e0..e44809c65 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -344,9 +344,9 @@ void TextEdit::onReadSelection ( gboolean dostyle, gboolean /*docontent*/ ) Inkscape::FontLister* fontlister = Inkscape::FontLister::get_instance(); - // This is done for us by text-toolbar. No need to do it twice. - // fontlister->update_font_list( sp_desktop_document( SP_ACTIVE_DESKTOP )); - // fontlister->selection_update(); + // This is normally done for us by text-toolbar but only when we are in text editing context + fontlister->update_font_list(sp_desktop_document(this->desktop)); + fontlister->selection_update(); Glib::ustring fontspec = fontlister->get_fontspec(); -- cgit v1.2.3 From 282a7ce3f988e792545c19854b5f55cff1291cbe Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 17 Aug 2014 13:44:01 -0400 Subject: Fix gtk3 crash when using "close" button Fixed bugs: - https://launchpad.net/bugs/1090936 (bzr r13341.1.143) --- src/ui/dialog/dialog.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 645294bb5..22ba0b6fb 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -317,20 +317,7 @@ void Dialog::_apply() void Dialog::_close() { - GtkWidget *dlg = GTK_WIDGET(_behavior->gobj()); - - GdkEventAny event; - event.type = GDK_DELETE; - event.window = gtk_widget_get_window(dlg); - event.send_event = TRUE; - - if (event.window) - g_object_ref(G_OBJECT(event.window)); - - gtk_main_do_event ((GdkEvent*)&event); - - if (event.window) - g_object_unref(G_OBJECT(event.window)); + _behavior->hide(); } void Dialog::_defocus() -- cgit v1.2.3 From 2a04905eb339f85263babd7d668dd43f072f75b3 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 17 Aug 2014 14:13:20 -0400 Subject: Fix accidental regression in previous commit (bzr r13341.1.144) --- src/ui/dialog/dialog.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 22ba0b6fb..f2c63ed8d 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -318,6 +318,7 @@ void Dialog::_apply() void Dialog::_close() { _behavior->hide(); + _onDeleteEvent(NULL); } void Dialog::_defocus() -- cgit v1.2.3 From 62339f48161baf01b49d331b7c31ab9d8fb64ec6 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 23 Aug 2014 14:54:39 +0200 Subject: fix Windows 64-bit build (bzr r13341.1.154) --- src/ui/dialog/print.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/print.cpp b/src/ui/dialog/print.cpp index ed39ebb32..a015d28f9 100644 --- a/src/ui/dialog/print.cpp +++ b/src/ui/dialog/print.cpp @@ -14,13 +14,13 @@ # include #endif +#include + #ifdef WIN32 #include #include #endif -#include - #include "preferences.h" #include "print.h" -- cgit v1.2.3 From fd314c7cbec965ec702c3ea80e1e48d41302d687 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 23 Aug 2014 21:30:32 +0100 Subject: Fix deprecated VBox use (bzr r13341.1.165) --- src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 2 +- src/ui/dialog/new-from-template.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index a68c7ee08..c1e16495b 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -44,7 +44,7 @@ namespace Dialogs { FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() : _desktop(NULL), _knotpoint(NULL), _position_visible(false) { - Gtk::Box *mainVBox = get_vbox(); + Gtk::Box *mainVBox = get_content_area(); mainVBox->set_homogeneous(false); _layout_table.set_spacings(4); _layout_table.resize(2, 2); diff --git a/src/ui/dialog/new-from-template.cpp b/src/ui/dialog/new-from-template.cpp index f326bb3ee..5ce96d10f 100644 --- a/src/ui/dialog/new-from-template.cpp +++ b/src/ui/dialog/new-from-template.cpp @@ -26,11 +26,11 @@ NewFromTemplate::NewFromTemplate() set_title(_("New From Template")); resize(400, 400); - get_vbox()->pack_start(_main_widget); + get_content_area()->pack_start(_main_widget); Gtk::Alignment *align; align = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER, 0.0, 0.0)); - get_vbox()->pack_end(*align, Gtk::PACK_SHRINK); + get_content_area()->pack_end(*align, Gtk::PACK_SHRINK); align->set_padding(0, 0, 0, 15); align->add(_create_template_button); -- cgit v1.2.3 From 6388fa1d00b2731feb0b9eedd03c2751d2efee84 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 23 Aug 2014 22:35:35 +0100 Subject: Migrate more widgets to Gtk::Grid (bzr r13341.1.169) --- src/ui/dialog/grid-arrange-tab.h | 8 +++++--- src/ui/dialog/polar-arrange-tab.cpp | 32 ++++++++++++++++++++++++++++++++ src/ui/dialog/polar-arrange-tab.h | 19 ++++++++++++++++++- 3 files changed, 55 insertions(+), 4 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/grid-arrange-tab.h b/src/ui/dialog/grid-arrange-tab.h index 9d6700b39..a137d1694 100644 --- a/src/ui/dialog/grid-arrange-tab.h +++ b/src/ui/dialog/grid-arrange-tab.h @@ -17,14 +17,16 @@ #ifndef INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H #define INKSCAPE_UI_DIALOG_GRID_ARRANGE_TAB_H -#include - +#include "ui/widget/scalar-unit.h" #include "ui/dialog/arrange-tab.h" #include "ui/widget/anchor-selector.h" -#include "ui/widget/scalar-unit.h" #include "ui/widget/spinbutton.h" +#include +#include +#include + namespace Inkscape { namespace UI { namespace Dialog { diff --git a/src/ui/dialog/polar-arrange-tab.cpp b/src/ui/dialog/polar-arrange-tab.cpp index a00b8fc02..80579c9d3 100644 --- a/src/ui/dialog/polar-arrange-tab.cpp +++ b/src/ui/dialog/polar-arrange-tab.cpp @@ -25,6 +25,7 @@ #include "desktop.h" #include "sp-ellipse.h" #include "sp-item-transform.h" +#include namespace Inkscape { namespace UI { @@ -32,7 +33,11 @@ namespace Dialog { PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_) : parent(parent_), +#if WITH_GTKMM_3_0 + parametersTable(), +#else parametersTable(3, 3, false), +#endif centerY("", "Y coordinate of the center", UNIT_TYPE_LINEAR), centerX("", "X coordinate of the center", centerY), radiusY("", "Y coordinate of the radius", UNIT_TYPE_LINEAR), @@ -76,7 +81,11 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_) pack_start(arrangeOnParametersRadio, false, false); centerLabel.set_text(_("Center X/Y:")); +#if WITH_GTKMM_3_0 + parametersTable.attach(centerLabel, 0, 0, 1, 1); +#else parametersTable.attach(centerLabel, 0, 1, 0, 1, Gtk::FILL); +#endif centerX.setDigits(2); centerX.setIncrements(0.2, 0); centerX.setRange(-10000, 10000); @@ -85,11 +94,20 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_) centerY.setIncrements(0.2, 0); centerY.setRange(-10000, 10000); centerY.setValue(0, "px"); +#if WITH_GTKMM_3_0 + parametersTable.attach(centerX, 1, 0, 1, 1); + parametersTable.attach(centerY, 2, 0, 1, 1); +#else parametersTable.attach(centerX, 1, 2, 0, 1, Gtk::FILL); parametersTable.attach(centerY, 2, 3, 0, 1, Gtk::FILL); +#endif radiusLabel.set_text(_("Radius X/Y:")); +#if WITH_GTKMM_3_0 + parametersTable.attach(radiusLabel, 0, 1, 1, 1); +#else parametersTable.attach(radiusLabel, 0, 1, 1, 2, Gtk::FILL); +#endif radiusX.setDigits(2); radiusX.setIncrements(0.2, 0); radiusX.setRange(0.001, 10000); @@ -98,11 +116,20 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_) radiusY.setIncrements(0.2, 0); radiusY.setRange(0.001, 10000); radiusY.setValue(100, "px"); +#if WITH_GTKMM_3_0 + parametersTable.attach(radiusX, 1, 1, 1, 1); + parametersTable.attach(radiusY, 2, 1, 1, 1); +#else parametersTable.attach(radiusX, 1, 2, 1, 2, Gtk::FILL); parametersTable.attach(radiusY, 2, 3, 1, 2, Gtk::FILL); +#endif angleLabel.set_text(_("Angle X/Y:")); +#if WITH_GTKMM_3_0 + parametersTable.attach(angleLabel, 0, 2, 1, 1); +#else parametersTable.attach(angleLabel, 0, 1, 2, 3, Gtk::FILL); +#endif angleX.setDigits(2); angleX.setIncrements(0.2, 0); angleX.setRange(-10000, 10000); @@ -111,8 +138,13 @@ PolarArrangeTab::PolarArrangeTab(ArrangeDialog *parent_) angleY.setIncrements(0.2, 0); angleY.setRange(-10000, 10000); angleY.setValue(180, "°"); +#if WITH_GTKMM_3_0 + parametersTable.attach(angleX, 1, 2, 1, 1); + parametersTable.attach(angleY, 2, 2, 1, 1); +#else parametersTable.attach(angleX, 1, 2, 2, 3, Gtk::FILL); parametersTable.attach(angleY, 2, 3, 2, 3, Gtk::FILL); +#endif pack_start(parametersTable, false, false); rotateObjectsCheckBox.set_label(_("Rotate objects")); diff --git a/src/ui/dialog/polar-arrange-tab.h b/src/ui/dialog/polar-arrange-tab.h index f6c3b2906..f7d7bf11f 100644 --- a/src/ui/dialog/polar-arrange-tab.h +++ b/src/ui/dialog/polar-arrange-tab.h @@ -10,9 +10,22 @@ #ifndef INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H #define INKSCAPE_UI_DIALOG_POLAR_ARRANGE_TAB_H +#if HAVE_CONFIG_H + #include "config.h" +#endif + +#include "ui/widget/scalar-unit.h" #include "ui/widget/anchor-selector.h" #include "ui/dialog/arrange-tab.h" -#include "ui/widget/scalar-unit.h" + +#include +#include + +#if WITH_GTKMM_3_0 + #include +#else + #include +#endif namespace Inkscape { namespace UI { @@ -62,7 +75,11 @@ private: Gtk::RadioButton arrangeOnLastCircleRadio; Gtk::RadioButton arrangeOnParametersRadio; +#if WITH_GTKMM_3_0 + Gtk::Grid parametersTable; +#else Gtk::Table parametersTable; +#endif Gtk::Label centerLabel; Inkscape::UI::Widget::ScalarUnit centerY; -- cgit v1.2.3 From 81ae160f5d204d3841505a6c364c064f77f17f88 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 23 Aug 2014 22:52:01 +0100 Subject: Finish Gtk::Grid migration (bzr r13341.1.170) --- src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 13 +++++++++++++ src/ui/dialog/lpe-fillet-chamfer-properties.h | 21 ++++++++++++++++++++- 2 files changed, 33 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index c1e16495b..f5a554b36 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -46,18 +46,31 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() { Gtk::Box *mainVBox = get_content_area(); mainVBox->set_homogeneous(false); + +#if WITH_GTKMM_3_0 + _layout_table.set_row_spacing(4); + _layout_table.set_column_spacing(4); +#else _layout_table.set_spacings(4); _layout_table.resize(2, 2); +#endif // Layer name widgets _fillet_chamfer_position_entry.set_activates_default(true); _fillet_chamfer_position_label.set_label(_("Radius (pixels):")); _fillet_chamfer_position_label.set_alignment(1.0, 0.5); +#if WITH_GTKMM_3_0 + _layout_table.attach(_fillet_chamfer_position_label, 0, 0, 1, 1); + _layout_table.attach(_fillet_chamfer_position_entry, 1, 0, 1, 1); + _fillet_chamfer_position_entry.set_hexpand(); +#else _layout_table.attach(_fillet_chamfer_position_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); _layout_table.attach(_fillet_chamfer_position_entry, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); +#endif + _fillet_chamfer_type_fillet.set_label(_("Fillet")); _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group); _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet")); diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index d3e859bff..6667e5785 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -8,10 +8,24 @@ #ifndef INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H #define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H +#if HAVE_CONFIG_H + #include "config.h" +#endif + #include <2geom/point.h> -#include #include "live_effects/parameter/filletchamferpointarray.h" +#include +#include +#include +#include + +#if WITH_GTKMM_3_0 + #include +#else + #include +#endif + class SPDesktop; namespace Inkscape { @@ -46,7 +60,12 @@ protected: Gtk::RadioButton _fillet_chamfer_type_chamfer; Gtk::RadioButton _fillet_chamfer_type_double_chamfer; +#if WITH_GTKMM_3_0 + Gtk::Grid _layout_table; +#else Gtk::Table _layout_table; +#endif + bool _position_visible; double _index; -- cgit v1.2.3 From a3e1d94ae50f769d2b1539307cf182ce5801e647 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sun, 24 Aug 2014 11:37:18 +0100 Subject: Fix Gtk+ 2 build (bzr r13341.1.171) --- src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 5 +++++ src/ui/dialog/lpe-fillet-chamfer-properties.h | 2 +- src/ui/dialog/new-from-template.cpp | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index f5a554b36..eef32d10d 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -44,7 +44,12 @@ namespace Dialogs { FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() : _desktop(NULL), _knotpoint(NULL), _position_visible(false) { +#if WITH_GTKMM_3_0 Gtk::Box *mainVBox = get_content_area(); +#else + Gtk::Box *mainVBox = get_vbox(); +#endif + mainVBox->set_homogeneous(false); #if WITH_GTKMM_3_0 diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index 6667e5785..9beca02e1 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -12,10 +12,10 @@ #include "config.h" #endif +#include #include <2geom/point.h> #include "live_effects/parameter/filletchamferpointarray.h" -#include #include #include #include diff --git a/src/ui/dialog/new-from-template.cpp b/src/ui/dialog/new-from-template.cpp index 5ce96d10f..e30b148bb 100644 --- a/src/ui/dialog/new-from-template.cpp +++ b/src/ui/dialog/new-from-template.cpp @@ -8,6 +8,9 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#if HAVE_CONFIG_H + #include "config.h" +#endif #include "new-from-template.h" #include "file.h" @@ -25,12 +28,22 @@ NewFromTemplate::NewFromTemplate() { set_title(_("New From Template")); resize(400, 400); - + +#if WITH_GTKMM_3_0 get_content_area()->pack_start(_main_widget); +#else + get_vbox()->pack_start(_main_widget); +#endif Gtk::Alignment *align; align = Gtk::manage(new Gtk::Alignment(Gtk::ALIGN_END, Gtk::ALIGN_CENTER, 0.0, 0.0)); + +#if WITH_GTKMM_3_0 get_content_area()->pack_end(*align, Gtk::PACK_SHRINK); +#else + get_vbox()->pack_end(*align, Gtk::PACK_SHRINK); +#endif + align->set_padding(0, 0, 0, 15); align->add(_create_template_button); -- cgit v1.2.3 From 2d1275f0337e3fe49ea493f58135c81d0e3af36d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Tue, 26 Aug 2014 11:55:28 +0100 Subject: Standardise InkscapeApplication GObject implementation (namespace not supported properly) (bzr r13341.1.179) --- src/ui/dialog/align-and-distribute.cpp | 4 ++-- src/ui/dialog/clonetiler.cpp | 4 ++-- src/ui/dialog/clonetiler.h | 4 ++-- src/ui/dialog/desktop-tracker.cpp | 2 +- src/ui/dialog/desktop-tracker.h | 5 ++--- src/ui/dialog/dialog-manager.cpp | 4 ++-- src/ui/dialog/dialog.cpp | 2 +- src/ui/dialog/dialog.h | 4 ++-- src/ui/dialog/document-metadata.cpp | 4 ++-- src/ui/dialog/document-metadata.h | 4 ++-- src/ui/dialog/document-properties.cpp | 4 ++-- src/ui/dialog/document-properties.h | 4 ++-- src/ui/dialog/fill-and-stroke.h | 2 +- src/ui/dialog/grid-arrange-tab.cpp | 2 +- src/ui/dialog/panel-dialog.h | 12 ++++++------ src/ui/dialog/transformation.cpp | 4 ++-- 16 files changed, 32 insertions(+), 33 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index e02ccd3f1..8352de1e3 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -829,14 +829,14 @@ private : -static void on_tool_changed(Inkscape::Application */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad) +static void on_tool_changed(InkscapeApplication */*inkscape*/, Inkscape::UI::Tools::ToolBase */*context*/, AlignAndDistribute *daad) { SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop && desktop->getEventContext()) daad->setMode(tools_active(desktop) == TOOLS_NODES); } -static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) +static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, AlignAndDistribute *daad) { daad->randomize_bbox = Geom::OptRect(); } diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index e5f18216c..d9e2c03ba 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -1349,7 +1349,7 @@ void CloneTiler::on_picker_color_changed(guint rgba) is_updating = false; } -void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg) +void CloneTiler::clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg) { GtkWidget *buttons = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "buttons_on_tiles")); GtkWidget *status = GTK_WIDGET(g_object_get_data (G_OBJECT(dlg), "status")); @@ -1378,7 +1378,7 @@ void CloneTiler::clonetiler_change_selection(Inkscape::Application * /*inkscape* } } -void CloneTiler::clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg) +void CloneTiler::clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg) { clonetiler_change_selection (NULL, sp_desktop_selection(SP_ACTIVE_DESKTOP), dlg); } diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h index e2a0240ee..9bacc701d 100644 --- a/src/ui/dialog/clonetiler.h +++ b/src/ui/dialog/clonetiler.h @@ -58,8 +58,8 @@ protected: static void clonetiler_keep_bbox_toggled(GtkToggleButton *tb, gpointer /*data*/); static void clonetiler_apply(GtkWidget */*widget*/, GtkWidget *dlg); static void clonetiler_unclump(GtkWidget */*widget*/, void *); - static void clonetiler_change_selection(Inkscape::Application * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg); - static void clonetiler_external_change(Inkscape::Application * /*inkscape*/, GtkWidget *dlg); + static void clonetiler_change_selection(InkscapeApplication * /*inkscape*/, Inkscape::Selection *selection, GtkWidget *dlg); + static void clonetiler_external_change(InkscapeApplication * /*inkscape*/, GtkWidget *dlg); static void clonetiler_disconnect_gsignal(GObject *widget, gpointer source); static void clonetiler_reset(GtkWidget */*widget*/, GtkWidget *dlg); static guint clonetiler_number_of_clones(SPObject *obj); diff --git a/src/ui/dialog/desktop-tracker.cpp b/src/ui/dialog/desktop-tracker.cpp index 8a359dd2d..3ed998252 100644 --- a/src/ui/dialog/desktop-tracker.cpp +++ b/src/ui/dialog/desktop-tracker.cpp @@ -94,7 +94,7 @@ sigc::connection DesktopTracker::connectDesktopChanged( const sigc::slottrackActive) { self->setDesktop(desktop); diff --git a/src/ui/dialog/desktop-tracker.h b/src/ui/dialog/desktop-tracker.h index 7da55cf2f..7b944ddfa 100644 --- a/src/ui/dialog/desktop-tracker.h +++ b/src/ui/dialog/desktop-tracker.h @@ -12,11 +12,10 @@ typedef struct _GtkWidget GtkWidget; class SPDesktop; +struct InkscapeApplication; namespace Inkscape { -struct Application; - namespace UI { namespace Dialog { @@ -37,7 +36,7 @@ public: sigc::connection connectDesktopChanged( const sigc::slot & slot ); private: - static gboolean activateDesktopCB(Inkscape::Application *inkscape, SPDesktop *desktop, DesktopTracker *self ); + static gboolean activateDesktopCB(InkscapeApplication *inkscape, SPDesktop *desktop, DesktopTracker *self ); static bool hierarchyChangeCB(GtkWidget *widget, GtkWidget* prev, DesktopTracker *self); void handleHierarchyChange(); diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 7e69e439a..0da638546 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -70,13 +70,13 @@ inline Dialog *create() { return PanelDialog::template create(); } /** * This class is provided as a container for Inkscape's various - * dialogs. This allows Inkscape::Application to treat the various + * dialogs. This allows InkscapeApplication to treat the various * dialogs it invokes, as abstractions. * * DialogManager is essentially a cache of dialogs. It lets us * initialize dialogs lazily - instead of constructing them during * application startup, they're constructed the first time they're - * actually invoked by Inkscape::Application. The constructed + * actually invoked by InkscapeApplication. The constructed * dialog is held here after that, so future invokations of the * dialog don't need to get re-constructed each time. The memory for * the dialogs are then reclaimed when the DialogManager is destroyed. diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index f2c63ed8d..4f0d9fbe1 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -41,7 +41,7 @@ namespace Inkscape { namespace UI { namespace Dialog { -void sp_retransientize(Inkscape::Application */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr) +void sp_retransientize(InkscapeApplication */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr) { Dialog *dlg = static_cast(dlgPtr); dlg->onDesktopActivated (desktop); diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h index ec5d203bc..ccff43a56 100644 --- a/src/ui/dialog/dialog.h +++ b/src/ui/dialog/dialog.h @@ -18,10 +18,10 @@ #include "floating-behavior.h" class SPDesktop; +struct InkscapeApplication; namespace Inkscape { class Selection; -struct Application; } namespace Inkscape { @@ -30,7 +30,7 @@ namespace Dialog { enum BehaviorType { FLOATING, DOCK }; -void sp_retransientize(Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr); +void sp_retransientize(InkscapeApplication *inkscape, SPDesktop *desktop, gpointer dlgPtr); gboolean sp_retransientize_again(gpointer dlgPtr); void sp_dialog_shutdown(GObject *object, gpointer dlgPtr); diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp index 09c505860..77ea175d9 100644 --- a/src/ui/dialog/document-metadata.cpp +++ b/src/ui/dialog/document-metadata.cpp @@ -223,7 +223,7 @@ DocumentMetadata::_handleDocumentReplaced(SPDesktop* desktop, SPDocument *) } void -DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop) +DocumentMetadata::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->addListener(&_repr_events, this); @@ -231,7 +231,7 @@ DocumentMetadata::_handleActivateDesktop(Inkscape::Application *, SPDesktop *des } void -DocumentMetadata::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop) +DocumentMetadata::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->removeListenerByData(this); diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h index 3b7ed1ec8..77084bc3d 100644 --- a/src/ui/dialog/document-metadata.h +++ b/src/ui/dialog/document-metadata.h @@ -56,8 +56,8 @@ protected: void init(); void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document); - void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop); - void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop); + void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop); + void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop); Gtk::Notebook _notebook; diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 4e4616724..5ad82644e 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -1594,7 +1594,7 @@ void DocumentProperties::_handleDocumentReplaced(SPDesktop* desktop, SPDocument update(); } -void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDesktop *desktop) +void DocumentProperties::_handleActivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->addListener(&_repr_events, this); @@ -1603,7 +1603,7 @@ void DocumentProperties::_handleActivateDesktop(Inkscape::Application *, SPDeskt update(); } -void DocumentProperties::_handleDeactivateDesktop(Inkscape::Application *, SPDesktop *desktop) +void DocumentProperties::_handleDeactivateDesktop(InkscapeApplication *, SPDesktop *desktop) { Inkscape::XML::Node *repr = sp_desktop_namedview(desktop)->getRepr(); repr->removeListenerByData(this); diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 495f3177d..ee7e88b18 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -94,8 +94,8 @@ protected: void save_default_metadata(); void _handleDocumentReplaced(SPDesktop* desktop, SPDocument *document); - void _handleActivateDesktop(Inkscape::Application *application, SPDesktop *desktop); - void _handleDeactivateDesktop(Inkscape::Application *application, SPDesktop *desktop); + void _handleActivateDesktop(InkscapeApplication *application, SPDesktop *desktop); + void _handleDeactivateDesktop(InkscapeApplication *application, SPDesktop *desktop); Inkscape::XML::SignalObserver _emb_profiles_observer, _scripts_observer; Gtk::Notebook _notebook; diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index 340cb860f..35c98ef9c 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -41,7 +41,7 @@ public: virtual void setDesktop(SPDesktop *desktop); - void selectionChanged(Inkscape::Application *inkscape, + void selectionChanged(InkscapeApplication *inkscape, Inkscape::Selection *selection); void showPageFill(); diff --git a/src/ui/dialog/grid-arrange-tab.cpp b/src/ui/dialog/grid-arrange-tab.cpp index 72217c729..1417b39fa 100644 --- a/src/ui/dialog/grid-arrange-tab.cpp +++ b/src/ui/dialog/grid-arrange-tab.cpp @@ -572,7 +572,7 @@ void GridArrangeTab::updateSelection() ## Experimental ##########################*/ -static void updateSelectionCallback(Inkscape::Application */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg) +static void updateSelectionCallback(InkscapeApplication */*inkscape*/, Inkscape::Selection */*selection*/, GridArrangeTab *dlg) { dlg->updateSelection(); } diff --git a/src/ui/dialog/panel-dialog.h b/src/ui/dialog/panel-dialog.h index 1fefd811e..b4a355083 100644 --- a/src/ui/dialog/panel-dialog.h +++ b/src/ui/dialog/panel-dialog.h @@ -49,19 +49,19 @@ public: virtual UI::Widget::Panel &getPanel() { return _panel; } protected: - static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) { + static void handle_deactivate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) { g_return_if_fail(data != NULL); static_cast(data)->_propagateDesktopDeactivated(application, desktop); } - static void _handle_activate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) { + static void _handle_activate_desktop(InkscapeApplication *application, SPDesktop *desktop, void *data) { g_return_if_fail(data != NULL); static_cast(data)->_propagateDesktopActivated(application, desktop); } inline virtual void _propagateDocumentReplaced(SPDesktop* desktop, SPDocument *document); - inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *); - inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *); + inline virtual void _propagateDesktopActivated(InkscapeApplication *, SPDesktop *); + inline virtual void _propagateDesktopDeactivated(InkscapeApplication *, SPDesktop *); UI::Widget::Panel &_panel; sigc::connection _document_replaced_connection; @@ -134,14 +134,14 @@ void PanelDialogBase::_propagateDocumentReplaced(SPDesktop *desktop, SPDocument _panel.signalDocumentReplaced().emit(desktop, document); } -void PanelDialogBase::_propagateDesktopActivated(Inkscape::Application *application, SPDesktop *desktop) +void PanelDialogBase::_propagateDesktopActivated(InkscapeApplication *application, SPDesktop *desktop) { _document_replaced_connection = desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialogBase::_propagateDocumentReplaced)); _panel.signalActivateDesktop().emit(application, desktop); } -void PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application, SPDesktop *desktop) +void PanelDialogBase::_propagateDesktopDeactivated(InkscapeApplication *application, SPDesktop *desktop) { _document_replaced_connection.disconnect(); _panel.signalDeactiveDesktop().emit(application, desktop); diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index a7f0b068e..3e135b9b2 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -47,13 +47,13 @@ namespace Inkscape { namespace UI { namespace Dialog { -static void on_selection_changed(Inkscape::Application */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) +static void on_selection_changed(InkscapeApplication */*inkscape*/, Inkscape::Selection *selection, Transformation *daad) { int page = daad->getCurrentPage(); daad->updateSelection((Inkscape::UI::Dialog::Transformation::PageType)page, selection); } -static void on_selection_modified( Inkscape::Application */*inkscape*/, +static void on_selection_modified( InkscapeApplication */*inkscape*/, Inkscape::Selection *selection, guint /*flags*/, Transformation *daad ) -- cgit v1.2.3 From 9066e62e9f0cb4972f3b7988004393e96e55e09d Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 30 Aug 2014 12:00:43 +0100 Subject: Fix modelines (bzr r13341.1.183) --- src/ui/dialog/aboutbox.cpp | 6 +++--- src/ui/dialog/aboutbox.h | 6 +++--- src/ui/dialog/inkscape-preferences.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index a66855b2a..44ed3b58f 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -941,13 +941,13 @@ void AboutBox::initStrings() { } // namespace UI } // namespace Inkscape -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/aboutbox.h b/src/ui/dialog/aboutbox.h index 7b3308672..015e344a1 100644 --- a/src/ui/dialog/aboutbox.h +++ b/src/ui/dialog/aboutbox.h @@ -55,13 +55,13 @@ private: #endif // INKSCAPE_UI_DIALOG_ABOUTBOX_H -/* +/* Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 9f37626ed..dcea91741 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -545,9 +545,9 @@ private: Local Variables: mode:c++ c-file-style:"stroustrup" - c-file-offsets:((innamespace . 0)(inline-open . 0)) + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) indent-tabs-mode:nil fill-column:99 End: */ -// vim: filetype=c++:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : -- cgit v1.2.3 From 977857ef75a45ed1ec79cfdcf0f25dd66d4a7e86 Mon Sep 17 00:00:00 2001 From: Alex Valavanis Date: Sat, 30 Aug 2014 14:00:28 +0100 Subject: Reduce header bloat (bzr r13341.1.184) --- src/ui/dialog/clonetiler.h | 1 - src/ui/dialog/export.h | 9 --------- src/ui/dialog/filedialogimpl-gtkmm.cpp | 1 + 3 files changed, 1 insertion(+), 10 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/clonetiler.h b/src/ui/dialog/clonetiler.h index 9bacc701d..70da86338 100644 --- a/src/ui/dialog/clonetiler.h +++ b/src/ui/dialog/clonetiler.h @@ -11,7 +11,6 @@ #define __SP_CLONE_TILER_H__ #include "ui/widget/panel.h" -#include #include "ui/dialog/desktop-tracker.h" #include "ui/widget/color-picker.h" diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 6f3c0dfac..23af0109b 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -12,20 +12,11 @@ #ifndef SP_EXPORT_H #define SP_EXPORT_H -#include -#include - -#include -#include -#include #include -#include -#include "desktop.h" #include "ui/dialog/desktop-tracker.h" #include "ui/widget/panel.h" #include "ui/widget/button.h" -#include "ui/widget/entry.h" namespace Gtk { class Dialog; diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 8ba3ad684..575519848 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -40,6 +40,7 @@ #include #include +#include "document.h" #include "extension/input.h" #include "extension/output.h" #include "extension/db.h" -- cgit v1.2.3 From 395b34493e806b4aa2333c694d7d6e4e4d4700a4 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Tue, 2 Sep 2014 17:14:55 -0400 Subject: Remove misleading dialogs directory (bzr r13341.1.192) --- src/ui/dialog/dock-behavior.cpp | 2 +- src/ui/dialog/export.cpp | 2 +- src/ui/dialog/filedialog.cpp | 2 +- src/ui/dialog/filedialogimpl-gtkmm.cpp | 2 +- src/ui/dialog/filedialogimpl-win32.cpp | 2 +- src/ui/dialog/find.cpp | 2 +- src/ui/dialog/floating-behavior.cpp | 2 +- src/ui/dialog/font-substitution.cpp | 2 +- src/ui/dialog/guides.cpp | 2 +- src/ui/dialog/ocaldialogs.cpp | 2 +- src/ui/dialog/ocaldialogs.h | 3 +-- src/ui/dialog/xml-tree.cpp | 2 +- 12 files changed, 12 insertions(+), 13 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp index 9b216e841..f65b298c9 100644 --- a/src/ui/dialog/dock-behavior.cpp +++ b/src/ui/dialog/dock-behavior.cpp @@ -24,7 +24,7 @@ #include "verbs.h" #include "dialog.h" #include "preferences.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include #include diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 913713e5c..cd8fdbd92 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -62,7 +62,7 @@ #include "sp-namedview.h" #include "selection-chemistry.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "preferences.h" #include "verbs.h" #include "interface.h" diff --git a/src/ui/dialog/filedialog.cpp b/src/ui/dialog/filedialog.cpp index e71605739..00ed09551 100644 --- a/src/ui/dialog/filedialog.cpp +++ b/src/ui/dialog/filedialog.cpp @@ -20,7 +20,7 @@ #include "filedialog.h" #include "gc-core.h" -#include +#include "ui/dialog-events.h" #include "extension/output.h" #include "preferences.h" diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 575519848..5778b44db 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -22,7 +22,7 @@ #endif #include "filedialogimpl-gtkmm.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "interface.h" #include "io/sys.h" #include "path-prefix.h" diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 06153a2d8..ee6a0ef3a 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -31,7 +31,7 @@ //Inkscape includes #include "inkscape.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "extension/input.h" #include "extension/output.h" #include "extension/db.h" diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 37f2761df..9b814bb9f 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -31,7 +31,7 @@ #include "selection.h" #include "desktop-handles.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "verbs.h" #include "interface.h" #include "preferences.h" diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp index dd07f009a..f286588b2 100644 --- a/src/ui/dialog/floating-behavior.cpp +++ b/src/ui/dialog/floating-behavior.cpp @@ -28,7 +28,7 @@ #include "inkscape.h" #include "desktop.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "interface.h" #include "preferences.h" #include "verbs.h" diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp index 6e9ecc3c8..db7bdf222 100644 --- a/src/ui/dialog/font-substitution.cpp +++ b/src/ui/dialog/font-substitution.cpp @@ -27,7 +27,7 @@ #include "document.h" #include "selection.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "desktop-handles.h" #include "selection-chemistry.h" #include "preferences.h" diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index 80740113c..76c26a3cb 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -28,7 +28,7 @@ #include "ui/tools/tool-base.h" #include "widgets/desktop-widget.h" #include -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "message-context.h" #include "xml/repr.h" #include "verbs.h" diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index f676e75fd..607087f6d 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -27,7 +27,7 @@ #include "filedialogimpl-gtkmm.h" #include "interface.h" #include "gc-core.h" -#include +#include "ui/dialog-events.h" #include "io/sys.h" #include "preferences.h" diff --git a/src/ui/dialog/ocaldialogs.h b/src/ui/dialog/ocaldialogs.h index e21030bcd..bd028c145 100644 --- a/src/ui/dialog/ocaldialogs.h +++ b/src/ui/dialog/ocaldialogs.h @@ -38,8 +38,7 @@ //Inkscape includes #include "ui/dialog/filedialog.h" - -#include +#include "ui/dialog-events.h" struct _xmlNode; typedef _xmlNode xmlNode; diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index c87e42633..9a8c188b2 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -24,7 +24,7 @@ #include "desktop.h" #include "desktop-handles.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "document.h" #include "document-undo.h" #include "ui/tools/tool-base.h" -- cgit v1.2.3 From 0d0958e3b2aff0ed5f3ad7a98b4035213475c7f1 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 7 Sep 2014 13:02:01 -0400 Subject: Update to experimental r13543 (bzr r13090.1.108) --- src/ui/dialog/aboutbox.cpp | 18 +++++++++++++++--- src/ui/dialog/dock-behavior.cpp | 2 +- src/ui/dialog/document-properties.cpp | 10 +++++++--- src/ui/dialog/export.cpp | 2 +- src/ui/dialog/filedialog.cpp | 2 +- src/ui/dialog/filedialogimpl-gtkmm.cpp | 2 +- src/ui/dialog/filedialogimpl-win32.cpp | 2 +- src/ui/dialog/find.cpp | 2 +- src/ui/dialog/floating-behavior.cpp | 2 +- src/ui/dialog/font-substitution.cpp | 2 +- src/ui/dialog/guides.cpp | 2 +- src/ui/dialog/objects.cpp | 2 +- src/ui/dialog/ocaldialogs.cpp | 2 +- src/ui/dialog/ocaldialogs.h | 3 +-- src/ui/dialog/tags.cpp | 2 +- src/ui/dialog/xml-tree.cpp | 2 +- 16 files changed, 36 insertions(+), 21 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 44ed3b58f..7212fa372 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -254,6 +254,7 @@ void AboutBox::initStrings() { "Nicholas Bishop\n" "Joshua L. Blocher\n" "Hanno Böck\n" +"Tomasz Boczkowski\n" "Henrik Bohre\n" "Boldewyn\n" "Daniel Borgmann\n" @@ -270,6 +271,7 @@ void AboutBox::initStrings() { "Gail Carmichael\n" "Ed Catmur\n" "Chema Celorio\n" +"Jabiertxo Arraiza Cenoz\n" "Johan Ceuppens\n" "Zbigniew Chyla\n" "Alexander Clausen\n" @@ -311,6 +313,7 @@ void AboutBox::initStrings() { "Hannes Hochreiner\n" "Thomas Holder\n" "Joel Holdsworth\n" +"Christoffer Holmstedt\n" "Alan Horkan\n" "Karl Ove Hufthammer\n" "Richard Hughes\n" @@ -319,6 +322,7 @@ void AboutBox::initStrings() { "Thomas Ingham\n" "Jean-Olivier Irisson\n" "Bob Jamison\n" +"Ted Janeczko\n" "jEsuSdA\n" "Fernando Lucchesi Bastos Jurema\n" "Lauris Kaplinski\n" @@ -342,7 +346,9 @@ void AboutBox::initStrings() { "Aurel-Aimé Marmion\n" "Colin Marquardt\n" "Craig Marshall\n" +"Ivan Masár\n" "Dmitry G. Mastrukov\n" +"David Mathog\n" "Matiphas\n" "Michael Meeks\n" "Federico Mena\n" @@ -360,8 +366,10 @@ void AboutBox::initStrings() { "Nick\n" "Andreas Nilsson\n" "Mitsuru Oka\n" +"Vinícius dos Santos Oliveira\n" "Martin Owens\n" "Alvin Penner\n" +"Matthew Petroff\n" "Jon Phillips\n" "Zdenko Podobny\n" "Alexandre Prokoudine\n" @@ -398,6 +406,8 @@ void AboutBox::initStrings() { "Joakim Verona\n" "Lucas Vieites\n" "Daniel Wagenaar\n" +"Liam P. White\n" +"Sebastian Wüst\n" "Michael Wybrow\n" "Gellule Xg\n" "Daniel Yacob\n" @@ -482,6 +492,7 @@ void AboutBox::initStrings() { "Elias Norberg , 2009.\n" "Equipe de Tradução Inkscape Brasil , 2007.\n" "Fatih Demir , 2000.\n" +"Firas Hanife , 2014.\n" "Foppe Benedictus , 2007-2009.\n" "Francesc Dorca , 2003. Traducció sodipodi.\n" "Francisco Javier F. Serrador , 2003.\n" @@ -493,8 +504,9 @@ void AboutBox::initStrings() { "Hizkuntza Politikarako Sailburuordetza , 2005.\n" "Ilia Penev , 2006.\n" "Ivan Masár , 2006-2010. \n" +"Ivan Řihošek , 2014.\n" "Iñaki Larrañaga , 2006.\n" -"Jānis Eisaks , 2012, 2013.\n" +"Jānis Eisaks , 2012-2014.\n" "Jeffrey Steve Borbón Sanabria , 2005.\n" "Jesper Öqvist , 2010, 2011.\n" "Joaquim Perez i Noguer , 2008-2009.\n" @@ -516,7 +528,7 @@ void AboutBox::initStrings() { "Kingsley Turner , 2006.\n" "Kitae , 2006.\n" "Kjartan Maraas , 2000-2002.\n" -"Kris De Gussem , 2008-2013.\n" +"Kris De Gussem , 2008-2014.\n" "Lauris Kaplinski , 2000.\n" "Leandro Regueiro , 2006-2008, 2010.\n" "Liu Xiaoqin , 2008.\n" @@ -536,7 +548,7 @@ void AboutBox::initStrings() { "Muhammad Bashir Al-Noimi , 2008.\n" "Myckel Habets , 2008.\n" "Nguyen Dinh Trung , 2007, 2008.\n" -"Nicolas Dufour , 2008-2013.\n" +"Nicolas Dufour , 2008-2014.\n" "Pawan Chitrakar , 2006.\n" "Przemysław Loesch , 2005.\n" "Quico Llach , 2000. Traducció sodipodi.\n" diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp index 9b216e841..f65b298c9 100644 --- a/src/ui/dialog/dock-behavior.cpp +++ b/src/ui/dialog/dock-behavior.cpp @@ -24,7 +24,7 @@ #include "verbs.h" #include "dialog.h" #include "preferences.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include #include diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 5ad82644e..2a3a1dd86 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -1736,9 +1736,13 @@ void DocumentProperties::onDocUnitChange() prefs->setBool("/options/transform/gradient", true); { ShapeEditor::blockSetItem(true); - gdouble viewscale_w = doc->getWidth().value("px")/doc->getRoot()->viewBox.width(); - gdouble viewscale_h = doc->getHeight().value("px")/doc->getRoot()->viewBox.height(); - gdouble viewscale = std::min(viewscale_h, viewscale_w); + gdouble viewscale = 1.0; + Geom::Rect vb = doc->getRoot()->viewBox; + if ( !vb.hasZeroArea() ) { + gdouble viewscale_w = doc->getWidth().value("px") / vb.width(); + gdouble viewscale_h = doc->getHeight().value("px")/ vb.height(); + viewscale = std::min(viewscale_h, viewscale_w); + } gdouble scale = Inkscape::Util::Quantity::convert(1, old_doc_unit, doc_unit); doc->getRoot()->scaleChildItemsRec(Geom::Scale(scale), Geom::Point(-viewscale*doc->getRoot()->viewBox.min()[Geom::X] + (doc->getWidth().value("px") - viewscale*doc->getRoot()->viewBox.width())/2, diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index 913713e5c..cd8fdbd92 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -62,7 +62,7 @@ #include "sp-namedview.h" #include "selection-chemistry.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "preferences.h" #include "verbs.h" #include "interface.h" diff --git a/src/ui/dialog/filedialog.cpp b/src/ui/dialog/filedialog.cpp index e71605739..00ed09551 100644 --- a/src/ui/dialog/filedialog.cpp +++ b/src/ui/dialog/filedialog.cpp @@ -20,7 +20,7 @@ #include "filedialog.h" #include "gc-core.h" -#include +#include "ui/dialog-events.h" #include "extension/output.h" #include "preferences.h" diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 575519848..5778b44db 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -22,7 +22,7 @@ #endif #include "filedialogimpl-gtkmm.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "interface.h" #include "io/sys.h" #include "path-prefix.h" diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index 06153a2d8..ee6a0ef3a 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -31,7 +31,7 @@ //Inkscape includes #include "inkscape.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "extension/input.h" #include "extension/output.h" #include "extension/db.h" diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 37f2761df..9b814bb9f 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -31,7 +31,7 @@ #include "selection.h" #include "desktop-handles.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "verbs.h" #include "interface.h" #include "preferences.h" diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp index dd07f009a..f286588b2 100644 --- a/src/ui/dialog/floating-behavior.cpp +++ b/src/ui/dialog/floating-behavior.cpp @@ -28,7 +28,7 @@ #include "inkscape.h" #include "desktop.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "interface.h" #include "preferences.h" #include "verbs.h" diff --git a/src/ui/dialog/font-substitution.cpp b/src/ui/dialog/font-substitution.cpp index 6e9ecc3c8..db7bdf222 100644 --- a/src/ui/dialog/font-substitution.cpp +++ b/src/ui/dialog/font-substitution.cpp @@ -27,7 +27,7 @@ #include "document.h" #include "selection.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "desktop-handles.h" #include "selection-chemistry.h" #include "preferences.h" diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index 80740113c..76c26a3cb 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -28,7 +28,7 @@ #include "ui/tools/tool-base.h" #include "widgets/desktop-widget.h" #include -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "message-context.h" #include "xml/repr.h" #include "verbs.h" diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 2d558daae..ecd4ff42f 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -25,7 +25,7 @@ #include "desktop.h" #include "desktop-style.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "document.h" #include "document-undo.h" #include "filter-chemistry.h" diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index f676e75fd..607087f6d 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -27,7 +27,7 @@ #include "filedialogimpl-gtkmm.h" #include "interface.h" #include "gc-core.h" -#include +#include "ui/dialog-events.h" #include "io/sys.h" #include "preferences.h" diff --git a/src/ui/dialog/ocaldialogs.h b/src/ui/dialog/ocaldialogs.h index e21030bcd..bd028c145 100644 --- a/src/ui/dialog/ocaldialogs.h +++ b/src/ui/dialog/ocaldialogs.h @@ -38,8 +38,7 @@ //Inkscape includes #include "ui/dialog/filedialog.h" - -#include +#include "ui/dialog-events.h" struct _xmlNode; typedef _xmlNode xmlNode; diff --git a/src/ui/dialog/tags.cpp b/src/ui/dialog/tags.cpp index b2ca1b6da..127e4d95e 100644 --- a/src/ui/dialog/tags.cpp +++ b/src/ui/dialog/tags.cpp @@ -50,7 +50,7 @@ #include "sp-root.h" #include "ui/tools/tool-base.h" //"event-context.h" #include "selection.h" -#include "dialogs/dialog-events.h" +//#include "dialogs/dialog-events.h" #include "widgets/sp-color-notebook.h" #include "style.h" #include "filter-chemistry.h" diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index c87e42633..9a8c188b2 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -24,7 +24,7 @@ #include "desktop.h" #include "desktop-handles.h" -#include "dialogs/dialog-events.h" +#include "ui/dialog-events.h" #include "document.h" #include "document-undo.h" #include "ui/tools/tool-base.h" -- cgit v1.2.3 From 39d4d238a04162c559f83011999cc16feb6da88f Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Thu, 11 Sep 2014 05:30:09 +0200 Subject: add radius support to fillet-chamfer, bugfixes (bzr r13341.1.203) --- src/ui/dialog/lpe-fillet-chamfer-properties.cpp | 71 +++++++++++++------------ src/ui/dialog/lpe-fillet-chamfer-properties.h | 31 ++++------- 2 files changed, 46 insertions(+), 56 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp index eef32d10d..ad8b66b8c 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.cpp +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.cpp @@ -12,9 +12,9 @@ #include #endif +#include #include "lpe-fillet-chamfer-properties.h" #include -#include #include #include #include "inkscape.h" @@ -31,9 +31,8 @@ #include "selection-chemistry.h" #include "ui/icon-names.h" #include "ui/widget/imagetoggler.h" -#include -#include #include "util/units.h" +#include //#include "event-context.h" @@ -44,38 +43,24 @@ namespace Dialogs { FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() : _desktop(NULL), _knotpoint(NULL), _position_visible(false) { -#if WITH_GTKMM_3_0 - Gtk::Box *mainVBox = get_content_area(); -#else Gtk::Box *mainVBox = get_vbox(); -#endif - mainVBox->set_homogeneous(false); - -#if WITH_GTKMM_3_0 - _layout_table.set_row_spacing(4); - _layout_table.set_column_spacing(4); -#else _layout_table.set_spacings(4); _layout_table.resize(2, 2); -#endif // Layer name widgets - _fillet_chamfer_position_entry.set_activates_default(true); + _fillet_chamfer_position_numeric.set_digits(4); + _fillet_chamfer_position_numeric.set_increments(1,1); + //todo: get tha max aloable infinity freeze the widget + _fillet_chamfer_position_numeric.set_range(0., 999999999999999999.); + _fillet_chamfer_position_label.set_label(_("Radius (pixels):")); _fillet_chamfer_position_label.set_alignment(1.0, 0.5); -#if WITH_GTKMM_3_0 - _layout_table.attach(_fillet_chamfer_position_label, 0, 0, 1, 1); - _layout_table.attach(_fillet_chamfer_position_entry, 1, 0, 1, 1); - _fillet_chamfer_position_entry.set_hexpand(); -#else _layout_table.attach(_fillet_chamfer_position_label, 0, 1, 0, 1, Gtk::FILL, Gtk::FILL); - _layout_table.attach(_fillet_chamfer_position_entry, 1, 2, 0, 1, + _layout_table.attach(_fillet_chamfer_position_numeric, 1, 2, 0, 1, Gtk::FILL | Gtk::EXPAND, Gtk::FILL); -#endif - _fillet_chamfer_type_fillet.set_label(_("Fillet")); _fillet_chamfer_type_fillet.set_group(_fillet_chamfer_type_group); _fillet_chamfer_type_inverse_fillet.set_label(_("Inverse fillet")); @@ -115,7 +100,7 @@ FilletChamferPropertiesDialog::FilletChamferPropertiesDialog() show_all_children(); - set_focus(_fillet_chamfer_position_entry); + set_focus(_fillet_chamfer_position_numeric); } FilletChamferPropertiesDialog::~FilletChamferPropertiesDialog() @@ -128,12 +113,16 @@ void FilletChamferPropertiesDialog::showDialog( SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit) + const gchar *unit, + bool use_distance, + bool aprox_radius) { FilletChamferPropertiesDialog *dialog = new FilletChamferPropertiesDialog(); dialog->_setDesktop(desktop); dialog->_setUnit(unit); + dialog->_set_use_distance(use_distance); + dialog->_set_aprox(aprox_radius); dialog->_setKnotPoint(knotpoint); dialog->_setPt(pt); @@ -150,9 +139,9 @@ void FilletChamferPropertiesDialog::showDialog( void FilletChamferPropertiesDialog::_apply() { - std::istringstream i_pos(_fillet_chamfer_position_entry.get_text()); - double d_pos, d_width; - if (i_pos >> d_pos) { + double d_width; + double d_pos = _fillet_chamfer_position_numeric.get_value(); + if (d_pos) { if (_fillet_chamfer_type_fillet.get_active() == true) { d_width = 1; } else if (_fillet_chamfer_type_inverse_fillet.get_active() == true) { @@ -203,6 +192,13 @@ void FilletChamferPropertiesDialog::_handleButtonEvent(GdkEventButton *event) void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) { double position; + std::string distance_or_radius = std::string(_("Radius ")); + if(aprox){ + distance_or_radius = std::string(_("Radius aproximated ")); + } + if(use_distance){ + distance_or_radius = std::string(_("Knot distance ")); + } if (knotpoint.x() > 0) { double intpart; position = modf(knotpoint[Geom::X], &intpart) * 100; @@ -211,16 +207,13 @@ void FilletChamferPropertiesDialog::_setKnotPoint(Geom::Point knotpoint) _fillet_chamfer_position_label.set_label(_("Position (%):")); } else { _flexible = false; - std::string posConcat = - std::string(_("Position (")) + std::string(unit) + std::string(")"); + std::string posConcat = distance_or_radius + + std::string(_("(")) + std::string(unit) + std::string(")"); _fillet_chamfer_position_label.set_label(_(posConcat.c_str())); position = knotpoint[Geom::X] * -1; position = Inkscape::Util::Quantity::convert(position, "px", unit); } - std::ostringstream s; - s.imbue(std::locale::classic()); - s << position; - _fillet_chamfer_position_entry.set_text(s.str()); + _fillet_chamfer_position_numeric.set_value(position); if (knotpoint.y() == 1) { _fillet_chamfer_type_fillet.set_active(true); } else if (knotpoint.y() == 2) { @@ -246,6 +239,16 @@ void FilletChamferPropertiesDialog::_setUnit(const gchar *abbr) unit = abbr; } +void FilletChamferPropertiesDialog::_set_use_distance(bool use_knot_distance) +{ + use_distance = use_knot_distance; +} + +void FilletChamferPropertiesDialog::_set_aprox(bool aprox_radius) +{ + aprox = aprox_radius; +} + void FilletChamferPropertiesDialog::_setDesktop(SPDesktop *desktop) { if (desktop) { diff --git a/src/ui/dialog/lpe-fillet-chamfer-properties.h b/src/ui/dialog/lpe-fillet-chamfer-properties.h index 9beca02e1..47ff97b00 100644 --- a/src/ui/dialog/lpe-fillet-chamfer-properties.h +++ b/src/ui/dialog/lpe-fillet-chamfer-properties.h @@ -8,24 +8,10 @@ #ifndef INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H #define INKSCAPE_DIALOG_FILLET_CHAMFER_PROPERTIES_H -#if HAVE_CONFIG_H - #include "config.h" -#endif - -#include #include <2geom/point.h> +#include #include "live_effects/parameter/filletchamferpointarray.h" -#include -#include -#include - -#if WITH_GTKMM_3_0 - #include -#else - #include -#endif - class SPDesktop; namespace Inkscape { @@ -44,7 +30,9 @@ public: static void showDialog(SPDesktop *desktop, Geom::Point knotpoint, const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt, - const gchar *unit); + const gchar *unit, + bool use_distance, + bool aprox_radius); protected: @@ -53,19 +41,14 @@ protected: _knotpoint; Gtk::Label _fillet_chamfer_position_label; - Gtk::Entry _fillet_chamfer_position_entry; + Gtk::SpinButton _fillet_chamfer_position_numeric; Gtk::RadioButton::Group _fillet_chamfer_type_group; Gtk::RadioButton _fillet_chamfer_type_fillet; Gtk::RadioButton _fillet_chamfer_type_inverse_fillet; Gtk::RadioButton _fillet_chamfer_type_chamfer; Gtk::RadioButton _fillet_chamfer_type_double_chamfer; -#if WITH_GTKMM_3_0 - Gtk::Grid _layout_table; -#else Gtk::Table _layout_table; -#endif - bool _position_visible; double _index; @@ -83,10 +66,14 @@ protected: void _setPt(const Inkscape::LivePathEffect:: FilletChamferPointArrayParamKnotHolderEntity *pt); void _setUnit(const gchar *abbr); + void _set_use_distance(bool use_knot_distance); + void _set_aprox(bool aprox_radius); void _apply(); void _close(); bool _flexible; const gchar *unit; + bool use_distance; + bool aprox; void _setKnotPoint(Geom::Point knotpoint); void _prepareLabelRenderer(Gtk::TreeModel::const_iterator const &row); -- cgit v1.2.3 From 3f649ca279f98542e8147e9bd5ab67691c6e21a0 Mon Sep 17 00:00:00 2001 From: root Date: Wed, 24 Sep 2014 21:22:34 +0200 Subject: Fix bug in object dialog, in highlight color couldent select opacity, now fixed (bzr r13341.1.224) --- src/ui/dialog/objects.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index ecd4ff42f..07a27c96e 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -1450,7 +1450,7 @@ void sp_highlight_picker_color_mod(SPColorSelector *csel, GObject * cp) guint32 rgba = color.toRGBA32( alpha ); ObjectsPanel *ptr = reinterpret_cast(cp); - + //Set the highlight color for all items in the _highlight_target (all selected items) for (std::vector::iterator iter = ptr->_highlight_target.begin(); iter != ptr->_highlight_target.end(); ++iter) { -- cgit v1.2.3 From e186cf544131e582a43316767257f199e6af986c Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Mon, 29 Sep 2014 16:21:07 +0200 Subject: Remove NRTypePosDef class and associated cruft. More direct CSS -> Pango translation. (bzr r13341.1.233) --- src/ui/dialog/text-edit.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index e44809c65..9996fc0f9 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -32,7 +32,6 @@ extern "C" { #include #include -#include #include #include -- cgit v1.2.3 From 380f71793aba455f86eae2c75532b24dc613e71d Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Fri, 3 Oct 2014 21:32:26 -0400 Subject: Refactor SPGuide to use more C++ (bzr r13341.1.241) --- src/ui/dialog/guides.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index 76c26a3cb..4519a905f 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -100,7 +100,7 @@ void GuidelinePropertiesDialog::_onOK() double rad_angle = Geom::deg_to_rad( deg_angle ); normal = Geom::rot90(Geom::Point::polar(rad_angle, 1.0)); } - sp_guide_set_normal(*_guide, normal, true); + _guide->set_normal(normal, true); double const points_x = _spin_button_x.getValue("px"); double const points_y = _spin_button_y.getValue("px"); @@ -108,11 +108,11 @@ void GuidelinePropertiesDialog::_onOK() if (!_mode) newpos += _oldpos; - sp_guide_moveto(*_guide, newpos, true); + _guide->moveto(newpos, true); const gchar* name = g_strdup( _label_entry.getEntry()->get_text().c_str() ); - sp_guide_set_label(*_guide, name, true); + _guide->set_label(name, true); g_free((gpointer) name); #if WITH_GTKMM_3_0 @@ -124,7 +124,7 @@ void GuidelinePropertiesDialog::_onOK() #endif //TODO: why 257? verify this! - sp_guide_set_color(*_guide, r, g, b, true); + _guide->set_color(r, g, b, true); DocumentUndo::done(_guide->document, SP_VERB_NONE, _("Set guide properties")); @@ -295,16 +295,17 @@ void GuidelinePropertiesDialog::_setup() { signal_response().connect(sigc::mem_fun(*this, &GuidelinePropertiesDialog::_response)); // initialize dialog - _oldpos = _guide->point_on_line; + _oldpos = _guide->getPoint(); if (_guide->isVertical()) { _oldangle = 90; } else if (_guide->isHorizontal()) { _oldangle = 0; } else { - _oldangle = Geom::rad_to_deg( std::atan2( - _guide->normal_to_line[Geom::X], _guide->normal_to_line[Geom::Y] ) ); + _oldangle = Geom::rad_to_deg( std::atan2( - _guide->getNormal()[Geom::X], _guide->getNormal()[Geom::Y] ) ); } { + // FIXME holy crap!!! Inkscape::XML::Node *repr = _guide->getRepr(); const gchar *guide_id = repr->attribute("id"); gchar *label = g_strdup_printf(_("Guideline ID: %s"), guide_id); @@ -312,7 +313,7 @@ void GuidelinePropertiesDialog::_setup() { g_free(label); } { - gchar *guide_description = sp_guide_description(_guide, false); + gchar *guide_description = _guide->description(false); gchar *label = g_strdup_printf(_("Current: %s"), guide_description); g_free(guide_description); _label_descr.set_markup(label); @@ -320,15 +321,15 @@ void GuidelinePropertiesDialog::_setup() { } // init name entry - _label_entry.getEntry()->set_text(_guide->label ? _guide->label : ""); + _label_entry.getEntry()->set_text(_guide->getLabel() ? _guide->getLabel() : ""); #if WITH_GTKMM_3_0 Gdk::RGBA c; - c.set_rgba(((_guide->color>>24)&0xff) / 255.0, ((_guide->color>>16)&0xff) / 255.0, ((_guide->color>>8)&0xff) / 255.0); + c.set_rgba(((_guide->getColor()>>24)&0xff) / 255.0, ((_guide->getColor()>>16)&0xff) / 255.0, ((_guide->getColor()>>8)&0xff) / 255.0); _color.set_rgba(c); #else Gdk::Color c; - c.set_rgb_p(((_guide->color>>24)&0xff) / 255.0, ((_guide->color>>16)&0xff) / 255.0, ((_guide->color>>8)&0xff) / 255.0); + c.set_rgb_p(((_guide->getColor()>>24)&0xff) / 255.0, ((_guide->getColor()>>16)&0xff) / 255.0, ((_guide->getColor()>>8)&0xff) / 255.0); _color.set_color(c); #endif -- cgit v1.2.3 From efd39893a4f5e629a9df2d0674222aea1be14199 Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 5 Oct 2014 12:38:15 -0400 Subject: Move obvious ui component to ui/ (bzr r13341.1.247) --- src/ui/dialog/clonetiler.cpp | 2 +- src/ui/dialog/dialog.cpp | 2 +- src/ui/dialog/dock-behavior.cpp | 2 +- src/ui/dialog/export.cpp | 2 +- src/ui/dialog/extension-editor.cpp | 2 +- src/ui/dialog/filedialogimpl-gtkmm.cpp | 2 +- src/ui/dialog/find.cpp | 2 +- src/ui/dialog/floating-behavior.cpp | 2 +- src/ui/dialog/ocaldialogs.cpp | 2 +- src/ui/dialog/spellcheck.cpp | 2 +- src/ui/dialog/template-load-tab.cpp | 2 +- src/ui/dialog/text-edit.cpp | 2 +- src/ui/dialog/xml-tree.cpp | 2 +- 13 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/clonetiler.cpp b/src/ui/dialog/clonetiler.cpp index d9e2c03ba..1d6d0403e 100644 --- a/src/ui/dialog/clonetiler.cpp +++ b/src/ui/dialog/clonetiler.cpp @@ -38,7 +38,7 @@ #include "util/units.h" #include "helper/window.h" #include "inkscape.h" -#include "interface.h" +#include "ui/interface.h" #include "macros.h" #include "message-stack.h" #include "preferences.h" diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 4f0d9fbe1..213965a18 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -28,7 +28,7 @@ #include "desktop-handles.h" #include "shortcuts.h" #include "preferences.h" -#include "interface.h" +#include "ui/interface.h" #include "verbs.h" #include "ui/tool/event-utils.h" diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp index f65b298c9..50a6db208 100644 --- a/src/ui/dialog/dock-behavior.cpp +++ b/src/ui/dialog/dock-behavior.cpp @@ -18,7 +18,7 @@ #include "dock-behavior.h" #include "inkscape.h" #include "desktop.h" -#include "interface.h" +#include "ui/interface.h" #include "widgets/icon.h" #include "ui/widget/dock.h" #include "verbs.h" diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index cd8fdbd92..a4d8801f7 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -65,7 +65,7 @@ #include "ui/dialog-events.h" #include "preferences.h" #include "verbs.h" -#include "interface.h" +#include "ui/interface.h" #include "sp-root.h" #include "extension/output.h" diff --git a/src/ui/dialog/extension-editor.cpp b/src/ui/dialog/extension-editor.cpp index cd5491c24..9bdddc0e0 100644 --- a/src/ui/dialog/extension-editor.cpp +++ b/src/ui/dialog/extension-editor.cpp @@ -25,7 +25,7 @@ #include "verbs.h" #include "preferences.h" -#include "interface.h" +#include "ui/interface.h" #include "extension/extension.h" #include "extension/db.h" diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 5778b44db..511237f4d 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -23,7 +23,7 @@ #include "filedialogimpl-gtkmm.h" #include "ui/dialog-events.h" -#include "interface.h" +#include "ui/interface.h" #include "io/sys.h" #include "path-prefix.h" #include "preferences.h" diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 9b814bb9f..1a4823e4a 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -33,7 +33,7 @@ #include "ui/dialog-events.h" #include "verbs.h" -#include "interface.h" +#include "ui/interface.h" #include "preferences.h" #include "sp-text.h" #include "sp-flowtext.h" diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp index f286588b2..11db14801 100644 --- a/src/ui/dialog/floating-behavior.cpp +++ b/src/ui/dialog/floating-behavior.cpp @@ -29,7 +29,7 @@ #include "inkscape.h" #include "desktop.h" #include "ui/dialog-events.h" -#include "interface.h" +#include "ui/interface.h" #include "preferences.h" #include "verbs.h" diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index 607087f6d..c4dd9df98 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -25,7 +25,7 @@ #include "path-prefix.h" #include "filedialogimpl-gtkmm.h" -#include "interface.h" +#include "ui/interface.h" #include "gc-core.h" #include "ui/dialog-events.h" #include "io/sys.h" diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index a887a7355..b8436ebf1 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -25,7 +25,7 @@ #include "desktop-handles.h" #include "tools-switch.h" #include "ui/tools/text-tool.h" -#include "interface.h" +#include "ui/interface.h" #include "preferences.h" #include "sp-text.h" #include "sp-flowtext.h" diff --git a/src/ui/dialog/template-load-tab.cpp b/src/ui/dialog/template-load-tab.cpp index d75f81456..13cb01eef 100644 --- a/src/ui/dialog/template-load-tab.cpp +++ b/src/ui/dialog/template-load-tab.cpp @@ -24,7 +24,7 @@ #include "extension/db.h" #include "extension/effect.h" #include "inkscape.h" -#include "interface.h" +#include "ui/interface.h" #include "file.h" #include "path-prefix.h" #include "preferences.h" diff --git a/src/ui/dialog/text-edit.cpp b/src/ui/dialog/text-edit.cpp index 9996fc0f9..0f4a6f7f1 100644 --- a/src/ui/dialog/text-edit.cpp +++ b/src/ui/dialog/text-edit.cpp @@ -51,7 +51,7 @@ extern "C" { #include "ui/icon-names.h" #include "preferences.h" #include "verbs.h" -#include "interface.h" +#include "ui/interface.h" #include "svg/css-ostringstream.h" #include "widgets/icon.h" #include "widgets/font-selector.h" diff --git a/src/ui/dialog/xml-tree.cpp b/src/ui/dialog/xml-tree.cpp index 9a8c188b2..7ab6c78ba 100644 --- a/src/ui/dialog/xml-tree.cpp +++ b/src/ui/dialog/xml-tree.cpp @@ -30,7 +30,7 @@ #include "ui/tools/tool-base.h" #include "helper/window.h" #include "inkscape.h" -#include "interface.h" +#include "ui/interface.h" #include "macros.h" #include "message-context.h" #include "message-stack.h" -- cgit v1.2.3 From b700110359cc8bba13357efe42f1b1bdb8069ed8 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 5 Oct 2014 21:48:43 +0200 Subject: Use actual SVG width and height property values in preview image text. (bzr r13341.1.251) --- src/ui/dialog/filedialogimpl-gtkmm.cpp | 40 ++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 511237f4d..2c13d40b6 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -40,6 +40,8 @@ #include #include +#include + #include "document.h" #include "extension/input.h" #include "extension/output.h" @@ -191,6 +193,40 @@ void SVGPreview::showImage(Glib::ustring &theFileName) { Glib::ustring fileName = theFileName; + // Let's get real width and height from SVG file. These are template + // files so we assume they are well formed. + + // std::cout << "SVGPreview::showImage: " << theFileName << std::endl; + std::ifstream input(theFileName.c_str()); + + std::string width; + std::string height; + + if( !input ) { + std::cout << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl; + } else { + + std::string token; + + Glib::MatchInfo match_info; + Glib::RefPtr regex1 = Glib::Regex::create("width=\"(.*)\""); + Glib::RefPtr regex2 = Glib::Regex::create("height=\"(.*)\""); + + while( !input.eof() && (height.empty() || width.empty()) ) { + + input >> token; + // std::cout << "|" << token << "|" << std::endl; + + if (regex1->match(token, match_info)) { + width = match_info.fetch(1).raw(); + } + + if (regex2->match(token, match_info)) { + height = match_info.fetch(1).raw(); + } + + } + } /*##################################### # LET'S HAVE SOME FUN WITH SVG! @@ -270,7 +306,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName) " style=\"font-size:24.000000;font-style:normal;font-weight:normal;" " fill:#000000;fill-opacity:1.0000000;stroke:none;" " font-family:Sans\"\n" - " x=\"10\" y=\"26\">%d x %d\n" //# VALUES HERE + " x=\"10\" y=\"26\">%s x %s\n" //# VALUES HERE "\n\n"; // if (!Glib::get_charset()) //If we are not utf8 @@ -280,7 +316,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName) /* FIXME: Do proper XML quoting for fileName. */ gchar *xmlBuffer = g_strdup_printf(xformat, previewWidth, previewHeight, imgX, imgY, scaledImgWidth, scaledImgHeight, - fileName.c_str(), rectX, rectY, rectWidth, rectHeight, imgWidth, imgHeight); + fileName.c_str(), rectX, rectY, rectWidth, rectHeight, width.c_str(), height.c_str() ); // g_message("%s\n", xmlBuffer); -- cgit v1.2.3 From 8a779e74c5243e3efe16431fdd215efe4380bcfc Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Sun, 5 Oct 2014 22:07:53 +0200 Subject: Attempt to fix build breakage reported by su_v (but not seen locally). (bzr r13341.1.252) --- src/ui/dialog/filedialogimpl-gtkmm.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 2c13d40b6..5d330f7f0 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -21,6 +21,8 @@ #include #endif +#include + #include "filedialogimpl-gtkmm.h" #include "ui/dialog-events.h" #include "ui/interface.h" @@ -203,7 +205,7 @@ void SVGPreview::showImage(Glib::ustring &theFileName) std::string height; if( !input ) { - std::cout << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl; + std::cerr << "SVGPreview::showImage: Failed to open file: " << theFileName << std::endl; } else { std::string token; -- cgit v1.2.3 From 156cf3323a936c7dfccd9e09458cd8b5d174b7fe Mon Sep 17 00:00:00 2001 From: "Liam P. White" Date: Sun, 5 Oct 2014 19:24:27 -0400 Subject: Move more UI code into ui/ (bzr r13341.1.253) --- src/ui/dialog/align-and-distribute.cpp | 2 +- src/ui/dialog/document-properties.cpp | 4 ++-- src/ui/dialog/objects.cpp | 2 +- src/ui/dialog/spellcheck.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 8352de1e3..431da7ad1 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -38,7 +38,7 @@ #include "sp-item-transform.h" #include "sp-text.h" #include "text-editing.h" -#include "tools-switch.h" +#include "ui/tools-switch.h" #include "ui/icon-names.h" #include "ui/tools/node-tool.h" #include "ui/tool/multi-path-manipulator.h" diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 2a3a1dd86..071ac037f 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -31,13 +31,13 @@ #include "inkscape.h" #include "io/sys.h" #include "preferences.h" -#include "shape-editor.h" +#include "ui/shape-editor.h" #include "sp-namedview.h" #include "sp-root.h" #include "sp-script.h" #include "style.h" #include "svg/stringstream.h" -#include "tools-switch.h" +#include "ui/tools-switch.h" #include "ui/widget/color-picker.h" #include "ui/widget/scalar-unit.h" #include "ui/dialog/filedialog.h" diff --git a/src/ui/dialog/objects.cpp b/src/ui/dialog/objects.cpp index 07a27c96e..93d5dfbd5 100644 --- a/src/ui/dialog/objects.cpp +++ b/src/ui/dialog/objects.cpp @@ -43,7 +43,7 @@ #include "sp-root.h" #include "sp-shape.h" #include "style.h" -#include "tools-switch.h" +#include "ui/tools-switch.h" #include "ui/icon-names.h" #include "ui/widget/imagetoggler.h" #include "ui/widget/layertypeicon.h" diff --git a/src/ui/dialog/spellcheck.cpp b/src/ui/dialog/spellcheck.cpp index b8436ebf1..9faa8a2cb 100644 --- a/src/ui/dialog/spellcheck.cpp +++ b/src/ui/dialog/spellcheck.cpp @@ -23,7 +23,7 @@ #include "selection.h" #include "desktop.h" #include "desktop-handles.h" -#include "tools-switch.h" +#include "ui/tools-switch.h" #include "ui/tools/text-tool.h" #include "ui/interface.h" #include "preferences.h" -- cgit v1.2.3 From 259976c863ccdd6c28698125179b20b91da32ec0 Mon Sep 17 00:00:00 2001 From: Tavmjong Bah Date: Thu, 9 Oct 2014 14:27:49 +0200 Subject: Apply cx, cy, etc. from template to newly created document window. (bzr r13341.1.264) --- src/ui/dialog/template-widget.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/ui/dialog') diff --git a/src/ui/dialog/template-widget.cpp b/src/ui/dialog/template-widget.cpp index 9758b35ac..f79d166f2 100644 --- a/src/ui/dialog/template-widget.cpp +++ b/src/ui/dialog/template-widget.cpp @@ -24,6 +24,7 @@ #include "document.h" #include "document-undo.h" #include "file.h" +#include "sp-namedview.h" #include "extension/implementation/implementation.h" #include "inkscape.h" @@ -69,7 +70,10 @@ void TemplateWidget::create() _current_template.tpl_effect->effect(desc); DocumentUndo::clearUndo(sp_desktop_document(desc)); sp_desktop_document(desc)->setModifiedSinceSave(false); - + + // Apply cx,cy etc. from document + sp_namedview_window_from_document( desc ); + if (desktop) desktop->clearWaitingCursor(); } -- cgit v1.2.3