1 /** @file
2 * @brief A panel holding dialog
3 */
4 /* Authors:
5 * Gustav Broberg <broberg@kth.se>
6 *
7 * Copyright (C) 2007 Authors
8 * Released under GNU GPL. Read the file 'COPYING' for more information.
9 */
11 #ifndef INKSCAPE_PANEL_DIALOG_H
12 #define INKSCAPE_PANEL_DIALOG_H
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #include <gtkmm/stock.h>
20 #include "verbs.h"
21 #include "dialog.h"
22 #include "ui/dialog/swatches.h"
23 #include "ui/dialog/floating-behavior.h"
24 #include "ui/dialog/dock-behavior.h"
25 #include "preferences.h"
27 namespace Inkscape {
28 namespace UI {
29 namespace Dialog {
31 class PanelDialogBase {
32 public:
33 PanelDialogBase(UI::Widget::Panel &panel, char const */*prefs_path*/, int const /*verb_num*/,
34 Glib::ustring const &/*apply_label*/) :
35 _panel (panel) { }
37 virtual void present() = 0;
38 virtual ~PanelDialogBase() {}
40 virtual UI::Widget::Panel &getPanel() { return _panel; }
42 protected:
43 static void handle_deactivate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) {
44 g_return_if_fail(data != NULL);
45 static_cast<PanelDialogBase *>(data)->_propagateDesktopDeactivated(application, desktop);
46 }
48 static void _handle_activate_desktop(Inkscape::Application *application, SPDesktop *desktop, void *data) {
49 g_return_if_fail(data != NULL);
50 static_cast<PanelDialogBase *>(data)->_propagateDesktopActivated(application, desktop);
51 }
53 inline virtual void _propagateDocumentReplaced(SPDesktop* desktop, SPDocument *document);
54 inline virtual void _propagateDesktopActivated(Inkscape::Application *, SPDesktop *);
55 inline virtual void _propagateDesktopDeactivated(Inkscape::Application *, SPDesktop *);
57 UI::Widget::Panel &_panel;
58 sigc::connection _document_replaced_connection;
59 };
61 template <typename Behavior>
62 class PanelDialog : public PanelDialogBase, public Inkscape::UI::Dialog::Dialog {
64 public:
65 PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num,
66 Glib::ustring const &apply_label);
68 virtual ~PanelDialog() {}
70 template <typename T>
71 static PanelDialog<Behavior> *create();
73 inline virtual void present();
75 private:
76 inline void _presentDialog();
78 PanelDialog(); // no constructor without params
79 PanelDialog(PanelDialog<Behavior> const &d); // no copy
80 PanelDialog<Behavior>& operator=(PanelDialog<Behavior> const &d); // no assign
81 };
84 template <>
85 class PanelDialog<Behavior::FloatingBehavior> :
86 public PanelDialogBase, public Inkscape::UI::Dialog::Dialog {
88 public:
89 inline PanelDialog(UI::Widget::Panel &contents, char const *prefs_path, int const verb_num,
90 Glib::ustring const &apply_label);
92 virtual ~PanelDialog() {}
94 template <typename T>
95 static PanelDialog<Behavior::FloatingBehavior> *create();
97 inline virtual void present();
99 private:
100 PanelDialog(); // no constructor without params
101 PanelDialog(PanelDialog<Behavior::FloatingBehavior> const &d); // no copy
102 PanelDialog<Behavior::FloatingBehavior>&
103 operator=(PanelDialog<Behavior::FloatingBehavior> const &d); // no assign
104 };
108 void
109 PanelDialogBase::_propagateDocumentReplaced(SPDesktop *desktop, SPDocument *document)
110 {
111 _panel.signalDocumentReplaced().emit(desktop, document);
112 }
114 void
115 PanelDialogBase::_propagateDesktopActivated(Inkscape::Application *application, SPDesktop *desktop)
116 {
117 _document_replaced_connection =
118 desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialogBase::_propagateDocumentReplaced));
119 _panel.signalActivateDesktop().emit(application, desktop);
120 }
122 void
123 PanelDialogBase::_propagateDesktopDeactivated(Inkscape::Application *application, SPDesktop *desktop)
124 {
125 _document_replaced_connection.disconnect();
126 _panel.signalDeactiveDesktop().emit(application, desktop);
127 }
130 template <typename B>
131 PanelDialog<B>::PanelDialog(Widget::Panel &panel, char const *prefs_path, int const verb_num,
132 Glib::ustring const &apply_label) :
133 PanelDialogBase(panel, prefs_path, verb_num, apply_label),
134 Dialog(&B::create, prefs_path, verb_num, apply_label)
135 {
136 Gtk::VBox *vbox = get_vbox();
137 _panel.signalResponse().connect(sigc::mem_fun(*this, &PanelDialog::_handleResponse));
138 _panel.signalPresent().connect(sigc::mem_fun(*this, &PanelDialog::_presentDialog));
140 vbox->pack_start(_panel, true, true, 0);
142 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
144 _propagateDesktopActivated(INKSCAPE, desktop);
146 _document_replaced_connection =
147 desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialog::_propagateDocumentReplaced));
149 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
150 if (prefs->getBool("/dialogs/showclose") || !apply_label.empty()) {
151 // TODO: make the order of buttons obey the global preference
152 if (!apply_label.empty()) {
153 panel.addResponseButton(apply_label, Gtk::RESPONSE_APPLY);
154 panel.setDefaultResponse(Gtk::RESPONSE_APPLY);
155 }
156 panel.addResponseButton(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
157 }
159 show_all_children();
160 }
162 template <typename B> template <typename P>
163 PanelDialog<B> *
164 PanelDialog<B>::create()
165 {
166 UI::Widget::Panel &panel = P::getInstance();
167 return new PanelDialog<B>(panel, panel.getPrefsPath(), panel.getVerb(), panel.getApplyLabel());
168 }
170 template <typename B>
171 void
172 PanelDialog<B>::present()
173 {
174 _panel.present();
175 }
177 template <typename B>
178 void
179 PanelDialog<B>::_presentDialog()
180 {
181 Dialog::present();
182 }
184 PanelDialog<Behavior::FloatingBehavior>::PanelDialog(UI::Widget::Panel &panel, char const *prefs_path,
185 int const verb_num, Glib::ustring const &apply_label) :
186 PanelDialogBase(panel, prefs_path, verb_num, apply_label),
187 Dialog(&Behavior::FloatingBehavior::create, prefs_path, verb_num, apply_label)
188 {
189 Gtk::VBox *vbox = get_vbox();
190 _panel.signalResponse().connect(sigc::mem_fun(*this, &PanelDialog::_handleResponse));
192 vbox->pack_start(_panel, true, true, 0);
194 SPDesktop *desktop = SP_ACTIVE_DESKTOP;
196 _propagateDesktopActivated(INKSCAPE, desktop);
198 _document_replaced_connection =
199 desktop->connectDocumentReplaced(sigc::mem_fun(*this, &PanelDialog::_propagateDocumentReplaced));
201 Inkscape::Preferences *prefs = Inkscape::Preferences::get();
202 if (prefs->getBool("/dialogs/showclose") || !apply_label.empty()) {
203 // TODO: make the order of buttons obey the global preference
204 if (!apply_label.empty()) {
205 panel.addResponseButton(apply_label, Gtk::RESPONSE_APPLY);
206 panel.setDefaultResponse(Gtk::RESPONSE_APPLY);
207 }
208 panel.addResponseButton(Gtk::Stock::CLOSE, Gtk::RESPONSE_CLOSE);
209 }
211 show_all_children();
212 }
214 void
215 PanelDialog<Behavior::FloatingBehavior>::present()
216 {
217 Dialog::present();
218 _panel.present();
219 }
221 /**
222 * Specialize factory method for panel dialogs with floating behavior in order to make them work as
223 * singletons, i.e. allow them track the current active desktop.
224 */
225 template <typename P>
226 PanelDialog<Behavior::FloatingBehavior> *
227 PanelDialog<Behavior::FloatingBehavior>::create()
228 {
229 UI::Widget::Panel &panel = P::getInstance();
230 PanelDialog<Behavior::FloatingBehavior> *instance =
231 new PanelDialog<Behavior::FloatingBehavior>(panel, panel.getPrefsPath(),
232 panel.getVerb(), panel.getApplyLabel());
234 g_signal_connect(G_OBJECT(INKSCAPE), "activate_desktop", G_CALLBACK(_handle_activate_desktop), instance);
235 g_signal_connect(G_OBJECT(INKSCAPE), "deactivate_desktop", G_CALLBACK(handle_deactivate_desktop), instance);
237 return instance;
238 }
240 } // namespace Dialog
241 } // namespace UI
242 } // namespace Inkscape
244 #endif //INKSCAPE_PANEL_DIALOG_H
246 /*
247 Local Variables:
248 mode:c++
249 c-file-style:"stroustrup"
250 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
251 indent-tabs-mode:nil
252 fill-column:99
253 End:
254 */
255 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :