1 /*
2 * go-editor.c :
3 *
4 * Copyright (C) 2003-2009 Jody Goldberg (jody@gnome.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of the
9 * License, or (at your option) version 3.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
19 * USA
20 */
21
22 /*****************************************************************************/
23
24 #include <goffice/goffice-config.h>
25 #include <goffice/utils/go-editor.h>
26 #include <string.h>
27
28
29 typedef struct {
30 char const *label; /* label for notebook page */
31 gpointer widget; /* GtkWidget* */
32 gpointer scrolled; /* GtkScrolledWindow embedding the widget.*/
33 } GOEditorPage;
34
35 struct _GOEditor {
36 unsigned *store_page; /* pointer to a place for storing last edited page */
37 GSList *pages; /* GOEditorPage */
38 GData *registered_widgets;
39 unsigned ref_count;
40 gboolean use_scrolled;
41 };
42
43 /**
44 * GOEditor:
45 *
46 * Embeds a notebook containing all the pages added to the editor.
47 **/
48
49 /**
50 * go_editor_new:
51 *
52 * Returns: (transfer full): a new GOEditor object, which is used to store a collection of
53 * property edition widgets (pages). The returned object must be freed
54 * using @go_editor_free.
55 **/
56 GOEditor *
go_editor_new(void)57 go_editor_new (void)
58 {
59 GOEditor *editor = g_new (GOEditor, 1);
60
61 editor->store_page = NULL;
62 editor->pages = NULL;
63 g_datalist_init (&editor->registered_widgets);
64 editor->ref_count = 1;
65 editor->use_scrolled = FALSE;
66
67 return editor;
68 }
69
70 static void
page_free(GOEditorPage * page)71 page_free (GOEditorPage *page)
72 {
73 if (page->scrolled)
74 g_object_unref (page->scrolled);
75 g_free (page);
76 }
77
78 /**
79 * go_editor_free:
80 * @editor: a #GOEditor
81 *
82 * Frees a GOEditor object.
83 **/
84
85 void
go_editor_free(GOEditor * editor)86 go_editor_free (GOEditor *editor)
87 {
88 if (editor == NULL || editor->ref_count-- >1)
89 return;
90 g_slist_foreach (editor->pages, (GFunc) page_free, NULL);
91 g_slist_free (editor->pages);
92 g_datalist_clear (&editor->registered_widgets);
93
94 g_free (editor);
95 }
96
97 static GOEditor *
go_editor_ref(GOEditor * editor)98 go_editor_ref (GOEditor *editor)
99 {
100 editor->ref_count++;
101 return editor;
102 }
103
104 GType
go_editor_get_type(void)105 go_editor_get_type (void)
106 {
107 static GType t = 0;
108
109 if (t == 0)
110 t = g_boxed_type_register_static ("GOEditor",
111 (GBoxedCopyFunc)go_editor_ref,
112 (GBoxedFreeFunc)go_editor_free);
113 return t;
114 }
115
116 /**
117 * go_editor_add_page:
118 * @editor: a #GOEditor
119 * @widget: property edition widget
120 * @label: a label identifying the widget
121 *
122 * Adds a page to @editor.
123 */
124
125 void
go_editor_add_page(GOEditor * editor,gpointer widget,char const * label)126 go_editor_add_page (GOEditor *editor, gpointer widget, char const *label)
127 {
128 GOEditorPage *page;
129
130 g_return_if_fail (editor != NULL);
131 page = g_new0 (GOEditorPage, 1);
132
133 page->widget = widget;
134 #ifdef GOFFICE_WITH_GTK
135 if (editor->use_scrolled) {
136 page->scrolled = g_object_ref (gtk_scrolled_window_new (NULL, NULL));
137 gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (page->scrolled),
138 widget);
139 } else
140 #endif
141 page->scrolled = g_object_ref (widget);
142 page->label = label;
143
144 editor->pages = g_slist_prepend (editor->pages, page);
145 }
146
147 /**
148 * go_editor_set_store_page:
149 * @editor: a #GOEditor
150 * @store_page: placeholder for the last selected page
151 *
152 * Sets a placeholder for storing the last active editor page.
153 **/
154
155 void
go_editor_set_store_page(GOEditor * editor,unsigned * store_page)156 go_editor_set_store_page (GOEditor *editor, unsigned *store_page)
157 {
158 g_return_if_fail (editor != NULL);
159
160 editor->store_page = store_page;
161 }
162
163 /**
164 * go_editor_set_use_scrolled_window:
165 * @editor: a #GOEditor
166 * @use_scrolled: boolean
167 *
168 * Sets whether each page of the editor should be displayed inside a scrolled
169 * window.
170 **/
171
172 void
go_editor_set_use_scrolled_window(GOEditor * editor,gboolean use_scrolled)173 go_editor_set_use_scrolled_window (GOEditor *editor, gboolean use_scrolled)
174 {
175 g_return_if_fail (editor != NULL);
176
177 editor->use_scrolled = use_scrolled;
178 }
179
180 #ifdef GOFFICE_WITH_GTK
181
182 /**
183 * go_editor_register_widget:
184 * @editor: a #GOEditor
185 * @widget: a #GtkWidget
186 *
187 * Registers a widget that then can be retrieved later using
188 * @go_editor_get_registered_widget. The main use of this function is to
189 * provide the ability to extend a page.
190 **/
191 void
go_editor_register_widget(GOEditor * editor,GtkWidget * widget)192 go_editor_register_widget (GOEditor *editor, GtkWidget *widget)
193 {
194 g_return_if_fail (editor != NULL);
195 g_return_if_fail (GTK_IS_WIDGET (widget));
196
197 g_datalist_set_data (&editor->registered_widgets, gtk_buildable_get_name (GTK_BUILDABLE (widget)), widget);
198 }
199
200 /**
201 * go_editor_get_registered_widget:
202 * @editor: a #GOEditor
203 * @name: the name of the registered widget
204 *
205 * Returns: (transfer none): a widget previously registered using @go_editor_register_widget.
206 **/
207 GtkWidget *
go_editor_get_registered_widget(GOEditor * editor,char const * name)208 go_editor_get_registered_widget (GOEditor *editor, char const *name)
209 {
210 g_return_val_if_fail (editor != NULL, NULL);
211
212 return g_datalist_get_data (&editor->registered_widgets, name);
213 }
214
215 static void
cb_switch_page(G_GNUC_UNUSED GtkNotebook * n,G_GNUC_UNUSED GtkWidget * p,guint page_num,guint * store_page)216 cb_switch_page (G_GNUC_UNUSED GtkNotebook *n, G_GNUC_UNUSED GtkWidget *p,
217 guint page_num, guint *store_page)
218 {
219 *store_page = page_num;
220 }
221
222 /**
223 * go_editor_get_notebook:
224 * @editor: a #GOEditor
225 *
226 * Returns: (transfer full): a GtkNotebook from the widget collection stored in @editor.
227 **/
228 GtkWidget *
go_editor_get_notebook(GOEditor * editor)229 go_editor_get_notebook (GOEditor *editor)
230 {
231 GtkWidget *notebook;
232 GOEditorPage *page;
233 GSList *ptr;
234 unsigned page_count = 0;
235
236 notebook = gtk_notebook_new ();
237 if (editor->pages != NULL) {
238 for (ptr = editor->pages; ptr != NULL; ptr = ptr->next) {
239 page = (GOEditorPage *) ptr->data;
240 gtk_notebook_prepend_page (GTK_NOTEBOOK (notebook),
241 GTK_WIDGET (page->scrolled),
242 gtk_label_new (page->label));
243 gtk_widget_show (page->scrolled);
244 page_count ++;
245 }
246 } else {
247 /* Display a blank page */
248 GtkWidget *label = gtk_label_new (NULL);
249 gtk_notebook_prepend_page (GTK_NOTEBOOK (notebook),
250 label, NULL);
251 gtk_widget_show (label);
252 page_count = 1;
253 }
254
255 if (editor->store_page != NULL) {
256 gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), *editor->store_page);
257 g_signal_connect (G_OBJECT (notebook),
258 "switch_page",
259 G_CALLBACK (cb_switch_page), editor->store_page);
260 } else
261 gtk_notebook_set_current_page (GTK_NOTEBOOK (notebook), 0);
262
263 return notebook;
264 }
265
266 /**
267 * go_editor_get_page:
268 * @editor: #GOEditor
269 * @name: page name
270 *
271 * Returns: (transfer none): the page with @name as name if any
272 **/
273 GtkWidget *
go_editor_get_page(GOEditor * editor,char const * name)274 go_editor_get_page (GOEditor *editor, char const *name)
275 {
276 GSList *ptr;
277 GOEditorPage *page;
278 for (ptr = editor->pages; ptr; ptr = ptr->next) {
279 page = (GOEditorPage *) ptr->data;
280 if (strcmp (page->label, name))
281 return page->widget;
282 }
283 return NULL;
284 }
285
286 #endif
287