Code

i18n. Context cleanup (context|string replaced with C_).
[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 <gtk/gtkiconfactory.h>
27 #include "panel.h"
28 #include "icon-size.h"
29 #include "preferences.h"
30 #include "desktop-handles.h"
31 #include "inkscape.h"
32 #include "widgets/eek-preview.h"
34 namespace Inkscape {
35 namespace UI {
36 namespace Widget {
38 static const int PANEL_SETTING_SIZE = 0;
39 static const int PANEL_SETTING_MODE = 1;
40 static const int PANEL_SETTING_SHAPE = 2;
41 static const int PANEL_SETTING_WRAP = 3;
42 static const int PANEL_SETTING_NEXTFREE = 4;
45 void Panel::prep() {
46     GtkIconSize sizes[] = {
47         Inkscape::getRegisteredIconSize(Inkscape::ICON_SIZE_DECORATION),
48         GTK_ICON_SIZE_MENU,
49         GTK_ICON_SIZE_SMALL_TOOLBAR,
50         GTK_ICON_SIZE_BUTTON,
51         GTK_ICON_SIZE_DND, // Not used by options, but included to make the last size larger
52         GTK_ICON_SIZE_DIALOG
53     };
54     eek_preview_set_size_mappings( G_N_ELEMENTS(sizes), sizes );
55 }
57 /**
58  *    Construct a Panel
59  */
61 Panel::Panel(Glib::ustring const &label, gchar const *prefs_path,
62              int verb_num, Glib::ustring const &apply_label,
63              bool menu_desired) :
64     _prefs_path(prefs_path),
65     _menu_desired(menu_desired),
66     _desktop(SP_ACTIVE_DESKTOP),
67     _label(label),
68     _apply_label(apply_label),
69     _verb_num(verb_num),
70     _temp_arrow(Gtk::ARROW_LEFT, Gtk::SHADOW_ETCHED_OUT),
71     _menu(0),
72     _action_area(0),
73     _fillable(0)
74 {
75     _init();
76 }
78 Panel::~Panel()
79 {
80     delete _menu;
81 }
83 void Panel::_popper(GdkEventButton* event)
84 {
85     if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) {
86         if (_menu) {
87             _menu->popup(event->button, event->time);
88         }
89     }
90 }
92 void Panel::_init()
93 {
94     Glib::ustring tmp("<");
95     _anchor = Gtk::ANCHOR_CENTER;
97     guint panel_size = 0, panel_mode = 0, panel_ratio = 100;
98     bool panel_wrap = 0;
99     if (!_prefs_path.empty()) {
100         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
101         panel_wrap = prefs->getBool(_prefs_path + "/panel_wrap");
102         panel_size = prefs->getIntLimited(_prefs_path + "/panel_size", 1, 0, PREVIEW_SIZE_HUGE);
103         panel_mode = prefs->getIntLimited(_prefs_path + "/panel_mode", 1, 0, 10);
104         panel_ratio = prefs->getIntLimited(_prefs_path + "/panel_ratio", 100, 0, 500 );
105     }
107     _menu = new Gtk::Menu();
109     {
110         Gtk::RadioMenuItem::Group group;
111         Glib::ustring one_label(_("List"));
112         Glib::ustring two_label(_("Grid"));
113         Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, one_label));
114         Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, two_label));
116         if (panel_mode == 0) {
117             one->set_active(true);
118         } else if (panel_mode == 1) {
119             two->set_active(true);
120         }
122         _menu->append(*one);
123         _non_horizontal.push_back(one);
124         _menu->append(*two);
125         _non_horizontal.push_back(two);
126         Gtk::MenuItem* sep = manage(new Gtk::SeparatorMenuItem());
127         _menu->append(*sep);
128         _non_horizontal.push_back(sep);
129         one->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 0));
130         two->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 1));
131     }
133     {
134         Glib::ustring heightItemLabel(C_("Swatches", "Size"));
136         //TRANSLATORS: Indicates size of colour swatches
137         const gchar *heightLabels[] = {
138             N_("Tiny"),
139             N_("Small"),
140             NC_("Swatches height", "Medium"),
141             N_("Large"),
142             N_("Huge")
143         };
145         Gtk::MenuItem *sizeItem = manage(new Gtk::MenuItem(heightItemLabel));
146         Gtk::Menu *sizeMenu = manage(new Gtk::Menu());
147         sizeItem->set_submenu(*sizeMenu);
149         Gtk::RadioMenuItem::Group heightGroup;
150         for (unsigned int i = 0; i < G_N_ELEMENTS(heightLabels); i++) {
151             Glib::ustring _label(Q_(heightLabels[i]));
152             Gtk::RadioMenuItem* _item = manage(new Gtk::RadioMenuItem(heightGroup, _label));
153             sizeMenu->append(*_item);
154             if (i == panel_size) {
155                 _item->set_active(true);
156             }
157             _item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i));
158        }
160        _menu->append(*sizeItem);
161     }
163     {
164         Glib::ustring widthItemLabel(C_("Swatches", "Width"));
166         //TRANSLATORS: Indicates width of colour swatches
167         const gchar *widthLabels[] = {
168             N_("Narrower"),
169             N_("Narrow"),
170             NC_("Swatches width", "Medium"),
171             N_("Wide"),
172             N_("Wider")
173         };
175         Gtk::MenuItem *item = manage( new Gtk::MenuItem(widthItemLabel));
176         Gtk::Menu *type_menu = manage(new Gtk::Menu());
177         item->set_submenu(*type_menu);
178         _menu->append(*item);
180         Gtk::RadioMenuItem::Group widthGroup;
182         guint values[] = {0, 25, 50, 100, 200, 400};
183         guint hot_index = 3;
184         for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) {
185             // Assume all values are in increasing order
186             if ( values[i] <= panel_ratio ) {
187                 hot_index = i;
188             }
189         }
190         for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) {
191             Glib::ustring _label(Q_(widthLabels[i]));
192             Gtk::RadioMenuItem *_item = manage(new Gtk::RadioMenuItem(widthGroup, _label));
193             type_menu->append(*_item);
194             if ( i <= hot_index ) {
195                 _item->set_active(true);
196             }
197             _item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SHAPE, values[i]));
198         }
199     }
201     {
202         //TRANSLATORS: "Wrap" indicates how colour swatches are displayed
203         Glib::ustring wrap_label(C_("Swatches","Wrap"));
204         Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label));
205         check->set_active(panel_wrap);
206         _menu->append(*check);
207         _non_vertical.push_back(check);
209         check->signal_toggled().connect(sigc::bind<Gtk::CheckMenuItem*>(sigc::mem_fun(*this, &Panel::_wrapToggled), check));
210     }
212     Gtk::SeparatorMenuItem *sep;
213     sep = manage(new Gtk::SeparatorMenuItem());
214     _menu->append(*sep);
216     _menu->show_all_children();
217     for ( std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter ) {
218         (*iter)->hide();
219     }
221     // _close_button.set_label("X");
223     if (!_label.empty()) {
224         _tab_title.set_label(_label);
225         _top_bar.pack_start(_tab_title);
226     }
228     // _top_bar.pack_end(_close_button, false, false);
231     if ( _menu_desired ) {
232         _top_bar.pack_end(_menu_popper, false, false);
233         gint width = 0;
234         gint height = 0;
236         if ( gtk_icon_size_lookup( Inkscape::getRegisteredIconSize(Inkscape::ICON_SIZE_DECORATION), &width, &height ) ) {
237             _temp_arrow.set_size_request(width, height);
238         }
240         _menu_popper.add(_temp_arrow);
241         _menu_popper.signal_button_press_event().connect_notify(sigc::mem_fun(*this, &Panel::_popper));
242     }
244     pack_start(_top_bar, false, false);
246     Gtk::HBox* boxy = manage(new Gtk::HBox());
248     boxy->pack_start(_contents, true, true);
249     boxy->pack_start(_right_bar, false, true);
251     pack_start(*boxy, true, true);
253     signalResponse().connect(sigc::mem_fun(*this, &Panel::_handleResponse));
255     signalActivateDesktop().connect(sigc::hide<0>(sigc::mem_fun(*this, &Panel::setDesktop)));
257     show_all_children();
259     _bounceCall(PANEL_SETTING_SIZE, panel_size);
260     _bounceCall(PANEL_SETTING_MODE, panel_mode);
261     _bounceCall(PANEL_SETTING_SHAPE, panel_ratio);
262     _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
265 void Panel::setLabel(Glib::ustring const &label)
267     if (_label.empty() && !label.empty())
268         _top_bar.pack_start(_tab_title);
269     else if (!_label.empty() && label.empty())
270         _top_bar.remove(_tab_title);
272     _label = label;
273     _tab_title.set_label(_label);
276 void Panel::setOrientation(Gtk::AnchorType how)
278     if (_anchor != how) {
279         _anchor = how;
280         switch (_anchor) {
281             case Gtk::ANCHOR_NORTH:
282             case Gtk::ANCHOR_SOUTH:
283             {
284                 if (_menu_desired) {
285                     _menu_popper.reference();
286                     _top_bar.remove(_menu_popper);
287                     _right_bar.pack_start(_menu_popper, false, false);
288                     _menu_popper.unreference();
290                     for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
291                         (*iter)->hide();
292                     }
293                     for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
294                         (*iter)->show();
295                     }
296                 }
297                 // Ensure we are not in "list" mode
298                 _bounceCall(PANEL_SETTING_MODE, 1);
299                 if (!_label.empty())
300                     _top_bar.remove(_tab_title);
301             }
302             break;
304             default:
305             {
306                 if ( _menu_desired ) {
307                     for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
308                         (*iter)->show();
309                     }
310                     for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
311                         (*iter)->hide();
312                     }
313                 }
314             }
315         }
316     }
319 void Panel::present()
321     _signal_present.emit();
325 void Panel::restorePanelPrefs()
327     guint panel_size = 0, panel_mode = 0, panel_ratio = 100;
328     bool panel_wrap = 0;
329     if (!_prefs_path.empty()) {
330         Inkscape::Preferences *prefs = Inkscape::Preferences::get();
331         panel_wrap = prefs->getBool(_prefs_path + "/panel_wrap");
332         panel_size = prefs->getIntLimited(_prefs_path + "/panel_size", 1, 0, PREVIEW_SIZE_HUGE);
333         panel_mode = prefs->getIntLimited(_prefs_path + "/panel_mode", 1, 0, 10);
334         panel_ratio = prefs->getIntLimited(_prefs_path + "/panel_ratio", 000, 0, 500 );
335     }
336     _bounceCall(PANEL_SETTING_SIZE, panel_size);
337     _bounceCall(PANEL_SETTING_MODE, panel_mode);
338     _bounceCall(PANEL_SETTING_SHAPE, panel_ratio);
339     _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
342 sigc::signal<void, int> &
343 Panel::signalResponse()
345     return _signal_response;
348 sigc::signal<void> &
349 Panel::signalPresent()
351     return _signal_present;
354 void Panel::_bounceCall(int i, int j)
356     _menu->set_active(0);
357     switch (i) {
358     case PANEL_SETTING_SIZE:
359         if (!_prefs_path.empty()) {
360             Inkscape::Preferences *prefs = Inkscape::Preferences::get();
361             prefs->setInt(_prefs_path + "/panel_size", j);
362         }
363         if (_fillable) {
364             ViewType curr_type = _fillable->getPreviewType();
365             guint curr_ratio = _fillable->getPreviewRatio();
366             switch (j) {
367             case 0:
368             {
369                 _fillable->setStyle(::PREVIEW_SIZE_TINY, curr_type, curr_ratio);
370             }
371             break;
372             case 1:
373             {
374                 _fillable->setStyle(::PREVIEW_SIZE_SMALL, curr_type, curr_ratio);
375             }
376             break;
377             case 2:
378             {
379                 _fillable->setStyle(::PREVIEW_SIZE_MEDIUM, curr_type, curr_ratio);
380             }
381             break;
382             case 3:
383             {
384                 _fillable->setStyle(::PREVIEW_SIZE_BIG, curr_type, curr_ratio);
385             }
386             break;
387             case 4:
388             {
389                 _fillable->setStyle(::PREVIEW_SIZE_HUGE, curr_type, curr_ratio);
390             }
391             break;
392             default:
393                 ;
394             }
395         }
396         break;
397     case PANEL_SETTING_MODE:
398         if (!_prefs_path.empty()) {
399             Inkscape::Preferences *prefs = Inkscape::Preferences::get();
400             prefs->setInt(_prefs_path + "/panel_mode", j);
401         }
402         if (_fillable) {
403             ::PreviewSize curr_size = _fillable->getPreviewSize();
404             guint curr_ratio = _fillable->getPreviewRatio();
405             switch (j) {
406             case 0:
407             {
408                 _fillable->setStyle(curr_size, VIEW_TYPE_LIST, curr_ratio);
409             }
410             break;
411             case 1:
412             {
413                 _fillable->setStyle(curr_size, VIEW_TYPE_GRID, curr_ratio);
414             }
415             break;
416             default:
417                 break;
418             }
419         }
420         break;
421     case PANEL_SETTING_SHAPE:
422         if (!_prefs_path.empty()) {
423             Inkscape::Preferences *prefs = Inkscape::Preferences::get();
424             prefs->setInt(_prefs_path + "/panel_ratio", j);
425         }
426         if ( _fillable ) {
427             ViewType curr_type = _fillable->getPreviewType();
428             ::PreviewSize curr_size = _fillable->getPreviewSize();
429             _fillable->setStyle(curr_size, curr_type, j);
430         }
431         break;
432     case PANEL_SETTING_WRAP:
433         if (!_prefs_path.empty()) {
434             Inkscape::Preferences *prefs = Inkscape::Preferences::get();
435             prefs->setBool(_prefs_path + "/panel_wrap", j);
436         }
437         if ( _fillable ) {
438             _fillable->setWrap(j);
439         }
440         break;
441     default:
442         _handleAction(i - PANEL_SETTING_NEXTFREE, j);
443     }
447 void Panel::_wrapToggled(Gtk::CheckMenuItem* toggler)
449     if (toggler) {
450         _bounceCall(PANEL_SETTING_WRAP, toggler->get_active() ? 1 : 0);
451     }
454 gchar const *Panel::getPrefsPath() const
456     return _prefs_path.data();
459 Glib::ustring const &Panel::getLabel() const
461     return _label;
464 int const &Panel::getVerb() const
466     return _verb_num;
469 Glib::ustring const &Panel::getApplyLabel() const
471     return _apply_label;
474 void Panel::setDesktop(SPDesktop *desktop)
476     _desktop = desktop;
479 void Panel::_setTargetFillable(PreviewFillable *target)
481     _fillable = target;
484 void Panel::_regItem(Gtk::MenuItem* item, int group, int id)
486     _menu->append(*item);
487     item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), group + PANEL_SETTING_NEXTFREE, id));
488     item->show();
491 void Panel::_handleAction(int /*set_id*/, int /*item_id*/)
493 // for subclasses to override
496 void
497 Panel::_apply()
499     g_warning("Apply button clicked for panel [Panel::_apply()]");
502 Gtk::Button *
503 Panel::addResponseButton(const Glib::ustring &button_text, int response_id)
505     Gtk::Button *button = new Gtk::Button(button_text);
506     _addResponseButton(button, response_id);
507     return button;
510 Gtk::Button *
511 Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id)
513     Gtk::Button *button = new Gtk::Button(stock_id);
514     _addResponseButton(button, response_id);
515     return button;
518 void
519 Panel::_addResponseButton(Gtk::Button *button, int response_id)
521     // Create a button box for the response buttons if it's the first button to be added
522     if (!_action_area) {
523         _action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6);
524         _action_area->set_border_width(4);
525         pack_end(*_action_area, Gtk::PACK_SHRINK, 0);
526     }
528     _action_area->pack_end(*button);
530     if (response_id != 0) {
531         // Re-emit clicked signals as response signals
532         button->signal_clicked().connect(sigc::bind(_signal_response.make_slot(), response_id));
533         _response_map[response_id] = button;
534     }
537 void
538 Panel::setDefaultResponse(int response_id)
540     ResponseMap::iterator widget_found;
541     widget_found = _response_map.find(response_id);
543     if (widget_found != _response_map.end()) {
544         widget_found->second->activate();
545         widget_found->second->property_can_default() = true;
546         widget_found->second->grab_default();
547     }
550 void
551 Panel::setResponseSensitive(int response_id, bool setting)
553     if (_response_map[response_id])
554         _response_map[response_id]->set_sensitive(setting);
557 sigc::signal<void, SPDesktop *, SPDocument *> &
558 Panel::signalDocumentReplaced()
560     return _signal_document_replaced;
563 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
564 Panel::signalActivateDesktop()
566     return _signal_activate_desktop;
569 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
570 Panel::signalDeactiveDesktop()
572     return _signal_deactive_desktop;
575 void
576 Panel::_handleResponse(int response_id)
578     switch (response_id) {
579         case Gtk::RESPONSE_APPLY: {
580             _apply();
581             break;
582         }
583     }
586 Inkscape::Selection *Panel::_getSelection()
588     return sp_desktop_selection(_desktop);
591 } // namespace Widget
592 } // namespace UI
593 } // namespace Inkscape
595 /*
596   Local Variables:
597   mode:c++
598   c-file-style:"stroustrup"
599   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
600   indent-tabs-mode:nil
601   fill-column:99
602   End:
603 */
604 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :