1 /**
2 * \brief Panel widget
3 *
4 * Authors:
5 * Bryce Harrington <bryce@bryceharrington.org>
6 * Jon A. Cruz <jon@joncruz.org>
7 *
8 * Copyright (C) 2004 Bryce Harrington
9 * Copyright (C) 2005 Jon A. Cruz
10 *
11 * Released under GNU GPL. Read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include <glibmm/i18n.h>
20 #include <gtkmm/dialog.h> // for Gtk::RESPONSE_*
21 #include <gtkmm/stock.h>
23 #include "panel.h"
24 #include "icon-size.h"
25 #include "prefs-utils.h"
26 #include "desktop-handles.h"
27 #include "inkscape.h"
29 namespace Inkscape {
30 namespace UI {
31 namespace Widget {
33 static const int PANEL_SETTING_SIZE = 0;
34 static const int PANEL_SETTING_MODE = 1;
35 static const int PANEL_SETTING_WRAP = 2;
36 static const int PANEL_SETTING_NEXTFREE = 3;
38 /**
39 * Construct a Panel
40 */
42 Panel::Panel(Glib::ustring const &label, gchar const *prefs_path,
43 int verb_num, Glib::ustring const &apply_label,
44 bool menu_desired) :
45 _prefs_path(prefs_path),
46 _menu_desired(menu_desired),
47 _label(label),
48 _apply_label(apply_label),
49 _verb_num(verb_num),
50 _temp_arrow(Gtk::ARROW_LEFT, Gtk::SHADOW_ETCHED_OUT),
51 _menu(0),
52 _action_area(0),
53 _fillable(0)
54 {
55 _init();
56 }
58 Panel::~Panel()
59 {
60 delete _menu;
61 }
63 void Panel::_popper(GdkEventButton* event)
64 {
65 if ( (event->type == GDK_BUTTON_PRESS) && (event->button == 3 || event->button == 1) ) {
66 if (_menu) {
67 _menu->popup(event->button, event->time);
68 }
69 }
70 }
72 void Panel::_init()
73 {
74 Glib::ustring tmp("<");
75 _anchor = Gtk::ANCHOR_CENTER;
77 guint panel_size = 0;
78 if (_prefs_path) {
79 panel_size = prefs_get_int_attribute_limited( _prefs_path, "panel_size", 1, 0, 10 );
80 }
82 guint panel_mode = 0;
83 if (_prefs_path) {
84 panel_mode = prefs_get_int_attribute_limited( _prefs_path, "panel_mode", 1, 0, 10 );
85 }
87 guint panel_wrap = 0;
88 if (_prefs_path) {
89 panel_wrap = prefs_get_int_attribute_limited( _prefs_path, "panel_wrap", 0, 0, 1 );
90 }
92 _menu = new Gtk::Menu();
93 {
94 const char *things[] = {
95 N_("tiny"),
96 N_("small"),
97 N_("medium"),
98 N_("large"),
99 N_("huge")
100 };
101 Gtk::RadioMenuItem::Group groupOne;
102 for (unsigned int i = 0; i < G_N_ELEMENTS(things); i++) {
103 Glib::ustring foo(gettext(things[i]));
104 Gtk::RadioMenuItem* single = manage(new Gtk::RadioMenuItem(groupOne, foo));
105 _menu->append(*single);
106 if (i == panel_size) {
107 single->set_active(true);
108 }
109 single->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_SIZE, i));
110 }
111 }
112 _menu->append(*manage(new Gtk::SeparatorMenuItem()));
113 Gtk::RadioMenuItem::Group group;
114 Glib::ustring one_label(_("List"));
115 Glib::ustring two_label(_("Grid"));
116 Gtk::RadioMenuItem *one = manage(new Gtk::RadioMenuItem(group, one_label));
117 Gtk::RadioMenuItem *two = manage(new Gtk::RadioMenuItem(group, two_label));
119 if (panel_mode == 0) {
120 one->set_active(true);
121 } else if (panel_mode == 1) {
122 two->set_active(true);
123 }
125 _menu->append(*one);
126 _non_horizontal.push_back(one);
127 _menu->append(*two);
128 _non_horizontal.push_back(two);
129 Gtk::MenuItem* sep = manage(new Gtk::SeparatorMenuItem());
130 _menu->append(*sep);
131 _non_horizontal.push_back(sep);
132 one->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 0));
133 two->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), PANEL_SETTING_MODE, 1));
135 {
136 Glib::ustring wrap_label(_("Wrap"));
137 Gtk::CheckMenuItem *check = manage(new Gtk::CheckMenuItem(wrap_label));
138 check->set_active(panel_wrap);
139 _menu->append(*check);
140 _non_vertical.push_back(check);
142 check->signal_toggled().connect(sigc::bind<Gtk::CheckMenuItem*>(sigc::mem_fun(*this, &Panel::_wrapToggled), check));
144 sep = manage(new Gtk::SeparatorMenuItem());
145 _menu->append(*sep);
146 _non_vertical.push_back(sep);
147 }
149 _menu->show_all_children();
150 for ( std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter ) {
151 (*iter)->hide();
152 }
154 // _close_button.set_label("X");
156 if (!_label.empty()) {
157 _tab_title.set_label(_label);
158 _top_bar.pack_start(_tab_title);
159 }
161 // _top_bar.pack_end(_close_button, false, false);
164 if ( _menu_desired ) {
165 _top_bar.pack_end(_menu_popper, false, false);
166 Gtk::Frame* outliner = manage(new Gtk::Frame());
167 outliner->set_shadow_type(Gtk::SHADOW_ETCHED_IN);
168 outliner->add(_temp_arrow);
169 _menu_popper.add(*outliner);
170 _menu_popper.signal_button_press_event().connect_notify(sigc::mem_fun(*this, &Panel::_popper));
171 }
173 pack_start(_top_bar, false, false);
175 Gtk::HBox* boxy = manage(new Gtk::HBox());
177 boxy->pack_start(_contents, true, true);
178 boxy->pack_start(_right_bar, false, true);
180 pack_start(*boxy, true, true);
182 signalResponse().connect(sigc::mem_fun(*this, &Panel::_handleResponse));
184 show_all_children();
186 _bounceCall(PANEL_SETTING_SIZE, panel_size);
187 _bounceCall(PANEL_SETTING_MODE, panel_mode);
188 _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
189 }
191 void Panel::setLabel(Glib::ustring const &label)
192 {
193 if (_label.empty() && !label.empty())
194 _top_bar.pack_start(_tab_title);
195 else if (!_label.empty() && label.empty())
196 _top_bar.remove(_tab_title);
198 _label = label;
199 _tab_title.set_label(_label);
200 }
202 void Panel::setOrientation(Gtk::AnchorType how)
203 {
204 if (_anchor != how) {
205 _anchor = how;
206 switch (_anchor) {
207 case Gtk::ANCHOR_NORTH:
208 case Gtk::ANCHOR_SOUTH:
209 {
210 if (_menu_desired) {
211 _menu_popper.reference();
212 _top_bar.remove(_menu_popper);
213 _right_bar.pack_start(_menu_popper, false, false);
214 _menu_popper.unreference();
216 for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
217 (*iter)->hide();
218 }
219 for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
220 (*iter)->show();
221 }
222 }
223 // Ensure we are not in "list" mode
224 _bounceCall(PANEL_SETTING_MODE, 1);
225 if (!_label.empty())
226 _top_bar.remove(_tab_title);
227 }
228 break;
230 default:
231 {
232 if ( _menu_desired ) {
233 for (std::vector<Gtk::Widget*>::iterator iter = _non_horizontal.begin(); iter != _non_horizontal.end(); ++iter) {
234 (*iter)->show();
235 }
236 for (std::vector<Gtk::Widget*>::iterator iter = _non_vertical.begin(); iter != _non_vertical.end(); ++iter) {
237 (*iter)->hide();
238 }
239 }
240 }
241 }
242 }
243 }
245 void Panel::present()
246 {
247 _signal_present.emit();
248 }
251 void Panel::restorePanelPrefs()
252 {
253 guint panel_size = 0;
254 if (_prefs_path) {
255 panel_size = prefs_get_int_attribute_limited(_prefs_path, "panel_size", 1, 0, 10);
256 }
257 guint panel_mode = 0;
258 if (_prefs_path) {
259 panel_mode = prefs_get_int_attribute_limited(_prefs_path, "panel_mode", 1, 0, 10);
260 }
261 guint panel_wrap = 0;
262 if (_prefs_path) {
263 panel_wrap = prefs_get_int_attribute_limited(_prefs_path, "panel_wrap", 0, 0, 1 );
264 }
265 _bounceCall(PANEL_SETTING_SIZE, panel_size);
266 _bounceCall(PANEL_SETTING_MODE, panel_mode);
267 _bounceCall(PANEL_SETTING_WRAP, panel_wrap);
268 }
270 sigc::signal<void, int> &
271 Panel::signalResponse()
272 {
273 return _signal_response;
274 }
276 sigc::signal<void> &
277 Panel::signalPresent()
278 {
279 return _signal_present;
280 }
282 void Panel::_bounceCall(int i, int j)
283 {
284 _menu->set_active(0);
285 switch (i) {
286 case PANEL_SETTING_SIZE:
287 if (_prefs_path) {
288 prefs_set_int_attribute(_prefs_path, "panel_size", j);
289 }
290 if (_fillable) {
291 ViewType curr_type = _fillable->getPreviewType();
292 switch (j) {
293 case 0:
294 {
295 _fillable->setStyle(Inkscape::ICON_SIZE_DECORATION, curr_type);
296 }
297 break;
298 case 1:
299 {
300 _fillable->setStyle(Inkscape::ICON_SIZE_MENU, curr_type);
301 }
302 break;
303 case 2:
304 {
305 _fillable->setStyle(Inkscape::ICON_SIZE_SMALL_TOOLBAR, curr_type);
306 }
307 break;
308 case 3:
309 {
310 _fillable->setStyle(Inkscape::ICON_SIZE_BUTTON, curr_type);
311 }
312 break;
313 case 4:
314 {
315 _fillable->setStyle(Inkscape::ICON_SIZE_DIALOG, curr_type);
316 }
317 break;
318 default:
319 ;
320 }
321 }
322 break;
323 case PANEL_SETTING_MODE:
324 if (_prefs_path) {
325 prefs_set_int_attribute (_prefs_path, "panel_mode", j);
326 }
327 if (_fillable) {
328 Inkscape::IconSize curr_size = _fillable->getPreviewSize();
329 switch (j) {
330 case 0:
331 {
332 _fillable->setStyle(curr_size, VIEW_TYPE_LIST);
333 }
334 break;
335 case 1:
336 {
337 _fillable->setStyle(curr_size, VIEW_TYPE_GRID);
338 }
339 break;
340 default:
341 break;
342 }
343 }
344 break;
345 case PANEL_SETTING_WRAP:
346 if (_prefs_path) {
347 prefs_set_int_attribute (_prefs_path, "panel_wrap", j ? 1 : 0);
348 }
349 if ( _fillable ) {
350 _fillable->setWrap(j);
351 }
352 break;
353 default:
354 _handleAction(i - PANEL_SETTING_NEXTFREE, j);
355 }
356 }
359 void Panel::_wrapToggled(Gtk::CheckMenuItem* toggler)
360 {
361 if (toggler) {
362 _bounceCall(PANEL_SETTING_WRAP, toggler->get_active() ? 1 : 0);
363 }
364 }
366 gchar const *Panel::getPrefsPath() const
367 {
368 return _prefs_path;
369 }
371 Glib::ustring const &Panel::getLabel() const
372 {
373 return _label;
374 }
376 int const &Panel::getVerb() const
377 {
378 return _verb_num;
379 }
381 Glib::ustring const &Panel::getApplyLabel() const
382 {
383 return _apply_label;
384 }
386 void Panel::_setTargetFillable(PreviewFillable *target)
387 {
388 _fillable = target;
389 }
391 void Panel::_regItem(Gtk::MenuItem* item, int group, int id)
392 {
393 _menu->append(*item);
394 item->signal_activate().connect(sigc::bind<int, int>(sigc::mem_fun(*this, &Panel::_bounceCall), group + PANEL_SETTING_NEXTFREE, id));
395 item->show();
396 }
398 void Panel::_handleAction(int set_id, int item_id)
399 {
400 // for subclasses to override
401 }
403 void
404 Panel::_apply()
405 {
406 g_warning("Apply button clicked for panel [Panel::_apply()]");
407 }
409 Gtk::Button *
410 Panel::addResponseButton(const Glib::ustring &button_text, int response_id)
411 {
412 Gtk::Button *button = new Gtk::Button(button_text);
413 _addResponseButton(button, response_id);
414 return button;
415 }
417 Gtk::Button *
418 Panel::addResponseButton(const Gtk::StockID &stock_id, int response_id)
419 {
420 Gtk::Button *button = new Gtk::Button(stock_id);
421 _addResponseButton(button, response_id);
422 return button;
423 }
425 void
426 Panel::_addResponseButton(Gtk::Button *button, int response_id)
427 {
428 // Create a button box for the response buttons if it's the first button to be added
429 if (!_action_area) {
430 _action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6);
431 _action_area->set_border_width(4);
432 pack_end(*_action_area, Gtk::PACK_SHRINK, 0);
433 }
435 _action_area->pack_end(*button);
437 if (response_id != 0) {
438 // Re-emit clicked signals as response signals
439 button->signal_clicked().connect(sigc::bind(_signal_response.make_slot(), response_id));
440 _response_map[response_id] = button;
441 }
442 }
444 void
445 Panel::setDefaultResponse(int response_id)
446 {
447 ResponseMap::iterator widget_found;
448 widget_found = _response_map.find(response_id);
450 if (widget_found != _response_map.end()) {
451 widget_found->second->activate();
452 widget_found->second->property_can_default() = true;
453 widget_found->second->grab_default();
454 }
455 }
457 void
458 Panel::setResponseSensitive(int response_id, bool setting)
459 {
460 if (_response_map[response_id])
461 _response_map[response_id]->set_sensitive(setting);
462 }
464 void
465 Panel::_handleResponse(int response_id)
466 {
467 switch (response_id) {
468 case Gtk::RESPONSE_APPLY: {
469 _apply();
470 break;
471 }
472 }
473 }
475 Inkscape::Selection *Panel::_getSelection()
476 {
477 return sp_desktop_selection(SP_ACTIVE_DESKTOP);
478 }
480 } // namespace Widget
481 } // namespace UI
482 } // namespace Inkscape
484 /*
485 Local Variables:
486 mode:c++
487 c-file-style:"stroustrup"
488 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
489 indent-tabs-mode:nil
490 fill-column:99
491 End:
492 */
493 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :