diff options
| author | gustav_b <gustav_b@users.sourceforge.net> | 2007-08-29 21:27:07 +0000 |
|---|---|---|
| committer | gustav_b <gustav_b@users.sourceforge.net> | 2007-08-29 21:27:07 +0000 |
| commit | 731f2b5adbb6f9e9fc853a6506c695fd2fcec320 (patch) | |
| tree | 6e7775c500ffc41d1376d7496c9334840b0f065f /src/ui | |
| parent | Don't snap node handles to the parent path, plus a small string change (diff) | |
| download | inkscape-731f2b5adbb6f9e9fc853a6506c695fd2fcec320.tar.gz inkscape-731f2b5adbb6f9e9fc853a6506c695fd2fcec320.zip | |
Dockable dialogs patch applied
(https://sourceforge.net/tracker/?func=detail&atid=604308&aid=1688508&group_id=93438)
(bzr r3613)
Diffstat (limited to 'src/ui')
55 files changed, 2227 insertions, 266 deletions
diff --git a/src/ui/dialog/Makefile_insert b/src/ui/dialog/Makefile_insert index d3bb8b62c..6679e99de 100644 --- a/src/ui/dialog/Makefile_insert +++ b/src/ui/dialog/Makefile_insert @@ -10,12 +10,17 @@ ui_dialog_libuidialog_a_SOURCES = \ ui/dialog/dialog-manager.h \ ui/dialog/dialog.cpp \ ui/dialog/dialog.h \ + ui/dialog/behavior.h \ + ui/dialog/dock-behavior.h \ + ui/dialog/dock-behavior.cpp \ + ui/dialog/floating-behavior.h \ + ui/dialog/floating-behavior.cpp \ ui/dialog/align-and-distribute.cpp \ ui/dialog/align-and-distribute.h \ ui/dialog/document-metadata.cpp \ ui/dialog/document-metadata.h \ ui/dialog/document-properties.cpp \ - ui/dialog/document-properties.h \ + ui/dialog/document-properties.h \ ui/dialog/export.cpp \ ui/dialog/export.h \ ui/dialog/extension-editor.cpp \ diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 34fa910cc..924a98790 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -774,8 +774,8 @@ void on_selection_changed(Inkscape::Application *inkscape, Inkscape::Selection * -AlignAndDistribute::AlignAndDistribute() - : Dialog ("dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE), +AlignAndDistribute::AlignAndDistribute(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.align", SP_VERB_DIALOG_ALIGN_DISTRIBUTE), randomize_bbox(NR::Nothing()), _alignFrame(_("Align")), _distributeFrame(_("Distribute")), diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h index 6d22071f3..0559a11e9 100644 --- a/src/ui/dialog/align-and-distribute.h +++ b/src/ui/dialog/align-and-distribute.h @@ -46,10 +46,11 @@ class Action; class AlignAndDistribute : public Dialog { public: - AlignAndDistribute(); + AlignAndDistribute(Behavior::BehaviorFactory behavior_factory); virtual ~AlignAndDistribute(); - static AlignAndDistribute *create() { return new AlignAndDistribute(); } + static AlignAndDistribute *create(Behavior::BehaviorFactory behavior_factory) + { return new AlignAndDistribute(behavior_factory); } enum AlignTarget { LAST=0, FIRST, BIGGEST, SMALLEST, PAGE, DRAWING, SELECTION }; diff --git a/src/ui/dialog/behavior.h b/src/ui/dialog/behavior.h new file mode 100644 index 000000000..b7455bbe5 --- /dev/null +++ b/src/ui/dialog/behavior.h @@ -0,0 +1,108 @@ +/** + * \brief Dialog behavior interface + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_DIALOG_BEHAVIOR_H +#define INKSCAPE_UI_DIALOG_BEHAVIOR_H + +#include <gtkmm/button.h> +#include <gtkmm/box.h> + +class SPDesktop; + +namespace Inkscape { +namespace UI { +namespace Dialog { + +class Dialog; + +namespace Behavior { + +class Behavior; + +typedef Behavior *(*BehaviorFactory)(Dialog& dialog); + +template <typename T> +Behavior *create(Dialog& dialog) +{ + return T::create(dialog); +} + + +class Behavior { + +public: + virtual ~Behavior() { } + + /** Gtk::Dialog methods */ + virtual operator Gtk::Widget&() =0; + virtual GtkWidget *gobj() =0; + virtual void present() =0; + virtual Gtk::VBox *get_vbox() =0; + virtual void show() =0; + virtual void hide() =0; + virtual void show_all_children() =0; + virtual void resize(int width, int height) =0; + virtual void move(int x, int y) =0; + virtual void set_position(Gtk::WindowPosition) =0; + virtual void set_size_request(int width, int height) =0; + virtual void size_request(Gtk::Requisition& requisition) =0; + virtual void get_position(int& x, int& y) =0; + virtual void get_size(int& width, int& height) =0; + virtual void set_title(Glib::ustring title) =0; + virtual void set_response_sensitive(int response_id, bool setting) =0; + virtual void set_sensitive(bool sensitive) =0; + virtual Gtk::Button *add_button(const Glib::ustring& button_text, int response_id) =0; + virtual Gtk::Button *add_button(const Gtk::StockID& stock_id, int response_id) =0; + virtual void set_default_response(int response_id) =0; + + /** Gtk::Dialog signal proxies */ + virtual Glib::SignalProxy0<void> signal_show() =0; + virtual Glib::SignalProxy0<void> signal_hide() =0; + virtual Glib::SignalProxy1<bool, GdkEventAny *> signal_delete_event() =0; + virtual Glib::SignalProxy1<void, int> signal_response() =0; + + /** Custom signal handlers */ + virtual void onHideF12() =0; + virtual void onShowF12() =0; + virtual void onShutdown() =0; + virtual void onDesktopActivated(SPDesktop *desktop) =0; + +protected: + Behavior(Dialog& dialog) + : _dialog (dialog) + { } + + Dialog& _dialog; //< reference to the owner + +private: + Behavior(); // no constructor without params + Behavior(const Behavior&); // no copy + Behavior& operator=(const Behavior&); // no assign +}; + +} // namespace Behavior +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + + +#endif //INKSCAPE_UI_DIALOG_BEHAVIOR_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index 23c64f1d5..e5d326efe 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -2,11 +2,12 @@ * \brief Object for managing a set of dialogs, including their signals and * construction/caching/destruction of them. * - * Author: + * Authors: * Bryce W. Harrington <bryce@bryceharrington.org> * Jon Phillips <jon@rejon.org> + * Gustav Broberg <broberg@kth.se> * - * Copyright (C) 2004, 2005 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -37,7 +38,12 @@ #include "ui/dialog/undo-history.h" #include "ui/dialog/xml-editor.h" +#include "dialogs/layers-panel.h" #include "dialogs/tiledialog.h" +#include "dialogs/iconpreview.h" + +#include "ui/dialog/floating-behavior.h" +#include "ui/dialog/dock-behavior.h" namespace Inkscape { namespace UI { @@ -45,8 +51,8 @@ namespace Dialog { namespace { -template <typename T> -Dialog *create() { return T::create(); } +template <typename T, typename B> +inline Dialog *create() { return T::create(&B::create); } } @@ -71,26 +77,63 @@ Dialog *create() { return T::create(); } * */ DialogManager::DialogManager() { - registerFactory("AlignAndDistribute", &create<AlignAndDistribute>); - registerFactory("DocumentMetadata", &create<DocumentMetadata>); - registerFactory("DocumentProperties", &create<DocumentProperties>); - registerFactory("Export", &create<Export>); - registerFactory("ExtensionEditor", &create<ExtensionEditor>); - registerFactory("FillAndStroke", &create<FillAndStroke>); - registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog>); - registerFactory("Find", &create<Find>); - registerFactory("InkscapePreferences", &create<InkscapePreferences>); - registerFactory("LayerEditor", &create<LayerEditor>); - registerFactory("LivePathEffect", &create<LivePathEffectEditor>); - registerFactory("Memory", &create<Memory>); - registerFactory("Messages", &create<Messages>); - registerFactory("Script", &create<ScriptDialog>); - registerFactory("TextProperties", &create<TextProperties>); - registerFactory("TileDialog", &create<TileDialog>); - registerFactory("Trace", &create<TraceDialog>); - registerFactory("Transformation", &create<Transformation>); - registerFactory("UndoHistory", &create<UndoHistory>); - registerFactory("XmlEditor", &create<XmlEditor>); + + using namespace Behavior; + using namespace Inkscape::UI::Dialogs; // temporary + + int dialogs_type = prefs_get_int_attribute_limited ("options.dialogtype", "value", DOCK, 0, 1); + + if (dialogs_type == FLOATING) { + + registerFactory("AlignAndDistribute", &create<AlignAndDistribute, FloatingBehavior>); + registerFactory("DocumentMetadata", &create<DocumentMetadata, FloatingBehavior>); + registerFactory("DocumentProperties", &create<DocumentProperties, FloatingBehavior>); + registerFactory("Export", &create<Export, FloatingBehavior>); + registerFactory("ExtensionEditor", &create<ExtensionEditor, FloatingBehavior>); + registerFactory("FillAndStroke", &create<FillAndStroke, FloatingBehavior>); + registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog, FloatingBehavior>); + registerFactory("Find", &create<Find, FloatingBehavior>); + registerFactory("IconPreviewPanel", &create<IconPreviewPanel, FloatingBehavior>); + registerFactory("InkscapePreferences", &create<InkscapePreferences, FloatingBehavior>); + registerFactory("LayerEditor", &create<LayerEditor, FloatingBehavior>); + registerFactory("LayersPanel", &create<LayersPanel, FloatingBehavior>); + registerFactory("LivePathEffect", &create<LivePathEffectEditor, FloatingBehavior>); + registerFactory("Memory", &create<Memory, FloatingBehavior>); + registerFactory("Messages", &create<Messages, FloatingBehavior>); + registerFactory("Script", &create<ScriptDialog, FloatingBehavior>); + registerFactory("TextProperties", &create<TextProperties, FloatingBehavior>); + registerFactory("TileDialog", &create<TileDialog, FloatingBehavior>); + registerFactory("Trace", &create<TraceDialog, FloatingBehavior>); + registerFactory("Transformation", &create<Transformation, FloatingBehavior>); + registerFactory("UndoHistory", &create<UndoHistory, FloatingBehavior>); + registerFactory("XmlEditor", &create<XmlEditor, FloatingBehavior>); + + } else { + + registerFactory("AlignAndDistribute", &create<AlignAndDistribute, DockBehavior>); + registerFactory("DocumentMetadata", &create<DocumentMetadata, DockBehavior>); + registerFactory("DocumentProperties", &create<DocumentProperties, DockBehavior>); + registerFactory("Export", &create<Export, DockBehavior>); + registerFactory("ExtensionEditor", &create<ExtensionEditor, DockBehavior>); + registerFactory("FillAndStroke", &create<FillAndStroke, DockBehavior>); + registerFactory("FilterEffectsDialog", &create<FilterEffectsDialog, DockBehavior>); + registerFactory("Find", &create<Find, DockBehavior>); + registerFactory("IconPreviewPanel", &create<IconPreviewPanel, DockBehavior>); + registerFactory("InkscapePreferences", &create<InkscapePreferences, DockBehavior>); + registerFactory("LayerEditor", &create<LayerEditor, DockBehavior>); + registerFactory("LayersPanel", &create<LayersPanel, DockBehavior>); + registerFactory("LivePathEffect", &create<LivePathEffectEditor, DockBehavior>); + registerFactory("Memory", &create<Memory, DockBehavior>); + registerFactory("Messages", &create<Messages, DockBehavior>); + registerFactory("Script", &create<ScriptDialog, DockBehavior>); + registerFactory("TextProperties", &create<TextProperties, DockBehavior>); + registerFactory("TileDialog", &create<TileDialog, DockBehavior>); + registerFactory("Trace", &create<TraceDialog, DockBehavior>); + registerFactory("Transformation", &create<Transformation, DockBehavior>); + registerFactory("UndoHistory", &create<UndoHistory, DockBehavior>); + registerFactory("XmlEditor", &create<XmlEditor, DockBehavior>); + + } } DialogManager::~DialogManager() { @@ -163,7 +206,6 @@ void DialogManager::showDialog(GQuark name) { Dialog *dialog=getDialog(name); if (dialog) { dialog->present(); - dialog->read_geometry(); } } diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index ac147d656..16124d9f5 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -2,12 +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 <bryce@bryceharrington.org> * buliabyak@gmail.com * Johan Engelen <j.b.c.engelen@ewi.utwente.nl> + * Gustav Broberg <broberg@kth.se> * - * Copyright (C) 2004-2007 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -32,23 +33,13 @@ #include "interface.h" #include "verbs.h" - #define MIN_ONSCREEN_DISTANCE 50 - namespace Inkscape { namespace UI { namespace Dialog { -static gboolean -sp_retransientize_again (gpointer dlgPtr) -{ - Dialog *dlg = (Dialog *)dlgPtr; - dlg->retransientize_suppress = false; - return FALSE; // so that it is only called once -} - static void sp_retransientize (Inkscape::Application *inkscape, SPDesktop *desktop, gpointer dlgPtr) { @@ -63,13 +54,6 @@ sp_dialog_shutdown (GtkObject *object, gpointer dlgPtr) dlg->onShutdown(); } -void -Dialog::present() -{ - _user_hidden = false; - Gtk::Dialog::present(); -} - void Dialog::save_geometry() { @@ -78,7 +62,7 @@ Dialog::save_geometry() get_position(x, y); get_size(w, h); -// g_print ("write %d %d %d %d\n", x, y, w, h); + // g_print ("write %d %d %d %d\n", x, y, w, h); if (x<0) x=0; if (y<0) y=0; @@ -87,8 +71,27 @@ Dialog::save_geometry() prefs_set_int_attribute (_prefs_path, "y", y); prefs_set_int_attribute (_prefs_path, "w", w); prefs_set_int_attribute (_prefs_path, "h", h); + } +void hideCallback(GtkObject *object, gpointer dlgPtr) +{ + g_return_if_fail( dlgPtr != NULL ); + + Dialog *dlg = (Dialog *)dlgPtr; + dlg->onHideF12(); +} + +void unhideCallback(GtkObject *object, gpointer dlgPtr) +{ + g_return_if_fail( dlgPtr != NULL ); + + Dialog *dlg = (Dialog *)dlgPtr; + dlg->onShowF12(); +} + + + void Dialog::read_geometry() { @@ -99,12 +102,12 @@ Dialog::read_geometry() 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); + // 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); + resize(w, h); } // If there are stored values for where the dialog should be @@ -116,22 +119,47 @@ Dialog::read_geometry() // ...otherwise just put it in the middle of the screen set_position(Gtk::WIN_POS_CENTER); } -} - -void hideCallback(GtkObject *object, gpointer dlgPtr) -{ - g_return_if_fail( dlgPtr != NULL ); - Dialog *dlg = (Dialog *)dlgPtr; - dlg->onHideF12(); } -void unhideCallback(GtkObject *object, gpointer dlgPtr) +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::show_all_children() { _behavior->show_all_children(); } +inline void Dialog::hide() { _behavior->hide(); } +inline void Dialog::show() { _behavior->show(); } +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<void> Dialog::signal_show () { return _behavior->signal_show(); } +Glib::SignalProxy0<void> Dialog::signal_hide () { return _behavior->signal_hide(); } +Glib::SignalProxy1<void, int> 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); } + +Dialog::Dialog(const char *prefs_path, int verb_num, const char *apply_label) { - g_return_if_fail( dlgPtr != NULL ); - Dialog *dlg = (Dialog *)dlgPtr; - dlg->onShowF12(); } //===================================================================== @@ -146,34 +174,24 @@ 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) +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) { - 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()); + gchar title[500]; if (verb_num) - { - gchar title[500]; sp_ui_dialog_title_string (Inkscape::Verb::get(verb_num), title); - set_title(title); - } - gtk_signal_connect( GTK_OBJECT (dlg), "event", GTK_SIGNAL_FUNC(sp_dialog_event_handler), dlg ); + _title = title; + + _behavior = behavior_factory(*this); + + gtk_signal_connect( GTK_OBJECT (gobj()), "event", GTK_SIGNAL_FUNC(sp_dialog_event_handler), gobj() ); - _hiddenF12 = false; if (Inkscape::NSApplication::Application::getNewGui()) { _desktop_activated_connection = Inkscape::NSApplication::Editor::connectDesktopActivated (sigc::mem_fun (*this, &Dialog::onDesktopActivated)); @@ -183,23 +201,25 @@ Dialog::Dialog(const char *prefs_path, int verb_num, const char *apply_label) } 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 (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_key_press_event().connect(sigc::ptr_fun(&windowKeyPress)); + + 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); + } read_geometry(); present(); - sp_transientize(dlg); - retransientize_suppress = false; -} - -Dialog::Dialog(BaseObjectType *gobj) - : Gtk::Dialog(gobj) -{ } Dialog::~Dialog() @@ -213,10 +233,11 @@ Dialog::~Dialog() } save_geometry(); + delete _behavior; } -bool Dialog::windowKeyPress( GtkWidget *widget, GdkEventKey *event ) +bool Dialog::windowKeyPress(GdkEventKey *event) { unsigned int shortcut = 0; shortcut = get_group0_keyval (event) | @@ -226,6 +247,7 @@ bool Dialog::windowKeyPress( GtkWidget *widget, GdkEventKey *event ) SP_SHORTCUT_CONTROL_MASK : 0 ) | ( event->state & GDK_MOD1_MASK ? SP_SHORTCUT_ALT_MASK : 0 ); + return sp_shortcut_invoke( shortcut, SP_ACTIVE_DESKTOP ); } @@ -259,8 +281,7 @@ void Dialog::onHideF12() { _hiddenF12 = true; - save_geometry(); - hide(); + _behavior->onHideF12(); } void @@ -270,8 +291,7 @@ Dialog::onShowF12() return; if (_hiddenF12) { - show(); - read_geometry(); + _behavior->onShowF12(); } _hiddenF12 = false; @@ -282,61 +302,15 @@ Dialog::onShutdown() { save_geometry(); _user_hidden = true; + _behavior->onShutdown(); } void -Dialog::onDesktopActivated (SPDesktop *desktop) +Dialog::onDesktopActivated(SPDesktop *desktop) { - gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2); - -#ifdef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs - if (prefs_get_int_attribute ( "options.dialogsontopwin32", "value", 0)) - transient_policy = 2; - else - return; -#endif - - if (!transient_policy) - return; - - - - GtkWindow *dialog_win = GTK_WINDOW(gobj()); - - 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 - */ - - // g_warning("Retranzientize aborted! You're switching windows too fast!"); - return; - } - - 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); - } - } - - // we're done, allow next retransientizing not sooner than after 120 msec - gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) this); + _behavior->onDesktopActivated(desktop); } - Inkscape::Selection* Dialog::_getSelection() { @@ -352,20 +326,26 @@ 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)); } } // namespace Dialog diff --git a/src/ui/dialog/dialog.h b/src/ui/dialog/dialog.h index dd3cdaafe..7530b9a35 100644 --- a/src/ui/dialog/dialog.h +++ b/src/ui/dialog/dialog.h @@ -1,11 +1,13 @@ /** - * \brief Base class for dialogs in Inkscape. This class provides certain - * common behaviors and styles wanted of all dialogs in the application. + * \brief Base class for dialogs in Inkscape. This class provides certain common behaviors and + * styles wanted of all dialogs in the application. Fundamental parts of the dialog's + * behavior is controlled by a Dialog::Behavior subclass instance connected to the dialog. * * Author: * Bryce W. Harrington <bryce@bryceharrington.org> + * Gustav Broberg <broberg@kth.se> * - * Copyright (C) 2004, 2005 Authors + * Copyright (C) 2004--2007 Authors * * Released under GNU GPL. Read the file 'COPYING' for more information. */ @@ -16,6 +18,9 @@ #include <gtkmm/dialog.h> #include <gtkmm/tooltips.h> +#include "dock-behavior.h" +#include "floating-behavior.h" + namespace Inkscape { class Selection; } class SPDesktop; @@ -23,11 +28,15 @@ namespace Inkscape { namespace UI { namespace Dialog { -class Dialog : public Gtk::Dialog { +enum BehaviorType { FLOATING, DOCK }; + +class Dialog { public: - Dialog(BaseObjectType *gobj); // fixme: remove this - Dialog(const char *prefs_path, int verb_num = 0, const char *apply_label = NULL); + Dialog(const char *prefs_path = NULL, int verb_num = 0, const char *apply_label = NULL); + + Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path = NULL, + int verb_num = 0, const char *apply_label = NULL); virtual ~Dialog(); @@ -37,20 +46,50 @@ public: virtual void present(); /** Hide and show dialogs */ - virtual void onHideF12(); - virtual void onShowF12(); + virtual void onHideF12(); + virtual void onShowF12(); + + virtual operator Gtk::Widget&(); + virtual GtkWidget *gobj(); + virtual Gtk::VBox *get_vbox(); + virtual void show(); + virtual void hide(); + virtual void show_all_children(); + virtual void set_resizable(bool); + virtual void set_sensitive(bool sensitive=true); + virtual void set_default(Gtk::Widget&); + virtual void set_size_request(int, int); + virtual void size_request(Gtk::Requisition&); + virtual void get_position(int& x, int& y); + virtual void get_size(int& width, int& height); + virtual void resize(int width, int height); + virtual void move(int x, int y); + virtual void set_position(Gtk::WindowPosition position); + virtual void set_title(Glib::ustring title); + + virtual void set_response_sensitive(int response_id, bool setting); + virtual Glib::SignalProxy0<void> signal_show(); + virtual Glib::SignalProxy0<void> signal_hide(); + virtual Glib::SignalProxy1<void, int> signal_response(); + + virtual Gtk::Button* add_button (const Glib::ustring& button_text, int response_id); + virtual Gtk::Button* add_button (const Gtk::StockID& stock_id, int response_id); + + virtual void set_default_response(int response_id); - bool _hiddenF12; bool _user_hidden; // when it is closed by the user, to prevent repopping on f12 + bool _hiddenF12; void read_geometry(); void save_geometry(); - const char *_prefs_path; - bool retransientize_suppress; // when true, do not retransientize (prevents races when switching new windows too fast) protected: + const char *_prefs_path; + int _verb_num; + Glib::ustring _title; + const char *_apply_label; /** * Tooltips object for all descendants to use @@ -62,7 +101,7 @@ protected: virtual void _apply(); virtual void _close(); - static bool windowKeyPress( GtkWidget *widget, GdkEventKey *event ); + static bool windowKeyPress(GdkEventKey *event); Inkscape::Selection* _getSelection(); @@ -72,10 +111,15 @@ protected: sigc::connection _shutdown_connection; private: + Behavior::Behavior* _behavior; + Dialog(); // no constructor without params Dialog(Dialog const &d); // no copy Dialog& operator=(Dialog const &d); // no assign + + friend class Behavior::FloatingBehavior; + friend class Behavior::DockBehavior; }; } // namespace Dialog diff --git a/src/ui/dialog/dock-behavior.cpp b/src/ui/dialog/dock-behavior.cpp new file mode 100644 index 000000000..188fc6fb1 --- /dev/null +++ b/src/ui/dialog/dock-behavior.cpp @@ -0,0 +1,308 @@ +/** + * \brief A dockable dialog implementation. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include "dock-behavior.h" +#include "inkscape.h" +#include "desktop.h" +#include "interface.h" +#include "widgets/icon.h" +#include "ui/widget/dock.h" +#include "verbs.h" +#include "dialog.h" +#include "prefs-utils.h" + +#include <gtkmm/invisible.h> +#include <gtkmm/label.h> +#include <gtkmm/stock.h> + +#include <gtk/gtk.h> + +namespace Inkscape { +namespace UI { +namespace Dialog { +namespace Behavior { + + +DockBehavior::DockBehavior(Dialog& dialog) : + Behavior(dialog), + _dock_item(*SP_ACTIVE_DESKTOP->getDock(), + Inkscape::Verb::get(dialog._verb_num)->get_id(), dialog._title.c_str(), + (Inkscape::Verb::get(dialog._verb_num)->get_image() ? + Inkscape::Verb::get(dialog._verb_num)->get_image() : ""), + static_cast<Widget::DockItem::State>( + prefs_get_int_attribute (_dialog._prefs_path, "state", + UI::Widget::DockItem::DOCKED_STATE))) +{ + // Connect signals + _signal_hide_connection = signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onHide)); + signal_response().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::on_response)); + signal_drag_end().connect(sigc::mem_fun(*this, &Inkscape::UI::Dialog::Behavior::DockBehavior::_onDragEnd)); +} + +DockBehavior::~DockBehavior() +{ +} + + +Behavior * +DockBehavior::create(Dialog& dialog) +{ + return new DockBehavior(dialog); +} + + +DockBehavior::operator Gtk::Widget&() +{ + return _dock_item.getWidget(); +} + +GtkWidget * +DockBehavior::gobj() +{ + return _dock_item.gobj(); +} + +Gtk::VBox * +DockBehavior::get_vbox() +{ + return _dock_item.get_vbox(); +} + +void +DockBehavior::present() +{ + bool was_attached = _dock_item.isAttached(); + + _dock_item.present(); + + if (!was_attached) + _dialog.read_geometry(); +} + +void +DockBehavior::hide() +{ + _signal_hide_connection.block(); + _dock_item.hide(); + _signal_hide_connection.unblock(); +} + +void +DockBehavior::show() +{ + _dock_item.show(); +} + +void +DockBehavior::show_all_children() +{ + get_vbox()->show_all_children(); +} + +void +DockBehavior::get_position(int& x, int& y) +{ + _dock_item.get_position(x, y); +} + +void +DockBehavior::get_size(int& width, int& height) +{ + _dock_item.get_size(width, height); +} + +void +DockBehavior::resize(int width, int height) +{ + _dock_item.resize(width, height); +} + +void +DockBehavior::move(int x, int y) +{ + _dock_item.move(x, y); +} + +void +DockBehavior::set_position(Gtk::WindowPosition position) +{ + _dock_item.set_position(position); +} + +void +DockBehavior::set_size_request(int width, int height) +{ + _dock_item.set_size_request(width, height); +} + +void +DockBehavior::size_request(Gtk::Requisition& requisition) +{ + _dock_item.size_request(requisition); +} + +void +DockBehavior::set_title(Glib::ustring title) +{ + _dock_item.set_title(title); +} + +void +DockBehavior::set_response_sensitive(int response_id, bool setting) +{ + if (_response_map[response_id]) + _response_map[response_id]->set_sensitive(setting); +} + +void +DockBehavior::set_sensitive(bool sensitive) +{ + get_vbox()->set_sensitive(); +} + +Gtk::Button * +DockBehavior::add_button(const Glib::ustring& button_text, int response_id) +{ + Gtk::Button *button = new Gtk::Button(button_text); + _addButton(button, response_id); + return button; +} + +Gtk::Button * +DockBehavior::add_button(const Gtk::StockID& stock_id, int response_id) +{ + Gtk::Button *button = new Gtk::Button(stock_id); + _addButton(button, response_id); + return button; +} + +void +DockBehavior::_addButton(Gtk::Button *button, int response_id) +{ + _dock_item.addButton(button, response_id); + + if (response_id != 0) { + + /* Pass the signal_clicked signals onto a our own signal handler that can re-emit them as + * signal_response signals + */ + button->signal_clicked().connect( + sigc::bind<int>(sigc::mem_fun(*this, + &Inkscape::UI::Dialog::Behavior::DockBehavior::_onResponse), + response_id)); + + _response_map[response_id] = button; + } +} + +void +DockBehavior::set_default_response(int response_id) +{ + ResponseMap::iterator widget_found; + widget_found = _response_map.find(response_id); + + if (widget_found != _response_map.end()) { + widget_found->second->activate(); + widget_found->second->property_can_default() = true; + widget_found->second->grab_default(); + } +} + + +void +DockBehavior::_onHide() +{ + _dialog.save_geometry(); + prefs_set_int_attribute (_dialog._prefs_path, "state", _dock_item.getPrevState()); +} + +void +DockBehavior::_onDragEnd(bool) +{ + Widget::DockItem::State prev_state = _dock_item.getPrevState(), state = _dock_item.getState(); + + if (prev_state != state) { + prefs_set_int_attribute (_dialog._prefs_path, "state", state); + } +} + +void +DockBehavior::_onResponse(int response_id) +{ + g_signal_emit_by_name (_dock_item.gobj(), "signal_response", response_id); +} + +void +DockBehavior::onHideF12() +{ + _dialog.save_geometry(); + hide(); +} + +void +DockBehavior::onShowF12() +{ + present(); +} + +void +DockBehavior::onShutdown() +{ + prefs_set_int_attribute (_dialog._prefs_path, "state", _dock_item.getPrevState()); +} + +void +DockBehavior::onDesktopActivated(SPDesktop *desktop) +{ +} + + +/* Signal wrappers */ + +Glib::SignalProxy0<void> +DockBehavior::signal_show() { return _dock_item.signal_show(); } + +Glib::SignalProxy0<void> +DockBehavior::signal_hide() { return _dock_item.signal_hide(); } + +Glib::SignalProxy1<void, int> +DockBehavior::signal_response() { return _dock_item.signal_response(); } + +Glib::SignalProxy1<bool, GdkEventAny *> +DockBehavior::signal_delete_event() { return _dock_item.signal_delete_event(); } + +Glib::SignalProxy0<void> +DockBehavior::signal_drag_begin() { return _dock_item.signal_drag_begin(); } + +Glib::SignalProxy1<void, bool> +DockBehavior::signal_drag_end() { return _dock_item.signal_drag_end(); } + + +} // namespace Behavior +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/dock-behavior.h b/src/ui/dialog/dock-behavior.h new file mode 100644 index 000000000..75bd14be4 --- /dev/null +++ b/src/ui/dialog/dock-behavior.h @@ -0,0 +1,119 @@ +/** + * \brief A dockable dialog implementation. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + + +#ifndef INKSCAPE_UI_DIALOG_DOCK_BEHAVIOR_H +#define INKSCAPE_UI_DIALOG_DOCK_BEHAVIOR_H + +#include <map> + +#include <gtkmm/buttonbox.h> +#include <gtkmm/frame.h> +#include <gtkmm/paned.h> + +#include "ui/widget/dock-item.h" + +#include "libgdl/libgdl.h" + +#include "behavior.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { +namespace Behavior { + +class DockBehavior : public Behavior { + +public: + static Behavior *create(Dialog& dialog); + + ~DockBehavior(); + + /** Gtk::Dialog methods */ + operator Gtk::Widget&(); + GtkWidget *gobj(); + void present(); + Gtk::VBox *get_vbox(); + void show(); + void hide(); + void show_all_children(); + void resize(int width, int height); + void move(int x, int y); + void set_position(Gtk::WindowPosition); + void set_size_request(int width, int height); + void size_request(Gtk::Requisition& requisition); + void get_position(int& x, int& y); + void get_size(int& width, int& height); + void set_title(Glib::ustring title); + void set_response_sensitive(int response_id, bool setting); + void set_sensitive(bool sensitive); + Gtk::Button *add_button(const Glib::ustring& button_text, int response_id); + Gtk::Button *add_button(const Gtk::StockID& stock_id, int response_id); + void set_default_response(int response_id); + + /** Gtk::Dialog signal proxies */ + Glib::SignalProxy0<void> signal_show(); + Glib::SignalProxy0<void> signal_hide(); + Glib::SignalProxy1<bool, GdkEventAny *> signal_delete_event(); + Glib::SignalProxy0<void> signal_drag_begin(); + Glib::SignalProxy1<void, bool> signal_drag_end(); + Glib::SignalProxy1<void, int> signal_response(); + + /** Custom signal handlers */ + void onHideF12(); + void onShowF12(); + void onDesktopActivated(SPDesktop *desktop); + void onShutdown(); + +private: + Widget::DockItem _dock_item; + + DockBehavior(Dialog& dialog); + + /** A map to store which widget that emits a certain response signal */ + typedef std::map<int, Gtk::Widget *> ResponseMap; + ResponseMap _response_map; + + /** Internal helpers */ + void _addButton(Gtk::Button *button, int response_id); + Gtk::Paned *_getPaned(); //< gives the parent pane, if the dock item has one + void _requestHeight(int height); //< tries to resize the dock item to the requested hieght + + /** Internal signal handlers */ + void _onHide(); + bool _onDeleteEvent(GdkEventAny *event); + void _onResponse(int response_id); + void _onDragBegin(); + void _onDragEnd(bool cancelled); + bool _onKeyPress(GdkEventKey *event); + + sigc::connection _signal_hide_connection; + sigc::connection _signal_key_press_event_connection; + +}; + +} // namespace Behavior +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_DIALOG_DOCK_BEHAVIOR_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/document-metadata.cpp b/src/ui/dialog/document-metadata.cpp index a3e87b31b..ca2da205e 100644 --- a/src/ui/dialog/document-metadata.cpp +++ b/src/ui/dialog/document-metadata.cpp @@ -63,10 +63,10 @@ static Inkscape::XML::NodeEventVector const _repr_events = { DocumentMetadata* -DocumentMetadata::create() +DocumentMetadata::create(Behavior::BehaviorFactory behavior_factory) { if (_instance) return _instance; - _instance = new DocumentMetadata; + _instance = new DocumentMetadata(behavior_factory); _instance->init(); return _instance; } @@ -81,8 +81,8 @@ DocumentMetadata::destroy() } } -DocumentMetadata::DocumentMetadata() - : Dialog ("dialogs.documentmetadata", SP_VERB_DIALOG_METADATA), +DocumentMetadata::DocumentMetadata(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.documentmetadata", SP_VERB_DIALOG_METADATA), _page_metadata1(1, 1), _page_metadata2(1, 1), _prefs_path("dialogs.documentmetadata") { diff --git a/src/ui/dialog/document-metadata.h b/src/ui/dialog/document-metadata.h index c3cba2d34..478f9334e 100644 --- a/src/ui/dialog/document-metadata.h +++ b/src/ui/dialog/document-metadata.h @@ -40,7 +40,7 @@ typedef std::list<EntityEntry*> RDElist; class DocumentMetadata : public Inkscape::UI::Dialog::Dialog { public: void update(); - static DocumentMetadata *create(); + static DocumentMetadata *create(Behavior::BehaviorFactory behavior_factory); static void destroy(); sigc::connection _doc_replaced_connection; @@ -62,7 +62,7 @@ protected: Registry _wr; private: - DocumentMetadata(); + DocumentMetadata(Behavior::BehaviorFactory behavior_factory); virtual ~DocumentMetadata(); }; diff --git a/src/ui/dialog/document-properties.cpp b/src/ui/dialog/document-properties.cpp index 141a0c8cb..e2dc2c0b9 100644 --- a/src/ui/dialog/document-properties.cpp +++ b/src/ui/dialog/document-properties.cpp @@ -72,10 +72,10 @@ static Inkscape::XML::NodeEventVector const _repr_events = { DocumentProperties* -DocumentProperties::create() +DocumentProperties::create(Behavior::BehaviorFactory behavior_factory) { if (_instance) return _instance; - _instance = new DocumentProperties; + _instance = new DocumentProperties(behavior_factory); _instance->init(); return _instance; } @@ -90,8 +90,8 @@ DocumentProperties::destroy() } } -DocumentProperties::DocumentProperties() - : Dialog ("dialogs.documentoptions", SP_VERB_DIALOG_NAMEDVIEW), +DocumentProperties::DocumentProperties(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.documentoptions", SP_VERB_DIALOG_NAMEDVIEW), _page_page(1, 1), _page_guides(1, 1), _page_snap(1, 1), _page_grids(1, 1), _grids_button_new(_("_New"), _("Create new grid.")), diff --git a/src/ui/dialog/document-properties.h b/src/ui/dialog/document-properties.h index 846d95341..aa6e9c03b 100644 --- a/src/ui/dialog/document-properties.h +++ b/src/ui/dialog/document-properties.h @@ -38,7 +38,7 @@ namespace Inkscape { class DocumentProperties : public Inkscape::UI::Dialog::Dialog { public: void update(); - static DocumentProperties *create(); + static DocumentProperties *create(Behavior::BehaviorFactory behavior_factory); static void destroy(); sigc::connection _doc_replaced_connection; @@ -88,7 +88,7 @@ protected: Registry _wr; private: - DocumentProperties(); + DocumentProperties(Behavior::BehaviorFactory behavior_factory); virtual ~DocumentProperties(); // callback methods for buttons on grids page. diff --git a/src/ui/dialog/export.cpp b/src/ui/dialog/export.cpp index d9ea2d25d..4e4efafb5 100644 --- a/src/ui/dialog/export.cpp +++ b/src/ui/dialog/export.cpp @@ -20,8 +20,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -Export::Export() - : Dialog ("dialogs.export", SP_VERB_FILE_EXPORT), +Export::Export(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.export", SP_VERB_FILE_EXPORT), _page_export(1, 1) { // Top level vbox diff --git a/src/ui/dialog/export.h b/src/ui/dialog/export.h index 567eae10d..c47c7c8cc 100644 --- a/src/ui/dialog/export.h +++ b/src/ui/dialog/export.h @@ -26,10 +26,11 @@ namespace Dialog { class Export : public Dialog { public: - Export(); + Export(Behavior::BehaviorFactory behavior_factory); virtual ~Export(); - static Export *create() { return new Export(); } + static Export *create(Behavior::BehaviorFactory behavior_factory) + { return new Export(behavior_factory); } protected: Gtk::Notebook _notebook; diff --git a/src/ui/dialog/extension-editor.cpp b/src/ui/dialog/extension-editor.cpp index 5f6386046..3a62cb144 100644 --- a/src/ui/dialog/extension-editor.cpp +++ b/src/ui/dialog/extension-editor.cpp @@ -42,8 +42,8 @@ namespace Dialog { about the selected extension. A handler is set up so that when a new extension is selected, the notebooks are changed appropriately. */ -ExtensionEditor::ExtensionEditor() - : Dialog ("dialogs.extensioneditor", SP_VERB_DIALOG_EXTENSIONEDITOR) +ExtensionEditor::ExtensionEditor(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.extensioneditor", SP_VERB_DIALOG_EXTENSIONEDITOR) { _notebook_info.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); _notebook_help.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); diff --git a/src/ui/dialog/extension-editor.h b/src/ui/dialog/extension-editor.h index b6c331eae..284a3651d 100644 --- a/src/ui/dialog/extension-editor.h +++ b/src/ui/dialog/extension-editor.h @@ -31,10 +31,11 @@ namespace Dialog { class ExtensionEditor : public Dialog { public: - ExtensionEditor(); + ExtensionEditor(Behavior::BehaviorFactory behavior_factory); virtual ~ExtensionEditor(); - static ExtensionEditor *create() { return new ExtensionEditor(); } + static ExtensionEditor *create(Behavior::BehaviorFactory behavior_factory) + { return new ExtensionEditor(behavior_factory); } static void show_help (gchar const * extension_id); diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 8cf6bcfb4..ad9a9f031 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -55,8 +55,8 @@ void on_selection_modified(Inkscape::Application *inkscape, } -FillAndStroke::FillAndStroke() - : Dialog ("dialogs.fillstroke", SP_VERB_DIALOG_FILL_STROKE), +FillAndStroke::FillAndStroke(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.fillstroke", SP_VERB_DIALOG_FILL_STROKE), _page_fill(1, 1, true, true), _page_stroke_paint(1, 1, true, true), _page_stroke_style(1, 1, true, true), diff --git a/src/ui/dialog/fill-and-stroke.h b/src/ui/dialog/fill-and-stroke.h index b573161d9..87d5181db 100644 --- a/src/ui/dialog/fill-and-stroke.h +++ b/src/ui/dialog/fill-and-stroke.h @@ -33,10 +33,11 @@ namespace Dialog { class FillAndStroke : public Dialog { public: - FillAndStroke(); + FillAndStroke(Behavior::BehaviorFactory behavior_factory); virtual ~FillAndStroke(); - static FillAndStroke *create() { return new FillAndStroke(); } + static FillAndStroke *create(Behavior::BehaviorFactory behavior_factory) + { return new FillAndStroke(behavior_factory); } void selectionChanged(Inkscape::Application *inkscape, Inkscape::Selection *selection); diff --git a/src/ui/dialog/filter-effects-dialog.cpp b/src/ui/dialog/filter-effects-dialog.cpp index 3fa7d73d4..3bffb1285 100644 --- a/src/ui/dialog/filter-effects-dialog.cpp +++ b/src/ui/dialog/filter-effects-dialog.cpp @@ -1166,7 +1166,8 @@ void FilterEffectsDialog::FilterModifier::duplicate_filter() void FilterEffectsDialog::FilterModifier::rename_filter() { SPFilter* filter = get_selected_filter(); - Gtk::Dialog m("", _dialog, true); + Gtk::Window *window = dynamic_cast<Gtk::Window *>(_dialog.get_vbox()->get_ancestor(GTK_TYPE_WINDOW)); + Gtk::Dialog m("", *window, true); m.add_button(Gtk::Stock::CANCEL, Gtk::RESPONSE_CANCEL); m.add_button(_("_Rename"), Gtk::RESPONSE_OK); m.set_default_response(Gtk::RESPONSE_OK); @@ -1843,8 +1844,8 @@ int FilterEffectsDialog::PrimitiveList::primitive_count() const /*** FilterEffectsDialog ***/ -FilterEffectsDialog::FilterEffectsDialog() - : Dialog ("dialogs.filtereffects", SP_VERB_DIALOG_FILTER_EFFECTS), +FilterEffectsDialog::FilterEffectsDialog(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.filtereffects", SP_VERB_DIALOG_FILTER_EFFECTS), _filter_modifier(*this), _primitive_list(*this), _add_primitive_type(FPConverter), diff --git a/src/ui/dialog/filter-effects-dialog.h b/src/ui/dialog/filter-effects-dialog.h index 1a4285dd9..743ce0239 100644 --- a/src/ui/dialog/filter-effects-dialog.h +++ b/src/ui/dialog/filter-effects-dialog.h @@ -40,11 +40,14 @@ class DualSpinButton; class MultiSpinButton; class FilterEffectsDialog : public Dialog { public: + + FilterEffectsDialog(Behavior::BehaviorFactory behavior_factory); ~FilterEffectsDialog(); - void set_attrs_locked(const bool); + static FilterEffectsDialog *create(Behavior::BehaviorFactory behavior_factory) + { return new FilterEffectsDialog(behavior_factory); } - static FilterEffectsDialog *create() { return new FilterEffectsDialog(); } + void set_attrs_locked(const bool); private: class SignalObserver; diff --git a/src/ui/dialog/find.cpp b/src/ui/dialog/find.cpp index 22fa608bf..0a0538c30 100644 --- a/src/ui/dialog/find.cpp +++ b/src/ui/dialog/find.cpp @@ -56,8 +56,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -Find::Find() - : Dialog ("dialogs.find", SP_VERB_DIALOG_FIND), +Find::Find(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.find", SP_VERB_DIALOG_FIND), _entry_text(_("_Text: "), _("Find objects by their text content (exact or partial match)")), _entry_id(_("_ID: "), _("Find objects by the value of the id attribute (exact or partial match)")), _entry_style(_("_Style: "), _("Find objects by the value of the style attribute (exact or partial match)")), diff --git a/src/ui/dialog/find.h b/src/ui/dialog/find.h index 9594669fa..fb52b2c8e 100644 --- a/src/ui/dialog/find.h +++ b/src/ui/dialog/find.h @@ -59,10 +59,11 @@ namespace Dialog { class Find : public Dialog { public: - Find(); + Find(Behavior::BehaviorFactory behavior_factory); virtual ~Find(); - static Find *create() { return new Find(); } + static Find *create(Behavior::BehaviorFactory behavior_factory) + { return new Find(behavior_factory); } protected: // Widgets: diff --git a/src/ui/dialog/floating-behavior.cpp b/src/ui/dialog/floating-behavior.cpp new file mode 100644 index 000000000..b6b6949da --- /dev/null +++ b/src/ui/dialog/floating-behavior.cpp @@ -0,0 +1,182 @@ +/** + * \brief A floating dialog implementation. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include <gtkmm/stock.h> +#include <gtk/gtk.h> + +#include "floating-behavior.h" +#include "dialog.h" + +#include "application/application.h" +#include "application/editor.h" +#include "inkscape.h" +#include "desktop.h" +#include "dialogs/dialog-events.h" +#include "interface.h" +#include "prefs-utils.h" +#include "verbs.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { +namespace Behavior { + +static gboolean +sp_retransientize_again (gpointer dlgPtr) +{ + Dialog *dlg = (Dialog *)dlgPtr; + dlg->retransientize_suppress = false; + return FALSE; // so that it is only called once +} + + +FloatingBehavior::FloatingBehavior(Dialog& dialog) : + Behavior(dialog), + _d (new Gtk::Dialog(_dialog._title)) +{ + hide(); + _d->set_has_separator(false); + + signal_response().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::on_response)); + _d->signal_delete_event().connect(sigc::mem_fun(_dialog, &Inkscape::UI::Dialog::Dialog::on_delete_event)); + + sp_transientize(GTK_WIDGET(_d->gobj())); + _dialog.retransientize_suppress = false; +} + +FloatingBehavior::~FloatingBehavior() +{ + delete _d; +} + +Behavior * +FloatingBehavior::create(Dialog& dialog) +{ + return new FloatingBehavior(dialog); +} + +inline FloatingBehavior::operator Gtk::Widget&() { return *_d; } +inline GtkWidget *FloatingBehavior::gobj() { return GTK_WIDGET(_d->gobj()); } +inline Gtk::VBox* FloatingBehavior::get_vbox() { return _d->get_vbox(); } +inline void FloatingBehavior::present() { _d->present(); } +inline void FloatingBehavior::hide() { _d->hide(); } +inline void FloatingBehavior::show() { _d->show(); } +inline void FloatingBehavior::show_all_children() { _d->show_all_children(); } +inline void FloatingBehavior::resize(int width, int height) { _d->resize(width, height); } +inline void FloatingBehavior::move(int x, int y) { _d->move(x, y); } +inline void FloatingBehavior::set_position(Gtk::WindowPosition position) { _d->set_position(position); } +inline void FloatingBehavior::set_size_request(int width, int height) { _d->set_size_request(width, height); } +inline void FloatingBehavior::size_request(Gtk::Requisition& requisition) { _d->size_request(requisition); } +inline void FloatingBehavior::get_position(int& x, int& y) { _d->get_position(x, y); } +inline void FloatingBehavior::get_size(int& width, int& height) { _d->get_size(width, height); } +inline void FloatingBehavior::set_title(Glib::ustring title) { _d->set_title(title); } +inline void FloatingBehavior::set_sensitive(bool sensitive) { _d->set_sensitive(sensitive); } + +void FloatingBehavior::set_response_sensitive(int response_id, bool setting) +{ _d->set_response_sensitive(response_id, setting); } + +Gtk::Button *FloatingBehavior::add_button(const Glib::ustring& button_text, int response_id) +{ return _d->add_button(button_text, response_id); } + +Gtk::Button *FloatingBehavior::add_button(const Gtk::StockID& stock_id, int response_id) +{ return _d->add_button(stock_id, response_id); } + +inline void FloatingBehavior::set_default_response(int response_id) { _d->set_default_response(response_id); } + +Glib::SignalProxy0<void> FloatingBehavior::signal_show() { return _d->signal_show(); } +Glib::SignalProxy0<void> FloatingBehavior::signal_hide() { return _d->signal_hide(); } +Glib::SignalProxy1<bool, GdkEventAny *> FloatingBehavior::signal_delete_event () { return _d->signal_delete_event(); } +Glib::SignalProxy1<void, int> FloatingBehavior::signal_response () { return _d->signal_response(); } + + +void +FloatingBehavior::onHideF12() +{ + _dialog.save_geometry(); + hide(); +} + +void +FloatingBehavior::onShowF12() +{ + show(); + _dialog.read_geometry(); +} + +void +FloatingBehavior::onShutdown() {} + +void +FloatingBehavior::onDesktopActivated (SPDesktop *desktop) +{ + gint transient_policy = prefs_get_int_attribute_limited ( "options.transientpolicy", "value", 1, 0, 2); + +#ifdef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs + if (prefs_get_int_attribute ( "options.dialogsontopwin32", "value", 0)) + transient_policy = 2; + else + return; +#endif + + if (!transient_policy) + return; + + GtkWindow *dialog_win = GTK_WINDOW(_d->gobj()); + + if (_dialog.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 + */ + + // g_warning("Retranzientize aborted! You're switching windows too fast!"); + return; + } + + if (dialog_win) + { + _dialog.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 && ! _dialog._hiddenF12 && !_dialog._user_hidden) { + // without this, a transient window not always emerges on top + gtk_window_present (dialog_win); + } + } + + // we're done, allow next retransientizing not sooner than after 120 msec + gtk_timeout_add (120, (GtkFunction) sp_retransientize_again, (gpointer) _d); +} + + +} // namespace Behavior +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/floating-behavior.h b/src/ui/dialog/floating-behavior.h new file mode 100644 index 000000000..354987dde --- /dev/null +++ b/src/ui/dialog/floating-behavior.h @@ -0,0 +1,88 @@ +/** + * \brief A floating dialog implementation. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + + +#ifndef INKSCAPE_UI_DIALOG_FLOATING_BEHAVIOR_H +#define INKSCAPE_UI_DIALOG_FLOATING_BEHAVIOR_H + +#include <gtkmm/dialog.h> +#include "behavior.h" + +namespace Inkscape { +namespace UI { +namespace Dialog { +namespace Behavior { + +class FloatingBehavior : public Behavior { + +public: + static Behavior *create(Dialog& dialog); + + ~FloatingBehavior(); + + /** Gtk::Dialog methods */ + operator Gtk::Widget&(); + GtkWidget *gobj(); + void present(); + Gtk::VBox *get_vbox(); + void show(); + void hide(); + void show_all_children(); + void resize(int width, int height); + void move(int x, int y); + void set_position(Gtk::WindowPosition); + void set_size_request(int width, int height); + void size_request(Gtk::Requisition& requisition); + void get_position(int& x, int& y); + void get_size(int& width, int& height); + void set_title(Glib::ustring title); + void set_response_sensitive(int response_id, bool setting); + void set_sensitive(bool sensitive); + Gtk::Button *add_button(const Glib::ustring& button_text, int response_id); + Gtk::Button *add_button(const Gtk::StockID& stock_id, int response_id); + void set_default_response(int response_id); + + /** Gtk::Dialog signal proxies */ + Glib::SignalProxy0<void> signal_show(); + Glib::SignalProxy0<void> signal_hide(); + Glib::SignalProxy1<bool, GdkEventAny *> signal_delete_event(); + Glib::SignalProxy1<void, int> signal_response(); + + /** Custom signal handlers */ + void onHideF12(); + void onShowF12(); + void onDesktopActivated(SPDesktop *desktop); + void onShutdown(); + +private: + FloatingBehavior(Dialog& dialog); + + Gtk::Dialog *_d; //< the actual dialog + +}; + +} // namespace Behavior +} // namespace Dialog +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_DIALOG_FLOATING_BEHAVIOR_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 744d4f555..138f36c29 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -42,8 +42,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -InkscapePreferences::InkscapePreferences() - : Dialog ("dialogs.preferences", SP_VERB_DIALOG_DISPLAY), +InkscapePreferences::InkscapePreferences(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.preferences", SP_VERB_DIALOG_DISPLAY), _max_dialog_width(0), _max_dialog_height(0), _current_page(0) @@ -429,6 +429,9 @@ void InkscapePreferences::initPageWindows() _win_save_geom_prefs.init ( _("Remember and use last window's geometry"), "options.savewindowgeometry", "value", 2, false, &_win_save_geom); _win_save_geom_off.init ( _("Don't save window geometry"), "options.savewindowgeometry", "value", 0, false, &_win_save_geom); + _win_dockable.init ( _("Dockable"), "options.dialogtype", "value", 1, true, 0); + _win_floating.init ( _("Floating"), "options.dialogtype", "value", 0, false, &_win_dockable); + _win_hide_task.init ( _("Dialogs are hidden in taskbar"), "options.dialogsskiptaskbar", "value", true); _win_zoom_resize.init ( _("Zoom when window is resized"), "options.stickyzoom", "value", false); _win_show_close.init ( _("Show close button on dialogs"), "dialogs", "showclose", false); @@ -449,6 +452,12 @@ void InkscapePreferences::initPageWindows() _page_windows.add_line( false, "", _win_save_geom, "", _("Save and restore window geometry for each document (saves geometry in the document)")); + _page_windows.add_group_header( _("Dialog behavior (requires restart):")); + _page_windows.add_line( true, "", _win_dockable, "", + _("Dockable")); + _page_windows.add_line( true, "", _win_floating, "", + _("Floating")); + _page_windows.add_group_header( _("Dialogs on top:")); #ifndef WIN32 // FIXME: Temporary Win32 special code to enable transient dialogs _page_windows.add_line( true, "", _win_ontop_none, "", diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 48cec9341..6798de21d 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -76,7 +76,9 @@ class InkscapePreferences : public Dialog { public: virtual ~InkscapePreferences(); - static InkscapePreferences *create() {return new InkscapePreferences(); } + static InkscapePreferences *create(Behavior::BehaviorFactory behavior_factory) + { return new InkscapePreferences(behavior_factory); } + void present(); protected: @@ -123,6 +125,7 @@ protected: PrefSpinButton _t_pencil_tolerance; + PrefRadioButton _win_dockable, _win_floating; PrefRadioButton _win_ontop_none, _win_ontop_normal, _win_ontop_agressive; PrefRadioButton _win_save_geom_off, _win_save_geom, _win_save_geom_prefs; PrefCheckButton _win_hide_task, _win_zoom_resize , _win_show_close; @@ -191,7 +194,7 @@ protected: void initPageMisc(); private: - InkscapePreferences(); + InkscapePreferences(Behavior::BehaviorFactory behavior_factory); InkscapePreferences(InkscapePreferences const &d); InkscapePreferences operator=(InkscapePreferences const &d); }; diff --git a/src/ui/dialog/layer-editor.cpp b/src/ui/dialog/layer-editor.cpp index 79c4fbcc2..cb4b8a0b4 100644 --- a/src/ui/dialog/layer-editor.cpp +++ b/src/ui/dialog/layer-editor.cpp @@ -20,8 +20,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -LayerEditor::LayerEditor() - : Dialog ("dialogs.layers", SP_VERB_NONE /*FIXME*/) +LayerEditor::LayerEditor(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.layers", SP_VERB_NONE /*FIXME*/) { // TODO: Insert widgets diff --git a/src/ui/dialog/layer-editor.h b/src/ui/dialog/layer-editor.h index 3d68a7fcf..3c25c7bc0 100644 --- a/src/ui/dialog/layer-editor.h +++ b/src/ui/dialog/layer-editor.h @@ -22,10 +22,11 @@ namespace Dialog { class LayerEditor : public Dialog { public: - LayerEditor(); + LayerEditor(Behavior::BehaviorFactory behavior_factory); virtual ~LayerEditor(); - static LayerEditor *create() { return new LayerEditor(); } + static LayerEditor *create(Behavior::BehaviorFactory behavior_factory) + { return new LayerEditor(behavior_factory); } protected: diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index 5f765b420..ee010eeca 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -66,8 +66,8 @@ static void lpeeditor_desktop_change(Inkscape::Application*, SPDesktop* desktop, /*#######################
* LivePathEffectEditor
*/
-LivePathEffectEditor::LivePathEffectEditor()
- : Dialog ("dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT),
+LivePathEffectEditor::LivePathEffectEditor(Behavior::BehaviorFactory behavior_factory)
+ : Dialog (behavior_factory, "dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT),
combo_effecttype(Inkscape::LivePathEffect::LPETypeConverter),
button_apply(_("_Apply"), _("Apply chosen effect to selection")),
button_remove(_("_Remove"), _("Remove effect from selection")),
diff --git a/src/ui/dialog/livepatheffect-editor.h b/src/ui/dialog/livepatheffect-editor.h index 5476f8a1d..d99177fdd 100644 --- a/src/ui/dialog/livepatheffect-editor.h +++ b/src/ui/dialog/livepatheffect-editor.h @@ -30,10 +30,11 @@ namespace Dialog { class LivePathEffectEditor : public Dialog {
public:
- LivePathEffectEditor();
+ LivePathEffectEditor(Behavior::BehaviorFactory behavior_factory);
virtual ~LivePathEffectEditor();
- static LivePathEffectEditor *create() { return new LivePathEffectEditor(); }
+ static LivePathEffectEditor *create(Behavior::BehaviorFactory behavior_factory)
+ { return new LivePathEffectEditor(behavior_factory); }
void onSelectionChanged(Inkscape::Selection *sel);
void setDesktop(SPDesktop *desktop);
diff --git a/src/ui/dialog/memory.cpp b/src/ui/dialog/memory.cpp index e81db17d8..eb61aaf9f 100644 --- a/src/ui/dialog/memory.cpp +++ b/src/ui/dialog/memory.cpp @@ -203,8 +203,8 @@ void Memory::Private::stop_update_task() { update_task.disconnect(); } -Memory::Memory() - : Dialog ("dialogs.memory", SP_VERB_HELP_MEMORY, _("Recalculate")), +Memory::Memory(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.memory", SP_VERB_HELP_MEMORY, _("Recalculate")), _private(*(new Memory::Private())) { get_vbox()->add(_private.view); diff --git a/src/ui/dialog/memory.h b/src/ui/dialog/memory.h index bec6c8fd0..0fe7f87c5 100644 --- a/src/ui/dialog/memory.h +++ b/src/ui/dialog/memory.h @@ -20,10 +20,11 @@ namespace Dialog { class Memory : public Dialog { public: - Memory(); + Memory(Behavior::BehaviorFactory behavior_factory); ~Memory(); - static Memory *create() { return new Memory(); } + static Memory *create(Behavior::BehaviorFactory behavior_factory) + { return new Memory(behavior_factory); } protected: void _apply(); diff --git a/src/ui/dialog/messages.cpp b/src/ui/dialog/messages.cpp index 9c7434edd..9e78903c9 100644 --- a/src/ui/dialog/messages.cpp +++ b/src/ui/dialog/messages.cpp @@ -45,8 +45,8 @@ void Messages::clear() /** * Constructor */ -Messages::Messages() - : Dialog ("dialogs.messages", SP_VERB_DIALOG_DEBUG) +Messages::Messages(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.messages", SP_VERB_DIALOG_DEBUG) { Gtk::VBox *mainVBox = get_vbox(); diff --git a/src/ui/dialog/messages.h b/src/ui/dialog/messages.h index 3ce7b5a87..85a7c4f0f 100644 --- a/src/ui/dialog/messages.h +++ b/src/ui/dialog/messages.h @@ -35,10 +35,11 @@ namespace Dialog { class Messages : public Dialog { public: - Messages(); + Messages(Behavior::BehaviorFactory behavior_factory); virtual ~Messages(); - static Messages *create() { return new Messages(); } + static Messages *create(Behavior::BehaviorFactory behavior_factory) + { return new Messages(behavior_factory); } /** * Clear all information from the dialog diff --git a/src/ui/dialog/scriptdialog.cpp b/src/ui/dialog/scriptdialog.cpp index 07f26b71f..304362f60 100644 --- a/src/ui/dialog/scriptdialog.cpp +++ b/src/ui/dialog/scriptdialog.cpp @@ -43,7 +43,7 @@ class ScriptDialogImpl : public ScriptDialog /** * Constructor */ - ScriptDialogImpl(); + ScriptDialogImpl(Behavior::BehaviorFactory behavior_factory); /** * Destructor @@ -192,7 +192,8 @@ void ScriptDialogImpl::executePerl() /** * Constructor */ -ScriptDialogImpl::ScriptDialogImpl() +ScriptDialogImpl::ScriptDialogImpl(Behavior::BehaviorFactory behavior_factory) : + ScriptDialog(behavior_factory) { Gtk::VBox *mainVBox = get_vbox(); @@ -249,9 +250,9 @@ ScriptDialogImpl::ScriptDialogImpl() /** * Factory method. Use this to create a new ScriptDialog */ -ScriptDialog *ScriptDialog::create() +ScriptDialog *ScriptDialog::create(Behavior::BehaviorFactory behavior_factory) { - ScriptDialog *dialog = new ScriptDialogImpl(); + ScriptDialog *dialog = new ScriptDialogImpl(behavior_factory); return dialog; } diff --git a/src/ui/dialog/scriptdialog.h b/src/ui/dialog/scriptdialog.h index b66aa93e7..00680d431 100644 --- a/src/ui/dialog/scriptdialog.h +++ b/src/ui/dialog/scriptdialog.h @@ -34,14 +34,15 @@ class ScriptDialog : public Dialog /** * Constructor */ - ScriptDialog() : Dialog ("dialogs.script", SP_VERB_DIALOG_SCRIPT) + ScriptDialog(Behavior::BehaviorFactory behavior_factory) : + Dialog (behavior_factory, "dialogs.script", SP_VERB_DIALOG_SCRIPT) {} /** * Factory method */ - static ScriptDialog *create(); + static ScriptDialog *create(Behavior::BehaviorFactory behavior_factory); /** * Destructor diff --git a/src/ui/dialog/text-properties.cpp b/src/ui/dialog/text-properties.cpp index a79992677..e6194ab56 100644 --- a/src/ui/dialog/text-properties.cpp +++ b/src/ui/dialog/text-properties.cpp @@ -20,8 +20,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -TextProperties::TextProperties() - : Dialog ("dialogs.textandfont", SP_VERB_DIALOG_TEXT), +TextProperties::TextProperties(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.textandfont", SP_VERB_DIALOG_TEXT), _page_font(1, 1), _page_text(1, 1) { diff --git a/src/ui/dialog/text-properties.h b/src/ui/dialog/text-properties.h index 2d5a03b9e..393ca63b2 100644 --- a/src/ui/dialog/text-properties.h +++ b/src/ui/dialog/text-properties.h @@ -26,10 +26,11 @@ namespace Dialog { class TextProperties : public Dialog { public: - TextProperties(); + TextProperties(Behavior::BehaviorFactory behavior_factory); virtual ~TextProperties(); - static TextProperties *create() { return new TextProperties(); } + static TextProperties *create(Behavior::BehaviorFactory behavior_factory) + { return new TextProperties(behavior_factory); } protected: Gtk::Notebook _notebook; diff --git a/src/ui/dialog/tracedialog.cpp b/src/ui/dialog/tracedialog.cpp index 2c041864f..b7602b36a 100644 --- a/src/ui/dialog/tracedialog.cpp +++ b/src/ui/dialog/tracedialog.cpp @@ -50,7 +50,7 @@ class TraceDialogImpl : public TraceDialog /** * Constructor */ - TraceDialogImpl(); + TraceDialogImpl(Behavior::BehaviorFactory behavior_factory); /** * Destructor @@ -376,7 +376,8 @@ void TraceDialogImpl::responseCallback(int response_id) /** * Constructor */ -TraceDialogImpl::TraceDialogImpl() +TraceDialogImpl::TraceDialogImpl(Behavior::BehaviorFactory behavior_factory) : + TraceDialog(behavior_factory) { Gtk::VBox *mainVBox = get_vbox(); @@ -685,9 +686,9 @@ TraceDialogImpl::TraceDialogImpl() /** * Factory method. Use this to create a new TraceDialog */ -TraceDialog *TraceDialog::create() +TraceDialog *TraceDialog::create(Behavior::BehaviorFactory behavior_factory) { - TraceDialog *dialog = new TraceDialogImpl(); + TraceDialog *dialog = new TraceDialogImpl(behavior_factory); return dialog; } diff --git a/src/ui/dialog/tracedialog.h b/src/ui/dialog/tracedialog.h index 80311bb15..0e352ce10 100644 --- a/src/ui/dialog/tracedialog.h +++ b/src/ui/dialog/tracedialog.h @@ -34,14 +34,15 @@ public: /** * Constructor */ - TraceDialog() : Dialog ("dialogs.trace", SP_VERB_SELECTION_TRACE) + TraceDialog(Behavior::BehaviorFactory behavior_factory) : + Dialog (behavior_factory, "dialogs.trace", SP_VERB_SELECTION_TRACE) {} /** * Factory method */ - static TraceDialog *create(); + static TraceDialog *create(Behavior::BehaviorFactory behavior_factory); /** * Destructor diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index be5a8bb03..b2385a29c 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -70,8 +70,8 @@ void on_selection_modified ( Inkscape::Application *inkscape, * we use the ScalarUnit class for this. * */ -Transformation::Transformation() - : Dialog ("dialogs.transformation", SP_VERB_DIALOG_TRANSFORM), +Transformation::Transformation(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.transformation", SP_VERB_DIALOG_TRANSFORM), _page_move (4, 2), _page_scale (4, 2), _page_rotate (4, 2), @@ -181,8 +181,8 @@ void Transformation::presentPage(Transformation::PageType page) { _notebook.set_current_page(page); - Gtk::Dialog::show(); - Gtk::Dialog::present(); + show(); + present(); } diff --git a/src/ui/dialog/transformation.h b/src/ui/dialog/transformation.h index 0c7833c9e..361b30a04 100644 --- a/src/ui/dialog/transformation.h +++ b/src/ui/dialog/transformation.h @@ -46,7 +46,7 @@ public: /** * Create a new transform */ - Transformation(); + Transformation(Behavior::BehaviorFactory behavior_factory); /** * Cleanup @@ -57,8 +57,8 @@ public: /** * Factory method. Create an instance of this class/interface */ - static Transformation *create() - { return new Transformation(); } + static Transformation *create(Behavior::BehaviorFactory behavior_factory) + { return new Transformation(behavior_factory); } /** diff --git a/src/ui/dialog/undo-history.cpp b/src/ui/dialog/undo-history.cpp index 98f8cc0cc..344efc557 100644 --- a/src/ui/dialog/undo-history.cpp +++ b/src/ui/dialog/undo-history.cpp @@ -103,10 +103,10 @@ static void on_activate_desktop(Inkscape::Application*, SPDesktop* desktop, void static void on_deactivate_desktop(Inkscape::Application*, SPDesktop* desktop, void*); UndoHistory* -UndoHistory::create() +UndoHistory::create(Behavior::BehaviorFactory behavior_factory) { if (_instance) return _instance; - _instance = new UndoHistory; + _instance = new UndoHistory(behavior_factory); return _instance; } @@ -131,8 +131,8 @@ UndoHistory::setDesktop(SPDesktop* desktop) _callback_connections[EventLog::CALLB_SELECTION_CHANGE].block(false); } -UndoHistory::UndoHistory() - : Dialog ("dialogs.undo-history", SP_VERB_DIALOG_UNDO_HISTORY), +UndoHistory::UndoHistory(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.undo-history", SP_VERB_DIALOG_UNDO_HISTORY), _desktop (SP_ACTIVE_DESKTOP), _document (SP_ACTIVE_DOCUMENT), _event_log (_desktop ? _desktop->event_log : NULL), @@ -141,7 +141,7 @@ UndoHistory::UndoHistory() { if( !_document || !_event_log || !_columns ) return; - set_size_request(300, 400); + set_size_request(300, 200); get_vbox()->pack_start(_scrolled_window); _scrolled_window.set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); diff --git a/src/ui/dialog/undo-history.h b/src/ui/dialog/undo-history.h index 7b900fde5..d7b00f343 100644 --- a/src/ui/dialog/undo-history.h +++ b/src/ui/dialog/undo-history.h @@ -120,7 +120,7 @@ class UndoHistory : public Dialog { public: virtual ~UndoHistory(); - static UndoHistory *create(); + static UndoHistory *create(Behavior::BehaviorFactory behavior_factory); void setDesktop(SPDesktop* desktop); sigc::connection _document_replaced_connection; @@ -146,9 +146,9 @@ protected: void _onCollapseEvent(const Gtk::TreeModel::iterator &iter, const Gtk::TreeModel::Path &path); private: + UndoHistory(Behavior::BehaviorFactory behavior_factory); // no default constructor, noncopyable, nonassignable - UndoHistory(); UndoHistory(UndoHistory const &d); UndoHistory operator=(UndoHistory const &d); diff --git a/src/ui/dialog/xml-editor.cpp b/src/ui/dialog/xml-editor.cpp index b8abf8bfd..53f3b4c2c 100644 --- a/src/ui/dialog/xml-editor.cpp +++ b/src/ui/dialog/xml-editor.cpp @@ -20,8 +20,8 @@ namespace Inkscape { namespace UI { namespace Dialog { -XmlEditor::XmlEditor() - : Dialog ("dialogs.xml", SP_VERB_DIALOG_XML_EDITOR) +XmlEditor::XmlEditor(Behavior::BehaviorFactory behavior_factory) + : Dialog (behavior_factory, "dialogs.xml", SP_VERB_DIALOG_XML_EDITOR) { // TODO: Insert widgets diff --git a/src/ui/dialog/xml-editor.h b/src/ui/dialog/xml-editor.h index b494ade1f..65f25423f 100644 --- a/src/ui/dialog/xml-editor.h +++ b/src/ui/dialog/xml-editor.h @@ -22,10 +22,11 @@ namespace Dialog { class XmlEditor : public Dialog { public: - XmlEditor(); + XmlEditor(Behavior::BehaviorFactory behavior_factory); virtual ~XmlEditor(); - static XmlEditor *create() { return new XmlEditor(); } + static XmlEditor *create(Behavior::BehaviorFactory behavior_factory) + { return new XmlEditor(behavior_factory); } protected: diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h index 8e388529e..c8219b7b2 100644 --- a/src/ui/view/edit-widget-interface.h +++ b/src/ui/view/edit-widget-interface.h @@ -18,9 +18,10 @@ #include "libnr/nr-point.h" #include "message.h" - #include <gtkmm/window.h> +namespace Inkscape { namespace UI { namespace Widget { class Dock; } } } + namespace Inkscape { namespace UI { namespace View { @@ -135,6 +136,8 @@ struct EditWidgetInterface /// Open yes/no dialog with warning text and confirmation question. virtual bool warnDialog (gchar*) = 0; + + virtual Inkscape::UI::Widget::Dock* getDock () = 0; }; } // namespace View diff --git a/src/ui/view/edit-widget.cpp b/src/ui/view/edit-widget.cpp index b87250e47..066d4d0ba 100644 --- a/src/ui/view/edit-widget.cpp +++ b/src/ui/view/edit-widget.cpp @@ -65,6 +65,8 @@ #include "interface.h" #include "extension/db.h" +#include "ui/dialog/dialog-manager.h" + using namespace Inkscape::UI; using namespace Inkscape::UI::Widget; @@ -152,7 +154,6 @@ EditWidget::initLayout() _viewport_table.attach(_svg_canvas.widget(), 1, 2, 1, 2, Gtk::FILL|Gtk::EXPAND, Gtk::FILL|Gtk::EXPAND); _svg_canvas.widget().show_all(); - // The statusbar comes last and appears at the bottom of _main_window_table initStatusbar(); @@ -1532,6 +1533,12 @@ EditWidget::warnDialog (gchar* msg) } +Inkscape::UI::Widget::Dock* +EditWidget::getDock () +{ + return &_dock; +} + void EditWidget::_namedview_modified (SPObject *obj, guint flags) { SPNamedView *nv = static_cast<SPNamedView *>(obj); if (flags & SP_OBJECT_MODIFIED_FLAG) { diff --git a/src/ui/view/edit-widget.h b/src/ui/view/edit-widget.h index 443b10ac8..4341f667c 100644 --- a/src/ui/view/edit-widget.h +++ b/src/ui/view/edit-widget.h @@ -27,6 +27,7 @@ #include "ui/dialog/dialog-manager.h" #include "ui/view/edit-widget-interface.h" +#include "ui/widget/dock.h" #include "ui/widget/selected-style.h" #include "ui/widget/ruler.h" #include "ui/widget/toolbox.h" @@ -132,6 +133,8 @@ public: virtual void setMessage (Inkscape::MessageType type, gchar const* msg); virtual bool warnDialog (gchar*); + virtual Inkscape::UI::Widget::Dock* getDock (); + protected: void _namedview_modified(SPObject *namedview, guint); @@ -157,6 +160,7 @@ protected: Gtk::ToggleButton _sticky_zoom; UI::Widget::SVGCanvas _svg_canvas; Gtk::HBox _statusbar; + UI::Widget::Dock _dock; UI::Widget::SelectedStyle _selected_style_status; UI::Widget::ZoomStatus _zoom_status; Inkscape::Widgets::LayerSelector _layer_selector; diff --git a/src/ui/widget/Makefile_insert b/src/ui/widget/Makefile_insert index 178e954a4..7113857c8 100644 --- a/src/ui/widget/Makefile_insert +++ b/src/ui/widget/Makefile_insert @@ -15,6 +15,10 @@ ui_widget_libuiwidget_a_SOURCES = \ ui/widget/combo-enums.h \ ui/widget/combo-text.cpp \ ui/widget/combo-text.h \ + ui/widget/dock.h \ + ui/widget/dock.cpp \ + ui/widget/dock-item.h \ + ui/widget/dock-item.cpp \ ui/widget/entity-entry.cpp \ ui/widget/entity-entry.h \ ui/widget/entry.cpp \ diff --git a/src/ui/widget/dock-item.cpp b/src/ui/widget/dock-item.cpp new file mode 100644 index 000000000..1e232cb4e --- /dev/null +++ b/src/ui/widget/dock-item.cpp @@ -0,0 +1,539 @@ +/** + * \brief A custom Inkscape wrapper around gdl_dock_item + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include "dock-item.h" +#include "desktop.h" +#include "inkscape.h" +#include "ui/widget/dock.h" +#include "widgets/icon.h" + +#include <gtk/gtk.h> + +#include <gtkmm/invisible.h> +#include <gtkmm/stock.h> + +namespace Inkscape { +namespace UI { +namespace Widget { + +DockItem::DockItem(Dock& dock, const Glib::ustring& name, const Glib::ustring& long_name, + const Glib::ustring& icon_name, State state) : + _dock (dock), + _prev_state (state), + _window (NULL), + _dock_item_action_area (NULL) +{ + /* Add a "signal_response" signal to the GdlDockItem, make sure it is + * only done once for the class. + */ + static guint response_signal = 0; + + if (response_signal == 0) { + response_signal = g_signal_new ("signal_response", + GDL_TYPE_DOCK_ITEM, + G_SIGNAL_RUN_FIRST, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + } + + + if (!icon_name.empty()) { + Gtk::Widget *icon = sp_icon_get_icon(icon_name, Inkscape::ICON_SIZE_MENU); + if (icon) { + // check icon type (inkscape, gtk, none) + if ( SP_IS_ICON(icon->gobj()) ) { + SPIcon* sp_icon = SP_ICON(icon->gobj()); + sp_icon_fetch_pixbuf(sp_icon); + _icon_pixbuf = Glib::wrap(sp_icon->pb, true); + } else if ( GTK_IS_IMAGE(icon->gobj()) ) { + _icon_pixbuf = Gtk::Invisible().render_icon(Gtk::StockID(icon_name), + Gtk::ICON_SIZE_MENU); + } + delete icon; + + _gdl_dock_item = + gdl_dock_item_new_with_pixbuf_icon(name.c_str(), long_name.c_str(), _icon_pixbuf->gobj(), + GDL_DOCK_ITEM_BEH_NORMAL); + } + } else { + _gdl_dock_item = + gdl_dock_item_new(name.c_str(), long_name.c_str(), GDL_DOCK_ITEM_BEH_NORMAL); + } + + _frame.set_shadow_type(Gtk::SHADOW_IN); + gtk_container_add (GTK_CONTAINER (_gdl_dock_item), GTK_WIDGET (_frame.gobj())); + _frame.add(_dock_item_box); + _dock_item_box.set_border_width(3); + + signal_drag_begin().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragBegin)); + signal_drag_end().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDragEnd)); + signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHide), false); + signal_show().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onShow), false); + signal_state_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onStateChanged)); + signal_delete_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onDeleteEvent)); + + _dock.addItem(*this, (_prev_state == FLOATING_STATE ? FLOATING : TOP)); + + show_all(); +} + +DockItem::~DockItem() +{ + g_free(_gdl_dock_item); +} + +Gtk::Widget& +DockItem::getWidget() +{ + return *Glib::wrap(GTK_WIDGET(_gdl_dock_item)); +} + +GtkWidget * +DockItem::gobj() +{ + return _gdl_dock_item; +} + +Gtk::VBox * +DockItem::get_vbox() +{ + return &_dock_item_box; +} + + +bool +DockItem::isAttached() const +{ + return GDL_DOCK_OBJECT_ATTACHED (_gdl_dock_item); +} + + +bool +DockItem::isFloating() const +{ + gboolean floating = FALSE; + if (GDL_IS_DOCK (gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT (_gdl_dock_item)))) { + GdlDock* dock = GDL_DOCK (gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT (_gdl_dock_item))); + g_object_get (dock, + "floating", &floating, + NULL); + } + return floating; +} + +bool +DockItem::isIconified() const +{ + return GDL_DOCK_ITEM_ICONIFIED (_gdl_dock_item); +} + +DockItem::State +DockItem::getState() const +{ + return (isAttached() ? (isFloating() ? FLOATING_STATE : DOCKED_STATE) : UNATTACHED); +} + +DockItem::State +DockItem::getPrevState() const +{ + return _prev_state; +} + +DockItem::Placement +DockItem::getPlacement() const +{ + GdlDockPlacement placement = (GdlDockPlacement)NONE; + gdl_dock_object_child_placement(gdl_dock_object_get_parent_object (GDL_DOCK_OBJECT(_gdl_dock_item)), + GDL_DOCK_OBJECT(_gdl_dock_item), + &placement); + return (Placement)placement; +} + + +void +DockItem::addButton(Gtk::Button* button, int response_id) +{ + // Create a button box for the response buttons if it's the first button to be added + if (!_dock_item_action_area) { + _dock_item_action_area = new Gtk::HButtonBox(Gtk::BUTTONBOX_END, 6); + _dock_item_box.pack_end(*_dock_item_action_area, Gtk::PACK_SHRINK, 0); + _dock_item_action_area->set_border_width(6); + } + + _dock_item_action_area->pack_start(*button); +} + +void +DockItem::hide() +{ + gdl_dock_item_hide_item (GDL_DOCK_ITEM(_gdl_dock_item)); +} + +void +DockItem::show() +{ + gdl_dock_item_show_item (GDL_DOCK_ITEM(_gdl_dock_item)); +} + +void +DockItem::show_all() +{ + gtk_widget_show_all(_gdl_dock_item); +} + +void +DockItem::present() +{ + // iconified + if (isIconified()) { + show(); + return; + } + + // unattached + if (!isAttached()) { + gdl_dock_item_show_item (GDL_DOCK_ITEM(_gdl_dock_item)); + return; + } + + // tabbed + if (getPlacement() == CENTER) { + int i = gtk_notebook_page_num (GTK_NOTEBOOK (_gdl_dock_item->parent), + GTK_WIDGET (_gdl_dock_item)); + if (i >= 0) + gtk_notebook_set_current_page (GTK_NOTEBOOK (_gdl_dock_item->parent), i); + return; + } + + // we're already present, do nothing +} + + +void +DockItem::get_position(int& x, int& y) +{ + if (_getWindow()) { + _getWindow()->get_position(x, y); + } else { + x = _x; + y = _y; + } +} + +void +DockItem::get_size(int& width, int& height) +{ + if (_window) { + _window->get_size(width, height); + } else { + width = get_vbox()->get_width(); + height = get_vbox()->get_height(); + } +} + + +void +DockItem::resize(int width, int height) +{ + if (_window) + _window->resize(width, height); +} + + +void +DockItem::move(int x, int y) +{ + if (_window) + _window->move(x, y); +} + +void +DockItem::set_position(Gtk::WindowPosition position) +{ + if (_window) + _window->set_position(position); +} + +void +DockItem::set_size_request(int width, int height) +{ + getWidget().set_size_request(width, height); +} + +void +DockItem::size_request(Gtk::Requisition& requisition) +{ + getWidget().size_request(requisition); +} + + +void +DockItem::set_title(Glib::ustring title) +{ + g_object_set (_gdl_dock_item, + "long-name", title.c_str(), + NULL); + + gdl_dock_item_set_tablabel(GDL_DOCK_ITEM(_gdl_dock_item), + gtk_label_new (title.c_str())); +} + +/* Signal wrappers */ + +Glib::SignalProxy0<void> +DockItem::signal_show() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_show_proxy); +} + +Glib::SignalProxy0<void> +DockItem::signal_hide() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_hide_proxy); +} + +Glib::SignalProxy1<bool, GdkEventAny *> +DockItem::signal_delete_event() +{ + return Glib::SignalProxy1<bool, GdkEventAny *>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_delete_event_proxy); +} + +Glib::SignalProxy1<void, int> +DockItem::signal_response() +{ + return Glib::SignalProxy1<void, int>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_response_proxy); +} + +Glib::SignalProxy0<void> +DockItem::signal_drag_begin() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_drag_begin_proxy); +} + +Glib::SignalProxy1<void, bool> +DockItem::signal_drag_end() +{ + return Glib::SignalProxy1<void, bool>(Glib::wrap(GTK_WIDGET(_gdl_dock_item)), + &_signal_drag_end_proxy); +} + +sigc::signal<void, DockItem::State, DockItem::State> +DockItem::signal_state_changed() +{ + return _signal_state_changed; +} + +void +DockItem::_onHideWindow() +{ + if (_window) + _window->get_position(_x, _y); +} + +void +DockItem::_onHide() +{ + _signal_state_changed.emit(UNATTACHED, getState()); +} + +void +DockItem::_onShow() +{ + _signal_state_changed.emit(UNATTACHED, getState()); +} + +void +DockItem::_onDragBegin() +{ + _prev_state = getState(); + if (_prev_state == FLOATING_STATE) + _dock.toggleDockable(getWidget().get_width(), getWidget().get_height()); +} + +void +DockItem::_onDragEnd(bool) +{ + State state = getState(); + + if (state != _prev_state) + _signal_state_changed.emit(_prev_state, state); + + if (state == FLOATING_STATE) { + if (_prev_state == FLOATING_STATE) + _dock.toggleDockable(); + } + + _prev_state = state; +} + +bool +DockItem::_onKeyPress(GdkEventKey *event) +{ + gboolean return_value; + g_signal_emit_by_name (_gdl_dock_item, "key_press_event", event, &return_value); + return return_value; +} + +void +DockItem::_onStateChanged(State prev_state, State new_state) +{ + _window = _getWindow(); + + if (new_state == FLOATING_STATE) { + _window->signal_hide().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onHideWindow)); + _signal_key_press_event_connection = + _window->signal_key_press_event().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::DockItem::_onKeyPress)); + } +} + + +bool +DockItem::_onDeleteEvent(GdkEventAny *event) +{ + hide(); + return false; +} + + +Gtk::Window * +DockItem::_getWindow() +{ + g_return_val_if_fail(_gdl_dock_item, 0); + Gtk::Container *parent = getWidget().get_parent(); + parent = (parent ? parent->get_parent() : 0); + return (parent ? dynamic_cast<Gtk::Window *>(parent) : 0); +} + +const Glib::SignalProxyInfo +DockItem::_signal_show_proxy = +{ + "show", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + +const Glib::SignalProxyInfo +DockItem::_signal_hide_proxy = +{ + "hide", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_delete_event_proxy = +{ + "delete_event", + (GCallback) &_signal_delete_event_callback, + (GCallback) &_signal_delete_event_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_response_proxy = +{ + "signal_response", + (GCallback) &_signal_response_callback, + (GCallback) &_signal_response_callback +}; + +const Glib::SignalProxyInfo +DockItem::_signal_drag_begin_proxy = +{ + "dock-drag-begin", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +const Glib::SignalProxyInfo +DockItem::_signal_drag_end_proxy = +{ + "dock_drag_end", + (GCallback) &_signal_drag_end_callback, + (GCallback) &_signal_drag_end_callback +}; + + +gboolean +DockItem::_signal_delete_event_callback(GtkWidget *self, GdkEventAny *event, void *data) +{ + using namespace Gtk; + typedef sigc::slot<bool, GdkEventAny *> SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) { + try { + if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) + return static_cast<int>( (*static_cast<SlotType*>(slot))(event) ); + } catch(...) { + Glib::exception_handlers_invoke(); + } + } + + typedef gboolean RType; + return RType(); +} + +void +DockItem::_signal_response_callback(GtkWidget *self, gint response_id, void *data) +{ + using namespace Gtk; + typedef sigc::slot<void, int> SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) { + try { + if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) + (*static_cast<SlotType *>(slot))(response_id); + } catch(...) { + Glib::exception_handlers_invoke(); + } + } +} + +void +DockItem::_signal_drag_end_callback(GtkWidget *self, gboolean cancelled, void *data) +{ + using namespace Gtk; + typedef sigc::slot<void, bool> SlotType; + + if (Glib::ObjectBase::_get_current_wrapper((GObject *) self)) { + try { + if(sigc::slot_base *const slot = Glib::SignalProxyNormal::data_to_slot(data)) + (*static_cast<SlotType *>(slot))(cancelled); + } catch(...) { + Glib::exception_handlers_invoke(); + } + } +} + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/dock-item.h b/src/ui/widget/dock-item.h new file mode 100644 index 000000000..38d13a579 --- /dev/null +++ b/src/ui/widget/dock-item.h @@ -0,0 +1,165 @@ +/** + * \brief A custom wrapper around gdl-dock-item + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + + +#ifndef INKSCAPE_UI_WIGET_DOCK_ITEM_H +#define INKSCAPE_UI_WIGET_DOCK_ITEM_H + +#include <gtkmm/button.h> +#include <gtkmm/buttonbox.h> +#include <gtkmm/frame.h> +#include <gtkmm/paned.h> +#include <gtkmm/window.h> + +#include "libgdl/libgdl.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Dock; + +class DockItem { + +public: + + enum State { UNATTACHED, FLOATING_STATE, DOCKED_STATE }; + + enum Placement { + NONE = GDL_DOCK_NONE, + TOP = GDL_DOCK_TOP, + BOTTOM = GDL_DOCK_BOTTOM, + RIGHT = GDL_DOCK_RIGHT, + LEFT = GDL_DOCK_LEFT, + CENTER = GDL_DOCK_CENTER, + FLOATING = GDL_DOCK_FLOATING + }; + + DockItem(Dock& dock, const Glib::ustring& name, const Glib::ustring& long_name, + const Glib::ustring& icon_name, State state); + + ~DockItem(); + + Gtk::Widget& getWidget(); + GtkWidget *gobj(); + + Gtk::VBox *get_vbox(); + + void get_position(int& x, int& y); + void get_size(int& width, int& height); + + void resize(int width, int height); + void move(int x, int y); + void set_position(Gtk::WindowPosition); + void set_size_request(int width, int height); + void size_request(Gtk::Requisition& requisition); + void set_title(Glib::ustring title); + + bool isAttached() const; + bool isFloating() const; + bool isIconified() const; + State getState() const; + State getPrevState() const; + Placement getPlacement() const; + + void addButton(Gtk::Button *button, int response_id); + + void hide(); + void show(); + void show_all(); + + void present(); + + Glib::SignalProxy0<void> signal_show(); + Glib::SignalProxy0<void> signal_hide(); + Glib::SignalProxy1<bool, GdkEventAny *> signal_delete_event(); + Glib::SignalProxy1<void, int> signal_response(); + Glib::SignalProxy0<void> signal_drag_begin(); + Glib::SignalProxy1<void, bool> signal_drag_end(); + + sigc::signal<void, State, State> signal_state_changed(); + +private: + Dock &_dock; //< parent dock + + State _prev_state; //< last known state + + int _prev_position; + + Gtk::Window *_window; //< reference to floating window, if any + int _x, _y; //< last known position of window, if floating + + GtkWidget *_gdl_dock_item; + Glib::RefPtr<Gdk::Pixbuf> _icon_pixbuf; + + /** Interface widgets, will be packed like + * gdl_dock_item -> _frame -> _dock_item_box -> (_dock_item_action_area) + */ + Gtk::Frame _frame; + Gtk::VBox _dock_item_box; + Gtk::HButtonBox *_dock_item_action_area; + + /** Internal signal handlers */ + void _onHide(); + void _onHideWindow(); + void _onShow(); + void _onResponse(int response_id); + void _onDragBegin(); + void _onDragEnd(bool cancelled); + bool _onKeyPress(GdkEventKey *event); + void _onStateChanged(State prev_state, State new_state); + bool _onDeleteEvent(GdkEventAny *event); + + void _onFoo(); + + sigc::connection _signal_key_press_event_connection; + + /** GdlDockItem signal proxy structures */ + static const Glib::SignalProxyInfo _signal_show_proxy; + static const Glib::SignalProxyInfo _signal_hide_proxy; + static const Glib::SignalProxyInfo _signal_delete_event_proxy; + static const Glib::SignalProxyInfo _signal_response_proxy; + static const Glib::SignalProxyInfo _signal_drag_begin_proxy; + static const Glib::SignalProxyInfo _signal_drag_end_proxy; + + static gboolean _signal_delete_event_callback(GtkWidget *self, GdkEventAny *event, void *data); + static void _signal_drag_end_callback(GtkWidget* self, gboolean p0, void* data); + + /** Internal helpers */ + Gtk::Window *_getWindow(); //< gives the parent window, if the dock item has one (i.e. it's floating) + + /** In order to emulate a signal_response signal like the one for Gtk::Dialog we inject a new + * signal into GdlDockItem. This signal will be emitted when a button in the dock item added + * through the addButton(..., response_id) method, is clicked. + */ + static void _signal_response_callback(GtkWidget* self, gint p0, void* data); + + sigc::signal<void, State, State> _signal_state_changed; + + DockItem(); +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif // INKSCAPE_UI_WIGET_DOCK_ITEM_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : diff --git a/src/ui/widget/dock.cpp b/src/ui/widget/dock.cpp new file mode 100644 index 000000000..828b70451 --- /dev/null +++ b/src/ui/widget/dock.cpp @@ -0,0 +1,235 @@ +/** + * \brief A desktop dock pane to dock dialogs. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#include "inkscape.h" +#include "desktop.h" + +#include "dock.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +namespace { + +void hideCallback(GtkObject *object, gpointer dock_ptr) +{ + g_return_if_fail( dock_ptr != NULL ); + + Dock *dock = (Dock *)dock_ptr; + dock->hide(); +} + +void unhideCallback(GtkObject *object, gpointer dock_ptr) +{ + g_return_if_fail( dock_ptr != NULL ); + + Dock *dock = (Dock *)dock_ptr; + dock->show(); +} + +} + +const int Dock::_default_empty_width = 0; +const int Dock::_default_dock_bar_width = 36; + + +Dock::Dock(Gtk::Orientation orientation) + : _gdl_dock (GDL_DOCK (gdl_dock_new())), + _gdl_dock_bar (GDL_DOCK_BAR (gdl_dock_bar_new(GDL_DOCK(_gdl_dock)))), + _scrolled_window (Gtk::manage(new Gtk::ScrolledWindow)) +{ + gdl_dock_bar_set_orientation(_gdl_dock_bar, static_cast<GtkOrientation>(orientation)); + + switch (orientation) { + case Gtk::ORIENTATION_VERTICAL: + _dock_box = Gtk::manage(new Gtk::HBox()); + _paned = Gtk::manage(new Gtk::VPaned()); + break; + case Gtk::ORIENTATION_HORIZONTAL: + _dock_box = Gtk::manage(new Gtk::VBox()); + _paned = Gtk::manage(new Gtk::HPaned()); + } + + _scrolled_window->add(*_dock_box); + _scrolled_window->set_policy(Gtk::POLICY_NEVER, Gtk::POLICY_AUTOMATIC); + + _paned->pack1(*Glib::wrap(GTK_WIDGET(_gdl_dock)), false, false); + _paned->pack2(_filler, true, false); + + _dock_box->pack_start(*_paned, Gtk::PACK_EXPAND_WIDGET); + _dock_box->pack_end(*Gtk::manage(Glib::wrap(GTK_WIDGET(_gdl_dock_bar))), Gtk::PACK_SHRINK); + _dock_box->get_parent()->set_resize_mode(Gtk::RESIZE_PARENT); + + _scrolled_window->set_size_request(0); + + g_object_set (GDL_DOCK_OBJECT(_gdl_dock)->master, + "switcher-style", GDL_SWITCHER_STYLE_BOTH, + NULL); + + 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); + + signal_layout_changed().connect(sigc::mem_fun(*this, &Inkscape::UI::Widget::Dock::_onLayoutChanged)); +} + +Dock::~Dock() +{ + g_free(_gdl_dock); + g_free(_gdl_dock_bar); +} + +void +Dock::addItem(DockItem& item, DockItem::Placement placement) +{ + _dock_items.push_back(&item); + gdl_dock_add_item(_gdl_dock, GDL_DOCK_ITEM(item.gobj()), (GdlDockPlacement)placement); + + // FIXME: This is a hack to prevent the dock from expanding the main window, this can't be done + // initially as the paned doesn't exist. + if (Gtk::Paned *paned = getParentPaned()) + paned->set_resize_mode(Gtk::RESIZE_QUEUE); +} + +Gtk::Widget& +Dock::getWidget() +{ + return *_scrolled_window; +} + +Gtk::Paned * +Dock::getParentPaned() +{ + g_return_val_if_fail(_dock_box, 0); + Gtk::Container *parent = getWidget().get_parent(); + return (parent != 0 ? dynamic_cast<Gtk::Paned *>(parent) : 0); +} + + +Gtk::Paned * +Dock::getPaned() +{ + return _paned; +} + + +bool +Dock::isEmpty() const +{ + std::list<const DockItem *>::const_iterator + i = _dock_items.begin(), + e = _dock_items.end(); + + for (; i != e; ++i) + if ((*i)->getState() == DockItem::DOCKED_STATE) + return false; + + return true; +} + +bool +Dock::hasIconifiedItems() const +{ + std::list<const DockItem *>::const_iterator + i = _dock_items.begin(), + e = _dock_items.end(); + + for (; i != e; ++i) + if ((*i)->isIconified()) + return true; + + return false; +} + +void +Dock::hide() +{ + getWidget().hide(); +} + +void +Dock::show() +{ + getWidget().show(); +} + +void +Dock::toggleDockable(int width, int height) +{ + static int prev_horizontal_position, prev_vertical_position; + + Gtk::Paned *parent_paned = getParentPaned(); + + if (width > 0 && height > 0) { + prev_horizontal_position = parent_paned->get_position(); + prev_vertical_position = _paned->get_position(); + + if (getWidget().get_width() < width) + parent_paned->set_position(parent_paned->get_width() - width); + + if (_paned->get_position() < height) + _paned->set_position(height); + + } else { + parent_paned->set_position(prev_horizontal_position); + _paned->set_position(prev_vertical_position); + } + +} + +Glib::SignalProxy0<void> +Dock::signal_layout_changed() +{ + return Glib::SignalProxy0<void>(Glib::wrap(GTK_WIDGET(_gdl_dock)), + &_signal_layout_changed_proxy); +} + +void +Dock::_onLayoutChanged() +{ + if (isEmpty()) { + + if (hasIconifiedItems()) + _scrolled_window->set_size_request(_default_dock_bar_width); + else + _scrolled_window->set_size_request(_default_empty_width); + + getParentPaned()->set_position(INT_MAX); + } else { + _scrolled_window->set_size_request(-1); + } +} + + +const Glib::SignalProxyInfo +Dock::_signal_layout_changed_proxy = +{ + "layout-changed", + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback, + (GCallback) &Glib::SignalProxyNormal::slot0_void_callback +}; + + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 diff --git a/src/ui/widget/dock.h b/src/ui/widget/dock.h new file mode 100644 index 000000000..be0c4ef1d --- /dev/null +++ b/src/ui/widget/dock.h @@ -0,0 +1,97 @@ +/** + * \brief A desktop dock pane to dock dialogs, a custom wrapper around gdl-dock. + * + * Author: + * Gustav Broberg <broberg@kth.se> + * + * Copyright (C) 2007 Authors + * + * Released under GNU GPL. Read the file 'COPYING' for more information. + */ + +#ifndef INKSCAPE_UI_WIDGET_DOCK_H +#define INKSCAPE_UI_WIDGET_DOCK_H + +#include <gtkmm/scrolledwindow.h> +#include <gtkmm/box.h> +#include <gtkmm/paned.h> + +#include <list> + +#include "ui/widget/dock-item.h" + +#include "libgdl/libgdl.h" + +namespace Inkscape { +namespace UI { +namespace Widget { + +class Dock { + +public: + + Dock(Gtk::Orientation orientation=Gtk::ORIENTATION_VERTICAL); + ~Dock(); + + void addItem(DockItem& item, DockItem::Placement placement); + + Gtk::Widget& getWidget(); //< return the top widget + Gtk::Paned *getParentPaned(); + + Gtk::Paned *getPaned(); + + bool isEmpty() const; //< true iff none of the dock's items are in state != UNATTACHED + bool hasIconifiedItems() const; + + Glib::SignalProxy0<void> signal_layout_changed(); + + void hide(); + void show(); + + /** Toggle size of dock between the previous dimensions and the ones sent as parameters */ + void toggleDockable(int width=0, int height=0); + +protected: + + std::list<const DockItem *> _dock_items; //< added dock items + + /** Interface widgets, will be packed like + * _scrolled_window -> (_dock_box -> (_paned -> (_dock -> _filler) | _dock_bar)) + */ + Gtk::Box *_dock_box; + Gtk::Paned* _paned; + GdlDock *_gdl_dock; + GdlDockBar *_gdl_dock_bar; + Gtk::VBox _filler; + Gtk::ScrolledWindow *_scrolled_window; + + /** Internal signal handlers */ + void _onLayoutChanged(); + + void _onFoo(); + + /** GdlDock signal proxy structures */ + static const Glib::SignalProxyInfo _signal_layout_changed_proxy; + + /** Standard widths */ + static const int _default_empty_width; + static const int _default_dock_bar_width; +}; + +} // namespace Widget +} // namespace UI +} // namespace Inkscape + +#endif //INKSCAPE_UI_DIALOG_BEHAVIOUR_H + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 + |
