1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2
3 /*
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU Lesser General Public License as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, see <http://www.gnu.org/licenses/>.
16 *
17 *
18 * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19 *
20 */
21
22 #include "evolution-config.h"
23
24 #include "e-composer-header.h"
25
26 #include <glib/gi18n-lib.h>
27
28 #define E_COMPOSER_HEADER_GET_PRIVATE(obj) \
29 (G_TYPE_INSTANCE_GET_PRIVATE \
30 ((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderPrivate))
31
32 struct _EComposerHeaderPrivate {
33 gchar *label;
34 gboolean button;
35
36 ESourceRegistry *registry;
37
38 guint sensitive : 1;
39 guint visible : 1;
40 };
41
42 #define E_COMPOSER_HEADER_GET_PRIVATE(obj) \
43 (G_TYPE_INSTANCE_GET_PRIVATE \
44 ((obj), E_TYPE_COMPOSER_HEADER, EComposerHeaderPrivate))
45
46 enum {
47 PROP_0,
48 PROP_BUTTON,
49 PROP_LABEL,
50 PROP_REGISTRY,
51 PROP_SENSITIVE,
52 PROP_VISIBLE
53 };
54
55 enum {
56 CHANGED,
57 CLICKED,
58 LAST_SIGNAL
59 };
60
61 static guint signal_ids[LAST_SIGNAL];
62
G_DEFINE_ABSTRACT_TYPE(EComposerHeader,e_composer_header,G_TYPE_OBJECT)63 G_DEFINE_ABSTRACT_TYPE (
64 EComposerHeader,
65 e_composer_header,
66 G_TYPE_OBJECT)
67
68 static void
69 composer_header_button_clicked_cb (GtkButton *button,
70 EComposerHeader *header)
71 {
72 gtk_widget_grab_focus (header->input_widget);
73 g_signal_emit (header, signal_ids[CLICKED], 0);
74 }
75
76 static void
composer_header_set_registry(EComposerHeader * header,ESourceRegistry * registry)77 composer_header_set_registry (EComposerHeader *header,
78 ESourceRegistry *registry)
79 {
80 g_return_if_fail (E_IS_SOURCE_REGISTRY (registry));
81 g_return_if_fail (header->priv->registry == NULL);
82
83 header->priv->registry = g_object_ref (registry);
84 }
85
86 static void
composer_header_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)87 composer_header_set_property (GObject *object,
88 guint property_id,
89 const GValue *value,
90 GParamSpec *pspec)
91 {
92 EComposerHeaderPrivate *priv;
93
94 priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
95
96 switch (property_id) {
97 case PROP_BUTTON: /* construct only */
98 priv->button = g_value_get_boolean (value);
99 return;
100
101 case PROP_LABEL: /* construct only */
102 priv->label = g_value_dup_string (value);
103 return;
104
105 case PROP_REGISTRY:
106 composer_header_set_registry (
107 E_COMPOSER_HEADER (object),
108 g_value_get_object (value));
109 return;
110
111 case PROP_SENSITIVE:
112 e_composer_header_set_sensitive (
113 E_COMPOSER_HEADER (object),
114 g_value_get_boolean (value));
115 return;
116
117 case PROP_VISIBLE:
118 e_composer_header_set_visible (
119 E_COMPOSER_HEADER (object),
120 g_value_get_boolean (value));
121 return;
122 }
123
124 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
125 }
126
127 static void
composer_header_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)128 composer_header_get_property (GObject *object,
129 guint property_id,
130 GValue *value,
131 GParamSpec *pspec)
132 {
133 EComposerHeaderPrivate *priv;
134
135 priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
136
137 switch (property_id) {
138 case PROP_BUTTON: /* construct only */
139 g_value_set_boolean (value, priv->button);
140 return;
141
142 case PROP_LABEL: /* construct only */
143 g_value_set_string (value, priv->label);
144 return;
145
146 case PROP_REGISTRY:
147 g_value_set_object (
148 value, e_composer_header_get_registry (
149 E_COMPOSER_HEADER (object)));
150 return;
151
152 case PROP_SENSITIVE:
153 g_value_set_boolean (
154 value, e_composer_header_get_sensitive (
155 E_COMPOSER_HEADER (object)));
156 return;
157
158 case PROP_VISIBLE:
159 g_value_set_boolean (
160 value, e_composer_header_get_visible (
161 E_COMPOSER_HEADER (object)));
162 return;
163 }
164
165 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
166 }
167
168 static void
composer_header_dispose(GObject * object)169 composer_header_dispose (GObject *object)
170 {
171 EComposerHeader *header = E_COMPOSER_HEADER (object);
172
173 g_clear_object (&header->title_widget);
174 g_clear_object (&header->input_widget);
175 g_clear_object (&header->priv->registry);
176
177 /* Chain up to parent's dispose() method. */
178 G_OBJECT_CLASS (e_composer_header_parent_class)->dispose (object);
179 }
180
181 static void
composer_header_finalize(GObject * object)182 composer_header_finalize (GObject *object)
183 {
184 EComposerHeaderPrivate *priv;
185
186 priv = E_COMPOSER_HEADER_GET_PRIVATE (object);
187
188 g_free (priv->label);
189
190 /* Chain up to parent's finalize() method. */
191 G_OBJECT_CLASS (e_composer_header_parent_class)->finalize (object);
192 }
193
194 static void
composer_header_constructed(GObject * object)195 composer_header_constructed (GObject *object)
196 {
197 EComposerHeader *header;
198 GtkWidget *widget;
199 GtkWidget *label;
200
201 header = E_COMPOSER_HEADER (object);
202
203 /* Chain up to parent's method. */
204 G_OBJECT_CLASS (e_composer_header_parent_class)->constructed (object);
205
206 if (header->input_widget == NULL) {
207 g_critical (
208 "EComposerHeader's input_widget "
209 "must be set before chaining up");
210 return;
211 }
212
213 if (header->priv->button) {
214 widget = gtk_button_new_with_mnemonic (header->priv->label);
215 gtk_widget_set_can_focus (widget, FALSE);
216 g_signal_connect (
217 widget, "clicked",
218 G_CALLBACK (composer_header_button_clicked_cb),
219 header);
220 label = gtk_bin_get_child (GTK_BIN (widget));
221 } else {
222 widget = gtk_label_new_with_mnemonic (header->priv->label);
223 gtk_label_set_mnemonic_widget (
224 GTK_LABEL (widget), header->input_widget);
225 label = widget;
226 }
227
228 gtk_misc_set_alignment (GTK_MISC (label), 1.0, 0.5);
229
230 header->title_widget = g_object_ref_sink (widget);
231
232 e_binding_bind_property (
233 header, "visible",
234 header->title_widget, "visible",
235 G_BINDING_SYNC_CREATE);
236
237 e_binding_bind_property (
238 header, "visible",
239 header->input_widget, "visible",
240 G_BINDING_SYNC_CREATE);
241 }
242
243 static void
e_composer_header_class_init(EComposerHeaderClass * class)244 e_composer_header_class_init (EComposerHeaderClass *class)
245 {
246 GObjectClass *object_class;
247
248 g_type_class_add_private (class, sizeof (EComposerHeaderPrivate));
249
250 object_class = G_OBJECT_CLASS (class);
251 object_class->set_property = composer_header_set_property;
252 object_class->get_property = composer_header_get_property;
253 object_class->dispose = composer_header_dispose;
254 object_class->finalize = composer_header_finalize;
255 object_class->constructed = composer_header_constructed;
256
257 g_object_class_install_property (
258 object_class,
259 PROP_BUTTON,
260 g_param_spec_boolean (
261 "button",
262 NULL,
263 NULL,
264 FALSE,
265 G_PARAM_READWRITE |
266 G_PARAM_CONSTRUCT_ONLY |
267 G_PARAM_STATIC_STRINGS));
268
269 g_object_class_install_property (
270 object_class,
271 PROP_LABEL,
272 g_param_spec_string (
273 "label",
274 NULL,
275 NULL,
276 NULL,
277 G_PARAM_READWRITE |
278 G_PARAM_CONSTRUCT_ONLY |
279 G_PARAM_STATIC_STRINGS));
280
281 g_object_class_install_property (
282 object_class,
283 PROP_REGISTRY,
284 g_param_spec_object (
285 "registry",
286 NULL,
287 NULL,
288 E_TYPE_SOURCE_REGISTRY,
289 G_PARAM_READWRITE |
290 G_PARAM_CONSTRUCT_ONLY |
291 G_PARAM_STATIC_STRINGS));
292
293 g_object_class_install_property (
294 object_class,
295 PROP_SENSITIVE,
296 g_param_spec_boolean (
297 "sensitive",
298 NULL,
299 NULL,
300 FALSE,
301 G_PARAM_READWRITE |
302 G_PARAM_STATIC_STRINGS));
303
304 g_object_class_install_property (
305 object_class,
306 PROP_VISIBLE,
307 g_param_spec_boolean (
308 "visible",
309 NULL,
310 NULL,
311 FALSE,
312 G_PARAM_READWRITE |
313 G_PARAM_STATIC_STRINGS));
314
315 signal_ids[CHANGED] = g_signal_new (
316 "changed",
317 G_TYPE_FROM_CLASS (class),
318 G_SIGNAL_RUN_LAST,
319 G_STRUCT_OFFSET (EComposerHeaderClass, changed),
320 NULL, NULL,
321 g_cclosure_marshal_VOID__VOID,
322 G_TYPE_NONE, 0);
323
324 signal_ids[CLICKED] = g_signal_new (
325 "clicked",
326 G_TYPE_FROM_CLASS (class),
327 G_SIGNAL_RUN_LAST,
328 G_STRUCT_OFFSET (EComposerHeaderClass, clicked),
329 NULL, NULL,
330 g_cclosure_marshal_VOID__VOID,
331 G_TYPE_NONE, 0);
332 }
333
334 static void
e_composer_header_init(EComposerHeader * header)335 e_composer_header_init (EComposerHeader *header)
336 {
337 header->priv = E_COMPOSER_HEADER_GET_PRIVATE (header);
338 }
339
340 const gchar *
e_composer_header_get_label(EComposerHeader * header)341 e_composer_header_get_label (EComposerHeader *header)
342 {
343 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL);
344
345 return header->priv->label;
346 }
347
348 ESourceRegistry *
e_composer_header_get_registry(EComposerHeader * header)349 e_composer_header_get_registry (EComposerHeader *header)
350 {
351 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), NULL);
352
353 return header->priv->registry;
354 }
355
356 gboolean
e_composer_header_get_sensitive(EComposerHeader * header)357 e_composer_header_get_sensitive (EComposerHeader *header)
358 {
359 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
360
361 return header->priv->sensitive;
362 }
363
364 void
e_composer_header_set_sensitive(EComposerHeader * header,gboolean sensitive)365 e_composer_header_set_sensitive (EComposerHeader *header,
366 gboolean sensitive)
367 {
368 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
369
370 if (header->priv->sensitive == sensitive)
371 return;
372
373 header->priv->sensitive = sensitive;
374
375 g_object_notify (G_OBJECT (header), "sensitive");
376 }
377
378 gboolean
e_composer_header_get_visible(EComposerHeader * header)379 e_composer_header_get_visible (EComposerHeader *header)
380 {
381 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
382
383 return header->priv->visible;
384 }
385
386 void
e_composer_header_set_visible(EComposerHeader * header,gboolean visible)387 e_composer_header_set_visible (EComposerHeader *header,
388 gboolean visible)
389 {
390 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
391
392 if (header->priv->visible == visible)
393 return;
394
395 header->priv->visible = visible;
396
397 g_object_notify (G_OBJECT (header), "visible");
398 }
399
400 void
e_composer_header_set_title_tooltip(EComposerHeader * header,const gchar * tooltip)401 e_composer_header_set_title_tooltip (EComposerHeader *header,
402 const gchar *tooltip)
403 {
404 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
405
406 gtk_widget_set_tooltip_text (header->title_widget, tooltip);
407 }
408
409 void
e_composer_header_set_input_tooltip(EComposerHeader * header,const gchar * tooltip)410 e_composer_header_set_input_tooltip (EComposerHeader *header,
411 const gchar *tooltip)
412 {
413 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
414
415 gtk_widget_set_tooltip_text (header->input_widget, tooltip);
416 }
417
418 gboolean
e_composer_header_get_title_has_tooltip(EComposerHeader * header)419 e_composer_header_get_title_has_tooltip (EComposerHeader *header)
420 {
421 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
422
423 return gtk_widget_get_has_tooltip (header->title_widget);
424 }
425
426 void
e_composer_header_set_title_has_tooltip(EComposerHeader * header,gboolean has_tooltip)427 e_composer_header_set_title_has_tooltip (EComposerHeader *header,
428 gboolean has_tooltip)
429 {
430 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
431
432 gtk_widget_set_has_tooltip (header->title_widget, has_tooltip);
433 }
434
435 gboolean
e_composer_header_get_input_has_tooltip(EComposerHeader * header)436 e_composer_header_get_input_has_tooltip (EComposerHeader *header)
437 {
438 g_return_val_if_fail (E_IS_COMPOSER_HEADER (header), FALSE);
439
440 return gtk_widget_get_has_tooltip (header->input_widget);
441 }
442
443 void
e_composer_header_set_input_has_tooltip(EComposerHeader * header,gboolean has_tooltip)444 e_composer_header_set_input_has_tooltip (EComposerHeader *header,
445 gboolean has_tooltip)
446 {
447 g_return_if_fail (E_IS_COMPOSER_HEADER (header));
448
449 gtk_widget_set_has_tooltip (header->input_widget, has_tooltip);
450 }
451