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 <gtk/gtkstock.h>
16 #include <gtk/gtkmain.h>
17 #include <gtkmm/widget.h>
18 #include <gtkmm/icontheme.h>
19 #include <glibmm/i18n.h>
21 #include "desktop.h"
22 #include "desktop-style.h"
23 #include "document.h"
24 #include "helper/action.h"
25 #include "inkscape.h"
26 #include "layer-fns.h"
27 #include "layer-manager.h"
28 #include "preferences.h"
29 #include "sp-item.h"
30 #include "sp-object.h"
31 #include "svg/css-ostringstream.h"
32 #include "ui/icon-names.h"
33 #include "ui/widget/imagetoggler.h"
34 #include "verbs.h"
35 #include "widgets/icon.h"
36 #include "xml/repr.h"
38 #include "layers.h"
40 //#define DUMP_LAYERS 1
42 namespace Inkscape {
43 namespace UI {
44 namespace Dialogs {
46 LayersPanel&
47 LayersPanel::getInstance()
48 {
49 return *new LayersPanel();
50 }
52 enum {
53 COL_VISIBLE = 1,
54 COL_LOCKED
55 };
57 enum {
58 BUTTON_NEW = 0,
59 BUTTON_RENAME,
60 BUTTON_TOP,
61 BUTTON_BOTTOM,
62 BUTTON_UP,
63 BUTTON_DOWN,
64 BUTTON_DUPLICATE,
65 BUTTON_DELETE,
66 BUTTON_SOLO
67 };
69 class LayersPanel::InternalUIBounce
70 {
71 public:
72 int _actionCode;
73 SPObject* _target;
74 };
76 static gboolean layers_panel_activated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
77 {
78 if ( data )
79 {
80 LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
81 panel->setDesktop(panel->getDesktop());
82 }
84 return FALSE;
85 }
87 static gboolean layers_panel_deactivated( GtkObject */*object*/, GdkEvent * /*event*/, gpointer data )
88 {
89 if ( data )
90 {
91 LayersPanel* panel = reinterpret_cast<LayersPanel*>(data);
92 panel->setDesktop(NULL);
93 }
95 return FALSE;
96 }
99 void LayersPanel::_styleButton( Gtk::Button& btn, SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback )
100 {
101 bool set = false;
103 if ( iconName ) {
104 GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, iconName );
105 gtk_widget_show( child );
106 btn.add( *manage(Glib::wrap(child)) );
107 set = true;
108 }
110 if ( desktop ) {
111 Verb *verb = Verb::get( code );
112 if ( verb ) {
113 SPAction *action = verb->get_action(desktop);
114 if ( !set && action && action->image ) {
115 GtkWidget *child = sp_icon_new( Inkscape::ICON_SIZE_SMALL_TOOLBAR, action->image );
116 gtk_widget_show( child );
117 btn.add( *manage(Glib::wrap(child)) );
118 set = true;
119 }
121 if ( action && action->tip ) {
122 _tips.set_tip( btn, action->tip );
123 }
124 }
125 }
127 if ( !set && fallback ) {
128 btn.set_label( fallback );
129 }
130 }
133 Gtk::MenuItem& LayersPanel::_addPopupItem( SPDesktop *desktop, unsigned int code, char const* iconName, char const* fallback, int id )
134 {
135 GtkWidget* iconWidget = 0;
136 const char* label = 0;
138 if ( iconName ) {
139 iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, iconName );
140 }
142 if ( desktop ) {
143 Verb *verb = Verb::get( code );
144 if ( verb ) {
145 SPAction *action = verb->get_action(desktop);
146 if ( !iconWidget && action && action->image ) {
147 iconWidget = sp_icon_new( Inkscape::ICON_SIZE_MENU, action->image );
148 }
150 if ( action ) {
151 label = action->name;
152 }
153 }
154 }
156 if ( !label && fallback ) {
157 label = fallback;
158 }
160 Gtk::Widget* wrapped = 0;
161 if ( iconWidget ) {
162 wrapped = manage(Glib::wrap(iconWidget));
163 wrapped->show();
164 }
168 Gtk::Menu::MenuList& menulist = _popupMenu.items();
170 if ( wrapped ) {
171 menulist.push_back( Gtk::Menu_Helpers::ImageMenuElem( label, *wrapped, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
172 } else {
173 menulist.push_back( Gtk::Menu_Helpers::MenuElem( label, sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), id)) );
174 }
175 return menulist.back();
176 }
178 void LayersPanel::_fireAction( unsigned int code )
179 {
180 if ( _desktop ) {
181 Verb *verb = Verb::get( code );
182 if ( verb ) {
183 SPAction *action = verb->get_action(_desktop);
184 if ( action ) {
185 sp_action_perform( action, NULL );
186 // } else {
187 // g_message("no action");
188 }
189 // } else {
190 // g_message("no verb for %u", code);
191 }
192 // } else {
193 // g_message("no active desktop");
194 }
195 }
197 // SP_VERB_LAYER_NEXT,
198 // SP_VERB_LAYER_PREV,
199 void LayersPanel::_takeAction( int val )
200 {
201 if ( !_pending ) {
202 _pending = new InternalUIBounce();
203 _pending->_actionCode = val;
204 _pending->_target = _selectedLayer();
205 Glib::signal_timeout().connect( sigc::mem_fun(*this, &LayersPanel::_executeAction), 0 );
206 }
207 }
209 bool LayersPanel::_executeAction()
210 {
211 // Make sure selected layer hasn't changed since the action was triggered
212 if ( _pending
213 && (
214 (_pending->_actionCode == BUTTON_NEW)
215 || !( (_desktop && _desktop->currentLayer())
216 && (_desktop->currentLayer() != _pending->_target)
217 )
218 )
219 ) {
220 int val = _pending->_actionCode;
221 // SPObject* target = _pending->_target;
223 switch ( val ) {
224 case BUTTON_NEW:
225 {
226 _fireAction( SP_VERB_LAYER_NEW );
227 }
228 break;
229 case BUTTON_RENAME:
230 {
231 _fireAction( SP_VERB_LAYER_RENAME );
232 }
233 break;
234 case BUTTON_TOP:
235 {
236 _fireAction( SP_VERB_LAYER_TO_TOP );
237 }
238 break;
239 case BUTTON_BOTTOM:
240 {
241 _fireAction( SP_VERB_LAYER_TO_BOTTOM );
242 }
243 break;
244 case BUTTON_UP:
245 {
246 _fireAction( SP_VERB_LAYER_RAISE );
247 }
248 break;
249 case BUTTON_DOWN:
250 {
251 _fireAction( SP_VERB_LAYER_LOWER );
252 }
253 break;
254 case BUTTON_DUPLICATE:
255 {
256 _fireAction( SP_VERB_LAYER_DUPLICATE );
257 }
258 break;
259 case BUTTON_DELETE:
260 {
261 _fireAction( SP_VERB_LAYER_DELETE );
262 }
263 break;
264 case BUTTON_SOLO:
265 {
266 _fireAction( SP_VERB_LAYER_SOLO );
267 }
268 break;
269 }
271 delete _pending;
272 _pending = 0;
273 }
275 return false;
276 }
278 class LayersPanel::ModelColumns : public Gtk::TreeModel::ColumnRecord
279 {
280 public:
282 ModelColumns()
283 {
284 add(_colObject);
285 add(_colVisible);
286 add(_colLocked);
287 add(_colLabel);
288 }
289 virtual ~ModelColumns() {}
291 Gtk::TreeModelColumn<SPObject*> _colObject;
292 Gtk::TreeModelColumn<Glib::ustring> _colLabel;
293 Gtk::TreeModelColumn<bool> _colVisible;
294 Gtk::TreeModelColumn<bool> _colLocked;
295 };
297 void LayersPanel::_updateLayer( SPObject *layer ) {
298 _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForUpdated), layer) );
299 }
301 bool LayersPanel::_checkForUpdated(const Gtk::TreePath &/*path*/, const Gtk::TreeIter& iter, SPObject* layer)
302 {
303 bool stopGoing = false;
304 Gtk::TreeModel::Row row = *iter;
305 Glib::ustring tmp = row[_model->_colLabel];
306 if ( layer == row[_model->_colObject] )
307 {
308 row[_model->_colLabel] = layer->label() ? layer->label() : SP_OBJECT_ID(layer);
309 row[_model->_colVisible] = SP_IS_ITEM(layer) ? !SP_ITEM(layer)->isHidden() : false;
310 row[_model->_colLocked] = SP_IS_ITEM(layer) ? SP_ITEM(layer)->isLocked() : false;
312 stopGoing = true;
313 }
315 return stopGoing;
316 }
318 void LayersPanel::_selectLayer( SPObject *layer ) {
319 if ( !layer || (_desktop && _desktop->doc() && (layer == _desktop->doc()->root)) ) {
320 if ( _tree.get_selection()->count_selected_rows() != 0 ) {
321 _tree.get_selection()->unselect_all();
322 }
323 } else {
324 _store->foreach( sigc::bind<SPObject*>(sigc::mem_fun(*this, &LayersPanel::_checkForSelected), layer) );
325 }
327 _checkTreeSelection();
328 }
330 bool LayersPanel::_checkForSelected(const Gtk::TreePath &path, const Gtk::TreeIter& iter, SPObject* layer)
331 {
332 bool stopGoing = false;
334 Gtk::TreeModel::Row row = *iter;
335 if ( layer == row[_model->_colObject] )
336 {
337 _tree.expand_to_path( path );
339 Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
341 select->select(iter);
343 stopGoing = true;
344 }
346 return stopGoing;
347 }
349 void LayersPanel::_layersChanged()
350 {
351 // g_message("_layersChanged()");
352 SPDocument* document = _desktop->doc();
353 SPObject* root = document->root;
354 if ( root ) {
355 _selectedConnection.block();
356 if ( _mgr && _mgr->includes( root ) ) {
357 SPObject* target = _desktop->currentLayer();
358 _store->clear();
360 #if DUMP_LAYERS
361 g_message("root:%p {%s} [%s]", root, root->id, root->label() );
362 #endif // DUMP_LAYERS
363 _addLayer( document, root, 0, target, 0 );
364 }
365 _selectedConnection.unblock();
366 }
367 }
369 void LayersPanel::_addLayer( SPDocument* doc, SPObject* layer, Gtk::TreeModel::Row* parentRow, SPObject* target, int level )
370 {
371 if ( layer && (level < _maxNestDepth) ) {
372 unsigned int counter = _mgr->childCount(layer);
373 for ( unsigned int i = 0; i < counter; i++ ) {
374 SPObject *child = _mgr->nthChildOf(layer, i);
375 if ( child ) {
376 #if DUMP_LAYERS
377 g_message(" %3d layer:%p {%s} [%s]", level, child, child->id, child->label() );
378 #endif // DUMP_LAYERS
380 Gtk::TreeModel::iterator iter = parentRow ? _store->prepend(parentRow->children()) : _store->prepend();
381 Gtk::TreeModel::Row row = *iter;
382 row[_model->_colObject] = child;
383 row[_model->_colLabel] = child->label() ? child->label() : SP_OBJECT_ID(child);
384 row[_model->_colVisible] = SP_IS_ITEM(child) ? !SP_ITEM(child)->isHidden() : false;
385 row[_model->_colLocked] = SP_IS_ITEM(child) ? SP_ITEM(child)->isLocked() : false;
387 if ( target && child == target ) {
388 _tree.expand_to_path( _store->get_path(iter) );
390 Glib::RefPtr<Gtk::TreeSelection> select = _tree.get_selection();
391 select->select(iter);
393 _checkTreeSelection();
394 }
396 _addLayer( doc, child, &row, target, level + 1 );
397 }
398 }
399 }
400 }
402 SPObject* LayersPanel::_selectedLayer()
403 {
404 SPObject* obj = 0;
406 Gtk::TreeModel::iterator iter = _tree.get_selection()->get_selected();
407 if ( iter ) {
408 Gtk::TreeModel::Row row = *iter;
409 obj = row[_model->_colObject];
410 }
412 return obj;
413 }
415 void LayersPanel::_pushTreeSelectionToCurrent()
416 {
417 SPObject* inTree = _selectedLayer();
418 // TODO hunt down the possible API abuse in getting NULL
419 if ( _desktop->currentRoot() ) {
420 if ( inTree ) {
421 SPObject* curr = _desktop->currentLayer();
422 if ( curr != inTree ) {
423 _mgr->setCurrentLayer( inTree );
424 }
425 } else {
426 _mgr->setCurrentLayer( _desktop->doc()->root );
427 }
428 }
429 }
431 void LayersPanel::_checkTreeSelection()
432 {
433 bool sensitive = false;
434 bool sensitiveNonTop = false;
435 bool sensitiveNonBottom = false;
436 if ( _tree.get_selection()->count_selected_rows() > 0 ) {
437 sensitive = true;
439 SPObject* inTree = _selectedLayer();
440 if ( inTree ) {
442 sensitiveNonTop = (Inkscape::next_layer(inTree->parent, inTree) != 0);
443 sensitiveNonBottom = (Inkscape::previous_layer(inTree->parent, inTree) != 0);
445 }
446 }
449 for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
450 (*it)->set_sensitive( sensitive );
451 }
452 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
453 (*it)->set_sensitive( sensitiveNonTop );
454 }
455 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
456 (*it)->set_sensitive( sensitiveNonBottom );
457 }
458 }
460 void LayersPanel::_preToggle( GdkEvent const *event )
461 {
462 if ( _toggleEvent ) {
463 gdk_event_free(_toggleEvent);
464 _toggleEvent = 0;
465 }
467 if ( event && (event->type == GDK_BUTTON_PRESS) ) {
468 // Make a copy so we can keep it around.
469 _toggleEvent = gdk_event_copy(const_cast<GdkEvent*>(event));
470 }
471 }
473 void LayersPanel::_toggled( Glib::ustring const& str, int targetCol )
474 {
475 Gtk::TreeModel::Children::iterator iter = _tree.get_model()->get_iter(str);
476 Gtk::TreeModel::Row row = *iter;
478 Glib::ustring tmp = row[_model->_colLabel];
480 SPObject* obj = row[_model->_colObject];
481 SPItem* item = ( obj && SP_IS_ITEM(obj) ) ? SP_ITEM(obj) : 0;
482 if ( item ) {
483 switch ( targetCol ) {
484 case COL_VISIBLE:
485 {
486 bool newValue = !row[_model->_colVisible];
487 row[_model->_colVisible] = newValue;
488 item->setHidden( !newValue );
489 item->updateRepr();
490 sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
491 newValue? _("Unhide layer") : _("Hide layer"));
492 }
493 break;
495 case COL_LOCKED:
496 {
497 bool newValue = !row[_model->_colLocked];
498 row[_model->_colLocked] = newValue;
499 item->setLocked( newValue );
500 item->updateRepr();
501 sp_document_done( _desktop->doc() , SP_VERB_DIALOG_LAYERS,
502 newValue? _("Lock layer") : _("Unlock layer"));
503 }
504 break;
505 }
506 }
507 }
509 void LayersPanel::_handleButtonEvent(GdkEventButton* evt)
510 {
511 // TODO - fix to a better is-popup function
512 if ( (evt->type == GDK_BUTTON_PRESS) && (evt->button == 3) ) {
515 {
516 Gtk::TreeModel::Path path;
517 Gtk::TreeViewColumn* col = 0;
518 int x = static_cast<int>(evt->x);
519 int y = static_cast<int>(evt->y);
520 int x2 = 0;
521 int y2 = 0;
522 if ( _tree.get_path_at_pos( x, y,
523 path, col,
524 x2, y2 ) ) {
525 _checkTreeSelection();
526 _popupMenu.popup(evt->button, evt->time);
527 }
528 }
530 }
531 }
533 void LayersPanel::_handleRowChange( Gtk::TreeModel::Path const& /*path*/, Gtk::TreeModel::iterator const& iter )
534 {
535 Gtk::TreeModel::Row row = *iter;
536 if ( row ) {
537 SPObject* obj = row[_model->_colObject];
538 if ( obj ) {
539 gchar const* oldLabel = obj->label();
540 Glib::ustring tmp = row[_model->_colLabel];
541 if ( oldLabel && oldLabel[0] && !tmp.empty() && (tmp != oldLabel) ) {
542 _mgr->renameLayer( obj, tmp.c_str(), FALSE );
543 row[_model->_colLabel] = obj->label();
544 }
545 }
546 }
547 }
549 bool LayersPanel::_rowSelectFunction( Glib::RefPtr<Gtk::TreeModel> const & /*model*/, Gtk::TreeModel::Path const & /*path*/, bool currentlySelected )
550 {
551 bool val = true;
552 if ( !currentlySelected && _toggleEvent )
553 {
554 GdkEvent* event = gtk_get_current_event();
555 if ( event ) {
556 // (keep these checks separate, so we know when to call gdk_event_free()
557 if ( event->type == GDK_BUTTON_PRESS ) {
558 GdkEventButton const* target = reinterpret_cast<GdkEventButton const*>(_toggleEvent);
559 GdkEventButton const* evtb = reinterpret_cast<GdkEventButton const*>(event);
561 if ( (evtb->window == target->window)
562 && (evtb->send_event == target->send_event)
563 && (evtb->time == target->time)
564 && (evtb->state == target->state)
565 )
566 {
567 // Ooooh! It's a magic one
568 val = false;
569 }
570 }
571 gdk_event_free(event);
572 }
573 }
574 return val;
575 }
577 /**
578 * Constructor
579 */
580 LayersPanel::LayersPanel() :
581 UI::Widget::Panel("", "/dialogs/layers", SP_VERB_DIALOG_LAYERS),
582 _maxNestDepth(20),
583 _mgr(0),
584 _desktop(0),
585 _model(0),
586 _pending(0),
587 _toggleEvent(0),
588 _compositeSettings(SP_VERB_DIALOG_LAYERS, "layers", UI::Widget::SimpleFilterModifier::BLEND)
589 {
590 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
591 _maxNestDepth = prefs->getIntLimited("/dialogs/layers/maxDepth", 20, 1, 1000);
593 ModelColumns *zoop = new ModelColumns();
594 _model = zoop;
596 _store = Gtk::TreeStore::create( *zoop );
598 _tree.set_model( _store );
599 _tree.set_headers_visible(false);
601 Inkscape::UI::Widget::ImageToggler *eyeRenderer = manage( new Inkscape::UI::Widget::ImageToggler(
602 INKSCAPE_ICON_OBJECT_VISIBLE, INKSCAPE_ICON_OBJECT_HIDDEN) );
603 int visibleColNum = _tree.append_column("vis", *eyeRenderer) - 1;
604 eyeRenderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
605 eyeRenderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_VISIBLE) );
606 eyeRenderer->property_activatable() = true;
607 Gtk::TreeViewColumn* col = _tree.get_column(visibleColNum);
608 if ( col ) {
609 col->add_attribute( eyeRenderer->property_active(), _model->_colVisible );
610 }
612 Inkscape::UI::Widget::ImageToggler * renderer = manage( new Inkscape::UI::Widget::ImageToggler(
613 INKSCAPE_ICON_OBJECT_LOCKED, INKSCAPE_ICON_OBJECT_UNLOCKED) );
614 int lockedColNum = _tree.append_column("lock", *renderer) - 1;
615 renderer->signal_pre_toggle().connect( sigc::mem_fun(*this, &LayersPanel::_preToggle) );
616 renderer->signal_toggled().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_toggled), (int)COL_LOCKED) );
617 renderer->property_activatable() = true;
618 col = _tree.get_column(lockedColNum);
619 if ( col ) {
620 col->add_attribute( renderer->property_active(), _model->_colLocked );
621 }
623 int nameColNum = _tree.append_column_editable("Name", _model->_colLabel) - 1;
625 _tree.set_expander_column( *_tree.get_column(nameColNum) );
627 _compositeSettings.setSubject(&_subject);
629 _selectedConnection = _tree.get_selection()->signal_changed().connect( sigc::mem_fun(*this, &LayersPanel::_pushTreeSelectionToCurrent) );
630 _tree.get_selection()->set_select_function( sigc::mem_fun(*this, &LayersPanel::_rowSelectFunction) );
632 _tree.get_model()->signal_row_changed().connect( sigc::mem_fun(*this, &LayersPanel::_handleRowChange) );
633 _tree.signal_button_press_event().connect_notify( sigc::mem_fun(*this, &LayersPanel::_handleButtonEvent) );
635 _scroller.add( _tree );
636 _scroller.set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC );
637 _scroller.set_shadow_type(Gtk::SHADOW_IN);
639 _watching.push_back( &_compositeSettings );
641 _layersPage.pack_start( _scroller, Gtk::PACK_EXPAND_WIDGET );
642 _layersPage.pack_end(_compositeSettings, Gtk::PACK_SHRINK);
643 _layersPage.pack_end(_buttonsRow, Gtk::PACK_SHRINK);
645 _getContents()->pack_start(_layersPage, Gtk::PACK_EXPAND_WIDGET);
647 SPDesktop* targetDesktop = getDesktop();
649 _buttonsRow.set_child_min_width( 16 );
651 Gtk::Button* btn = manage( new Gtk::Button() );
652 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_NEW, GTK_STOCK_ADD, _("New") );
653 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_NEW) );
654 _buttonsRow.add( *btn );
656 btn = manage( new Gtk::Button() );
657 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_TOP, GTK_STOCK_GOTO_TOP, _("Top") );
658 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_TOP) );
659 _watchingNonTop.push_back( btn );
660 _buttonsRow.add( *btn );
662 btn = manage( new Gtk::Button() );
663 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, _("Up") );
664 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_UP) );
665 _watchingNonTop.push_back( btn );
666 _buttonsRow.add( *btn );
668 btn = manage( new Gtk::Button() );
669 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, _("Dn") );
670 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DOWN) );
671 _watchingNonBottom.push_back( btn );
672 _buttonsRow.add( *btn );
674 btn = manage( new Gtk::Button() );
675 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_TO_BOTTOM, GTK_STOCK_GOTO_BOTTOM, _("Bot") );
676 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_BOTTOM) );
677 _watchingNonBottom.push_back( btn );
678 _buttonsRow.add( *btn );
680 // btn = manage( new Gtk::Button("Dup") );
681 // btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DUPLICATE) );
682 // _buttonsRow.add( *btn );
684 btn = manage( new Gtk::Button() );
685 _styleButton( *btn, targetDesktop, SP_VERB_LAYER_DELETE, GTK_STOCK_REMOVE, _("X") );
686 btn->signal_clicked().connect( sigc::bind( sigc::mem_fun(*this, &LayersPanel::_takeAction), (int)BUTTON_DELETE) );
687 _watching.push_back( btn );
688 _buttonsRow.add( *btn );
693 // -------------------------------------------------------
694 {
695 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RENAME, 0, "Rename", (int)BUTTON_RENAME ) );
696 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_DUPLICATE, 0, "Duplicate", (int)BUTTON_DUPLICATE ) );
697 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_NEW, 0, "New", (int)BUTTON_NEW ) );
698 _watching.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_SOLO, 0, "Solo", (int)BUTTON_SOLO ) );
700 _popupMenu.items().push_back( Gtk::Menu_Helpers::SeparatorElem() );
702 _watchingNonTop.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_RAISE, GTK_STOCK_GO_UP, "Up", (int)BUTTON_UP ) );
703 _watchingNonBottom.push_back( &_addPopupItem( targetDesktop, SP_VERB_LAYER_LOWER, GTK_STOCK_GO_DOWN, "Down", (int)BUTTON_DOWN ) );
705 _popupMenu.show_all_children();
706 }
707 // -------------------------------------------------------
711 for ( std::vector<Gtk::Widget*>::iterator it = _watching.begin(); it != _watching.end(); ++it ) {
712 (*it)->set_sensitive( false );
713 }
714 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonTop.begin(); it != _watchingNonTop.end(); ++it ) {
715 (*it)->set_sensitive( false );
716 }
717 for ( std::vector<Gtk::Widget*>::iterator it = _watchingNonBottom.begin(); it != _watchingNonBottom.end(); ++it ) {
718 (*it)->set_sensitive( false );
719 }
721 g_signal_connect( G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK( layers_panel_activated ), this );
722 g_signal_connect( G_OBJECT(INKSCAPE), "deactivate_desktop", G_CALLBACK( layers_panel_deactivated ), this );
723 setDesktop( targetDesktop );
725 show_all_children();
727 // restorePanelPrefs();
728 }
730 LayersPanel::~LayersPanel()
731 {
732 setDesktop(NULL);
734 _compositeSettings.setSubject(NULL);
736 if ( _model )
737 {
738 delete _model;
739 }
741 if ( _toggleEvent )
742 {
743 gdk_event_free( _toggleEvent );
744 _toggleEvent = 0;
745 }
746 }
749 void LayersPanel::setDesktop( SPDesktop* desktop )
750 {
751 Panel::setDesktop(desktop);
753 if ( desktop != _desktop ) {
754 _layerChangedConnection.disconnect();
755 _layerUpdatedConnection.disconnect();
756 _changedConnection.disconnect();
757 if ( _mgr ) {
758 _mgr = 0;
759 }
760 if ( _desktop ) {
761 _desktop = 0;
762 }
764 _desktop = getDesktop();
765 if ( _desktop ) {
766 //setLabel( _desktop->doc()->name );
768 _mgr = _desktop->layer_manager;
769 if ( _mgr ) {
770 _layerChangedConnection = _mgr->connectCurrentLayerChanged( sigc::mem_fun(*this, &LayersPanel::_selectLayer) );
771 _layerUpdatedConnection = _mgr->connectLayerDetailsChanged( sigc::mem_fun(*this, &LayersPanel::_updateLayer) );
772 _changedConnection = _mgr->connectChanged( sigc::mem_fun(*this, &LayersPanel::_layersChanged) );
773 }
775 _layersChanged();
776 }
777 }
778 /*
779 GSList const *layers=sp_document_get_resource_list( _desktop->doc(), "layer" );
780 g_message( "layers list starts at %p", layers );
781 for ( GSList const *iter=layers ; iter ; iter = iter->next ) {
782 SPObject *layer=static_cast<SPObject *>(iter->data);
783 g_message(" {%s} [%s]", layer->id, layer->label() );
784 }
785 */
786 }
790 } //namespace Dialogs
791 } //namespace UI
792 } //namespace Inkscape
795 /*
796 Local Variables:
797 mode:c++
798 c-file-style:"stroustrup"
799 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
800 indent-tabs-mode:nil
801 fill-column:99
802 End:
803 */
804 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :