Code

884037c259f00303f53a71ee22239e4615d3cbdb
[inkscape.git] / src / ui / dialog / floating-behavior.cpp
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;
125 #endif
127 FloatingBehavior::~FloatingBehavior()
129     delete _d;
130     _d = 0;
133 Behavior *
134 FloatingBehavior::create(Dialog &dialog)
136     return new FloatingBehavior(dialog);
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()
164     _dialog.save_geometry();
165     hide();
168 void
169 FloatingBehavior::onShowF12()
171     show();
172     _dialog.read_geometry();
175 void
176 FloatingBehavior::onShutdown() {}
178 void
179 FloatingBehavior::onDesktopActivated (SPDesktop *desktop)
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);
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:encoding=utf-8:textwidth=99 :