1 /** @file
2 * @brief A dockable dialog implementation.
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 */
13 #ifdef HAVE_CONFIG_H
14 # include <config.h>
15 #endif
17 #include "dock-behavior.h"
18 #include "inkscape.h"
19 #include "desktop.h"
20 #include "interface.h"
21 #include "widgets/icon.h"
22 #include "ui/widget/dock.h"
23 #include "verbs.h"
24 #include "dialog.h"
25 #include "preferences.h"
26 #include "dialogs/dialog-events.h"
28 #include <gtkmm/invisible.h>
29 #include <gtkmm/label.h>
30 #include <gtkmm/stock.h>
32 #include <gtk/gtk.h>
34 namespace Inkscape {
35 namespace UI {
36 namespace Dialog {
37 namespace Behavior {
40 DockBehavior::DockBehavior(Dialog &dialog) :
41 Behavior(dialog),
42 _dock_item(*SP_ACTIVE_DESKTOP->getDock(),
43 Inkscape::Verb::get(dialog._verb_num)->get_id(), dialog._title.c_str(),
44 (Inkscape::Verb::get(dialog._verb_num)->get_image() ?
45 Inkscape::Verb::get(dialog._verb_num)->get_image() : ""),
46 static_cast<Widget::DockItem::State>(
47 Inkscape::Preferences::get()->getInt(_dialog._prefs_path + "/state",
48 UI::Widget::DockItem::DOCKED_STATE)))
49 {
50 // Connect signals
51 _signal_hide_connection = signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onHide));
52 _dock_item.signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onStateChanged));
54 if (_dock_item.getState() == Widget::DockItem::FLOATING_STATE) {
55 if (Gtk::Window *floating_win = _dock_item.getWindow())
56 sp_transientize(GTK_WIDGET(floating_win->gobj()));
57 }
58 }
60 DockBehavior::~DockBehavior()
61 {
62 }
65 Behavior *
66 DockBehavior::create(Dialog &dialog)
67 {
68 return new DockBehavior(dialog);
69 }
72 DockBehavior::operator Gtk::Widget &()
73 {
74 return _dock_item.getWidget();
75 }
77 GtkWidget *
78 DockBehavior::gobj()
79 {
80 return _dock_item.gobj();
81 }
83 Gtk::VBox *
84 DockBehavior::get_vbox()
85 {
86 return _dock_item.get_vbox();
87 }
89 void
90 DockBehavior::present()
91 {
92 bool was_attached = _dock_item.isAttached();
94 _dock_item.present();
96 if (!was_attached)
97 _dialog.read_geometry();
98 }
100 void
101 DockBehavior::hide()
102 {
103 _signal_hide_connection.block();
104 _dock_item.hide();
105 _signal_hide_connection.unblock();
106 }
108 void
109 DockBehavior::show()
110 {
111 _dock_item.show();
112 }
114 void
115 DockBehavior::show_all_children()
116 {
117 get_vbox()->show_all_children();
118 }
120 void
121 DockBehavior::get_position(int &x, int &y)
122 {
123 _dock_item.get_position(x, y);
124 }
126 void
127 DockBehavior::get_size(int &width, int &height)
128 {
129 _dock_item.get_size(width, height);
130 }
132 void
133 DockBehavior::resize(int width, int height)
134 {
135 _dock_item.resize(width, height);
136 }
138 void
139 DockBehavior::move(int x, int y)
140 {
141 _dock_item.move(x, y);
142 }
144 void
145 DockBehavior::set_position(Gtk::WindowPosition position)
146 {
147 _dock_item.set_position(position);
148 }
150 void
151 DockBehavior::set_size_request(int width, int height)
152 {
153 _dock_item.set_size_request(width, height);
154 }
156 void
157 DockBehavior::size_request(Gtk::Requisition &requisition)
158 {
159 _dock_item.size_request(requisition);
160 }
162 void
163 DockBehavior::set_title(Glib::ustring title)
164 {
165 _dock_item.set_title(title);
166 }
168 void
169 DockBehavior::set_sensitive(bool sensitive)
170 {
171 // TODO check this. Seems to be bad that we ignore the parameter
172 get_vbox()->set_sensitive();
173 }
176 void
177 DockBehavior::_onHide()
178 {
179 _dialog.save_geometry();
180 _dialog._user_hidden = true;
181 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
182 prefs->setInt(_dialog._prefs_path + "/state", _dock_item.getPrevState());
183 }
185 void
186 DockBehavior::_onStateChanged(Widget::DockItem::State /*prev_state*/,
187 Widget::DockItem::State new_state)
188 {
189 // TODO probably need to avoid window calls unless the state is different. Check.
190 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
191 prefs->setInt(_dialog._prefs_path + "/state", new_state);
193 if (new_state == Widget::DockItem::FLOATING_STATE) {
194 if (Gtk::Window *floating_win = _dock_item.getWindow())
195 sp_transientize(GTK_WIDGET(floating_win->gobj()));
196 }
197 }
199 void
200 DockBehavior::onHideF12()
201 {
202 _dialog.save_geometry();
203 hide();
204 }
206 void
207 DockBehavior::onShowF12()
208 {
209 present();
210 }
212 void
213 DockBehavior::onShutdown()
214 {
215 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
216 prefs->setInt(_dialog._prefs_path + "/state", _dock_item.getPrevState());
217 }
219 void
220 DockBehavior::onDesktopActivated(SPDesktop *desktop)
221 {
222 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
223 gint transient_policy = prefs->getIntLimited( "/options/transientpolicy/value", 1, 0, 2);
225 #ifdef WIN32 // Win32 special code to enable transient dialogs
226 transient_policy = 2;
227 #endif
229 if (!transient_policy)
230 return;
232 Gtk::Window *floating_win = _dock_item.getWindow();
234 if (floating_win) {
236 if (_dialog.retransientize_suppress) {
237 /* if retransientizing of this dialog is still forbidden after
238 * previous call warning turned off because it was confusingly fired
239 * when loading many files from command line
240 */
242 // g_warning("Retranzientize aborted! You're switching windows too fast!");
243 return;
244 }
246 if (GtkWindow *dialog_win = floating_win->gobj()) {
248 _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog
250 desktop->setWindowTransient (dialog_win);
252 /*
253 * This enables "aggressive" transientization,
254 * i.e. dialogs always emerging on top when you switch documents. Note
255 * however that this breaks "click to raise" policy of a window
256 * manager because the switched-to document will be raised at once
257 * (so that its transients also could raise)
258 */
259 if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) {
260 // without this, a transient window not always emerges on top
261 gtk_window_present (dialog_win);
262 }
263 }
265 // we're done, allow next retransientizing not sooner than after 120 msec
266 gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) floating_win);
267 }
268 }
271 /* Signal wrappers */
273 Glib::SignalProxy0<void>
274 DockBehavior::signal_show() { return _dock_item.signal_show(); }
276 Glib::SignalProxy0<void>
277 DockBehavior::signal_hide() { return _dock_item.signal_hide(); }
279 Glib::SignalProxy1<bool, GdkEventAny *>
280 DockBehavior::signal_delete_event() { return _dock_item.signal_delete_event(); }
282 Glib::SignalProxy0<void>
283 DockBehavior::signal_drag_begin() { return _dock_item.signal_drag_begin(); }
285 Glib::SignalProxy1<void, bool>
286 DockBehavior::signal_drag_end() { return _dock_item.signal_drag_end(); }
289 } // namespace Behavior
290 } // namespace Dialog
291 } // namespace UI
292 } // namespace Inkscape
294 /*
295 Local Variables:
296 mode:c++
297 c-file-style:"stroustrup"
298 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
299 indent-tabs-mode:nil
300 fill-column:99
301 End:
302 */
303 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :