Code

Prevented automatic center docking from happening and added the
[inkscape.git] / src / ui / widget / dock-item.cpp
1 /**
2  * \brief A custom Inkscape wrapper around gdl_dock_item
3  *
4  * Author:
5  *   Gustav Broberg <broberg@kth.se>
6  *
7  * Copyright (C) 2007 Authors
8  *
9  * Released under GNU GPL.  Read the file 'COPYING' for more information.
10  */
12 #include "dock-item.h"
13 #include "desktop.h"
14 #include "inkscape.h"
15 #include "prefs-utils.h"
16 #include "ui/widget/dock.h"
17 #include "widgets/icon.h"
19 #include <gtk/gtk.h>
21 #include <gtkmm/invisible.h>
22 #include <gtkmm/stock.h>
24 namespace Inkscape {
25 namespace UI {
26 namespace Widget {
28 DockItem::DockItem(Dock& dock, const Glib::ustring& name, const Glib::ustring& long_name,
29                    const Glib::ustring& icon_name, State state) :
30     _dock (dock),
31     _prev_state (state),
32     _window (NULL),
33     _dock_item_action_area (NULL)
34 {
35     /* Add a "signal_response" signal to the GdlDockItem, make sure it is
36      * only done once for the class.
37      */
38     static guint response_signal = 0;
40     if (response_signal == 0) {
41         response_signal = g_signal_new ("signal_response",
42                                         GDL_TYPE_DOCK_ITEM,
43                                         G_SIGNAL_RUN_FIRST,
44                                         0,
45                                         NULL, NULL,
46                                         g_cclosure_marshal_VOID__INT,
47                                         G_TYPE_NONE, 1, G_TYPE_INT);
48     }
51     GdlDockItemBehavior gdl_dock_behavior = 
52         (prefs_get_int_attribute_limited ("options.dialogscancenterdock", "value", 1, 0, 1) == 0 ?
53          GDL_DOCK_ITEM_BEH_CANT_DOCK_CENTER
54          : GDL_DOCK_ITEM_BEH_NORMAL);
56     if (!icon_name.empty()) {
57         Gtk::Widget *icon = sp_icon_get_icon(icon_name, Inkscape::ICON_SIZE_MENU);
58         if (icon) {
59             // check icon type (inkscape, gtk, none) 
60             if ( SP_IS_ICON(icon->gobj()) ) { 
61                 SPIcon* sp_icon = SP_ICON(icon->gobj());
62                 sp_icon_fetch_pixbuf(sp_icon);
63                 _icon_pixbuf = Glib::wrap(sp_icon->pb, true);
64             } else if ( GTK_IS_IMAGE(icon->gobj()) ) {
65                 _icon_pixbuf = Gtk::Invisible().render_icon(Gtk::StockID(icon_name),
66                                                             Gtk::ICON_SIZE_MENU);
67             }
68             delete icon;
70             _gdl_dock_item = 
71                 gdl_dock_item_new_with_pixbuf_icon(name.c_str(), long_name.c_str(), 
72                                                    _icon_pixbuf->gobj(), gdl_dock_behavior);
73         }
74     } else {
75         _gdl_dock_item = 
76             gdl_dock_item_new(name.c_str(), long_name.c_str(), gdl_dock_behavior);
77     }
79     _frame.set_shadow_type(Gtk::SHADOW_IN);
80     gtk_container_add (GTK_CONTAINER (_gdl_dock_item), GTK_WIDGET (_frame.gobj()));
81     _frame.add(_dock_item_box);
82     _dock_item_box.set_border_width(3);
84     signal_drag_begin().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragBegin));
85     signal_drag_end().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragEnd));
86     signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHide), false);
87     signal_show().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onShow), false);
88     signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onStateChanged));
89     signal_delete_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDeleteEvent));
91     _dock.addItem(*this, (_prev_state == FLOATING_STATE ? FLOATING : TOP));
93     show_all();
94 }
96 DockItem::~DockItem()
97 {
98     g_free(_gdl_dock_item);
99 }
101 Gtk::Widget&
102 DockItem::getWidget()
104     return *Glib::wrap(GTK_WIDGET(_gdl_dock_item));
107 GtkWidget *
108 DockItem::gobj()
110     return _gdl_dock_item;
113 Gtk::VBox *
114 DockItem::get_vbox()
116     return &_dock_item_box;
120 bool
121 DockItem::isAttached() const
123     return GDL_DOCK_OBJECT_ATTACHED (_gdl_dock_item);
127 bool
128 DockItem::isFloating() const
130     gboolean floating = FALSE;
131     if (GDL_IS_DOCK (gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT (_gdl_dock_item)))) {
132         GdlDock* dock = GDL_DOCK (gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT (_gdl_dock_item)));
133         g_object_get (dock,
134                       "floating", &floating,
135                       NULL);
136     }
137     return floating;
140 bool
141 DockItem::isIconified() const
143     return GDL_DOCK_ITEM_ICONIFIED (_gdl_dock_item);
146 DockItem::State
147 DockItem::getState() const
149     return (isAttached() ? (isFloating() ? FLOATING_STATE : DOCKED_STATE) : UNATTACHED);
152 DockItem::State
153 DockItem::getPrevState() const
155     return _prev_state;
158 DockItem::Placement
159 DockItem::getPlacement() const
161     GdlDockPlacement placement = (GdlDockPlacement)NONE;
162     gdl_dock_object_child_placement(gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT(_gdl_dock_item)),
163                                     GDL_DOCK_OBJECT(_gdl_dock_item),
164                                     &placement);
165     return (Placement)placement;
169 void
170 DockItem::addButton(Gtk::Button* button, int response_id)
172     // Create a button box for the response buttons if it's the first button to be added
173     if (!_dock_item_action_area) {
174         _dock_item_action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6);
175         _dock_item_box.pack_end(*_dock_item_action_area, Gtk::PACK_SHRINK, 0);
176         _dock_item_action_area->set_border_width(6);
177     }
179     _dock_item_action_area->pack_start(*button);
182 void
183 DockItem::hide()
185     gdl_dock_item_hide_item (GDL_DOCK_ITEM(_gdl_dock_item));
188 void
189 DockItem::show()
191     gdl_dock_item_show_item (GDL_DOCK_ITEM(_gdl_dock_item));
194 void
195 DockItem::show_all()
197     gtk_widget_show_all(_gdl_dock_item);
200 void
201 DockItem::present()
203     // iconified
204     if (isIconified()) {
205         show();
206         return;
207     }
208     
209     // unattached
210     if (!isAttached()) {
211         gdl_dock_item_show_item (GDL_DOCK_ITEM(_gdl_dock_item));
212         return;
213     }
215     // tabbed
216     if (getPlacement() == CENTER) {
217         int i = gtk_notebook_page_num (GTK_NOTEBOOK (_gdl_dock_item->parent),
218                                        GTK_WIDGET (_gdl_dock_item));
219         if (i >= 0)
220             gtk_notebook_set_current_page (GTK_NOTEBOOK (_gdl_dock_item->parent), i);
221         return;
222     }
224     // we're already present, do nothing
228 void 
229 DockItem::get_position(int& x, int& y)
230
231     if (getWindow()) {
232         getWindow()->get_position(x, y);
233     } else {
234         x = _x;
235         y = _y;
236     }
239 void 
240 DockItem::get_size(int& width, int& height)
241
242     if (_window) {
243         _window->get_size(width, height);
244     } else {
245         width = get_vbox()->get_width();
246         height = get_vbox()->get_height();
247     }
251 void
252 DockItem::resize(int width, int height) 
254     if (_window)
255         _window->resize(width, height);
259 void
260 DockItem::move(int x, int y)
262     if (_window)
263         _window->move(x, y);
266 void
267 DockItem::set_position(Gtk::WindowPosition position)
269     if (_window)
270         _window->set_position(position);
273 void
274 DockItem::set_size_request(int width, int height)
276     getWidget().set_size_request(width, height);
279 void 
280 DockItem::size_request(Gtk::Requisition& requisition)
281
282     getWidget().size_request(requisition);
286 void
287 DockItem::set_title(Glib::ustring title)
289     g_object_set (_gdl_dock_item,
290                   "long-name", title.c_str(),
291                   NULL);
293     gdl_dock_item_set_tablabel(GDL_DOCK_ITEM(_gdl_dock_item),
294                                gtk_label_new (title.c_str()));
297 /* Signal wrappers */
299 Glib::SignalProxy0<void>
300 DockItem::signal_show()
301
302     return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), 
303                                     &_signal_show_proxy);
306 Glib::SignalProxy0<void>
307 DockItem::signal_hide()
308
309     return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), 
310                                     &_signal_hide_proxy);
313 Glib::SignalProxy1<bool, GdkEventAny *>
314 DockItem::signal_delete_event()
316     return Glib::SignalProxy1<bool, GdkEventAny *>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)),
317                                                   &_signal_delete_event_proxy);
320 Glib::SignalProxy1<void, int>
321 DockItem::signal_response()
323     return Glib::SignalProxy1<void, int>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), 
324                                          &_signal_response_proxy);
327 Glib::SignalProxy0<void>
328 DockItem::signal_drag_begin()
330     return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)),
331                                     &_signal_drag_begin_proxy);
334 Glib::SignalProxy1<void, bool>
335 DockItem::signal_drag_end()
337     return Glib::SignalProxy1<void, bool>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)),
338                                           &_signal_drag_end_proxy);
341 sigc::signal<void, DockItem::State, DockItem::State>
342 DockItem::signal_state_changed()
344     return _signal_state_changed;
347 void
348 DockItem::_onHideWindow()
350     if (_window)
351         _window->get_position(_x, _y);
354 void
355 DockItem::_onHide()
357     _signal_state_changed.emit(UNATTACHED, getState());
360 void
361 DockItem::_onShow()
363     _signal_state_changed.emit(UNATTACHED, getState());
366 void
367 DockItem::_onDragBegin()
369     _prev_state = getState();
370     if (_prev_state == FLOATING_STATE)
371         _dock.toggleDockable(getWidget().get_width(), getWidget().get_height());
374 void
375 DockItem::_onDragEnd(bool)
377     State state = getState();
379     if (state != _prev_state)
380         _signal_state_changed.emit(_prev_state, state);
382     if (state == FLOATING_STATE) {
383         if (_prev_state == FLOATING_STATE)
384             _dock.toggleDockable();
385     }
387     _prev_state = state;
390 bool
391 DockItem::_onKeyPress(GdkEventKey *event)
393     gboolean return_value;
394     g_signal_emit_by_name (_gdl_dock_item, "key_press_event", event, &return_value);
395     return return_value;
398 void
399 DockItem::_onStateChanged(State prev_state, State new_state)
401     _window = getWindow();
403     if (new_state == FLOATING_STATE) {
404         _window->signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHideWindow));
405         _signal_key_press_event_connection = 
406             _window->signal_key_press_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onKeyPress));
407     }
411 bool
412 DockItem::_onDeleteEvent(GdkEventAny *event)
414     hide();
415     return false;
419 Gtk::Window *
420 DockItem::getWindow()
422     g_return_val_if_fail(_gdl_dock_item, 0);
423     Gtk::Container *parent = getWidget().get_parent();
424     parent = (parent ? parent->get_parent() : 0);
425     return (parent ? dynamic_cast<Gtk::Window *>(parent) : 0);
428 const Glib::SignalProxyInfo
429 DockItem::_signal_show_proxy = 
431     "show",
432     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback,
433     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback
434 };
436 const Glib::SignalProxyInfo
437 DockItem::_signal_hide_proxy = 
439     "hide",
440     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback,
441     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback
442 };
445 const Glib::SignalProxyInfo
446 DockItem::_signal_delete_event_proxy = 
448     "delete_event",
449     (GCallback) &_signal_delete_event_callback,
450     (GCallback) &_signal_delete_event_callback
451 };
454 const Glib::SignalProxyInfo
455 DockItem::_signal_response_proxy = 
457     "signal_response",
458     (GCallback) &_signal_response_callback,
459     (GCallback) &_signal_response_callback
460 };
462 const Glib::SignalProxyInfo
463 DockItem::_signal_drag_begin_proxy = 
465     "dock-drag-begin",
466     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback,
467     (GCallback) &Glib::SignalProxyNormal::slot0_void_callback
468 };
471 const Glib::SignalProxyInfo
472 DockItem::_signal_drag_end_proxy = 
474     "dock_drag_end",
475     (GCallback) &_signal_drag_end_callback,
476     (GCallback) &_signal_drag_end_callback
477 };
480 gboolean
481 DockItem::_signal_delete_event_callback(GtkWidget *self, GdkEventAny *event, void *data)
483     using namespace Gtk;
484     typedef sigc::slot<bool, GdkEventAny *> SlotType;
486     if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) {
487         try {
488             if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
489                 return static_cast<int>( (*static_cast<SlotType*>(slot))(event) );
490         } catch(...) {
491             Glib::exception_handlers_invoke();
492         }
493     }
495     typedef gboolean RType;
496     return RType();
499 void 
500 DockItem::_signal_response_callback(GtkWidget *self, gint response_id, void *data)
502     using namespace Gtk;
503     typedef sigc::slot<void, int> SlotType;
505     if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) {
506         try {
507             if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
508                 (*static_cast<SlotType *>(slot))(response_id);
509         } catch(...) {
510             Glib::exception_handlers_invoke();
511         }
512     }
515 void 
516 DockItem::_signal_drag_end_callback(GtkWidget *self, gboolean cancelled, void *data)
518     using namespace Gtk;
519     typedef sigc::slot<void, bool> SlotType;
521     if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) {
522         try {
523             if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data))
524                 (*static_cast<SlotType *>(slot))(cancelled);
525         } catch(...) {
526             Glib::exception_handlers_invoke();
527         }
528     }
532 } // namespace Widget
533 } // namespace UI
534 } // namespace Inkscape
536 /*
537   Local Variables:
538   mode:c++
539   c-file-style:"stroustrup"
540   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
541   indent-tabs-mode:nil
542   fill-column:99
543   End:
544 */
545 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :