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);
194 }
196 void Panel::setLabel(Glib::ustring const &label)
197 {
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);
205 }
207 void Panel::setOrientation(Gtk::AnchorType how)
208 {
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 }
248 }
250 void Panel::present()
251 {
252 _signal_present.emit();
253 }
256 void Panel::restorePanelPrefs()
257 {
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);
273 }
275 sigc::signal<void, int> &
276 Panel::signalResponse()
277 {
278 return _signal_response;
279 }
281 sigc::signal<void> &
282 Panel::signalPresent()
283 {
284 return _signal_present;
285 }
287 void Panel::_bounceCall(int i, int j)
288 {
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 }
361 }
364 void Panel::_wrapToggled(Gtk::CheckMenuItem* toggler)
365 {
366 if (toggler) {
367 _bounceCall(PANEL_SETTING_WRAP, toggler->get_active() ? 1 : 0);
368 }
369 }
371 gchar const *Panel::getPrefsPath() const
372 {
373 return _prefs_path;
374 }
376 Glib::ustring const &Panel::getLabel() const
377 {
378 return _label;
379 }
381 int const &Panel::getVerb() const
382 {
383 return _verb_num;
384 }
386 Glib::ustring const &Panel::getApplyLabel() const
387 {
388 return _apply_label;
389 }
391 void Panel::setDesktop(SPDesktop *desktop)
392 {
393 _desktop = desktop;
394 }
396 void Panel::_setTargetFillable(PreviewFillable *target)
397 {
398 _fillable = target;
399 }
401 void Panel::_regItem(Gtk::MenuItem* item, int group, int id)
402 {
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();
406 }
408 void Panel::_handleAction(int /*set_id*/, int /*item_id*/)
409 {
410 // for subclasses to override
411 }
413 void
414 Panel::_apply()
415 {
416 g_warning("Apply button clicked for panel [Panel::_apply()]");
417 }
419 Gtk::Button *
420 Panel::addResponseButton(const Glib::ustring &button_text, int response_id)
421 {
422 Gtk::Button *button = new Gtk::Button(button_text);
423 _addResponseButton(button, response_id);
424 return button;
425 }
427 Gtk::Button *
428 Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id)
429 {
430 Gtk::Button *button = new Gtk::Button(stock_id);
431 _addResponseButton(button, response_id);
432 return button;
433 }
435 void
436 Panel::_addResponseButton(Gtk::Button *button, int response_id)
437 {
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 }
452 }
454 void
455 Panel::setDefaultResponse(int response_id)
456 {
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 }
465 }
467 void
468 Panel::setResponseSensitive(int response_id, bool setting)
469 {
470 if (_response_map[response_id])
471 _response_map[response_id]->set_sensitive(setting);
472 }
474 sigc::signal<void, SPDesktop *, SPDocument *> &
475 Panel::signalDocumentReplaced()
476 {
477 return _signal_document_replaced;
478 }
480 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
481 Panel::signalActivateDesktop()
482 {
483 return _signal_activate_desktop;
484 }
486 sigc::signal<void, Inkscape::Application *, SPDesktop *> &
487 Panel::signalDeactiveDesktop()
488 {
489 return _signal_deactive_desktop;
490 }
492 void
493 Panel::_handleResponse(int response_id)
494 {
495 switch (response_id) {
496 case Gtk::RESPONSE_APPLY: {
497 _apply();
498 break;
499 }
500 }
501 }
503 Inkscape::Selection *Panel::_getSelection()
504 {
505 return sp_desktop_selection(_desktop);
506 }
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 :