1 /** @file
2 * @brief Floating 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 */
12 #include <gtkmm/stock.h>
13 #include <gtk/gtk.h>
15 #include "floating-behavior.h"
16 #include "dialog.h"
18 #include "inkscape.h"
19 #include "desktop.h"
20 #include "dialogs/dialog-events.h"
21 #include "interface.h"
22 #include "preferences.h"
23 #include "verbs.h"
25 namespace Inkscape {
26 namespace UI {
27 namespace Dialog {
28 namespace Behavior {
30 FloatingBehavior::FloatingBehavior(Dialog &dialog) :
31 Behavior(dialog),
32 _d (new Gtk::Dialog(_dialog._title))
33 #if GTK_VERSION_GE(2, 12)
34 ,_dialog_active(_d->property_is_active())
35 ,_steps(0)
36 ,_trans_focus(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0))
37 ,_trans_blur(Inkscape::Preferences::get()->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0))
38 ,_trans_time(Inkscape::Preferences::get()->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000))
39 #endif
40 {
41 hide();
42 _d->set_has_separator(false);
44 signal_delete_event().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::_onDeleteEvent));
46 sp_transientize(GTK_WIDGET(_d->gobj()));
47 _dialog.retransientize_suppress = false;
49 #if GTK_VERSION_GE(2, 12)
50 _focus_event();
51 _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event));
52 #endif
54 }
56 #if GTK_VERSION_GE(2, 12)
57 /** \brief A function called when the window gets focus
59 This function gets called on a focus event. It figures out how much
60 time is required for a transition, and the number of steps that'll take,
61 and sets up the _trans_timer function to do the work. If the transition
62 time is set to 0 ms it just calls _trans_timer once with _steps equal to
63 zero so that the transition happens instantaneously. This occurs on
64 windows as opacity changes cause flicker there.
65 */
66 void FloatingBehavior::_focus_event (void)
67 {
68 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
69 _steps = 0;
70 _trans_focus = prefs->getDoubleLimited("/dialogs/transparency/on-focus", 0.95, 0.0, 1.0);
71 _trans_blur = prefs->getDoubleLimited("/dialogs/transparency/on-blur", 0.50, 0.0, 1.0);
72 _trans_time = prefs->getIntLimited("/dialogs/transparency/animate-time", 100, 0, 5000);
74 if (_trans_time != 0) {
75 float diff = _trans_focus - _trans_blur;
76 if (diff < 0.0) diff *= -1.0;
78 while (diff > 0.05) {
79 _steps++;
80 diff = diff / 2.0;
81 }
83 if (_steps != 0) {
84 Glib::signal_timeout().connect(sigc::mem_fun(this, &FloatingBehavior::_trans_timer), _trans_time / _steps);
85 }
86 }
87 _trans_timer();
89 return;
90 }
92 /** \brief Move the opacity of a window towards our goal
94 This is a timer function that is set up by _focus_event to slightly
95 move the opacity of the window along in an animated fashion. It moves
96 the opacity half way to the goal until it runs out of steps, and then
97 it just forces the goal.
98 */
99 bool FloatingBehavior::_trans_timer (void) {
100 // printf("Go go gadget timer: %d\n", _steps);
101 if (_steps == 0) {
102 if (_dialog_active.get_value()) {
103 _d->set_opacity(_trans_focus);
104 } else {
105 _d->set_opacity(_trans_blur);
106 }
108 return false;
109 }
111 float goal, current;
112 goal = current = _d->get_opacity();
114 if (_dialog_active.get_value()) {
115 goal = _trans_focus;
116 } else {
117 goal = _trans_blur;
118 }
120 _d->set_opacity(current - ((current - goal) / 2));
121 _steps--;
122 return true;
123 }
125 #endif
127 FloatingBehavior::~FloatingBehavior()
128 {
129 delete _d;
130 _d = 0;
131 }
133 Behavior *
134 FloatingBehavior::create(Dialog &dialog)
135 {
136 return new FloatingBehavior(dialog);
137 }
139 inline FloatingBehavior::operator Gtk::Widget &() { return *_d; }
140 inline GtkWidget *FloatingBehavior::gobj() { return GTK_WIDGET(_d->gobj()); }
141 inline Gtk::VBox* FloatingBehavior::get_vbox() { return _d->get_vbox(); }
142 inline void FloatingBehavior::present() { _d->present(); }
143 inline void FloatingBehavior::hide() { _d->hide(); }
144 inline void FloatingBehavior::show() { _d->show(); }
145 inline void FloatingBehavior::show_all_children() { _d->show_all_children(); }
146 inline void FloatingBehavior::resize(int width, int height) { _d->resize(width, height); }
147 inline void FloatingBehavior::move(int x, int y) { _d->move(x, y); }
148 inline void FloatingBehavior::set_position(Gtk::WindowPosition position) { _d->set_position(position); }
149 inline void FloatingBehavior::set_size_request(int width, int height) { _d->set_size_request(width, height); }
150 inline void FloatingBehavior::size_request(Gtk::Requisition &requisition) { _d->size_request(requisition); }
151 inline void FloatingBehavior::get_position(int &x, int &y) { _d->get_position(x, y); }
152 inline void FloatingBehavior::get_size(int &width, int &height) { _d->get_size(width, height); }
153 inline void FloatingBehavior::set_title(Glib::ustring title) { _d->set_title(title); }
154 inline void FloatingBehavior::set_sensitive(bool sensitive) { _d->set_sensitive(sensitive); }
156 Glib::SignalProxy0<void> FloatingBehavior::signal_show() { return _d->signal_show(); }
157 Glib::SignalProxy0<void> FloatingBehavior::signal_hide() { return _d->signal_hide(); }
158 Glib::SignalProxy1<bool, GdkEventAny *> FloatingBehavior::signal_delete_event () { return _d->signal_delete_event(); }
161 void
162 FloatingBehavior::onHideF12()
163 {
164 _dialog.save_geometry();
165 hide();
166 }
168 void
169 FloatingBehavior::onShowF12()
170 {
171 show();
172 _dialog.read_geometry();
173 }
175 void
176 FloatingBehavior::onShutdown() {}
178 void
179 FloatingBehavior::onDesktopActivated (SPDesktop *desktop)
180 {
181 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
182 gint transient_policy = prefs->getIntLimited("/options/transientpolicy/value", 1, 0, 2);
184 #ifdef WIN32 // Win32 special code to enable transient dialogs
185 transient_policy = 2;
186 #endif
188 if (!transient_policy)
189 return;
191 GtkWindow *dialog_win = GTK_WINDOW(_d->gobj());
193 if (_dialog.retransientize_suppress) {
194 /* if retransientizing of this dialog is still forbidden after
195 * previous call warning turned off because it was confusingly fired
196 * when loading many files from command line
197 */
199 // g_warning("Retranzientize aborted! You're switching windows too fast!");
200 return;
201 }
203 if (dialog_win)
204 {
205 _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog
207 desktop->setWindowTransient (dialog_win);
209 /*
210 * This enables "aggressive" transientization,
211 * i.e. dialogs always emerging on top when you switch documents. Note
212 * however that this breaks "click to raise" policy of a window
213 * manager because the switched-to document will be raised at once
214 * (so that its transients also could raise)
215 */
216 if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) {
217 // without this, a transient window not always emerges on top
218 gtk_window_present (dialog_win);
219 }
220 }
222 // we're done, allow next retransientizing not sooner than after 120 msec
223 gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) _d);
224 }
227 } // namespace Behavior
228 } // namespace Dialog
229 } // namespace UI
230 } // namespace Inkscape
232 /*
233 Local Variables:
234 mode:c++
235 c-file-style:"stroustrup"
236 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
237 indent-tabs-mode:nil
238 fill-column:99
239 End:
240 */
241 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :