X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fui%2Fdialog%2Fdialog.cpp;h=4fbc217abefb59b856b14195cf219dfc75db7d88;hb=4533e5e378aae1df5a980a1dd6b2359d02891513;hp=074ee0d36528bc93b353ccb545caf7178a98c544;hpb=f4f507228b30d55fd7e39386ba513f3a0a54bd5d;p=inkscape.git diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 074ee0d36..4fbc217ab 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -2,11 +2,13 @@ * \brief Base class for dialogs in Inkscape. This class provides certain * common behaviors and styles wanted of all dialogs in the application. * - * Author: + * Authors: * Bryce W. Harrington - * buliabyak@gmail.com + * buliabyak@gmail.com + * Johan Engelen + * Gustav Broberg * - * Copyright (C) 2004, 2005 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -17,6 +19,7 @@ #include #include +#include #include "application/application.h" #include "application/editor.h" @@ -25,95 +28,41 @@ #include "desktop.h" #include "desktop-handles.h" #include "dialog-manager.h" -#include "dialogs/dialog-events.h" +#include "modifier-fns.h" #include "shortcuts.h" #include "prefs-utils.h" #include "interface.h" #include "verbs.h" +#define MIN_ONSCREEN_DISTANCE 50 + + namespace Inkscape { namespace UI { namespace Dialog { -#ifndef WIN32 -static gboolean -sp_retransientize_again (gpointer dlgPtr) -{ - Dialog *dlg = (Dialog *)dlgPtr; - dlg->retransientize_suppress = false; - return FALSE; // so that it is only called once -} -#endif - -static void +void sp_retransientize (Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr) { Dialog *dlg = (Dialog *)dlgPtr; dlg->onDesktopActivated (desktop); } -static void -sp_dialog_shutdown (GtkObject *object, gpointer dlgPtr) +gboolean +sp_retransientize_again (gpointer dlgPtr) { Dialog *dlg = (Dialog *)dlgPtr; - dlg->onShutdown(); -} - -void -Dialog::present() -{ - Gtk::Dialog::present(); + dlg->retransientize_suppress = false; + return FALSE; // so that it is only called once } void -Dialog::save_geometry() +sp_dialog_shutdown (GtkObject *object, gpointer dlgPtr) { - int y, x, w, h; - - get_position(x, y); - get_size(w, h); - -// g_print ("write %d %d %d %d\n", x, y, w, h); - - if (x<0) x=0; - if (y<0) y=0; - - prefs_set_int_attribute (_prefs_path, "x", x); - prefs_set_int_attribute (_prefs_path, "y", y); - prefs_set_int_attribute (_prefs_path, "w", w); - prefs_set_int_attribute (_prefs_path, "h", h); + Dialog *dlg = (Dialog *)dlgPtr; + dlg->onShutdown(); } -void -Dialog::read_geometry() -{ - _user_hidden = false; - - int x = prefs_get_int_attribute (_prefs_path, "x", -1000); - int y = prefs_get_int_attribute (_prefs_path, "y", -1000); - int w = prefs_get_int_attribute (_prefs_path, "w", 0); - int h = prefs_get_int_attribute (_prefs_path, "h", 0); - -// g_print ("read %d %d %d %d\n", x, y, w, h); - - if (x<0) x=0; - if (y<0) y=0; - - // If there are stored height and width values for the dialog, - // resize the window to match; otherwise we leave it at its default - if (w != 0 && h != 0) { - resize (w, h); - } - - // If there are stored values for where the dialog should be - // located, then restore the dialog to that position. - if (x != -1000 && y != -1000) { - move(x, y); - } else { - // ...otherwise just put it in the middle of the screen - set_position(Gtk::WIN_POS_CENTER); - } -} void hideCallback(GtkObject *object, gpointer dlgPtr) { @@ -131,6 +80,7 @@ void unhideCallback(GtkObject *object, gpointer dlgPtr) dlg->onShowF12(); } + //===================================================================== /** @@ -143,61 +93,48 @@ void unhideCallback(GtkObject *object, gpointer dlgPtr) * It also provides some general purpose signal handlers for things like * showing and hiding all dialogs. */ -Dialog::Dialog(const char *prefs_path, int verb_num, const char *apply_label) -{ - hide(); - set_has_separator(false); - - _prefs_path = prefs_path; - if (prefs_get_int_attribute ("dialogs", "showclose", 0) || apply_label) { - // TODO: make the order of buttons obey the global preference - if (apply_label) { - add_button(Glib::ustring(apply_label), Gtk::RESPONSE_APPLY); - set_default_response(Gtk::RESPONSE_APPLY); - } - add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE); - } - - GtkWidget *dlg = GTK_WIDGET(gobj()); +Dialog::Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path, int verb_num, + const char *apply_label) + : _hiddenF12 (false), + _prefs_path (prefs_path), + _verb_num(verb_num), + _apply_label (apply_label) +{ + gchar title[500]; if (verb_num) - { - gchar title[500]; sp_ui_dialog_title_string (Inkscape::Verb::get(verb_num), title); - set_title(title); - } - sp_transientize(dlg); - retransientize_suppress = false; + _title = title; - gtk_signal_connect( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC(sp_dialog_event_handler), dlg ); - - _hiddenF12 = false; - if (Inkscape::NSApplication::Application::getNewGui()) - { + _behavior = behavior_factory(*this); + + if (Inkscape::NSApplication::Application::getNewGui()) { _desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*this, &Dialog::onDesktopActivated)); _dialogs_hidden_connection = Inkscape::NSApplication::Editor::connectDialogsHidden (sigc::mem_fun (*this, &Dialog::onHideF12)); _dialogs_unhidden_connection = Inkscape::NSApplication::Editor::connectDialogsUnhidden (sigc::mem_fun (*this, &Dialog::onShowF12)); _shutdown_connection = Inkscape::NSApplication::Editor::connectShutdown (sigc::mem_fun (*this, &Dialog::onShutdown)); - } - else - { - g_signal_connect (G_OBJECT (INKSCAPE), "activate_desktop", G_CALLBACK (sp_retransientize), (void *)this); - g_signal_connect( G_OBJECT(INKSCAPE), "dialogs_hide", G_CALLBACK(hideCallback), (void *)this ); - g_signal_connect( G_OBJECT(INKSCAPE), "dialogs_unhide", G_CALLBACK(unhideCallback), (void *)this ); - g_signal_connect (G_OBJECT (INKSCAPE), "shut_down", G_CALLBACK (sp_dialog_shutdown), (void *)this); + } else { + g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(sp_retransientize), (void *)this); + g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_hide", G_CALLBACK(hideCallback), (void *)this); + g_signal_connect(G_OBJECT(INKSCAPE), "dialogs_unhide", G_CALLBACK(unhideCallback), (void *)this); + g_signal_connect(G_OBJECT(INKSCAPE), "shut_down", G_CALLBACK(sp_dialog_shutdown), (void *)this); } - g_signal_connect_after( gobj(), "key_press_event", (GCallback)windowKeyPress, NULL ); + Glib::wrap(gobj())->signal_event().connect(sigc::mem_fun(*this, &Dialog::_onEvent)); + Glib::wrap(gobj())->signal_key_press_event().connect(sigc::mem_fun(*this, &Dialog::_onKeyPress)); - read_geometry(); - present(); -} + if (prefs_get_int_attribute ("dialogs", "showclose", 0) || apply_label) { + // TODO: make the order of buttons obey the global preference + if (apply_label) { + add_button(Glib::ustring(apply_label), Gtk::RESPONSE_APPLY); + set_default_response(Gtk::RESPONSE_APPLY); + } + add_button(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE); + } -Dialog::Dialog(BaseObjectType *gobj) - : Gtk::Dialog(gobj) -{ + read_geometry(); } Dialog::~Dialog() @@ -211,54 +148,32 @@ Dialog::~Dialog() } save_geometry(); + delete _behavior; } -bool Dialog::windowKeyPress( GtkWidget *widget, GdkEventKey *event ) -{ - unsigned int shortcut = 0; - shortcut = get_group0_keyval (event) | - ( event->state & GDK_SHIFT_MASK ? - SP_SHORTCUT_SHIFT_MASK : 0 ) | - ( event->state & GDK_CONTROL_MASK ? - SP_SHORTCUT_CONTROL_MASK : 0 ) | - ( event->state & GDK_MOD1_MASK ? - SP_SHORTCUT_ALT_MASK : 0 ); - return sp_shortcut_invoke( shortcut, SP_ACTIVE_DESKTOP ); -} - //--------------------------------------------------------------------- + void -Dialog::on_response(int response_id) +Dialog::onDesktopActivated(SPDesktop *desktop) { - switch (response_id) { - case Gtk::RESPONSE_APPLY: { - _apply(); - break; - } - case Gtk::RESPONSE_CLOSE: { - _close(); - break; - } - } + _behavior->onDesktopActivated(desktop); } -bool -Dialog::on_delete_event (GdkEventAny *event) +void +Dialog::onShutdown() { save_geometry(); _user_hidden = true; - - return false; + _behavior->onShutdown(); } void Dialog::onHideF12() { _hiddenF12 = true; - save_geometry(); - hide(); + _behavior->onHideF12(); } void @@ -268,70 +183,170 @@ Dialog::onShowF12() return; if (_hiddenF12) { - show(); - read_geometry(); + _behavior->onShowF12(); } _hiddenF12 = false; } -void -Dialog::onShutdown() + +inline Dialog::operator Gtk::Widget&() { return *_behavior; } +inline GtkWidget *Dialog::gobj() { return _behavior->gobj(); } +inline void Dialog::present() { _behavior->present(); } +inline Gtk::VBox *Dialog::get_vbox() { return _behavior->get_vbox(); } +inline void Dialog::hide() { _behavior->hide(); } +inline void Dialog::show() { _behavior->show(); } +inline void Dialog::show_all_children() { _behavior->show_all_children(); } +inline void Dialog::set_size_request(int width, int height) { _behavior->set_size_request(width, height); } +inline void Dialog::size_request(Gtk::Requisition& requisition) { _behavior->size_request(requisition); } +inline void Dialog::get_position(int& x, int& y) { _behavior->get_position(x, y); } +inline void Dialog::get_size(int& width, int& height) { _behavior->get_size(width, height); } +inline void Dialog::resize(int width, int height) { _behavior->resize(width, height); } +inline void Dialog::move(int x, int y) { _behavior->move(x, y); } +inline void Dialog::set_position(Gtk::WindowPosition position) { _behavior->set_position(position); } +inline void Dialog::set_title(Glib::ustring title) { _behavior->set_title(title); } +inline void Dialog::set_sensitive(bool sensitive) { _behavior->set_sensitive(sensitive); } + +inline void Dialog::set_response_sensitive(int response_id, bool setting) +{ _behavior->set_response_sensitive(response_id, setting); } + +void Dialog::set_resizable(bool) { } +void Dialog::set_default(Gtk::Widget&) { } + +inline void Dialog::set_default_response(int response_id) { _behavior->set_default_response(response_id); } + +Glib::SignalProxy0 Dialog::signal_show () { return _behavior->signal_show(); } +Glib::SignalProxy0 Dialog::signal_hide () { return _behavior->signal_hide(); } +Glib::SignalProxy1 Dialog::signal_response () { return _behavior->signal_response(); } + +Gtk::Button* Dialog::add_button (const Glib::ustring& button_text, int response_id) +{ return _behavior->add_button(button_text, response_id); } + +Gtk::Button* Dialog::add_button (const Gtk::StockID& stock_id, int response_id) +{ return _behavior->add_button(stock_id, response_id); } + + +void +Dialog::read_geometry() { - save_geometry(); - _user_hidden = true; + _user_hidden = false; + + int x = prefs_get_int_attribute (_prefs_path, "x", -1000); + int y = prefs_get_int_attribute (_prefs_path, "y", -1000); + int w = prefs_get_int_attribute (_prefs_path, "w", 0); + int h = prefs_get_int_attribute (_prefs_path, "h", 0); + + // g_print ("read %d %d %d %d\n", x, y, w, h); + + // If there are stored height and width values for the dialog, + // resize the window to match; otherwise we leave it at its default + if (w != 0 && h != 0) { + resize(w, h); + } + + // If there are stored values for where the dialog should be + // located, then restore the dialog to that position. + // also check if (x,y) is actually onscreen with the current screen dimensions + if ( (x >= 0) && (y >= 0) && (x < (gdk_screen_width()-MIN_ONSCREEN_DISTANCE)) && (y < (gdk_screen_height()-MIN_ONSCREEN_DISTANCE)) ) { + move(x, y); + } else { + // ...otherwise just put it in the middle of the screen + set_position(Gtk::WIN_POS_CENTER); + } + } + void -Dialog::onDesktopActivated (SPDesktop *desktop) +Dialog::save_geometry() { - gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2); + int y, x, w, h; - if (!transient_policy) - return; + get_position(x, y); + get_size(w, h); -#ifndef WIN32 - GtkWindow *dialog_win = GTK_WINDOW(gobj()); + // g_print ("write %d %d %d %d\n", x, y, w, h); - if (retransientize_suppress) { - /* if retransientizing of this dialog is still forbidden after - * previous call warning turned off because it was confusingly fired - * when loading many files from command line - */ + if (x<0) x=0; + if (y<0) y=0; - // g_warning("Retranzientize aborted! You're switching windows too fast!"); - return; - } + prefs_set_int_attribute (_prefs_path, "x", x); + prefs_set_int_attribute (_prefs_path, "y", y); + prefs_set_int_attribute (_prefs_path, "w", w); + prefs_set_int_attribute (_prefs_path, "h", h); - if (dialog_win) - { - retransientize_suppress = true; // disallow other attempts to retranzientize this dialog - - desktop->setWindowTransient (dialog_win); - - /* - * This enables "aggressive" transientization, - * i.e. dialogs always emerging on top when you switch documents. Note - * however that this breaks "click to raise" policy of a window - * manager because the switched-to document will be raised at once - * (so that its transients also could raise) - */ - if (transient_policy == 2 && !_hiddenF12 && !_user_hidden) { - // without this, a transient window not always emerges on top - gtk_window_present (dialog_win); +} + +void +Dialog::_onResponse(int response_id) +{ + switch (response_id) { + case Gtk::RESPONSE_APPLY: { + _apply(); + break; + } + case Gtk::RESPONSE_CLOSE: { + _close(); + break; } } +} - // we're done, allow next retransientizing not sooner than after 120 msec - gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) this); -#endif +bool +Dialog::_onDeleteEvent(GdkEventAny *event) +{ + save_geometry(); + _user_hidden = true; + + return false; } +bool +Dialog::_onEvent(GdkEvent *event) +{ + bool ret = false; + + switch (event->type) { + case GDK_KEY_PRESS: { + switch (get_group0_keyval (&event->key)) { + case GDK_Escape: { + _defocus(); + ret = true; + break; + } + case GDK_F4: + case GDK_w: + case GDK_W: { + if (mod_ctrl_only(event->key.state)) { + _close(); + ret = true; + } + break; + } + default: { // pass keypress to the canvas + break; + } + } + } + default: + ; + } -Inkscape::Selection* -Dialog::_getSelection() + return ret; +} + +bool +Dialog::_onKeyPress(GdkEventKey *event) { - return sp_desktop_selection(SP_ACTIVE_DESKTOP); + unsigned int shortcut; + shortcut = get_group0_keyval(event) | + ( event->state & GDK_SHIFT_MASK ? + SP_SHORTCUT_SHIFT_MASK : 0 ) | + ( event->state & GDK_CONTROL_MASK ? + SP_SHORTCUT_CONTROL_MASK : 0 ) | + ( event->state & GDK_MOD1_MASK ? + SP_SHORTCUT_ALT_MASK : 0 ); + return sp_shortcut_invoke(shortcut, SP_ACTIVE_DESKTOP); } void @@ -343,20 +358,49 @@ Dialog::_apply() void Dialog::_close() { - GtkWidget *dlg = GTK_WIDGET(gobj()); - - /* this code sends a delete_event to the dialog, - * instead of just destroying it, so that the - * dialog can do some housekeeping, such as remember - * its position. - */ - GdkEventAny event; - event.type = GDK_DELETE; - event.window = dlg->window; - event.send_event = TRUE; - g_object_ref (G_OBJECT (event.window)); - gtk_main_do_event ((GdkEvent*)&event); - g_object_unref (G_OBJECT (event.window)); + GtkWidget *dlg = GTK_WIDGET(_behavior->gobj()); + + /* this code sends a delete_event to the dialog, + * instead of just destroying it, so that the + * dialog can do some housekeeping, such as remember + * its position. + */ + + GdkEventAny event; + event.type = GDK_DELETE; + event.window = dlg->window; + event.send_event = TRUE; + + if (event.window) + g_object_ref(G_OBJECT(event.window)); + + gtk_main_do_event ((GdkEvent*)&event); + + if (event.window) + g_object_unref(G_OBJECT(event.window)); +} + +void +Dialog::_defocus() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + + if (desktop) { + Gtk::Widget *canvas = Glib::wrap(GTK_WIDGET(desktop->canvas)); + + // make sure the canvas window is present before giving it focus + Gtk::Window *toplevel_window = dynamic_cast(canvas->get_toplevel()); + if (toplevel_window) + toplevel_window->present(); + + canvas->grab_focus(); + } +} + +Inkscape::Selection* +Dialog::_getSelection() +{ + return sp_desktop_selection(SP_ACTIVE_DESKTOP); } } // namespace Dialog