4af154062b004563b70255de2cc2da51a3e5f028
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
155 {
156 public:
157 int _actionCode;
158 SPObject* _target;
159 };
161 static gboolean layers_panel_activated( GtkObject *object, GdkEvent * /*event*/, gpointer data )
162 {
163 if ( data )
164 {
165 LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
166 panel->setDesktop( SP_ACTIVE_DESKTOP );
167 }
169 return FALSE;
170 }
173 void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
174 {
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 }
204 }
207 Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
208 {
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();
250 }
252 void LayersPanel::_fireAction( unsigned int code )
253 {
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 }
269 }
271 // SP_VERB_LAYER_NEXT,
272 // SP_VERB_LAYER_PREV,
273 void LayersPanel::_takeAction( int val )
274 {
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 }
281 }
283 bool LayersPanel::_executeAction()
284 {
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;
336 }
338 class LayersPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
339 {
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) );
359 }
361 bool LayersPanel::_checkForUpdated(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
362 {
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;
376 }
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();
388 }
390 bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
391 {
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;
406 }
408 void LayersPanel::_layersChanged()
409 {
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 }
424 }
426 void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
427 {
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 }
456 }
458 SPObject* LayersPanel::_selectedLayer()
459 {
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;
469 }
471 void LayersPanel::_pushTreeSelectionToCurrent()
472 {
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 }
486 }
488 void LayersPanel::_checkTreeSelection()
489 {
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 }
513 }
515 void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
516 {
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 }
547 }
549 void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
550 {
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 }
570 }
572 void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& path, Gtk::TreeModel::iterator const& iter )
573 {
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 }
586 }
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)
598 {
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();
724 }
726 LayersPanel::~LayersPanel()
727 {
728 if ( _model )
729 {
730 delete _model;
731 }
732 }
735 void LayersPanel::setDesktop( SPDesktop* desktop )
736 {
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 */
770 }
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 :