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>
18 #include <gtk/gtkmain.h>
20 #include <gtkmm/icontheme.h>
22 #include "inkscape.h"
24 #include "layers-panel.h"
26 #include "layer-manager.h"
27 #include "layer-fns.h"
29 #include "verbs.h"
30 #include "helper/action.h"
32 #include "document.h"
33 #include "desktop.h"
34 #include "sp-object.h"
35 #include "sp-item.h"
36 #include "widgets/icon.h"
37 #include "ui/widget/imagetoggler.h"
38 #include <gtkmm/widget.h>
39 #include "prefs-utils.h"
40 #include "xml/repr.h"
41 #include "svg/css-ostringstream.h"
42 #include "desktop-style.h"
44 //#define DUMP_LAYERS 1
46 namespace Inkscape {
47 namespace UI {
48 namespace Dialogs {
50 LayersPanel&
51 LayersPanel::getInstance()
52 {
53 return *new LayersPanel();
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 BUTTON_SOLO
71 };
73 class LayersPanel::InternalUIBounce
74 {
75 public:
76 int _actionCode;
77 SPObject* _target;
78 };
80 static gboolean layers_panel_activated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
81 {
82 if ( data )
83 {
84 LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
85 panel->setDesktop(panel->getDesktop());
86 }
88 return FALSE;
89 }
92 void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
93 {
94 bool set = false;
96 if ( iconName ) {
97 GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
98 gtk_widget_show( child );
99 btn.add( *manage(Glib::wrap(child)) );
100 set = true;
101 }
103 if ( desktop ) {
104 Verb *verb = Verb::get( code );
105 if ( verb ) {
106 SPAction *action = verb->get_action(desktop);
107 if ( !set && action && action->image ) {
108 GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
109 gtk_widget_show( child );
110 btn.add( *manage(Glib::wrap(child)) );
111 set = true;
112 }
114 if ( action && action->tip ) {
115 _tips.set_tip( btn, action->tip );
116 }
117 }
118 }
120 if ( !set && fallback ) {
121 btn.set_label( fallback );
122 }
123 }
126 Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
127 {
128 GtkWidget* iconWidget = 0;
129 const char* label = 0;
131 if ( iconName ) {
132 iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
133 }
135 if ( desktop ) {
136 Verb *verb = Verb::get( code );
137 if ( verb ) {
138 SPAction *action = verb->get_action(desktop);
139 if ( !iconWidget && action && action->image ) {
140 iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
141 }
143 if ( action ) {
144 label = action->name;
145 }
146 }
147 }
149 if ( !label && fallback ) {
150 label = fallback;
151 }
153 Gtk::Widget* wrapped = 0;
154 if ( iconWidget ) {
155 wrapped = manage(Glib::wrap(iconWidget));
156 wrapped->show();
157 }
161 Gtk::Menu::MenuList& menulist = _popupMenu.items();
163 if ( wrapped ) {
164 menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem( label, *wrapped, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
165 } else {
166 menulist.push_back( Gtk::Menu_Helpers::MenuElem( label, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
167 }
168 return menulist.back();
169 }
171 void LayersPanel::_fireAction( unsigned int code )
172 {
173 if ( _desktop ) {
174 Verb *verb = Verb::get( code );
175 if ( verb ) {
176 SPAction *action = verb->get_action(_desktop);
177 if ( action ) {
178 sp_action_perform( action, NULL );
179 // } else {
180 // g_message("no action");
181 }
182 // } else {
183 // g_message("no verb for %u", code);
184 }
185 // } else {
186 // g_message("no active desktop");
187 }
188 }
190 // SP_VERB_LAYER_NEXT,
191 // SP_VERB_LAYER_PREV,
192 void LayersPanel::_takeAction( int val )
193 {
194 if ( !_pending ) {
195 _pending = new InternalUIBounce();
196 _pending->_actionCode = val;
197 _pending->_target = _selectedLayer();
198 Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
199 }
200 }
202 bool LayersPanel::_executeAction()
203 {
204 // Make sure selected layer hasn't changed since the action was triggered
205 if ( _pending
206 && (
207 (_pending->_actionCode == BUTTON_NEW)
208 || !( (_desktop && _desktop->currentLayer())
209 && (_desktop->currentLayer() != _pending->_target)
210 )
211 )
212 ) {
213 int val = _pending->_actionCode;
214 // SPObject* target = _pending->_target;
216 switch ( val ) {
217 case BUTTON_NEW:
218 {
219 _fireAction( SP_VERB_LAYER_NEW );
220 }
221 break;
222 case BUTTON_RENAME:
223 {
224 _fireAction( SP_VERB_LAYER_RENAME );
225 }
226 break;
227 case BUTTON_TOP:
228 {
229 _fireAction( SP_VERB_LAYER_TO_TOP );
230 }
231 break;
232 case BUTTON_BOTTOM:
233 {
234 _fireAction( SP_VERB_LAYER_TO_BOTTOM );
235 }
236 break;
237 case BUTTON_UP:
238 {
239 _fireAction( SP_VERB_LAYER_RAISE );
240 }
241 break;
242 case BUTTON_DOWN:
243 {
244 _fireAction( SP_VERB_LAYER_LOWER );
245 }
246 break;
247 case BUTTON_DUPLICATE:
248 {
249 _fireAction( SP_VERB_LAYER_DUPLICATE );
250 }
251 break;
252 case BUTTON_DELETE:
253 {
254 _fireAction( SP_VERB_LAYER_DELETE );
255 }
256 case BUTTON_SOLO:
257 {
258 _fireAction( SP_VERB_LAYER_SOLO );
259 }
260 break;
261 }
263 delete _pending;
264 _pending = 0;
265 }
267 return false;
268 }
270 class LayersPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
271 {
272 public:
274 ModelColumns()
275 {
276 add(_colObject);
277 add(_colVisible);
278 add(_colLocked);
279 add(_colLabel);
280 }
281 virtual ~ModelColumns() {}
283 Gtk::TreeModelColumn<SPObject*> _colObject;
284 Gtk::TreeModelColumn<Glib::ustring> _colLabel;
285 Gtk::TreeModelColumn<bool> _colVisible;
286 Gtk::TreeModelColumn<bool> _colLocked;
287 };
289 void LayersPanel::_updateLayer( SPObject *layer ) {
290 _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForUpdated), layer) );
291 }
293 bool LayersPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* layer)
294 {
295 bool stopGoing = false;
296 Gtk::TreeModel::Row row = *iter;
297 Glib::ustring tmp = row[_model->_colLabel];
298 if ( layer == row[_model->_colObject] )
299 {
300 row[_model->_colLabel] = layer->label() ? layer->label() : SP_OBJECT_ID(layer);
301 row[_model->_colVisible] = SP_IS_ITEM(layer) ? !SP_ITEM(layer)->isHidden() : false;
302 row[_model->_colLocked] = SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false;
304 stopGoing = true;
305 }
307 return stopGoing;
308 }
310 void LayersPanel::_selectLayer( SPObject *layer ) {
311 if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
312 if ( _tree.get_selection()->count_selected_rows() != 0 ) {
313 _tree.get_selection()->unselect_all();
314 }
315 } else {
316 _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
317 }
319 _checkTreeSelection();
320 }
322 bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
323 {
324 bool stopGoing = false;
326 Gtk::TreeModel::Row row = *iter;
327 if ( layer == row[_model->_colObject] )
328 {
329 _tree.expand_to_path( path );
331 Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
333 select->select(iter);
335 stopGoing = true;
336 }
338 return stopGoing;
339 }
341 void LayersPanel::_layersChanged()
342 {
343 // g_message("_layersChanged()");
344 SPDocument* document = _desktop->doc();
345 SPObject* root = document->root;
346 if ( root ) {
347 _selectedConnection.block();
348 if ( _mgr && _mgr->includes( root ) ) {
349 SPObject* target = _desktop->currentLayer();
350 _store->clear();
352 #if DUMP_LAYERS
353 g_message("root:%p {%s} [%s]", root, root->id, root->label() );
354 #endif // DUMP_LAYERS
355 _addLayer( document, root, 0, target, 0 );
356 }
357 _selectedConnection.unblock();
358 }
359 }
361 void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
362 {
363 if ( layer && (level < _maxNestDepth) ) {
364 unsigned int counter = _mgr->childCount(layer);
365 for ( unsigned int i = 0; i < counter; i++ ) {
366 SPObject *child = _mgr->nthChildOf(layer, i);
367 if ( child ) {
368 #if DUMP_LAYERS
369 g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() );
370 #endif // DUMP_LAYERS
372 Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
373 Gtk::TreeModel::Row row = *iter;
374 row[_model->_colObject] = child;
375 row[_model->_colLabel] = child->label() ? child->label() : SP_OBJECT_ID(child);
376 row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
377 row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
379 if ( target && child == target ) {
380 _tree.expand_to_path( _store->get_path(iter) );
382 Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
383 select->select(iter);
385 _checkTreeSelection();
386 }
388 _addLayer( doc, child, &row, target, level + 1 );
389 }
390 }
391 }
392 }
394 SPObject* LayersPanel::_selectedLayer()
395 {
396 SPObject* obj = 0;
398 Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
399 if ( iter ) {
400 Gtk::TreeModel::Row row = *iter;
401 obj = row[_model->_colObject];
402 }
404 return obj;
405 }
407 void LayersPanel::_pushTreeSelectionToCurrent()
408 {
409 SPObject* inTree = _selectedLayer();
410 // TODO hunt down the possible API abuse in getting NULL
411 if ( _desktop->currentRoot() ) {
412 if ( inTree ) {
413 SPObject* curr = _desktop->currentLayer();
414 if ( curr != inTree ) {
415 _mgr->setCurrentLayer( inTree );
416 }
417 } else {
418 _mgr->setCurrentLayer( _desktop->doc()->root );
419 }
420 }
421 }
423 void LayersPanel::_checkTreeSelection()
424 {
425 bool sensitive = false;
426 bool sensitiveNonTop = false;
427 bool sensitiveNonBottom = false;
428 if ( _tree.get_selection()->count_selected_rows() > 0 ) {
429 sensitive = true;
431 SPObject* inTree = _selectedLayer();
432 if ( inTree ) {
434 sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
435 sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
437 }
438 }
441 for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
442 (*it)->set_sensitive( sensitive );
443 }
444 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
445 (*it)->set_sensitive( sensitiveNonTop );
446 }
447 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
448 (*it)->set_sensitive( sensitiveNonBottom );
449 }
450 }
452 void LayersPanel::_preToggle( GdkEvent const *event )
453 {
454 if ( _toggleEvent ) {
455 gdk_event_free(_toggleEvent);
456 _toggleEvent = 0;
457 }
459 if ( event && (event->type == GDK_BUTTON_PRESS) ) {
460 // Make a copy so we can keep it around.
461 _toggleEvent = gdk_event_copy(const_cast<GdkEvent*>(event));
462 }
463 }
465 void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
466 {
467 Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(str);
468 Gtk::TreeModel::Row row = *iter;
470 Glib::ustring tmp = row[_model->_colLabel];
472 SPObject* obj = row[_model->_colObject];
473 SPItem* item = ( obj && SP_IS_ITEM(obj) ) ? SP_ITEM(obj) : 0;
474 if ( item ) {
475 switch ( targetCol ) {
476 case COL_VISIBLE:
477 {
478 bool newValue = !row[_model->_colVisible];
479 row[_model->_colVisible] = newValue;
480 item->setHidden( !newValue );
481 item->updateRepr();
482 sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
483 newValue? _("Unhide layer") : _("Hide layer"));
484 }
485 break;
487 case COL_LOCKED:
488 {
489 bool newValue = !row[_model->_colLocked];
490 row[_model->_colLocked] = newValue;
491 item->setLocked( newValue );
492 item->updateRepr();
493 sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
494 newValue? _("Lock layer") : _("Unlock layer"));
495 }
496 break;
497 }
498 }
499 }
501 void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
502 {
503 // TODO - fix to a better is-popup function
504 if ( (evt->type == GDK_BUTTON_PRESS) && (evt->button == 3) ) {
507 {
508 Gtk::TreeModel::Path path;
509 Gtk::TreeViewColumn* col = 0;
510 int x = static_cast<int>(evt->x);
511 int y = static_cast<int>(evt->y);
512 int x2 = 0;
513 int y2 = 0;
514 if ( _tree.get_path_at_pos( x, y,
515 path, col,
516 x2, y2 ) ) {
517 _checkTreeSelection();
518 _popupMenu.popup(evt->button, evt->time);
519 }
520 }
522 }
523 }
525 void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& /*path*/, Gtk::TreeModel::iterator const& iter )
526 {
527 Gtk::TreeModel::Row row = *iter;
528 if ( row ) {
529 SPObject* obj = row[_model->_colObject];
530 if ( obj ) {
531 gchar const* oldLabel = obj->label();
532 Glib::ustring tmp = row[_model->_colLabel];
533 if ( oldLabel && oldLabel[0] && !tmp.empty() && (tmp != oldLabel) ) {
534 _mgr->renameLayer( obj, tmp.c_str() );
535 row[_model->_colLabel] = obj->label();
536 }
537 }
538 }
539 }
541 bool LayersPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
542 {
543 bool val = true;
544 if ( !currentlySelected && _toggleEvent )
545 {
546 GdkEvent* event = gtk_get_current_event();
547 if ( event ) {
548 // (keep these checks separate, so we know when to call gdk_event_free()
549 if ( event->type == GDK_BUTTON_PRESS ) {
550 GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
551 GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
553 if ( (evtb->window == target->window)
554 && (evtb->send_event == target->send_event)
555 && (evtb->time == target->time)
556 && (evtb->state == target->state)
557 )
558 {
559 // Ooooh! It's a magic one
560 val = false;
561 }
562 }
563 gdk_event_free(event);
564 }
565 }
566 return val;
567 }
569 /**
570 * Constructor
571 */
572 LayersPanel::LayersPanel() :
573 UI::Widget::Panel("", "dialogs.layers", SP_VERB_DIALOG_LAYERS),
574 _maxNestDepth(20),
575 _mgr(0),
576 _desktop(0),
577 _model(0),
578 _pending(0),
579 _toggleEvent(0),
580 _compositeSettings(SP_VERB_DIALOG_LAYERS, "layers", UI::Widget::SimpleFilterModifier::BLEND)
581 {
582 _maxNestDepth = prefs_get_int_attribute_limited("dialogs.layers", "maxDepth", 20, 1, 1000);
584 ModelColumns *zoop = new ModelColumns();
585 _model = zoop;
587 _store = Gtk::TreeStore::create( *zoop );
589 _tree.set_model( _store );
590 _tree.set_headers_visible(false);
592 Inkscape::UI::Widget::ImageToggler *eyeRenderer = manage( new Inkscape::UI::Widget::ImageToggler("visible", "hidden") );
593 int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1;
594 eyeRenderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
595 eyeRenderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_VISIBLE) );
596 eyeRenderer->property_activatable() = true;
597 Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
598 if ( col ) {
599 col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
600 }
602 Inkscape::UI::Widget::ImageToggler * renderer = manage( new Inkscape::UI::Widget::ImageToggler("width_height_lock", "lock_unlocked") );
603 int lockedColNum = _tree.append_column("lock", *renderer) - 1;
604 renderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
605 renderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_LOCKED) );
606 renderer->property_activatable() = true;
607 col = _tree.get_column(lockedColNum);
608 if ( col ) {
609 col->add_attribute( renderer->property_active(), _model->_colLocked );
610 }
612 int nameColNum = _tree.append_column_editable("Name", _model->_colLabel) - 1;
614 _tree.set_expander_column( *_tree.get_column(nameColNum) );
616 _compositeSettings.setSubject(&_subject);
618 _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
619 _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &LayersPanel::_rowSelectFunction) );
621 _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
622 _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
624 _scroller.add( _tree );
625 _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
626 _scroller.set_shadow_type(Gtk::SHADOW_IN);
628 _watching.push_back( &_compositeSettings );
630 _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
631 _layersPage.pack_end(_compositeSettings, Gtk::PACK_SHRINK);
632 _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
634 _notebook.append_page(_layersPage, _("Layers"));
636 _getContents()->pack_start(_notebook, Gtk::PACK_EXPAND_WIDGET);
638 SPDesktop* targetDesktop = getDesktop();
640 _buttonsRow.set_child_min_width( 16 );
642 Gtk::Button* btn = manage( new Gtk::Button() );
643 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("New") );
644 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) );
645 _buttonsRow.add( *btn );
647 btn = manage( new Gtk::Button() );
648 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, _("Top") );
649 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) );
650 _watchingNonTop.push_back( btn );
651 _buttonsRow.add( *btn );
653 btn = manage( new Gtk::Button() );
654 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, _("Up") );
655 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) );
656 _watchingNonTop.push_back( btn );
657 _buttonsRow.add( *btn );
659 btn = manage( new Gtk::Button() );
660 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, _("Dn") );
661 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) );
662 _watchingNonBottom.push_back( btn );
663 _buttonsRow.add( *btn );
665 btn = manage( new Gtk::Button() );
666 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, _("Bot") );
667 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) );
668 _watchingNonBottom.push_back( btn );
669 _buttonsRow.add( *btn );
671 // btn = manage( new Gtk::Button("Dup") );
672 // btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
673 // _buttonsRow.add( *btn );
675 btn = manage( new Gtk::Button() );
676 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") );
677 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) );
678 _watching.push_back( btn );
679 _buttonsRow.add( *btn );
684 // -------------------------------------------------------
685 {
686 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
687 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
688 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
689 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
691 _popupMenu.items().push_back( Gtk::Menu_Helpers::SeparatorElem() );
693 _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
694 _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
696 _popupMenu.show_all_children();
697 }
698 // -------------------------------------------------------
702 for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
703 (*it)->set_sensitive( false );
704 }
705 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
706 (*it)->set_sensitive( false );
707 }
708 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
709 (*it)->set_sensitive( false );
710 }
712 g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( layers_panel_activated ), this );
713 setDesktop( targetDesktop );
715 show_all_children();
717 // restorePanelPrefs();
718 }
720 LayersPanel::~LayersPanel()
721 {
722 _compositeSettings.setSubject(NULL);
724 if ( _model )
725 {
726 delete _model;
727 }
729 if ( _toggleEvent )
730 {
731 gdk_event_free( _toggleEvent );
732 _toggleEvent = 0;
733 }
734 }
737 void LayersPanel::setDesktop( SPDesktop* desktop )
738 {
739 Panel::setDesktop(desktop);
741 if ( desktop != _desktop ) {
742 _layerChangedConnection.disconnect();
743 _layerUpdatedConnection.disconnect();
744 _changedConnection.disconnect();
745 if ( _mgr ) {
746 _mgr = 0;
747 }
748 if ( _desktop ) {
749 _desktop = 0;
750 }
752 _desktop = getDesktop();
753 if ( _desktop ) {
754 //setLabel( _desktop->doc()->name );
756 _mgr = _desktop->layer_manager;
757 if ( _mgr ) {
758 _layerChangedConnection = _mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) );
759 _layerUpdatedConnection = _mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) );
760 _changedConnection = _mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) );
761 }
763 _layersChanged();
764 }
765 }
766 /*
767 GSList const *layers=sp_document_get_resource_list( _desktop->doc(), "layer" );
768 g_message( "layers list starts at %p", layers );
769 for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
770 SPObject *layer=static_cast<SPObject *>(iter->data);
771 g_message(" {%s} [%s]", layer->id, layer->label() );
772 }
773 */
774 }
778 } //namespace Dialogs
779 } //namespace UI
780 } //namespace Inkscape
783 /*
784 Local Variables:
785 mode:c++
786 c-file-style:"stroustrup"
787 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
788 indent-tabs-mode:nil
789 fill-column:99
790 End:
791 */
792 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :