~valavanisalex/ubuntu/precise/inkscape/fix-943984

« back to all changes in this revision

Viewing changes to inkscape-0.47pre1/src/ui/dialog/dialog.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bryce Harrington
  • Date: 2009-07-02 17:09:45 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20090702170945-nn6d6zswovbwju1t
Tags: 0.47~pre1-0ubuntu1
* New upstream release.
  - Don't constrain maximization on small resolution devices (pre0)
    (LP: #348842)
  - Fixes segfault on startup (pre0)
    (LP: #391149)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** @file
 
2
 * @brief Base class for dialogs in Inkscape - implementation
 
3
 */
 
4
/* Authors:
 
5
 *   Bryce W. Harrington <bryce@bryceharrington.org>
 
6
 *   buliabyak@gmail.com
 
7
 *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
 
8
 *   Gustav Broberg <broberg@kth.se>
 
9
 *
 
10
 * Copyright (C) 2004--2007 Authors
 
11
 *
 
12
 * Released under GNU GPL.  Read the file 'COPYING' for more information.
 
13
 */
 
14
 
 
15
#ifdef HAVE_CONFIG_H
 
16
# include <config.h>
 
17
#endif
 
18
 
 
19
#include <gtkmm/stock.h>
 
20
#include <gtk/gtk.h>
 
21
#include <gdk/gdkkeysyms.h>
 
22
 
 
23
#include "application/application.h"
 
24
#include "application/editor.h"
 
25
#include "inkscape.h"
 
26
#include "event-context.h"
 
27
#include "desktop.h"
 
28
#include "desktop-handles.h"
 
29
#include "dialog-manager.h"
 
30
#include "modifier-fns.h"
 
31
#include "shortcuts.h"
 
32
#include "preferences.h"
 
33
#include "interface.h"
 
34
#include "verbs.h"
 
35
 
 
36
#define MIN_ONSCREEN_DISTANCE 50
 
37
 
 
38
 
 
39
namespace Inkscape {
 
40
namespace UI {
 
41
namespace Dialog {
 
42
 
 
43
void
 
44
sp_retransientize(Inkscape::Application */*inkscape*/, SPDesktop *desktop, gpointer dlgPtr)
 
45
{
 
46
    Dialog *dlg = (Dialog *)dlgPtr;
 
47
    dlg->onDesktopActivated (desktop);
 
48
}
 
49
 
 
50
gboolean
 
51
sp_retransientize_again(gpointer dlgPtr)
 
52
{
 
53
    Dialog *dlg = (Dialog *)dlgPtr;
 
54
    dlg->retransientize_suppress = false;
 
55
    return FALSE; // so that it is only called once
 
56
}
 
57
 
 
58
void
 
59
sp_dialog_shutdown(GtkObject */*object*/, gpointer dlgPtr)
 
60
{
 
61
    Dialog *dlg = (Dialog *)dlgPtr;
 
62
    dlg->onShutdown();
 
63
}
 
64
 
 
65
 
 
66
void hideCallback(GtkObject */*object*/, gpointer dlgPtr)
 
67
{
 
68
    g_return_if_fail( dlgPtr != NULL );
 
69
 
 
70
    Dialog *dlg = (Dialog *)dlgPtr;
 
71
    dlg->onHideF12();
 
72
}
 
73
 
 
74
void unhideCallback(GtkObject */*object*/, gpointer dlgPtr)
 
75
{
 
76
    g_return_if_fail( dlgPtr != NULL );
 
77
 
 
78
    Dialog *dlg = (Dialog *)dlgPtr;
 
79
    dlg->onShowF12();
 
80
}
 
81
 
 
82
 
 
83
//=====================================================================
 
84
 
 
85
/**
 
86
 * UI::Dialog::Dialog is a base class for all dialogs in Inkscape.  The
 
87
 * purpose of this class is to provide a unified place for ensuring
 
88
 * style and behavior.  Specifically, this class provides functionality
 
89
 * for saving and restoring the size and position of dialogs (through
 
90
 * the user's preferences file).
 
91
 *
 
92
 * It also provides some general purpose signal handlers for things like
 
93
 * showing and hiding all dialogs.
 
94
 */
 
95
 
 
96
Dialog::Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path, int verb_num,
 
97
               Glib::ustring const &apply_label)
 
98
    : _hiddenF12 (false),
 
99
      _prefs_path (prefs_path),
 
100
      _verb_num(verb_num),
 
101
      _apply_label (apply_label)
 
102
{
 
103
    gchar title[500];
 
104
 
 
105
    if (verb_num)
 
106
        sp_ui_dialog_title_string (Inkscape::Verb::get(verb_num), title);
 
107
 
 
108
    _title = title;
 
109
 
 
110
    _behavior = behavior_factory(*this);
 
111
 
 
112
    if (Inkscape::NSApplication::Application::getNewGui()) {
 
113
        _desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*this, &Dialog::onDesktopActivated));
 
114
        _dialogs_hidden_connection = Inkscape::NSApplication::Editor::connectDialogsHidden (sigc::mem_fun (*this, &Dialog::onHideF12));
 
115
        _dialogs_unhidden_connection = Inkscape::NSApplication::Editor::connectDialogsUnhidden (sigc::mem_fun (*this, &Dialog::onShowF12));
 
116
        _shutdown_connection = Inkscape::NSApplication::Editor::connectShutdown (sigc::mem_fun (*this, &Dialog::onShutdown));
 
117
    } else {
 
118
        g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(sp_retransientize), (void *)this);
 
119
        g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_hide", G_CALLBACK(hideCallback), (void *)this);
 
120
        g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_unhide", G_CALLBACK(unhideCallback), (void *)this);
 
121
        g_signal_connect(G_OBJECT(INKSCAPE), "shut_down", G_CALLBACK(sp_dialog_shutdown), (void *)this);
 
122
    }
 
123
 
 
124
    Glib::wrap(gobj())->signal_event().connect(sigc::mem_fun(*this, &Dialog::_onEvent));
 
125
    Glib::wrap(gobj())->signal_key_press_event().connect(sigc::mem_fun(*this, &Dialog::_onKeyPress));
 
126
 
 
127
    read_geometry();
 
128
}
 
129
 
 
130
Dialog::~Dialog()
 
131
{
 
132
    if (Inkscape::NSApplication::Application::getNewGui())
 
133
    {
 
134
        _desktop_activated_connection.disconnect();
 
135
        _dialogs_hidden_connection.disconnect();
 
136
        _dialogs_unhidden_connection.disconnect();
 
137
        _shutdown_connection.disconnect();
 
138
    }
 
139
 
 
140
    save_geometry();
 
141
    delete _behavior;
 
142
}
 
143
 
 
144
 
 
145
//---------------------------------------------------------------------
 
146
 
 
147
 
 
148
void
 
149
Dialog::onDesktopActivated(SPDesktop *desktop)
 
150
{
 
151
    _behavior->onDesktopActivated(desktop);
 
152
}
 
153
 
 
154
void
 
155
Dialog::onShutdown()
 
156
{
 
157
    save_geometry();
 
158
    _user_hidden = true;
 
159
    _behavior->onShutdown();
 
160
}
 
161
 
 
162
void
 
163
Dialog::onHideF12()
 
164
{
 
165
    _hiddenF12 = true;
 
166
    _behavior->onHideF12();
 
167
}
 
168
 
 
169
void
 
170
Dialog::onShowF12()
 
171
{
 
172
    if (_user_hidden)
 
173
        return;
 
174
 
 
175
    if (_hiddenF12) {
 
176
        _behavior->onShowF12();
 
177
    }
 
178
 
 
179
    _hiddenF12 = false;
 
180
}
 
181
 
 
182
 
 
183
inline Dialog::operator Gtk::Widget &()                          { return *_behavior; }
 
184
inline GtkWidget *Dialog::gobj()                                 { return _behavior->gobj(); }
 
185
inline void Dialog::present()                                    { _behavior->present(); }
 
186
inline Gtk::VBox *Dialog::get_vbox()                             {  return _behavior->get_vbox(); }
 
187
inline void Dialog::hide()                                       { _behavior->hide(); }
 
188
inline void Dialog::show()                                       { _behavior->show(); }
 
189
inline void Dialog::show_all_children()                          { _behavior->show_all_children(); }
 
190
inline void Dialog::set_size_request(int width, int height)      { _behavior->set_size_request(width, height); }
 
191
inline void Dialog::size_request(Gtk::Requisition &requisition)  { _behavior->size_request(requisition); }
 
192
inline void Dialog::get_position(int &x, int &y)                 { _behavior->get_position(x, y); }
 
193
inline void Dialog::get_size(int &width, int &height)            { _behavior->get_size(width, height); }
 
194
inline void Dialog::resize(int width, int height)                { _behavior->resize(width, height); }
 
195
inline void Dialog::move(int x, int y)                           { _behavior->move(x, y); }
 
196
inline void Dialog::set_position(Gtk::WindowPosition position)   { _behavior->set_position(position); }
 
197
inline void Dialog::set_title(Glib::ustring title)               { _behavior->set_title(title); }
 
198
inline void Dialog::set_sensitive(bool sensitive)                { _behavior->set_sensitive(sensitive); }
 
199
 
 
200
Glib::SignalProxy0<void> Dialog::signal_show() { return _behavior->signal_show(); }
 
201
Glib::SignalProxy0<void> Dialog::signal_hide() { return _behavior->signal_hide(); }
 
202
 
 
203
void
 
204
Dialog::read_geometry()
 
205
{
 
206
    _user_hidden = false;
 
207
 
 
208
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
209
    int x = prefs->getInt(_prefs_path + "/x", -1000);
 
210
    int y = prefs->getInt(_prefs_path + "/y", -1000);
 
211
    int w = prefs->getInt(_prefs_path + "/w", 0);
 
212
    int h = prefs->getInt(_prefs_path + "/h", 0);
 
213
 
 
214
    // g_print ("read %d %d %d %d\n", x, y, w, h);
 
215
 
 
216
    // If there are stored height and width values for the dialog,
 
217
    // resize the window to match; otherwise we leave it at its default
 
218
    if (w != 0 && h != 0) {
 
219
        resize(w, h);
 
220
    }
 
221
 
 
222
    // If there are stored values for where the dialog should be
 
223
    // located, then restore the dialog to that position.
 
224
    // also check if (x,y) is actually onscreen with the current screen dimensions
 
225
    if ( (x >= 0) && (y >= 0) && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE)) ) {
 
226
        move(x, y);
 
227
    } else {
 
228
        // ...otherwise just put it in the middle of the screen
 
229
        set_position(Gtk::WIN_POS_CENTER);
 
230
    }
 
231
 
 
232
}
 
233
 
 
234
 
 
235
void
 
236
Dialog::save_geometry()
 
237
{
 
238
    int y, x, w, h;
 
239
 
 
240
    get_position(x, y);
 
241
    get_size(w, h);
 
242
 
 
243
    // g_print ("write %d %d %d %d\n", x, y, w, h);
 
244
 
 
245
    if (x<0) x=0;
 
246
    if (y<0) y=0;
 
247
 
 
248
    Inkscape::Preferences *prefs = Inkscape::Preferences::get();
 
249
    prefs->setInt(_prefs_path + "/x", x);
 
250
    prefs->setInt(_prefs_path + "/y", y);
 
251
    prefs->setInt(_prefs_path + "/w", w);
 
252
    prefs->setInt(_prefs_path + "/h", h);
 
253
 
 
254
}
 
255
 
 
256
void
 
257
Dialog::_handleResponse(int response_id)
 
258
{
 
259
    switch (response_id) {
 
260
        case Gtk::RESPONSE_CLOSE: {
 
261
            _close();
 
262
            break;
 
263
        }
 
264
    }
 
265
}
 
266
 
 
267
bool
 
268
Dialog::_onDeleteEvent(GdkEventAny */*event*/)
 
269
{
 
270
    save_geometry();
 
271
    _user_hidden = true;
 
272
 
 
273
    return false;
 
274
}
 
275
 
 
276
bool
 
277
Dialog::_onEvent(GdkEvent *event)
 
278
{
 
279
    bool ret = false;
 
280
 
 
281
    switch (event->type) {
 
282
        case GDK_KEY_PRESS: {
 
283
            switch (get_group0_keyval (&event->key)) {
 
284
                case GDK_Escape: {
 
285
                    _defocus();
 
286
                    ret = true;
 
287
                    break;
 
288
                }
 
289
                case GDK_F4:
 
290
                case GDK_w:
 
291
                case GDK_W: {
 
292
                    if (mod_ctrl_only(event->key.state)) {
 
293
                        _close();
 
294
                        ret = true;
 
295
                    }
 
296
                    break;
 
297
                }
 
298
                default: { // pass keypress to the canvas
 
299
                    break;
 
300
                }
 
301
            }
 
302
        }
 
303
        default:
 
304
            ;
 
305
    }
 
306
 
 
307
    return ret;
 
308
}
 
309
 
 
310
bool
 
311
Dialog::_onKeyPress(GdkEventKey *event)
 
312
{
 
313
    unsigned int shortcut;
 
314
    shortcut = get_group0_keyval(event) |
 
315
        ( event->state & GDK_SHIFT_MASK ?
 
316
          SP_SHORTCUT_SHIFT_MASK : 0 ) |
 
317
        ( event->state & GDK_CONTROL_MASK ?
 
318
          SP_SHORTCUT_CONTROL_MASK : 0 ) |
 
319
        ( event->state & GDK_MOD1_MASK ?
 
320
          SP_SHORTCUT_ALT_MASK : 0 );
 
321
    return sp_shortcut_invoke(shortcut, SP_ACTIVE_DESKTOP);
 
322
}
 
323
 
 
324
void
 
325
Dialog::_apply()
 
326
{
 
327
    g_warning("Apply button clicked for dialog [Dialog::_apply()]");
 
328
}
 
329
 
 
330
void
 
331
Dialog::_close()
 
332
{
 
333
    GtkWidget *dlg = GTK_WIDGET(_behavior->gobj());
 
334
 
 
335
    /* this code sends a delete_event to the dialog,
 
336
     * instead of just destroying it, so that the
 
337
     * dialog can do some housekeeping, such as remember
 
338
     * its position.
 
339
     */
 
340
 
 
341
    GdkEventAny event;
 
342
    event.type = GDK_DELETE;
 
343
    event.window = dlg->window;
 
344
    event.send_event = TRUE;
 
345
 
 
346
    if (event.window)
 
347
        g_object_ref(G_OBJECT(event.window));
 
348
 
 
349
    gtk_main_do_event ((GdkEvent*)&event);
 
350
 
 
351
    if (event.window)
 
352
        g_object_unref(G_OBJECT(event.window));
 
353
}
 
354
 
 
355
void
 
356
Dialog::_defocus()
 
357
{
 
358
    SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
359
 
 
360
    if (desktop) {
 
361
        Gtk::Widget *canvas = Glib::wrap(GTK_WIDGET(desktop->canvas));
 
362
 
 
363
        // make sure the canvas window is present before giving it focus
 
364
        Gtk::Window *toplevel_window = dynamic_cast<Gtk::Window *>(canvas->get_toplevel());
 
365
        if (toplevel_window)
 
366
            toplevel_window->present();
 
367
 
 
368
        canvas->grab_focus();
 
369
    }
 
370
}
 
371
 
 
372
Inkscape::Selection*
 
373
Dialog::_getSelection()
 
374
{
 
375
    return sp_desktop_selection(SP_ACTIVE_DESKTOP);
 
376
}
 
377
 
 
378
} // namespace Dialog
 
379
} // namespace UI
 
380
} // namespace Inkscape
 
381
 
 
382
/*
 
383
  Local Variables:
 
384
  mode:c++
 
385
  c-file-style:"stroustrup"
 
386
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
 
387
  indent-tabs-mode:nil
 
388
  fill-column:99
 
389
  End:
 
390
*/
 
391
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :