1 /**
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 "prefs-utils.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 prefs_get_int_attribute (_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 signal_response().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::on_response));
53 _dock_item.signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onStateChanged));
55 if (_dock_item.getState() == Widget::DockItem::FLOATING_STATE) {
56 if (Gtk::Window *floating_win = _dock_item.getWindow())
57 sp_transientize(GTK_WIDGET(floating_win->gobj()));
58 }
59 }
61 DockBehavior::~DockBehavior()
62 {
63 }
66 Behavior *
67 DockBehavior::create(Dialog& dialog)
68 {
69 return new DockBehavior(dialog);
70 }
73 DockBehavior::operator Gtk::Widget&()
74 {
75 return _dock_item.getWidget();
76 }
78 GtkWidget *
79 DockBehavior::gobj()
80 {
81 return _dock_item.gobj();
82 }
84 Gtk::VBox *
85 DockBehavior::get_vbox()
86 {
87 return _dock_item.get_vbox();
88 }
90 void
91 DockBehavior::present()
92 {
93 bool was_attached = _dock_item.isAttached();
95 _dock_item.present();
97 if (!was_attached)
98 _dialog.read_geometry();
99 }
101 void
102 DockBehavior::hide()
103 {
104 _signal_hide_connection.block();
105 _dock_item.hide();
106 _signal_hide_connection.unblock();
107 }
109 void
110 DockBehavior::show()
111 {
112 _dock_item.show();
113 }
115 void
116 DockBehavior::show_all_children()
117 {
118 get_vbox()->show_all_children();
119 }
121 void
122 DockBehavior::get_position(int& x, int& y)
123 {
124 _dock_item.get_position(x, y);
125 }
127 void
128 DockBehavior::get_size(int& width, int& height)
129 {
130 _dock_item.get_size(width, height);
131 }
133 void
134 DockBehavior::resize(int width, int height)
135 {
136 _dock_item.resize(width, height);
137 }
139 void
140 DockBehavior::move(int x, int y)
141 {
142 _dock_item.move(x, y);
143 }
145 void
146 DockBehavior::set_position(Gtk::WindowPosition position)
147 {
148 _dock_item.set_position(position);
149 }
151 void
152 DockBehavior::set_size_request(int width, int height)
153 {
154 _dock_item.set_size_request(width, height);
155 }
157 void
158 DockBehavior::size_request(Gtk::Requisition& requisition)
159 {
160 _dock_item.size_request(requisition);
161 }
163 void
164 DockBehavior::set_title(Glib::ustring title)
165 {
166 _dock_item.set_title(title);
167 }
169 void
170 DockBehavior::set_response_sensitive(int response_id, bool setting)
171 {
172 if (_response_map[response_id])
173 _response_map[response_id]->set_sensitive(setting);
174 }
176 void
177 DockBehavior::set_sensitive(bool sensitive)
178 {
179 get_vbox()->set_sensitive();
180 }
182 Gtk::Button *
183 DockBehavior::add_button(const Glib::ustring& button_text, int response_id)
184 {
185 Gtk::Button *button = new Gtk::Button(button_text);
186 _addButton(button, response_id);
187 return button;
188 }
190 Gtk::Button *
191 DockBehavior::add_button(const Gtk::StockID& stock_id, int response_id)
192 {
193 Gtk::Button *button = new Gtk::Button(stock_id);
194 _addButton(button, response_id);
195 return button;
196 }
198 void
199 DockBehavior::_addButton(Gtk::Button *button, int response_id)
200 {
201 _dock_item.addButton(button, response_id);
203 if (response_id != 0) {
205 /* Pass the signal_clicked signals onto a our own signal handler that can re-emit them as
206 * signal_response signals
207 */
208 button->signal_clicked().connect(
209 sigc::bind<int>(sigc::mem_fun(*this,
210 &Inkscape::UI::Dialog::Behavior::DockBehavior::_onResponse),
211 response_id));
213 _response_map[response_id] = button;
214 }
215 }
217 void
218 DockBehavior::set_default_response(int response_id)
219 {
220 ResponseMap::iterator widget_found;
221 widget_found = _response_map.find(response_id);
223 if (widget_found != _response_map.end()) {
224 widget_found->second->activate();
225 widget_found->second->property_can_default() = true;
226 widget_found->second->grab_default();
227 }
228 }
231 void
232 DockBehavior::_onHide()
233 {
234 _dialog.save_geometry();
235 _dialog._user_hidden = true;
236 prefs_set_int_attribute (_dialog._prefs_path, "state", _dock_item.getPrevState());
237 }
239 void
240 DockBehavior::_onStateChanged(Widget::DockItem::State prev_state,
241 Widget::DockItem::State new_state)
242 {
243 prefs_set_int_attribute (_dialog._prefs_path, "state", new_state);
245 if (new_state == Widget::DockItem::FLOATING_STATE) {
246 if (Gtk::Window *floating_win = _dock_item.getWindow())
247 sp_transientize(GTK_WIDGET(floating_win->gobj()));
248 }
249 }
251 void
252 DockBehavior::_onResponse(int response_id)
253 {
254 g_signal_emit_by_name (_dock_item.gobj(), "signal_response", response_id);
255 }
257 void
258 DockBehavior::onHideF12()
259 {
260 _dialog.save_geometry();
261 hide();
262 }
264 void
265 DockBehavior::onShowF12()
266 {
267 present();
268 }
270 void
271 DockBehavior::onShutdown()
272 {
273 prefs_set_int_attribute (_dialog._prefs_path, "state", _dock_item.getPrevState());
274 }
276 void
277 DockBehavior::onDesktopActivated(SPDesktop *desktop)
278 {
279 gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2);
281 #ifdef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs
282 if (prefs_get_int_attribute ( "options.dialogsontopwin32", "value", 0))
283 transient_policy = 2;
284 else
285 return;
286 #endif
288 if (!transient_policy)
289 return;
291 Gtk::Window *floating_win = _dock_item.getWindow();
293 if (floating_win) {
295 if (_dialog.retransientize_suppress) {
296 /* if retransientizing of this dialog is still forbidden after
297 * previous call warning turned off because it was confusingly fired
298 * when loading many files from command line
299 */
301 // g_warning("Retranzientize aborted! You're switching windows too fast!");
302 return;
303 }
305 if (GtkWindow *dialog_win = floating_win->gobj()) {
307 _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog
309 desktop->setWindowTransient (dialog_win);
311 /*
312 * This enables "aggressive" transientization,
313 * i.e. dialogs always emerging on top when you switch documents. Note
314 * however that this breaks "click to raise" policy of a window
315 * manager because the switched-to document will be raised at once
316 * (so that its transients also could raise)
317 */
318 if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) {
319 // without this, a transient window not always emerges on top
320 gtk_window_present (dialog_win);
321 }
322 }
324 // we're done, allow next retransientizing not sooner than after 120 msec
325 gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) floating_win);
326 }
327 }
330 /* Signal wrappers */
332 Glib::SignalProxy0<void>
333 DockBehavior::signal_show() { return _dock_item.signal_show(); }
335 Glib::SignalProxy0<void>
336 DockBehavior::signal_hide() { return _dock_item.signal_hide(); }
338 Glib::SignalProxy1<void, int>
339 DockBehavior::signal_response() { return _dock_item.signal_response(); }
341 Glib::SignalProxy1<bool, GdkEventAny *>
342 DockBehavior::signal_delete_event() { return _dock_item.signal_delete_event(); }
344 Glib::SignalProxy0<void>
345 DockBehavior::signal_drag_begin() { return _dock_item.signal_drag_begin(); }
347 Glib::SignalProxy1<void, bool>
348 DockBehavior::signal_drag_end() { return _dock_item.signal_drag_end(); }
351 } // namespace Behavior
352 } // namespace Dialog
353 } // namespace UI
354 } // namespace Inkscape
356 /*
357 Local Variables:
358 mode:c++
359 c-file-style:"stroustrup"
360 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
361 indent-tabs-mode:nil
362 fill-column:99
363 End:
364 */
365 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :