9333ffc359d185590d2c4ebff1ccdcfca4f3892c
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 "prefs-utils.h"
30 #include "desktop-handles.h"
31 #include "inkscape.h"
32 #include "dialogs/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;
98 if (_prefs_path) {
99 panel_size = prefs_get_int_attribute_limited( _prefs_path, "panel_size", 1, 0, static_cast<long long>(PREVIEW_SIZE_HUGE) );
100 }
102 guint panel_mode = 0;
103 if (_prefs_path) {
104 panel_mode = prefs_get_int_attribute_limited( _prefs_path, "panel_mode", 1, 0, 10 );
105 }
107 guint panel_wrap = 0;
108 if (_prefs_path) {
109 panel_wrap = prefs_get_int_attribute_limited( _prefs_path, "panel_wrap", 0, 0, 1 );
110 }
112 guint panel_ratio = 100;
113 if (_prefs_path) {
114 panel_ratio = prefs_get_int_attribute_limited( _prefs_path, "panel_ratio", 100, 0, 500 );
115 }
117 _menu = new Gtk::Menu();
119 {
120 Gtk::RadioMenuItem::Group group;
121 Glib::ustring one_label(_("List"));
122 Glib::ustring two_label(_("Grid"));
123 Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, one_label));
124 Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, two_label));
126 if (panel_mode == 0) {
127 one->set_active(true);
128 } else if (panel_mode == 1) {
129 two->set_active(true);
130 }
132 _menu->append(*one);
133 _non_horizontal.push_back(one);
134 _menu->append(*two);
135 _non_horizontal.push_back(two);
136 Gtk::MenuItem* sep = manage(new Gtk::SeparatorMenuItem());
137 _menu->append(*sep);
138 _non_horizontal.push_back(sep);
139 one->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 0));
140 two->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 1));
141 }
143 {
144 Glib::ustring heightItemLabel(Q_("swatches|Size"));
146 //TRANSLATORS: Indicates size of colour swatches
147 const gchar *heightLabels[] = {
148 N_("tiny"),
149 N_("small"),
150 //TRANSLATORS: Translate only the word "medium". Indicates size of colour swatches
151 N_("swatchesHeight|medium"),
152 N_("large"),
153 N_("huge")
154 };
156 Gtk::MenuItem *sizeItem = manage(new Gtk::MenuItem(heightItemLabel));
157 Gtk::Menu *sizeMenu = manage(new Gtk::Menu());
158 sizeItem->set_submenu(*sizeMenu);
160 Gtk::RadioMenuItem::Group heightGroup;
161 for (unsigned int i = 0; i < G_N_ELEMENTS(heightLabels); i++) {
162 Glib::ustring _label(Q_(heightLabels[i]));
163 Gtk::RadioMenuItem* _item = manage(new Gtk::RadioMenuItem(heightGroup, _label));
164 sizeMenu->append(*_item);
165 if (i == panel_size) {
166 _item->set_active(true);
167 }
168 _item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i));
169 }
171 _menu->append(*sizeItem);
172 }
174 {
175 Glib::ustring widthItemLabel(Q_("swatches|Width"));
177 //TRANSLATORS: Indicates width of colour swatches
178 const gchar *widthLabels[] = {
179 N_("narrower"),
180 N_("narrow"),
181 //TRANSLATORS: Translate only the word "medium". Indicates width of colour swatches
182 N_("swatchesWidth|medium"),
183 N_("wide"),
184 N_("wider")
185 };
187 Gtk::MenuItem *item = manage( new Gtk::MenuItem(widthItemLabel));
188 Gtk::Menu *type_menu = manage(new Gtk::Menu());
189 item->set_submenu(*type_menu);
190 _menu->append(*item);
192 Gtk::RadioMenuItem::Group widthGroup;
194 guint values[] = {0, 25, 50, 100, 200, 400};
195 guint hot_index = 3;
196 for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) {
197 // Assume all values are in increasing order
198 if ( values[i] <= panel_ratio ) {
199 hot_index = i;
200 }
201 }
202 for ( guint i = 0; i < G_N_ELEMENTS(widthLabels); ++i ) {
203 Glib::ustring _label(Q_(widthLabels[i]));
204 Gtk::RadioMenuItem *_item = manage(new Gtk::RadioMenuItem(widthGroup, _label));
205 type_menu->append(*_item);
206 if ( i <= hot_index ) {
207 _item->set_active(true);
208 }
209 _item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SHAPE, values[i]));
210 }
211 }
213 {
214 //TRANSLATORS: Translate only the word "Wrap". Indicates how colour swatches are displayed
215 Glib::ustring wrap_label(Q_("swatches|Wrap"));
216 Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label));
217 check->set_active(panel_wrap);
218 _menu->append(*check);
219 _non_vertical.push_back(check);
221 check->signal_toggled().connect(sigc::bind<Gtk::CheckMenuItem*>(sigc::mem_fun(*this, &Panel::_wrapToggled), check));
222 }
224 Gtk::SeparatorMenuItem *sep;
225 sep = manage(new Gtk::SeparatorMenuItem());
226 _menu->append(*sep);
228 _menu->show_all_children();
229 for ( std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter ) {
230 (*iter)->hide();
231 }
233 // _close_button.set_label("X");
235 if (!_label.empty()) {
236 _tab_title.set_label(_label);
237 _top_bar.pack_start(_tab_title);
238 }
240 // _top_bar.pack_end(_close_button, false, false);
243 if ( _menu_desired ) {
244 _top_bar.pack_end(_menu_popper, false, false);
245 gint width = 0;
246 gint height = 0;
248 if ( gtk_icon_size_lookup( Inkscape::getRegisteredIconSize(Inkscape::ICON_SIZE_DECORATION), &width, &height ) ) {
249 _temp_arrow.set_size_request(width, height);
250 }
252 _menu_popper.add(_temp_arrow);
253 _menu_popper.signal_button_press_event().connect_notify(sigc::mem_fun(*this, &Panel::_popper));
254 }
256 pack_start(_top_bar, false, false);
258 Gtk::HBox* boxy = manage(new Gtk::HBox());
260 boxy->pack_start(_contents, true, true);
261 boxy->pack_start(_right_bar, false, true);
263 pack_start(*boxy, true, true);
265 signalResponse().connect(sigc::mem_fun(*this, &Panel::_handleResponse));
267 signalActivateDesktop().connect(sigc::hide<0>(sigc::mem_fun(*this, &Panel::setDesktop)));
269 show_all_children();
271 _bounceCall(PANEL_SETTING_SIZE, panel_size);
272 _bounceCall(PANEL_SETTING_MODE, panel_mode);
273 _bounceCall(PANEL_SETTING_SHAPE, panel_ratio);
274 _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
275 }
277 void Panel::setLabel(Glib::ustring const &label)
278 {
279 if (_label.empty() && !label.empty())
280 _top_bar.pack_start(_tab_title);
281 else if (!_label.empty() && label.empty())
282 _top_bar.remove(_tab_title);
284 _label = label;
285 _tab_title.set_label(_label);
286 }
288 void Panel::setOrientation(Gtk::AnchorType how)
289 {
290 if (_anchor != how) {
291 _anchor = how;
292 switch (_anchor) {
293 case Gtk::ANCHOR_NORTH:
294 case Gtk::ANCHOR_SOUTH:
295 {
296 if (_menu_desired) {
297 _menu_popper.reference();
298 _top_bar.remove(_menu_popper);
299 _right_bar.pack_start(_menu_popper, false, false);
300 _menu_popper.unreference();
302 for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
303 (*iter)->hide();
304 }
305 for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
306 (*iter)->show();
307 }
308 }
309 // Ensure we are not in "list" mode
310 _bounceCall(PANEL_SETTING_MODE, 1);
311 if (!_label.empty())
312 _top_bar.remove(_tab_title);
313 }
314 break;
316 default:
317 {
318 if ( _menu_desired ) {
319 for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
320 (*iter)->show();
321 }
322 for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
323 (*iter)->hide();
324 }
325 }
326 }
327 }
328 }
329 }
331 void Panel::present()
332 {
333 _signal_present.emit();
334 }
337 void Panel::restorePanelPrefs()
338 {
339 guint panel_size = 0;
340 if (_prefs_path) {
341 panel_size = prefs_get_int_attribute_limited(_prefs_path, "panel_size", 1, 0, static_cast<long long>(PREVIEW_SIZE_HUGE));
342 }
343 guint panel_mode = 0;
344 if (_prefs_path) {
345 panel_mode = prefs_get_int_attribute_limited(_prefs_path, "panel_mode", 1, 0, 10);
346 }
347 guint panel_wrap = 0;
348 if (_prefs_path) {
349 panel_wrap = prefs_get_int_attribute_limited(_prefs_path, "panel_wrap", 0, 0, 1 );
350 }
351 guint panel_ratio = 100;
352 if (_prefs_path) {
353 panel_ratio = prefs_get_int_attribute_limited(_prefs_path, "panel_ratio", 000, 0, 500 );
354 }
355 _bounceCall(PANEL_SETTING_SIZE, panel_size);
356 _bounceCall(PANEL_SETTING_MODE, panel_mode);
357 _bounceCall(PANEL_SETTING_SHAPE, panel_ratio);
358 _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
359 }
361 sigc::signal<void, int> &
362 Panel::signalResponse()
363 {
364 return _signal_response;
365 }
367 sigc::signal<void> &
368 Panel::signalPresent()
369 {
370 return _signal_present;
371 }
373 void Panel::_bounceCall(int i, int j)
374 {
375 _menu->set_active(0);
376 switch (i) {
377 case PANEL_SETTING_SIZE:
378 if (_prefs_path) {
379 prefs_set_int_attribute(_prefs_path, "panel_size", j);
380 }
381 if (_fillable) {
382 ViewType curr_type = _fillable->getPreviewType();
383 guint curr_ratio = _fillable->getPreviewRatio();
384 switch (j) {
385 case 0:
386 {
387 _fillable->setStyle(::PREVIEW_SIZE_TINY, curr_type, curr_ratio);
388 }
389 break;
390 case 1:
391 {
392 _fillable->setStyle(::PREVIEW_SIZE_SMALL, curr_type, curr_ratio);
393 }
394 break;
395 case 2:
396 {
397 _fillable->setStyle(::PREVIEW_SIZE_MEDIUM, curr_type, curr_ratio);
398 }
399 break;
400 case 3:
401 {
402 _fillable->setStyle(::PREVIEW_SIZE_BIG, curr_type, curr_ratio);
403 }
404 break;
405 case 4:
406 {
407 _fillable->setStyle(::PREVIEW_SIZE_HUGE, curr_type, curr_ratio);
408 }
409 break;
410 default:
411 ;
412 }
413 }
414 break;
415 case PANEL_SETTING_MODE:
416 if (_prefs_path) {
417 prefs_set_int_attribute (_prefs_path, "panel_mode", j);
418 }
419 if (_fillable) {
420 ::PreviewSize curr_size = _fillable->getPreviewSize();
421 guint curr_ratio = _fillable->getPreviewRatio();
422 switch (j) {
423 case 0:
424 {
425 _fillable->setStyle(curr_size, VIEW_TYPE_LIST, curr_ratio);
426 }
427 break;
428 case 1:
429 {
430 _fillable->setStyle(curr_size, VIEW_TYPE_GRID, curr_ratio);
431 }
432 break;
433 default:
434 break;
435 }
436 }
437 break;
438 case PANEL_SETTING_SHAPE:
439 if (_prefs_path) {
440 prefs_set_int_attribute (_prefs_path, "panel_ratio", j);
441 }
442 if ( _fillable ) {
443 ViewType curr_type = _fillable->getPreviewType();
444 ::PreviewSize curr_size = _fillable->getPreviewSize();
445 _fillable->setStyle(curr_size, curr_type, j);
446 }
447 break;
448 case PANEL_SETTING_WRAP:
449 if (_prefs_path) {
450 prefs_set_int_attribute (_prefs_path, "panel_wrap", j ? 1 : 0);
451 }
452 if ( _fillable ) {
453 _fillable->setWrap(j);
454 }
455 break;
456 default:
457 _handleAction(i - PANEL_SETTING_NEXTFREE, j);
458 }
459 }
462 void Panel::_wrapToggled(Gtk::CheckMenuItem* toggler)
463 {
464 if (toggler) {
465 _bounceCall(PANEL_SETTING_WRAP, toggler->get_active() ? 1 : 0);
466 }
467 }
469 gchar const *Panel::getPrefsPath() const
470 {
471 return _prefs_path;
472 }
474 Glib::ustring const &Panel::getLabel() const
475 {
476 return _label;
477 }
479 int const &Panel::getVerb() const
480 {
481 return _verb_num;
482 }
484 Glib::ustring const &Panel::getApplyLabel() const
485 {
486 return _apply_label;
487 }
489 void Panel::setDesktop(SPDesktop *desktop)
490 {
491 _desktop = desktop;
492 }
494 void Panel::_setTargetFillable(PreviewFillable *target)
495 {
496 _fillable = target;
497 }
499 void Panel::_regItem(Gtk::MenuItem* item, int group, int id)
500 {
501 _menu->append(*item);
502 item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), group + PANEL_SETTING_NEXTFREE, id));
503 item->show();
504 }
506 void Panel::_handleAction(int /*set_id*/, int /*item_id*/)
507 {
508 // for subclasses to override
509 }
511 void
512 Panel::_apply()
513 {
514 g_warning("Apply button clicked for panel [Panel::_apply()]");
515 }
517 Gtk::Button *
518 Panel::addResponseButton(const Glib::ustring &button_text, int response_id)
519 {
520 Gtk::Button *button = new Gtk::Button(button_text);
521 _addResponseButton(button, response_id);
522 return button;
523 }
525 Gtk::Button *
526 Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id)
527 {
528 Gtk::Button *button = new Gtk::Button(stock_id);
529 _addResponseButton(button, response_id);
530 return button;
531 }
533 void
534 Panel::_addResponseButton(Gtk::Button *button, int response_id)
535 {
536 // Create a button box for the response buttons if it's the first button to be added
537 if (!_action_area) {
538 _action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6);
539 _action_area->set_border_width(4);
540 pack_end(*_action_area, Gtk::PACK_SHRINK, 0);
541 }
543 _action_area->pack_end(*button);
545 if (response_id != 0) {
546 // Re-emit clicked signals as response signals
547 button->signal_clicked().connect(sigc::bind(_signal_response.make_slot(), response_id));
548 _response_map[response_id] = button;
549 }
550 }
552 void
553 Panel::setDefaultResponse(int response_id)
554 {
555 ResponseMap::iterator widget_found;
556 widget_found = _response_map.find(response_id);
558 if (widget_found != _response_map.end()) {
559 widget_found->second->activate();
560 widget_found->second->property_can_default() = true;
561 widget_found->second->grab_default();
562 }
563 }
565 void
566 Panel::setResponseSensitive(int response_id, bool setting)
567 {
568 if (_response_map[response_id])
569 _response_map[response_id]->set_sensitive(setting);
570 }
572 sigc::signal<void, SPDesktop *, SPDocument *> &
573 Panel::signalDocumentReplaced()
574 {
575 return _signal_document_replaced;
576 }
578 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
579 Panel::signalActivateDesktop()
580 {
581 return _signal_activate_desktop;
582 }
584 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
585 Panel::signalDeactiveDesktop()
586 {
587 return _signal_deactive_desktop;
588 }
590 void
591 Panel::_handleResponse(int response_id)
592 {
593 switch (response_id) {
594 case Gtk::RESPONSE_APPLY: {
595 _apply();
596 break;
597 }
598 }
599 }
601 Inkscape::Selection *Panel::_getSelection()
602 {
603 return sp_desktop_selection(_desktop);
604 }
606 } // namespace Widget
607 } // namespace UI
608 } // namespace Inkscape
610 /*
611 Local Variables:
612 mode:c++
613 c-file-style:"stroustrup"
614 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
615 indent-tabs-mode:nil
616 fill-column:99
617 End:
618 */
619 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :