Code

Merging from trunk
[inkscape.git] / src / ui / dialog / floating-behavior.cpp
1 /**
2  * \brief A 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 "application/application.h"
19 #include "application/editor.h"
20 #include "inkscape.h"
21 #include "desktop.h"
22 #include "dialogs/dialog-events.h"
23 #include "interface.h"
24 #include "prefs-utils.h"
25 #include "verbs.h"
27 namespace Inkscape {
28 namespace UI {
29 namespace Dialog {
30 namespace Behavior {
32 FloatingBehavior::FloatingBehavior(Dialog &dialog) :
33     Behavior(dialog),
34     _d (new Gtk::Dialog(_dialog._title))
35 #if GTK_VERSION_GE(2, 12)
36         ,_dialog_active(_d->property_is_active())
37         ,_steps(0)
38         ,_trans_focus(prefs_get_double_attribute_limited("dialogs.transparency", "on-focus", 0.95, 0.0, 1.0))
39         ,_trans_blur(prefs_get_double_attribute_limited("dialogs.transparency", "on-blur", 0.50, 0.0, 1.0))
40         ,_trans_time(prefs_get_int_attribute_limited("dialogs.transparency", "animate-time", 100, 0, 5000))
41 #endif
42 {
43     hide();
44     _d->set_has_separator(false);
46     signal_delete_event().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::_onDeleteEvent));
48     sp_transientize(GTK_WIDGET(_d->gobj()));
49     _dialog.retransientize_suppress = false;
51 #if GTK_VERSION_GE(2, 12)
52         _focus_event();
53         _dialog_active.signal_changed().connect(sigc::mem_fun(this, &FloatingBehavior::_focus_event));
54 #endif
56 }
58 #if GTK_VERSION_GE(2, 12)
59 /** \brief  A function called when the window gets focus
61         This function gets called on a focus event.  It figures out how much
62         time is required for a transition, and the number of steps that'll take,
63         and sets up the _trans_timer function to do the work.  If the transition
64         time is set to 0 ms it just calls _trans_timer once with _steps equal to
65         zero so that the transition happens instantaneously.  This occurs on
66         windows as opacity changes cause flicker there.
67 */
68 void FloatingBehavior::_focus_event (void) {
69         _steps = 0;
70         _trans_focus = prefs_get_double_attribute_limited("dialogs.transparency", "on-focus", 0.95, 0.0, 1.0);
71         _trans_blur = prefs_get_double_attribute_limited("dialogs.transparency", "on-blur", 0.50, 0.0, 1.0);
72         _trans_time = prefs_get_int_attribute_limited("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         }
119         
120         _d->set_opacity(current - ((current - goal) / 2));
121         _steps--;
122         return true;
125 #endif
127 FloatingBehavior::~FloatingBehavior() 
128
129     delete _d;
132 Behavior *
133 FloatingBehavior::create(Dialog &dialog)
135     return new FloatingBehavior(dialog);
138 inline FloatingBehavior::operator Gtk::Widget &()                          { return *_d; }
139 inline GtkWidget *FloatingBehavior::gobj()                                { return GTK_WIDGET(_d->gobj()); }
140 inline Gtk::VBox* FloatingBehavior::get_vbox()                            { return _d->get_vbox(); }
141 inline void FloatingBehavior::present()                                   { _d->present(); }
142 inline void FloatingBehavior::hide()                                      { _d->hide(); }
143 inline void FloatingBehavior::show()                                      { _d->show(); }
144 inline void FloatingBehavior::show_all_children()                         { _d->show_all_children(); }
145 inline void FloatingBehavior::resize(int width, int height)               { _d->resize(width, height); }
146 inline void FloatingBehavior::move(int x, int y)                          { _d->move(x, y); }
147 inline void FloatingBehavior::set_position(Gtk::WindowPosition position)  { _d->set_position(position); }
148 inline void FloatingBehavior::set_size_request(int width, int height)     { _d->set_size_request(width, height); }
149 inline void FloatingBehavior::size_request(Gtk::Requisition &requisition) { _d->size_request(requisition); }
150 inline void FloatingBehavior::get_position(int &x, int &y)                { _d->get_position(x, y); }
151 inline void FloatingBehavior::get_size(int &width, int &height)           { _d->get_size(width, height); }
152 inline void FloatingBehavior::set_title(Glib::ustring title)              { _d->set_title(title); }
153 inline void FloatingBehavior::set_sensitive(bool sensitive)               { _d->set_sensitive(sensitive); }
155 Glib::SignalProxy0<void> FloatingBehavior::signal_show() { return _d->signal_show(); }
156 Glib::SignalProxy0<void> FloatingBehavior::signal_hide() { return _d->signal_hide(); }
157 Glib::SignalProxy1<bool, GdkEventAny *> FloatingBehavior::signal_delete_event () { return _d->signal_delete_event(); }
160 void
161 FloatingBehavior::onHideF12()
163     _dialog.save_geometry();
164     hide();
167 void
168 FloatingBehavior::onShowF12()
170     show();
171     _dialog.read_geometry();
174 void
175 FloatingBehavior::onShutdown() {}
177 void
178 FloatingBehavior::onDesktopActivated (SPDesktop *desktop)
180     gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2);
182 #ifdef WIN32 // Win32 special code to enable transient dialogs
183     transient_policy = 2;
184 #endif        
186     if (!transient_policy) 
187         return;
189     GtkWindow *dialog_win = GTK_WINDOW(_d->gobj());
191     if (_dialog.retransientize_suppress) {
192          /* if retransientizing of this dialog is still forbidden after
193           * previous call warning turned off because it was confusingly fired
194           * when loading many files from command line
195           */
197          // g_warning("Retranzientize aborted! You're switching windows too fast!");
198         return;
199     }
201     if (dialog_win)
202     {
203         _dialog.retransientize_suppress = true; // disallow other attempts to retranzientize this dialog
205         desktop->setWindowTransient (dialog_win);
207         /*
208          * This enables "aggressive" transientization,
209          * i.e. dialogs always emerging on top when you switch documents. Note
210          * however that this breaks "click to raise" policy of a window
211          * manager because the switched-to document will be raised at once
212          * (so that its transients also could raise)
213          */
214         if (transient_policy == 2 && ! _dialog._hiddenF12 && !_dialog._user_hidden) {
215             // without this, a transient window not always emerges on top
216             gtk_window_present (dialog_win);
217         }
218     }
220     // we're done, allow next retransientizing not sooner than after 120 msec
221     gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) _d);
225 } // namespace Behavior
226 } // namespace Dialog
227 } // namespace UI
228 } // namespace Inkscape
230 /*
231   Local Variables:
232   mode:c++
233   c-file-style:"stroustrup"
234   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
235   indent-tabs-mode:nil
236   fill-column:99
237   End:
238 */
239 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :