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