Code

4af154062b004563b70255de2cc2da51a3e5f028
[inkscape.git] / src / dialogs / layers-panel.cpp
1 /*
2  * A simple panel for layers
3  *
4  * Authors:
5  *   Jon A. Cruz
6  *
7  * Copyright (C) 2006 Jon A. Cruz
8  *
9  * Released under GNU GPL, read the file 'COPYING' for more information
10  */
11 #ifdef HAVE_CONFIG_H
12 # include <config.h>
13 #endif
15 #include <glibmm/i18n.h>
17 #include <gtk/gtkstock.h>
19 #include "inkscape.h"
21 #include "layers-panel.h"
23 #include "layer-manager.h"
24 #include "layer-fns.h"
26 #include "verbs.h"
27 #include "helper/action.h"
29 #include "document.h"
30 #include "desktop.h"
31 #include "desktop-handles.h"
32 #include "selection.h"
33 #include "sp-object.h"
34 #include "sp-item.h"
35 #include "widgets/icon.h"
36 #include <gtkmm/widget.h>
37 #include "prefs-utils.h"
39 //#define DUMP_LAYERS 1
41 namespace Inkscape {
42 namespace UI {
43 namespace Dialogs {
45 LayersPanel* LayersPanel::instance = 0;
47 LayersPanel& LayersPanel::getInstance()
48 {
49     if ( !instance ) {
50         instance = new LayersPanel();
51     }
53     return *instance;
54 }
56 enum {
57     COL_VISIBLE = 1,
58     COL_LOCKED
59 };
61 enum {
62     BUTTON_NEW = 0,
63     BUTTON_RENAME,
64     BUTTON_TOP,
65     BUTTON_BOTTOM,
66     BUTTON_UP,
67     BUTTON_DOWN,
68 //    BUTTON_DUPLICATE,
69     BUTTON_DELETE
70 };
72 class ImageToggler : public Gtk::CellRendererPixbuf {
73 public:
74     ImageToggler( char const* on, char const* off) :
75         Glib::ObjectBase(typeid(ImageToggler)),
76         Gtk::CellRendererPixbuf(),
77         _pixOnName(on),
78         _pixOffName(off),
79         _property_active(*this, "active", false),
80         _property_activatable(*this, "activatable", true),
81         _property_pixbuf_on(*this, "pixbuf_on", Glib::RefPtr<Gdk::Pixbuf>(0)),
82         _property_pixbuf_off(*this, "pixbuf_off", Glib::RefPtr<Gdk::Pixbuf>(0))
83     {
84         property_mode() = Gtk::CELL_RENDERER_MODE_ACTIVATABLE;
86         Gtk::Widget* thingie = sp_icon_get_icon(_pixOnName.c_str(), Inkscape::ICON_SIZE_DECORATION);
87         if ( thingie ) {
88             if ( SP_IS_ICON(thingie->gobj()) ) {
89                 SPIcon* icon = SP_ICON(thingie->gobj());
90                 sp_icon_fetch_pixbuf( icon );
91                 _property_pixbuf_on = Glib::wrap( icon->pb, true );
92             }
93             delete thingie;
94         }
95         thingie = sp_icon_get_icon(_pixOffName.c_str(), Inkscape::ICON_SIZE_DECORATION);
96         if ( thingie ) {
97             if ( SP_IS_ICON(thingie->gobj()) ) {
98                 SPIcon* icon = SP_ICON(thingie->gobj());
99                 sp_icon_fetch_pixbuf( icon );
100                 _property_pixbuf_off = Glib::wrap( icon->pb, true );
101             }
102             delete thingie;
103         }
104         property_pixbuf() = _property_pixbuf_off.get_value();
105     }
107     sigc::signal<void, const Glib::ustring&> signal_toggled()
108     {
109         return _signal_toggled;
110     }
112     Glib::PropertyProxy<bool> property_active() { return _property_active.get_proxy(); }
113     Glib::PropertyProxy<bool> property_activatable() { return _property_activatable.get_proxy(); }
114     Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_on();
115     Glib::PropertyProxy< Glib::RefPtr<Gdk::Pixbuf> > property_pixbuf_off();
116 //  virtual Glib::PropertyProxy_Base _property_renderable(); //override
118 protected:
119     virtual void render_vfunc( const Glib::RefPtr<Gdk::Drawable>& window,
120                                Gtk::Widget& widget,
121                                const Gdk::Rectangle& background_area,
122                                const Gdk::Rectangle& cell_area,
123                                const Gdk::Rectangle& expose_area,
124                                Gtk::CellRendererState flags )
125     {
126         property_pixbuf() = _property_active.get_value() ? _property_pixbuf_on : _property_pixbuf_off;
127         Gtk::CellRendererPixbuf::render_vfunc( window, widget, background_area, cell_area, expose_area, flags );
128     }
130     virtual bool activate_vfunc(GdkEvent* event,
131                                 Gtk::Widget& widget,
132                                 const Glib::ustring& path,
133                                 const Gdk::Rectangle& background_area,
134                                 const Gdk::Rectangle& cell_area,
135                                 Gtk::CellRendererState flags)
136     {
137         _signal_toggled.emit(path);
138         return false;
139     }
142 private:
143     Glib::ustring _pixOnName;
144     Glib::ustring _pixOffName;
146     Glib::Property<bool> _property_active;
147     Glib::Property<bool> _property_activatable;
148     Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_on;
149     Glib::Property< Glib::RefPtr<Gdk::Pixbuf> > _property_pixbuf_off;
151     sigc::signal<void, const Glib::ustring&> _signal_toggled;
152 };
154 class LayersPanel::InternalUIBounce
156 public:
157     int _actionCode;
158     SPObject* _target;
159 };
161 static gboolean layers_panel_activated( GtkObject *object, GdkEvent * /*event*/, gpointer data )
163     if ( data )
164     {
165         LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
166         panel->setDesktop( SP_ACTIVE_DESKTOP );
167     }
169     return FALSE;
173 void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
175     bool set = false;
177     if ( iconName ) {
178         GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
179         gtk_widget_show( child );
180         btn.add( *manage(Glib::wrap(child)) );
181         set = true;
182     }
184     if ( desktop ) {
185         Verb *verb = Verb::get( code );
186         if ( verb ) {
187             SPAction *action = verb->get_action(desktop);
188             if ( !set && action && action->image ) {
189                 GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
190                 gtk_widget_show( child );
191                 btn.add( *manage(Glib::wrap(child)) );
192                 set = true;
193             }
195             if ( action && action->tip ) {
196                 _tips.set_tip( btn, action->tip );
197             }
198         }
199     }
201     if ( !set && fallback ) {
202         btn.set_label( fallback );
203     }
207 Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
209     GtkWidget* iconWidget = 0;
210     const char* label = 0;
212     if ( iconName ) {
213         iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
214     }
216     if ( desktop ) {
217         Verb *verb = Verb::get( code );
218         if ( verb ) {
219             SPAction *action = verb->get_action(desktop);
220             if ( !iconWidget && action && action->image ) {
221                 iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
222             }
224             if ( action ) {
225                 label = action->name;
226             }
227         }
228     }
230     if ( !label && fallback ) {
231         label = fallback;
232     }
234     Gtk::Widget* wrapped = 0;
235     if ( iconWidget ) {
236         wrapped = manage(Glib::wrap(iconWidget));
237         wrapped->show();
238     }
242     Gtk::Menu::MenuList& menulist = _popupMenu.items();
244     if ( wrapped ) {
245         menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem( label, *wrapped, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
246     } else {
247         menulist.push_back( Gtk::Menu_Helpers::MenuElem( label, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
248     }
249     return menulist.back();
252 void LayersPanel::_fireAction( unsigned int code )
254     if ( _desktop ) {
255         Verb *verb = Verb::get( code );
256         if ( verb ) {
257             SPAction *action = verb->get_action(_desktop);
258             if ( action ) {
259                 sp_action_perform( action, NULL );
260 //             } else {
261 //                 g_message("no action");
262             }
263 //         } else {
264 //             g_message("no verb for %u", code);
265         }
266 //     } else {
267 //         g_message("no active desktop");
268     }
271 //     SP_VERB_LAYER_NEXT,
272 //     SP_VERB_LAYER_PREV,
273 void LayersPanel::_takeAction( int val )
275     if ( !_pending ) {
276         _pending = new InternalUIBounce();
277         _pending->_actionCode = val;
278         _pending->_target = _selectedLayer();
279         Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
280     }
283 bool LayersPanel::_executeAction()
285     // Make sure selected layer hasn't changed since the action was triggered
286     if ( _pending
287          && !( (_desktop && _desktop->currentLayer())
288                && (_desktop->currentLayer() != _pending->_target)
289              ) ) {
290         int val = _pending->_actionCode;
291 //        SPObject* target = _pending->_target;
293         switch ( val ) {
294             case BUTTON_NEW:
295             {
296                 _fireAction( SP_VERB_LAYER_NEW );
297             }
298             break;
299             case BUTTON_RENAME:
300             {
301                 _fireAction( SP_VERB_LAYER_RENAME );
302             }
303             break;
304             case BUTTON_TOP:
305             {
306                 _fireAction( SP_VERB_LAYER_TO_TOP );
307             }
308             break;
309             case BUTTON_BOTTOM:
310             {
311                 _fireAction( SP_VERB_LAYER_TO_BOTTOM );
312             }
313             break;
314             case BUTTON_UP:
315             {
316                 _fireAction( SP_VERB_LAYER_RAISE );
317             }
318             break;
319             case BUTTON_DOWN:
320             {
321                 _fireAction( SP_VERB_LAYER_LOWER );
322             }
323             break;
324             case BUTTON_DELETE:
325             {
326                 _fireAction( SP_VERB_LAYER_DELETE );
327             }
328             break;
329         }
331         delete _pending;
332         _pending = 0;
333     }
335     return false;
338 class LayersPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
340 public:
342     ModelColumns()
343     {
344         add(_colObject);
345         add(_colVisible);
346         add(_colLocked);
347         add(_colLabel);
348     }
349     virtual ~ModelColumns() {}
351     Gtk::TreeModelColumn<SPObject*> _colObject;
352     Gtk::TreeModelColumn<Glib::ustring> _colLabel;
353     Gtk::TreeModelColumn<bool> _colVisible;
354     Gtk::TreeModelColumn<bool> _colLocked;
355 };
357 void LayersPanel::_updateLayer( SPObject *layer ) {
358     _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForUpdated), layer) );
361 bool LayersPanel::_checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
363     bool stopGoing = false;
364     Gtk::TreeModel::Row row = *iter;
365     Glib::ustring tmp = row[_model->_colLabel];
366     if ( layer == row[_model->_colObject] )
367     {
368         row[_model->_colLabel] = layer->label() ? layer->label() : SP_OBJECT_ID(layer);
369         row[_model->_colVisible] = SP_IS_ITEM(layer) ? !SP_ITEM(layer)->isHidden() : false;
370         row[_model->_colLocked] = SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false;
372         stopGoing = true;
373     }
375     return stopGoing;
378 void LayersPanel::_selectLayer( SPObject *layer ) {
379     if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
380         if ( _tree.get_selection()->count_selected_rows() != 0 ) {
381             _tree.get_selection()->unselect_all();
382         }
383     } else {
384         _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
385     }
387     _checkTreeSelection();
390 bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
392     bool stopGoing = false;
394     Gtk::TreeModel::Row row = *iter;
395     if ( layer == row[_model->_colObject] )
396     {
397         _tree.expand_to_path( path );
399         Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
400         select->select(iter);
402         stopGoing = true;
403     }
405     return stopGoing;
408 void LayersPanel::_layersChanged()
410 //    g_message("_layersChanged()");
411     SPDocument* document = _desktop->doc();
412     SPObject* root = document->root;
413     if ( root ) {
414         if ( _mgr && _mgr->includes( root ) ) {
415             SPObject* target = _desktop->currentLayer();
416             _store->clear();
418 #if DUMP_LAYERS
419             g_message("root:%p  {%s}   [%s]", root, root->id, root->label() );
420 #endif // DUMP_LAYERS
421             _addLayer( document, root, 0, target, 0 );
422         }
423     }
426 void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
428     if ( layer && (level < _maxNestDepth) ) {
429         unsigned int counter = _mgr->childCount(layer);
430         for ( unsigned int i = 0; i < counter; i++ ) {
431             SPObject *child = _mgr->nthChildOf(layer, i);
432             if ( child ) {
433 #if DUMP_LAYERS
434                 g_message(" %3d    layer:%p  {%s}   [%s]", level, child, child->id, child->label() );
435 #endif // DUMP_LAYERS
437                 Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
438                 Gtk::TreeModel::Row row = *iter;
439                 row[_model->_colObject] = child;
440                 row[_model->_colLabel] = child->label() ? child->label() : SP_OBJECT_ID(child);
441                 row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
442                 row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
444                 if ( target && child == target ) {
445                     _tree.expand_to_path( _store->get_path(iter) );
447                     Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
448                     select->select(iter);
449                     _checkTreeSelection();
450                 }
452                 _addLayer( doc, child, &row, target, level + 1 );
453             }
454         }
455     }
458 SPObject* LayersPanel::_selectedLayer()
460     SPObject* obj = 0;
462     Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
463     if ( iter ) {
464         Gtk::TreeModel::Row row = *iter;
465         obj = row[_model->_colObject];
466     }
468     return obj;
471 void LayersPanel::_pushTreeSelectionToCurrent()
473     SPObject* inTree = _selectedLayer();
474     if ( inTree ) {
475         SPObject* curr = _desktop->currentLayer();
476         if ( curr != inTree ) {
477             // TODO - move these to a function in layer-manager.cpp
478             _desktop->setCurrentLayer( inTree );
479             sp_desktop_selection(_desktop)->clear();
480         }
481     } else {
482         // TODO - move these to a function in layer-manager.cpp
483         _desktop->setCurrentLayer( _desktop->doc()->root );
484         sp_desktop_selection(_desktop)->clear();
485     }
488 void LayersPanel::_checkTreeSelection()
490     bool sensitive = false;
491     bool sensitiveNonTop = false;
492     bool sensitiveNonBottom = false;
493     if ( _tree.get_selection()->count_selected_rows() > 0 ) {
494         sensitive = true;
496         SPObject* inTree = _selectedLayer();
497         if ( inTree ) {
499             sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
500             sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
501         }
502     }
504     for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
505         (*it)->set_sensitive( sensitive );
506     }
507     for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
508         (*it)->set_sensitive( sensitiveNonTop );
509     }
510     for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
511         (*it)->set_sensitive( sensitiveNonBottom );
512     }
515 void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
517     Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(str);
518     Gtk::TreeModel::Row row = *iter;
520     Glib::ustring tmp = row[_model->_colLabel];
522     SPObject* obj = row[_model->_colObject];
523     SPItem* item = ( obj && SP_IS_ITEM(obj) ) ? SP_ITEM(obj) : 0;
524     if ( item ) {
525         switch ( targetCol ) {
526             case COL_VISIBLE:
527             {
528                 bool newValue = !row[_model->_colVisible];
529                 row[_model->_colVisible] = newValue;
530                 item->setHidden( !newValue  );
531                 item->updateRepr();
532                 sp_document_done( _desktop->doc() );
533             }
534             break;
536             case COL_LOCKED:
537             {
538                 bool newValue = !row[_model->_colLocked];
539                 row[_model->_colLocked] = newValue;
540                 item->setLocked( newValue );
541                 item->updateRepr();
542                 sp_document_done( _desktop->doc() );
543             }
544             break;
545         }
546     }
549 void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
551     if ( (evt->type == GDK_BUTTON_PRESS) && (evt->button == 3) ) {
554         {
555             Gtk::TreeModel::Path path;
556             Gtk::TreeViewColumn* col = 0;
557             int x = static_cast<int>(evt->x);
558             int y = static_cast<int>(evt->y);
559             int x2 = 0;
560             int y2 = 0;
561             if ( _tree.get_path_at_pos( x, y,
562                                         path, col,
563                                         x2, y2 ) ) {
564                 _checkTreeSelection();
565                 _popupMenu.popup(evt->button, evt->time);
566             }
567         }
569     }
572 void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeModel::iterator const& iter )
574     Gtk::TreeModel::Row row = *iter;
575     if ( row ) {
576         SPObject* obj = row[_model->_colObject];
577         if ( obj ) {
578             gchar const* oldLabel = obj->label();
579             Glib::ustring tmp = row[_model->_colLabel];
580             if ( oldLabel && oldLabel[0] && !tmp.empty() && (tmp != oldLabel) ) {
581                 _mgr->renameLayer( obj, tmp.c_str() );
582                 row[_model->_colLabel] = obj->label();
583             }
584         }
585     }
588 /**
589  * Constructor
590  */
591 LayersPanel::LayersPanel() :
592     Inkscape::UI::Widget::Panel( Glib::ustring(), "dialogs.layers" ),
593     _maxNestDepth(20),
594     _mgr(0),
595     _desktop(0),
596     _model(0),
597     _pending(0)
599     _maxNestDepth = prefs_get_int_attribute_limited("dialogs.layers", "maxDepth", 20, 1, 1000);
601     ModelColumns *zoop = new ModelColumns();
602     _model = zoop;
604     _store = Gtk::TreeStore::create( *zoop );
606     _tree.set_model( _store );
607     _tree.set_headers_visible(false);
609     ImageToggler* eyeRenderer = manage( new ImageToggler("visible", "hidden") );
610     int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1;
611     eyeRenderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_VISIBLE) );
612     eyeRenderer->property_activatable() = true;
613     Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
614     if ( col ) {
615         col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
616     }
618     ImageToggler * renderer = manage( new ImageToggler("width_height_lock", "lock_unlocked") );
619     int lockedColNum = _tree.append_column("lock", *renderer) - 1;
620     renderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_LOCKED) );
621     renderer->property_activatable() = true;
622     col = _tree.get_column(lockedColNum);
623     if ( col ) {
624         col->add_attribute( renderer->property_active(), _model->_colLocked );
625     }
627     int nameColNum = _tree.append_column_editable("Name", _model->_colLabel) - 1;
629     _tree.set_expander_column( *_tree.get_column(nameColNum) );
632     _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
634     _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
635     _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
637     _scroller.add( _tree );
638     _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
639     _getContents()->pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
640     _getContents()->pack_end(_buttonsRow, Gtk::PACK_SHRINK);
642     SPDesktop* targetDesktop = SP_ACTIVE_DESKTOP;
644     _buttonsRow.set_child_min_width( 16 );
646     Gtk::Button* btn = manage( new Gtk::Button() );
647     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("New") );
648     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) );
649     _buttonsRow.add( *btn );
651     btn = manage( new Gtk::Button() );
652     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, _("Top") );
653     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) );
654     _watchingNonTop.push_back( btn );
655     _buttonsRow.add( *btn );
657     btn = manage( new Gtk::Button() );
658     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, _("Up") );
659     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) );
660     _watchingNonTop.push_back( btn );
661     _buttonsRow.add( *btn );
663     btn = manage( new Gtk::Button() );
664     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, _("Dn") );
665     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) );
666     _watchingNonBottom.push_back( btn );
667     _buttonsRow.add( *btn );
669     btn = manage( new Gtk::Button() );
670     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, _("Bot") );
671     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) );
672     _watchingNonBottom.push_back( btn );
673     _buttonsRow.add( *btn );
675 //     btn = manage( new Gtk::Button("Dup") );
676 //     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
677 //     _buttonsRow.add( *btn );
679     btn = manage( new Gtk::Button() );
680     _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") );
681     btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) );
682     _watching.push_back( btn );
683     _buttonsRow.add( *btn );
688     // -------------------------------------------------------
689     {
690         _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
691         _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
693          _popupMenu.items().push_back( Gtk::Menu_Helpers::SeparatorElem() );
695         _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
696         _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
698         _popupMenu.show_all_children();
699     }
700     // -------------------------------------------------------
704     for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
705         (*it)->set_sensitive( false );
706     }
707     for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
708         (*it)->set_sensitive( false );
709     }
710     for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
711         (*it)->set_sensitive( false );
712     }
714     g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( layers_panel_activated ), this );
717     setDesktop( targetDesktop );
721     show_all_children();
723     restorePanelPrefs();
726 LayersPanel::~LayersPanel()
728     if ( _model )
729     {
730         delete _model;
731     }
735 void LayersPanel::setDesktop( SPDesktop* desktop )
737     if ( desktop != _desktop ) {
738         _layerChangedConnection.disconnect();
739         _layerUpdatedConnection.disconnect();
740         _changedConnection.disconnect();
741         if ( _mgr ) {
742             _mgr = 0;
743         }
744         if ( _desktop ) {
745             _desktop = 0;
746         }
748         _desktop = SP_ACTIVE_DESKTOP;
749         if ( _desktop ) {
750             setLabel( _desktop->doc()->name );
752             _mgr = _desktop->layer_manager;
753             if ( _mgr ) {
754                 _layerChangedConnection = _mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) );
755                 _layerUpdatedConnection = _mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) );
756                 _changedConnection = _mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) );
757             }
759             _layersChanged();
760         }
761     }
762 /*
763     GSList const *layers=sp_document_get_resource_list( _desktop->doc(), "layer" );
764     g_message( "layers list starts at %p", layers );
765     for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
766         SPObject *layer=static_cast<SPObject *>(iter->data);
767         g_message("  {%s}   [%s]", layer->id, layer->label() );
768     }
769 */
774 } //namespace Dialogs
775 } //namespace UI
776 } //namespace Inkscape
779 /*
780   Local Variables:
781   mode:c++
782   c-file-style:"stroustrup"
783   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
784   indent-tabs-mode:nil
785   fill-column:99
786   End:
787 */
788 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :