objects.cpp revision c10edd3236e4ac02e1918837596756ed1ef8b441
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * A simple panel for objects
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Theodore Janeczko
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Tweaked by Liam P White for use in Inkscape
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Copyright (C) Theodore Janeczko 2012 <flutterguy317@gmail.com>
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Released under GNU GPL, read the file 'COPYING' for more information
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico//#define DUMP_LAYERS 1
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico * Gets an instance of the Objects panel
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico return *new ObjectsPanel();
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico * Column enumeration
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico// COL_INSERTORDER,
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico * Button enumeration
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico// BUTTON_SETINVCLIP,
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Xml node observer for observing objects in the document
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoclass ObjectsPanel::ObjectWatcher : public Inkscape::XML::NodeObserver {
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Creates a new object watcher
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param pnl The panel to which the object watcher belongs
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param obj The object to watch
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _highlightAttr(g_quark_from_string("inkscape:highlight-color")),
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _lockedAttr(g_quark_from_string("sodipodi:insensitive")),
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _labelAttr(g_quark_from_string("inkscape:label")),
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _groupAttr(g_quark_from_string("inkscape:groupmode")),
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico virtual void notifyChildAdded( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico virtual void notifyChildRemoved( Node &/*node*/, Node &/*child*/, Node */*prev*/ )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico virtual void notifyChildOrderChanged( Node &/*node*/, Node &/*child*/, Node */*old_prev*/, Node */*new_prev*/ )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico virtual void notifyContentChanged( Node &/*node*/, Util::ptr_shared<char> /*old_content*/, Util::ptr_shared<char> /*new_content*/ ) {}
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico virtual void notifyAttributeChanged( Node &/*node*/, GQuark name, Util::ptr_shared<char> /*old_value*/, Util::ptr_shared<char> /*new_value*/ ) {
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if ( name == _lockedAttr || name == _labelAttr || name == _highlightAttr || name == _groupAttr || name == _styleAttr || name == _clipAttr || name == _maskAttr ) {
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _pnl->_updateObject(_obj, name == _highlightAttr);
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Objects panel to which this watcher belongs
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * The object that is being observed
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * The xml representation of the object that is being observed
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico /* These are quarks which define the attributes that we are observing */
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoclass ObjectsPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //add(_colInsertOrder);
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Gtk::TreeModelColumn<int> _colInsertOrder;
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico * Stylizes a button using the given icon name and tooltip
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_styleButton(Gtk::Button& btn, char const* iconName, char const* tooltip)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Adds an item to the pop-up (right-click) menu
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param desktop The active destktop
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param code Action code
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param iconName Icon name
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param fallback Fallback text
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param id Button id for callback function
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @return The generated menu item
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicoGtk::MenuItem& ObjectsPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico const char* label = 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico // label = action->name;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico item = Gtk::manage(new Gtk::ImageMenuItem(*wrapped, label, true));
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico item = Gtk::manage(new Gtk::MenuItem(label, true));
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico item->signal_activate().connect(sigc::bind(sigc::mem_fun(*this, &ObjectsPanel::_takeAction), id));
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Callback function for when an object changes. Essentially refreshes the entire tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param obj Object which was changed (currently not used as the entire tree is recreated)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_objectsChanged(SPObject */*obj*/)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //First, unattach the watchers
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ObjectsPanel::ObjectWatcher *w = _objectWatchers.back();
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Get the current document's root and use that to enumerate the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Clear the tree store
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Add all items recursively
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //Set the tree selection
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Handle button sensitivity
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Recursively adds the children of the given item to the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param obj Root object to add to the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param parentRow Parent tree row (or NULL if adding to tree root)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_addObject(SPObject* obj, Gtk::TreeModel::Row* parentRow)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for ( SPObject *child = obj->children; child != NULL; child = child->next) {
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico SPGroup * group = SP_IS_GROUP(child) ? SP_GROUP(child) : 0;
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //Add the item to the tree and set the column information
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //this seems to crash on convert stroke to path then undo (probably no ID?)
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico row[_model->_colLabel] = item->label() ? item->label() : item->getId();
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico } catch (...) {
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico row[_model->_colLabel] = Glib::ustring("getId_failure");
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico g_critical("item->getId() failed, using \"getId_failure\"");
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colHighlight] = item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colClipMask] = item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0);
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //If our parent object is a group and it's expanded, expand the tree
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if (SP_IS_GROUP(obj) && SP_GROUP(obj)->expanded())
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Add an object watcher to the item
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico ObjectsPanel::ObjectWatcher *w = new ObjectsPanel::ObjectWatcher(this, child);
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //If the item is a group, recursively add its children
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Updates an item in the tree and optionally recursively updates the item's children
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param obj The item to update in the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param recurse Whether to recurse through the item's children
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_updateObject( SPObject *obj, bool recurse ) {
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Find the object in the tree store and update it
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _store->foreach_iter( sigc::bind<SPObject*>(sigc::mem_fun(*this, &ObjectsPanel::_checkForUpdated), obj) );
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico for (SPObject * iter = obj->children; iter != NULL; iter = iter->next)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Checks items in the tree store and updates the given item
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param iter Current item being looked at in the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param obj Object to update
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicobool ObjectsPanel::_checkForUpdated(const Gtk::TreeIter& iter, SPObject* obj)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //We found our item in the tree!! Update it!
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico SPItem * item = SP_IS_ITEM(obj) ? SP_ITEM(obj) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico SPGroup * group = SP_IS_GROUP(obj) ? SP_GROUP(obj) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colLabel] = obj->label() ? obj->label() : obj->getId();
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colVisible] = item ? !item->isHidden() : false;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colLocked] = item ? !item->isSensitive() : false;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colType] = group ? (group->layerMode() == SPGroup::LAYER ? 2 : 1) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colHighlight] = item ? (item->isHighlightSet() ? item->highlight_color() : item->highlight_color() & 0xffffff00) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico row[_model->_colClipMask] = item ? (item->clip_ref && item->clip_ref->getObject() ? 1 : (item->mask_ref && item->mask_ref->getObject() ? 2 : 0)) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //row[_model->_colInsertOrder] = group ? (group->insertBottom() ? 2 : 1) : 0;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return true;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico return false;
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Updates the composite controls for the selected item
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Set the default values
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Get/set the values
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _tree.get_selection()->selected_foreach_iter(sigc::bind<bool *>(sigc::mem_fun(*this, &ObjectsPanel::_compositingChanged), &setValues));
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Sets the compositing values for the first selected item in the tree
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param iter Current tree item
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param setValues Whether to set the compositing values
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param blur Blur value to use
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_compositingChanged( const Gtk::TreeModel::iterator& iter, bool *setValues )
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Occurs when the current desktop selection changes
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param sel The current selection
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_objectsSelected( Selection *sel ) {
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico std::vector<SPItem*> const items = sel->itemList();
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for(std::vector<SPItem*>::const_iterator i=items.begin(); i!=items.end(); ++i){
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, (*i)==items.back()));
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico if (_desktop->currentLayer() && SP_IS_ITEM(_desktop->currentLayer())) {
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico _store->foreach(sigc::bind<SPItem *, bool>( sigc::mem_fun(*this, &ObjectsPanel::_checkForSelected), item, true));
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * Helper function for setting the compositing values
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico * @param item Item to use for setting the compositing values
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNicovoid ObjectsPanel::_setCompositingValues(SPItem *item)
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Block the connections to avoid interference
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //Set the opacity
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico _opacity_adjustment->set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment->get_upper());
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _opacity_adjustment.set_value((item->style->opacity.set ? SP_SCALE24_TO_FLOAT(item->style->opacity.value) : 1) * _opacity_adjustment.get_upper());
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico for(SPObject *primitive_obj = item->style->getFilter()->children; primitive_obj && SP_IS_FILTER_PRIMITIVE(primitive_obj); primitive_obj = primitive_obj->next) {
181d91ade6a7f4e59fbfe1e10567dda3f8f0e2a6JazzyNico //Get the blend mode
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico if(SP_IS_GAUSSIANBLUR(primitive_obj) && !spblur) {
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Get the blur value
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico //Set the blend mode
6ef5df7d35ba31c1d98da3922c78610a3f1c2f6f~suv _fe_cb.set_blend_mode(spblend ? spblend->blend_mode : Inkscape::Filters::BLEND_NORMAL);
6ef5df7d35ba31c1d98da3922c78610a3f1c2f6f~suv //Set the blur value
6ef5df7d35ba31c1d98da3922c78610a3f1c2f6f~suv Geom::OptRect bbox = item->bounds(SPItem::GEOMETRIC_BBOX);
6ef5df7d35ba31c1d98da3922c78610a3f1c2f6f~suv double perimeter = bbox->dimensions()[Geom::X] + bbox->dimensions()[Geom::Y]; // fixme: this is only half the perimeter, is that correct?
55409b97452fc42cc6fbb542da79ab133ed705b3JazzyNico _fe_blur.set_blur_value(spblur->stdDeviation.getNumber() * 400 / perimeter);
bool ObjectsPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPItem* item, bool scrollto)
bool stopGoing = false;
if (scrollto) {
stopGoing = true;
return stopGoing;
bool setOpacity = true;
_tree.get_selection()->selected_foreach_iter( sigc::bind<bool *>(sigc::mem_fun(*this, &ObjectsPanel::_selected_row_callback), &setOpacity));
void ObjectsPanel::_selected_row_callback( const Gtk::TreeModel::iterator& iter, bool *setCompositingValues )
if (iter) {
//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 (*setCompositingValues)
*setCompositingValues = false;
bool sensitiveNonTop = true;
bool sensitiveNonBottom = true;
for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
if (item)
if (item)
case GDK_KEY_Return:
case GDK_KEY_KP_Enter:
case GDK_KEY_F2:
grab_focus();
case GDK_KEY_Home:
case GDK_KEY_End:
case GDK_KEY_Page_Up:
case GDK_KEY_Page_Down:
static unsigned doubleclick = 0;
static bool overVisible = false;
overVisible = false;
int x2 = 0;
int y2 = 0;
overVisible = 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, &ObjectsPanel::_rowSelectFunction));
int x2 = 0;
int y2 = 0;
if (_defer_target) {
DocumentUndo::maybeDone(_desktop->doc(), "layer:lockothers", SP_VERB_LAYER_LOCK_OTHERS, _("Lock other layers"));
if (overVisible) {
_tree.get_selection()->selected_foreach_iter(sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setVisibleIter), newValue));
overVisible = false;
_tree.get_selection()->selected_foreach_iter(sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setLockedIter), newValue));
_tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeHighlightTarget));
if (_selectedColor)
doubleclick = 0;
int x2 = 0;
int y2 = 0;
grab_focus();
if (item)
bool ObjectsPanel::_handleDragDrop(const Glib::RefPtr<Gdk::DragContext>& /*context*/, int x, int y, guint /*time*/)
_dnd_into = false;
_tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_storeDragSource));
_dnd_into = true;
if (item)
if ( _desktop ) {
if ( verb ) {
if ( action ) {
if ( !_pending ) {
switch ( val ) {
case BUTTON_NEW:
case BUTTON_RENAME:
case BUTTON_TOP:
case BUTTON_BOTTOM:
case BUTTON_UP:
case BUTTON_DOWN:
case BUTTON_DUPLICATE:
case BUTTON_DELETE:
case BUTTON_SOLO:
case BUTTON_SHOW_ALL:
case BUTTON_HIDE_ALL:
case BUTTON_LOCK_OTHERS:
case BUTTON_LOCK_ALL:
case BUTTON_UNLOCK_ALL:
case BUTTON_CLIPGROUP:
case BUTTON_SETCLIP:
case BUTTON_UNSETCLIP:
case BUTTON_SETMASK:
case BUTTON_UNSETMASK:
case BUTTON_GROUP:
case BUTTON_UNGROUP:
case BUTTON_COLLAPSE_ALL:
case DRAGNDROP:
_doTreeMove( );
delete _pending;
_pending = 0;
if ( item ) {
bool ObjectsPanel::_noSelection( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool /*currentlySelected*/ )
bool ObjectsPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
bool val = true;
if ( event ) {
val = false;
return val;
void ObjectsPanel::_setExpanded(const Gtk::TreeModel::iterator& iter, const Gtk::TreeModel::Path& /*path*/, bool isexpanded)
if (isexpanded)
float alpha = 0;
for (std::vector<SPItem *>::iterator iter = _highlight_target.begin(); iter != _highlight_target.end(); ++iter)
DocumentUndo::maybeDone(SP_ACTIVE_DOCUMENT, "highlight", SP_VERB_DIALOG_OBJECTS, _("Set object highlight color"));
_blockCompositeUpdate = true;
_tree.get_selection()->selected_foreach_iter(sigc::mem_fun(*this, &ObjectsPanel::_opacityChangedIter));
_blockCompositeUpdate = false;
if (item)
#if WITH_GTKMM_3_0
item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment->get_value() / _opacity_adjustment->get_upper());
item->style->opacity.value = SP_SCALE24_FROM_FLOAT(_opacity_adjustment.get_value() / _opacity_adjustment.get_upper());
_blockCompositeUpdate = true;
_tree.get_selection()->selected_foreach_iter(sigc::bind<Glib::ustring>(sigc::mem_fun(*this, &ObjectsPanel::_blendChangedIter), blendmode));
_blockCompositeUpdate = false;
if (item)
for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
if (bbox) {
for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
_blockCompositeUpdate = true;
_tree.get_selection()->selected_foreach_iter(sigc::bind<double>(sigc::mem_fun(*this, &ObjectsPanel::_blurChangedIter), _fe_blur.get_blur_value()));
_blockCompositeUpdate = false;
if (item)
if (style) {
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 = 0;
if (radius != 0) {
for (SPObject *primitive = item->style->getFilter()->children; primitive && SP_IS_FILTER_PRIMITIVE(primitive); primitive = primitive->next) {
_rootWatcher(0),
_deskTrack(),
_desktop(0),
_document(0),
_model(0),
_pending(0),
_toggleEvent(0),
_composite_vbox(false, 0),
_opacity_vbox(false, 0),
#if WITH_GTKMM_3_0
_fe_vbox(false, 0),
_blur_vbox(false, 0),
Inkscape::UI::Widget::ImageToggler *eyeRenderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler(
if ( col ) {
Inkscape::UI::Widget::ImageToggler * renderer = Gtk::manage( new Inkscape::UI::Widget::ImageToggler(
if ( col ) {
Inkscape::UI::Widget::LayerTypeIcon * typeRenderer = Gtk::manage( new Inkscape::UI::Widget::LayerTypeIcon());
if ( col ) {
_typeHeader.set_tooltip_text(_("Type: Layer, Group, or Object. Clicking on Layer or Group icon, toggles between the two types."));
/*Inkscape::UI::Widget::InsertOrderIcon * insertRenderer = Gtk::manage( new Inkscape::UI::Widget::InsertOrderIcon());
Inkscape::UI::Widget::ClipMaskIcon * clipRenderer = Gtk::manage( new Inkscape::UI::Widget::ClipMaskIcon());
if ( col ) {
Inkscape::UI::Widget::HighlightPicker * highlightRenderer = Gtk::manage( new Inkscape::UI::Widget::HighlightPicker());
if ( col ) {
_highlightHeader.set_tooltip_text(_("Highlight color of outline in Node tool. Click to set. If alpha is zero, use inherited color."));
if( _name_column ) {
_nameHeader.set_tooltip_text(_("Layer/Group/Object label (inkscape:label). Double-click to set. Default value is object 'id'."));
_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) );
_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_row_collapsed().connect( sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), false));
_tree.signal_row_expanded().connect( sigc::bind<bool>(sigc::mem_fun(*this, &ObjectsPanel::_setExpanded), true));
_text_renderer->signal_editing_canceled().connect( sigc::mem_fun(*this, &ObjectsPanel::_handleEditingCancelled) );
#if WITH_GTKMM_3_0
_blendConnection = _fe_cb.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blendValueChanged));
_blurConnection = _fe_blur.signal_blend_blur_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_blurValueChanged));
#if WITH_GTKMM_3_0
_opacityConnection = _opacity_adjustment->signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged));
_opacityConnection = _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectsPanel::_opacityValueChanged));
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_NEW) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DELETE) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_BOTTOM) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_DOWN) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_UP) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_TOP) );
btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &ObjectsPanel::_takeAction), (int)BUTTON_COLLAPSE_ALL) );
_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 ) );
_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 ) );
_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 ) );
_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 ) );
_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 ) );
_watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_OBJECT_SET_CLIPPATH, 0, _("Set Clip"), (int)BUTTON_SETCLIP ) );
_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_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 ) );
_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 ) );
for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
Gtk::Widget *color_selector = Gtk::manage(new Inkscape::UI::Widget::ColorNotebook(*_selectedColor));
*color_selector, true, true, 0);
_selectedColor->signal_dragged.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
_selectedColor->signal_released.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
_selectedColor->signal_changed.connect(sigc::mem_fun(*this, &ObjectsPanel::_highlightPickerColorMod));
desktopChangeConn = _deskTrack.connectDesktopChanged( sigc::mem_fun(*this, &ObjectsPanel::setDesktop) );
if ( _model )
delete _model;
_model = 0;
if (_pending) {
delete _pending;
_pending = 0;
if ( _toggleEvent )
_toggleEvent = 0;
if (_rootWatcher)
delete _rootWatcher;
if ( _desktop ) {
_desktop = 0;
if ( _desktop ) {
_documentChangedConnection = _desktop->connectDocumentReplaced( sigc::mem_fun(*this, &ObjectsPanel::setDocument));
_selectionChangedConnection = _desktop->selection->connectChanged( sigc::mem_fun(*this, &ObjectsPanel::_objectsSelected));
if (SP_ACTIVE_DESKTOP ) {
if (SP_ACTIVE_DESKTOP ) {