Code

first crack at enabling blend for layers dialog
[inkscape.git] / src / ui / widget / panel.cpp
1 /**
2  * \brief Panel widget
3  *
4  * Authors:
5  *   Bryce Harrington <bryce@bryceharrington.org>
6  *   Jon A. Cruz <jon@joncruz.org>
7  *   Gustav Broberg <broberg@kth.se>
8  *
9  * Copyright (C) 2004 Bryce Harrington
10  * Copyright (C) 2005 Jon A. Cruz
11  * Copyright (C) 2007 Gustav Broberg
12  *
13  * Released under GNU GPL.  Read the file 'COPYING' for more information
14  */
16 #ifdef HAVE_CONFIG_H
17 # include <config.h>
18 #endif
20 #include <glibmm/i18n.h>
22 #include <gtkmm/dialog.h> // for Gtk::RESPONSE_*
23 #include <gtkmm/stock.h>
25 #include "panel.h"
26 #include "icon-size.h"
27 #include "prefs-utils.h"
28 #include "desktop-handles.h"
29 #include "inkscape.h"
31 namespace Inkscape {
32 namespace UI {
33 namespace Widget {
35 static const int PANEL_SETTING_SIZE = 0;
36 static const int PANEL_SETTING_MODE = 1;
37 static const int PANEL_SETTING_WRAP = 2;
38 static const int PANEL_SETTING_NEXTFREE = 3;
40 /**
41  *    Construct a Panel
42  */
44 Panel::Panel(Glib::ustring const &label, gchar const *prefs_path,
45              int verb_num, Glib::ustring const &apply_label,
46              bool menu_desired) :
47     _prefs_path(prefs_path),
48     _menu_desired(menu_desired),
49     _desktop(SP_ACTIVE_DESKTOP),
50     _label(label),
51     _apply_label(apply_label),
52     _verb_num(verb_num),
53     _temp_arrow(Gtk::ARROW_LEFT, Gtk::SHADOW_ETCHED_OUT),
54     _menu(0),
55     _action_area(0),
56     _fillable(0)
57 {
58     _init();
59 }
61 Panel::~Panel()
62 {
63     delete _menu;
64 }
66 void Panel::_popper(GdkEventButton* event)
67 {
68     if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) {
69         if (_menu) {
70             _menu->popup(event->button, event->time);
71         }
72     }
73 }
75 void Panel::_init()
76 {
77     Glib::ustring tmp("<");
78     _anchor = Gtk::ANCHOR_CENTER;
80     guint panel_size = 0;
81     if (_prefs_path) {
82         panel_size = prefs_get_int_attribute_limited( _prefs_path, "panel_size", 1, 0, 10 );
83     }
85     guint panel_mode = 0;
86     if (_prefs_path) {
87         panel_mode = prefs_get_int_attribute_limited( _prefs_path, "panel_mode", 1, 0, 10 );
88     }
90     guint panel_wrap = 0;
91     if (_prefs_path) {
92         panel_wrap = prefs_get_int_attribute_limited( _prefs_path, "panel_wrap", 0, 0, 1 );
93     }
95     _menu = new Gtk::Menu();
96     {
97         const char *things[] = {
98             N_("tiny"),
99             N_("small"),
100             N_("medium"),
101             N_("large"),
102             N_("huge")
103         };
104         Gtk::RadioMenuItem::Group groupOne;
105         for (unsigned int i = 0; i < G_N_ELEMENTS(things); i++) {
106             Glib::ustring foo(gettext(things[i]));
107             Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, foo));
108             _menu->append(*single);
109             if (i == panel_size) {
110                 single->set_active(true);
111             }
112             single->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i));
113        }
114     }
115     _menu->append(*manage(new Gtk::SeparatorMenuItem()));
116     Gtk::RadioMenuItem::Group group;
117     Glib::ustring one_label(_("List"));
118     Glib::ustring two_label(_("Grid"));
119     Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, one_label));
120     Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, two_label));
122     if (panel_mode == 0) {
123         one->set_active(true);
124     } else if (panel_mode == 1) {
125         two->set_active(true);
126     }
128     _menu->append(*one);
129     _non_horizontal.push_back(one);
130     _menu->append(*two);
131     _non_horizontal.push_back(two);
132     Gtk::MenuItem* sep = manage(new Gtk::SeparatorMenuItem());
133     _menu->append(*sep);
134     _non_horizontal.push_back(sep);
135     one->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 0));
136     two->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 1));
138     {
139         Glib::ustring wrap_label(_("Wrap"));
140         Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label));
141         check->set_active(panel_wrap);
142         _menu->append(*check);
143         _non_vertical.push_back(check);
145         check->signal_toggled().connect(sigc::bind<Gtk::CheckMenuItem*>(sigc::mem_fun(*this, &Panel::_wrapToggled), check));
147         sep = manage(new Gtk::SeparatorMenuItem());
148         _menu->append(*sep);
149         _non_vertical.push_back(sep);
150     }
152     _menu->show_all_children();
153     for ( std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter ) {
154         (*iter)->hide();
155     }
157     // _close_button.set_label("X");
159     if (!_label.empty()) {
160         _tab_title.set_label(_label);
161         _top_bar.pack_start(_tab_title);
162     }
164     // _top_bar.pack_end(_close_button, false, false);
167     if ( _menu_desired ) {
168         _top_bar.pack_end(_menu_popper, false, false);
169         Gtk::Frame* outliner = manage(new Gtk::Frame());
170         outliner->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
171         outliner->add(_temp_arrow);
172         _menu_popper.add(*outliner);
173         _menu_popper.signal_button_press_event().connect_notify(sigc::mem_fun(*this, &Panel::_popper));
174     }
176     pack_start(_top_bar, false, false);
178     Gtk::HBox* boxy = manage(new Gtk::HBox());
180     boxy->pack_start(_contents, true, true);
181     boxy->pack_start(_right_bar, false, true);
183     pack_start(*boxy, true, true);
185     signalResponse().connect(sigc::mem_fun(*this, &Panel::_handleResponse));
187     signalActivateDesktop().connect(sigc::hide<0>(sigc::mem_fun(*this, &Panel::setDesktop)));
189     show_all_children();
191     _bounceCall(PANEL_SETTING_SIZE, panel_size);
192     _bounceCall(PANEL_SETTING_MODE, panel_mode);
193     _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
196 void Panel::setLabel(Glib::ustring const &label)
198     if (_label.empty() && !label.empty())
199         _top_bar.pack_start(_tab_title);
200     else if (!_label.empty() && label.empty())
201         _top_bar.remove(_tab_title);
203     _label = label;
204     _tab_title.set_label(_label);
207 void Panel::setOrientation(Gtk::AnchorType how)
209     if (_anchor != how) {
210         _anchor = how;
211         switch (_anchor) {
212             case Gtk::ANCHOR_NORTH:
213             case Gtk::ANCHOR_SOUTH:
214             {
215                 if (_menu_desired) {
216                     _menu_popper.reference();
217                     _top_bar.remove(_menu_popper);
218                     _right_bar.pack_start(_menu_popper, false, false);
219                     _menu_popper.unreference();
221                     for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
222                         (*iter)->hide();
223                     }
224                     for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
225                         (*iter)->show();
226                     }
227                 }
228                 // Ensure we are not in "list" mode
229                 _bounceCall(PANEL_SETTING_MODE, 1);
230                 if (!_label.empty())
231                     _top_bar.remove(_tab_title);
232             }
233             break;
235             default:
236             {
237                 if ( _menu_desired ) {
238                     for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
239                         (*iter)->show();
240                     }
241                     for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
242                         (*iter)->hide();
243                     }
244                 }
245             }
246         }
247     }
250 void Panel::present()
252     _signal_present.emit();
256 void Panel::restorePanelPrefs()
258     guint panel_size = 0;
259     if (_prefs_path) {
260         panel_size = prefs_get_int_attribute_limited(_prefs_path, "panel_size", 1, 0, 10);
261     }
262     guint panel_mode = 0;
263     if (_prefs_path) {
264         panel_mode = prefs_get_int_attribute_limited(_prefs_path, "panel_mode", 1, 0, 10);
265     }
266     guint panel_wrap = 0;
267     if (_prefs_path) {
268         panel_wrap = prefs_get_int_attribute_limited(_prefs_path, "panel_wrap", 0, 0, 1 );
269     }
270     _bounceCall(PANEL_SETTING_SIZE, panel_size);
271     _bounceCall(PANEL_SETTING_MODE, panel_mode);
272     _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
275 sigc::signal<void, int> &
276 Panel::signalResponse()
278     return _signal_response;
281 sigc::signal<void> &
282 Panel::signalPresent()
284     return _signal_present;
287 void Panel::_bounceCall(int i, int j)
289     _menu->set_active(0);
290     switch (i) {
291     case PANEL_SETTING_SIZE:
292         if (_prefs_path) {
293             prefs_set_int_attribute(_prefs_path, "panel_size", j);
294         }
295         if (_fillable) {
296             ViewType curr_type = _fillable->getPreviewType();
297             switch (j) {
298             case 0:
299             {
300                 _fillable->setStyle(Inkscape::ICON_SIZE_DECORATION, curr_type);
301             }
302             break;
303             case 1:
304             {
305                 _fillable->setStyle(Inkscape::ICON_SIZE_MENU, curr_type);
306             }
307             break;
308             case 2:
309             {
310                 _fillable->setStyle(Inkscape::ICON_SIZE_SMALL_TOOLBAR, curr_type);
311             }
312             break;
313             case 3:
314             {
315                 _fillable->setStyle(Inkscape::ICON_SIZE_BUTTON, curr_type);
316             }
317             break;
318             case 4:
319             {
320                 _fillable->setStyle(Inkscape::ICON_SIZE_DIALOG, curr_type);
321             }
322             break;
323             default:
324                 ;
325             }
326         }
327         break;
328     case PANEL_SETTING_MODE:
329         if (_prefs_path) {
330             prefs_set_int_attribute (_prefs_path, "panel_mode", j);
331         }
332         if (_fillable) {
333             Inkscape::IconSize curr_size = _fillable->getPreviewSize();
334             switch (j) {
335             case 0:
336             {
337                 _fillable->setStyle(curr_size, VIEW_TYPE_LIST);
338             }
339             break;
340             case 1:
341             {
342                 _fillable->setStyle(curr_size, VIEW_TYPE_GRID);
343             }
344             break;
345             default:
346                 break;
347             }
348         }
349         break;
350     case PANEL_SETTING_WRAP:
351         if (_prefs_path) {
352             prefs_set_int_attribute (_prefs_path, "panel_wrap", j ? 1 : 0);
353         }
354         if ( _fillable ) {
355             _fillable->setWrap(j);
356         }
357         break;
358     default:
359         _handleAction(i - PANEL_SETTING_NEXTFREE, j);
360     }
364 void Panel::_wrapToggled(Gtk::CheckMenuItem* toggler)
366     if (toggler) {
367         _bounceCall(PANEL_SETTING_WRAP, toggler->get_active() ? 1 : 0);
368     }
371 gchar const *Panel::getPrefsPath() const
373     return _prefs_path;
376 Glib::ustring const &Panel::getLabel() const
378     return _label;
381 int const &Panel::getVerb() const
383     return _verb_num;
386 Glib::ustring const &Panel::getApplyLabel() const
388     return _apply_label;
391 void Panel::setDesktop(SPDesktop *desktop)
393     _desktop = desktop;
396 void Panel::_setTargetFillable(PreviewFillable *target)
398     _fillable = target;
401 void Panel::_regItem(Gtk::MenuItem* item, int group, int id)
403     _menu->append(*item);
404     item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), group + PANEL_SETTING_NEXTFREE, id));
405     item->show();
408 void Panel::_handleAction(int /*set_id*/, int /*item_id*/)
410 // for subclasses to override
413 void
414 Panel::_apply()
416     g_warning("Apply button clicked for panel [Panel::_apply()]");
419 Gtk::Button *
420 Panel::addResponseButton(const Glib::ustring &button_text, int response_id)
422     Gtk::Button *button = new Gtk::Button(button_text);
423     _addResponseButton(button, response_id);
424     return button;
427 Gtk::Button *
428 Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id)
430     Gtk::Button *button = new Gtk::Button(stock_id);
431     _addResponseButton(button, response_id);
432     return button;
435 void
436 Panel::_addResponseButton(Gtk::Button *button, int response_id)
438     // Create a button box for the response buttons if it's the first button to be added
439     if (!_action_area) {
440         _action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6);
441         _action_area->set_border_width(4);
442         pack_end(*_action_area, Gtk::PACK_SHRINK, 0);
443     }
445     _action_area->pack_end(*button);
447     if (response_id != 0) {
448         // Re-emit clicked signals as response signals
449         button->signal_clicked().connect(sigc::bind(_signal_response.make_slot(), response_id));
450         _response_map[response_id] = button;
451     }
454 void
455 Panel::setDefaultResponse(int response_id)
457     ResponseMap::iterator widget_found;
458     widget_found = _response_map.find(response_id);
460     if (widget_found != _response_map.end()) {
461         widget_found->second->activate();
462         widget_found->second->property_can_default() = true;
463         widget_found->second->grab_default();
464     }
467 void
468 Panel::setResponseSensitive(int response_id, bool setting)
470     if (_response_map[response_id])
471         _response_map[response_id]->set_sensitive(setting);
474 sigc::signal<void, SPDesktop *, SPDocument *> &
475 Panel::signalDocumentReplaced()
477     return _signal_document_replaced;
480 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
481 Panel::signalActivateDesktop()
483     return _signal_activate_desktop;
486 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
487 Panel::signalDeactiveDesktop()
489     return _signal_deactive_desktop;
492 void
493 Panel::_handleResponse(int response_id)
495     switch (response_id) {
496         case Gtk::RESPONSE_APPLY: {
497             _apply();
498             break;
499         }
500     }
503 Inkscape::Selection *Panel::_getSelection()
505     return sp_desktop_selection(_desktop);
508 } // namespace Widget
509 } // namespace UI
510 } // namespace Inkscape
512 /*
513   Local Variables:
514   mode:c++
515   c-file-style:"stroustrup"
516   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
517   indent-tabs-mode:nil
518   fill-column:99
519   End:
520 */
521 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :