1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, see <http://www.gnu.org/licenses/>.
13  *
14  *
15  * Authors:
16  *		Chris Lahey <clahey@ximian.com>
17  *
18  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
19  *
20  */
21 
22 #include "evolution-config.h"
23 
24 #include "e-minicard-label.h"
25 
26 #include <gtk/gtk.h>
27 #include <glib/gi18n.h>
28 #include <gdk/gdkkeysyms.h>
29 
30 #include <libgnomecanvas/libgnomecanvas.h>
31 
32 #include "e-util/e-util.h"
33 
34 static void e_minicard_label_set_property  (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
35 static void e_minicard_label_get_property  (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
36 static gboolean e_minicard_label_event (GnomeCanvasItem *item, GdkEvent *event);
37 static void e_minicard_label_realize (GnomeCanvasItem *item);
38 static void e_minicard_label_reflow (GnomeCanvasItem *item, gint flags);
39 static void e_minicard_label_style_updated (EMinicardLabel *label);
40 
41 static void e_minicard_label_resize_children (EMinicardLabel *e_minicard_label);
42 
43 static void set_colors (EMinicardLabel *label);
44 
45 enum {
46 	PROP_0,
47 	PROP_WIDTH,
48 	PROP_HEIGHT,
49 	PROP_HAS_FOCUS,
50 	PROP_FIELD,
51 	PROP_FIELDNAME,
52 	PROP_TEXT_MODEL,
53 	PROP_MAX_FIELD_NAME_WIDTH,
54 	PROP_EDITABLE
55 };
56 
57 enum {
58 	STYLE_UPDATED,
59 	LAST_SIGNAL
60 };
61 
62 static guint e_minicard_label_signals[LAST_SIGNAL] = {0, };
63 
G_DEFINE_TYPE(EMinicardLabel,e_minicard_label,GNOME_TYPE_CANVAS_GROUP)64 G_DEFINE_TYPE (
65 	EMinicardLabel,
66 	e_minicard_label,
67 	GNOME_TYPE_CANVAS_GROUP)
68 
69 static void
70 e_minicard_label_class_init (EMinicardLabelClass *class)
71 {
72 	GObjectClass *object_class;
73 	GnomeCanvasItemClass *item_class;
74 
75 	object_class = G_OBJECT_CLASS (class);
76 	item_class = (GnomeCanvasItemClass *) class;
77 
78 	class->style_updated = e_minicard_label_style_updated;
79 
80 	object_class->set_property = e_minicard_label_set_property;
81 	object_class->get_property = e_minicard_label_get_property;
82 
83 	g_object_class_install_property (
84 		object_class,
85 		PROP_WIDTH,
86 		g_param_spec_double (
87 			"width",
88 			"Width",
89 			NULL,
90 			0.0, G_MAXDOUBLE, 10.0,
91 			G_PARAM_READWRITE));
92 
93 	g_object_class_install_property (
94 		object_class,
95 		PROP_HEIGHT,
96 		g_param_spec_double (
97 			"height",
98 			"Height",
99 			NULL,
100 			0.0, G_MAXDOUBLE, 10.0,
101 			G_PARAM_READWRITE));
102 
103 	g_object_class_install_property (
104 		object_class,
105 		PROP_HAS_FOCUS,
106 		g_param_spec_boolean (
107 			"has_focus",
108 			"Has Focus",
109 			NULL,
110 			FALSE,
111 			G_PARAM_READWRITE));
112 
113 	g_object_class_install_property (
114 		object_class,
115 		PROP_FIELD,
116 		g_param_spec_string (
117 			"field",
118 			"Field",
119 			NULL,
120 			NULL,
121 			G_PARAM_READWRITE));
122 
123 	g_object_class_install_property (
124 		object_class,
125 		PROP_FIELDNAME,
126 		g_param_spec_string (
127 			"fieldname",
128 			"Field Name",
129 			NULL,
130 			NULL,
131 			G_PARAM_READWRITE));
132 
133 	g_object_class_install_property (
134 		object_class,
135 		PROP_TEXT_MODEL,
136 		g_param_spec_object (
137 			"text_model",
138 			"Text Model",
139 			NULL,
140 			E_TYPE_TEXT_MODEL,
141 			G_PARAM_READWRITE));
142 
143 	g_object_class_install_property (
144 		object_class,
145 		PROP_MAX_FIELD_NAME_WIDTH,
146 		g_param_spec_double (
147 			"max_field_name_length",
148 			"Max field name length",
149 			NULL,
150 			-1.0, G_MAXDOUBLE, -1.0,
151 			G_PARAM_READWRITE));
152 
153 	g_object_class_install_property (
154 		object_class,
155 		PROP_EDITABLE,
156 		g_param_spec_boolean (
157 			"editable",
158 			"Editable",
159 			NULL,
160 			FALSE,
161 			G_PARAM_READWRITE));
162 
163 	e_minicard_label_signals[STYLE_UPDATED] = g_signal_new (
164 		"style_updated",
165 		G_TYPE_FROM_CLASS (object_class),
166 		G_SIGNAL_RUN_FIRST,
167 		G_STRUCT_OFFSET (EMinicardLabelClass, style_updated),
168 		NULL, NULL,
169 		g_cclosure_marshal_VOID__VOID,
170 		G_TYPE_NONE, 0);
171 
172 	/* GnomeCanvasItem method overrides */
173 	item_class->realize = e_minicard_label_realize;
174 	item_class->event = e_minicard_label_event;
175 }
176 
177 static void
e_minicard_label_init(EMinicardLabel * minicard_label)178 e_minicard_label_init (EMinicardLabel *minicard_label)
179 {
180 	minicard_label->width = 10;
181 	minicard_label->height = 10;
182 	minicard_label->rect = NULL;
183 	minicard_label->fieldname = NULL;
184 	minicard_label->field = NULL;
185 
186 	minicard_label->max_field_name_length = -1;
187 
188 	e_canvas_item_set_reflow_callback (
189 		GNOME_CANVAS_ITEM (minicard_label),
190 		e_minicard_label_reflow);
191 }
192 
193 static void
e_minicard_label_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)194 e_minicard_label_set_property (GObject *object,
195                                guint property_id,
196                                const GValue *value,
197                                GParamSpec *pspec)
198 {
199 	EMinicardLabel *e_minicard_label;
200 	GnomeCanvasItem *item;
201 
202 	e_minicard_label = E_MINICARD_LABEL (object);
203 	item = GNOME_CANVAS_ITEM (object);
204 
205 	switch (property_id) {
206 	case PROP_WIDTH:
207 		e_minicard_label->width = g_value_get_double (value);
208 		e_minicard_label_resize_children (e_minicard_label);
209 		e_canvas_item_request_reflow (item);
210 		break;
211 	case PROP_HAS_FOCUS:
212 		if (e_minicard_label->field && (g_value_get_boolean (value) != E_FOCUS_NONE))
213 			e_canvas_item_grab_focus (e_minicard_label->field, FALSE);
214 		break;
215 	case PROP_FIELD:
216 		gnome_canvas_item_set (e_minicard_label->field, "text", g_value_get_string (value), NULL);
217 		break;
218 	case PROP_FIELDNAME:
219 		gnome_canvas_item_set (e_minicard_label->fieldname, "text", g_value_get_string (value), NULL);
220 		break;
221 	case PROP_TEXT_MODEL:
222 		gnome_canvas_item_set (e_minicard_label->field, "model", g_value_get_object (value), NULL);
223 		break;
224 	case PROP_MAX_FIELD_NAME_WIDTH:
225 		e_minicard_label->max_field_name_length = g_value_get_double (value);
226 		break;
227 	case PROP_EDITABLE:
228 		e_minicard_label->editable = g_value_get_boolean (value);
229 		g_object_set (e_minicard_label->field, "editable", FALSE /* e_minicard_label->editable */, NULL);
230 		break;
231 	default:
232 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
233 		break;
234 	}
235 }
236 
237 static void
e_minicard_label_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)238 e_minicard_label_get_property (GObject *object,
239                                guint property_id,
240                                GValue *value,
241                                GParamSpec *pspec)
242 {
243 	EMinicardLabel *e_minicard_label;
244 
245 	e_minicard_label = E_MINICARD_LABEL (object);
246 
247 	switch (property_id) {
248 	case PROP_WIDTH:
249 		g_value_set_double (value, e_minicard_label->width);
250 		break;
251 	case PROP_HEIGHT:
252 		g_value_set_double (value, e_minicard_label->height);
253 		break;
254 	case PROP_HAS_FOCUS:
255 		g_value_set_boolean (value, e_minicard_label->has_focus ? E_FOCUS_CURRENT : E_FOCUS_NONE);
256 		break;
257 	case PROP_FIELD:
258 		g_object_get_property (
259 			G_OBJECT (e_minicard_label->field),
260 			"text", value);
261 		break;
262 	case PROP_FIELDNAME:
263 		g_object_get_property (
264 			G_OBJECT (e_minicard_label->fieldname),
265 			"text", value);
266 		break;
267 	case PROP_TEXT_MODEL:
268 		g_object_get_property (
269 			G_OBJECT (e_minicard_label->field),
270 			"model", value);
271 		break;
272 	case PROP_MAX_FIELD_NAME_WIDTH:
273 		g_value_set_double (value, e_minicard_label->max_field_name_length);
274 		break;
275 	case PROP_EDITABLE:
276 		g_value_set_boolean (value, e_minicard_label->editable);
277 		break;
278 	default:
279 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
280 		break;
281 	}
282 }
283 
284 static void
e_minicard_label_realize(GnomeCanvasItem * item)285 e_minicard_label_realize (GnomeCanvasItem *item)
286 {
287 	EMinicardLabel *e_minicard_label;
288 	GnomeCanvasGroup *group;
289 
290 	e_minicard_label = E_MINICARD_LABEL (item);
291 	group = GNOME_CANVAS_GROUP (item);
292 
293 	GNOME_CANVAS_ITEM_CLASS (e_minicard_label_parent_class)->realize (item);
294 
295 	e_canvas_item_request_reflow (item);
296 
297 	e_minicard_label->rect = gnome_canvas_item_new (
298 		group,
299 		gnome_canvas_rect_get_type (),
300 		"x1", (gdouble) 0,
301 		"y1", (gdouble) 0,
302 		"x2", (gdouble) e_minicard_label->width - 1,
303 		"y2", (gdouble) e_minicard_label->height - 1,
304 		"outline_color", NULL,
305 		NULL);
306 
307 	e_minicard_label->fieldname = gnome_canvas_item_new (
308 		group,
309 		e_text_get_type (),
310 		"clip_width", (gdouble) (e_minicard_label->width / 2 - 4),
311 		"clip", TRUE,
312 		"use_ellipsis", TRUE,
313 		"fill_color", "black",
314 		"im_context", E_CANVAS (item->canvas)->im_context,
315 		NULL);
316 
317 	e_canvas_item_move_absolute (e_minicard_label->fieldname, 2, 1);
318 
319 	e_minicard_label->field = gnome_canvas_item_new (
320 		group,
321 		e_text_get_type (),
322 		"clip_width", (gdouble) ((e_minicard_label->width + 1) / 2 - 4),
323 		"clip", TRUE,
324 		"use_ellipsis", TRUE,
325 		"fill_color", "black",
326 		"editable", FALSE, /* e_minicard_label->editable, */
327 		"im_context", E_CANVAS (item->canvas)->im_context,
328 		NULL);
329 
330 	e_canvas_item_move_absolute (
331 		e_minicard_label->field,
332 		(e_minicard_label->width / 2 + 2), 1);
333 
334 	set_colors (e_minicard_label);
335 
336 	e_canvas_item_request_reflow (item);
337 }
338 
339 static gboolean
e_minicard_label_event(GnomeCanvasItem * item,GdkEvent * event)340 e_minicard_label_event (GnomeCanvasItem *item,
341                         GdkEvent *event)
342 {
343 	EMinicardLabel *e_minicard_label;
344 
345 	e_minicard_label = E_MINICARD_LABEL (item);
346 
347 	switch (event->type) {
348 	case GDK_KEY_PRESS:
349 		if (event->key.keyval == GDK_KEY_Escape) {
350 			GnomeCanvasItem *parent;
351 
352 			e_text_cancel_editing (E_TEXT (e_minicard_label->field));
353 
354 			parent = GNOME_CANVAS_ITEM (e_minicard_label)->parent;
355 			if (parent)
356 				e_canvas_item_grab_focus (parent, FALSE);
357 		}
358 		break;
359 	case GDK_FOCUS_CHANGE: {
360 		GdkEventFocus *focus_event = (GdkEventFocus *) event;
361 
362 		e_minicard_label->has_focus = focus_event->in;
363 		set_colors (e_minicard_label);
364 
365 		g_object_set (
366 			e_minicard_label->field,
367 			"handle_popup", e_minicard_label->has_focus,
368 			NULL);
369 		break;
370 	}
371 	case GDK_BUTTON_PRESS:
372 	case GDK_BUTTON_RELEASE:
373 	case GDK_MOTION_NOTIFY:
374 	case GDK_ENTER_NOTIFY:
375 	case GDK_LEAVE_NOTIFY: {
376 		gboolean return_val;
377 		g_signal_emit_by_name (e_minicard_label->field, "event", event, &return_val);
378 		return return_val;
379 	}
380 	default:
381 		break;
382 	}
383 
384 	return GNOME_CANVAS_ITEM_CLASS (e_minicard_label_parent_class)->
385 		event (item, event);
386 }
387 
388 static void
e_minicard_label_resize_children(EMinicardLabel * e_minicard_label)389 e_minicard_label_resize_children (EMinicardLabel *e_minicard_label)
390 {
391 	gdouble left_width;
392 	gdouble fieldnamewidth;
393 	gdouble fieldwidth;
394 	gboolean is_rtl = (gtk_widget_get_default_direction () == GTK_TEXT_DIR_RTL);
395 	if (e_minicard_label->max_field_name_length != -1 && ((e_minicard_label->width / 2) - 4 > e_minicard_label->max_field_name_length))
396 		left_width = e_minicard_label->max_field_name_length;
397 	else
398 		left_width = e_minicard_label->width / 2 - 4;
399 
400 	fieldnamewidth = (gdouble) MAX (left_width, 0);
401 	fieldwidth = (gdouble) MAX (e_minicard_label->width - 8 - left_width, 0);
402 	gnome_canvas_item_set (
403 		e_minicard_label->fieldname,
404 		"clip_width", is_rtl ? fieldwidth : fieldnamewidth,
405 		NULL);
406 	gnome_canvas_item_set (
407 		e_minicard_label->field,
408 		"clip_width", is_rtl ? fieldnamewidth : fieldwidth,
409 		NULL);
410 }
411 
412 static void
set_colors(EMinicardLabel * label)413 set_colors (EMinicardLabel *label)
414 {
415 	GnomeCanvasItem *item = GNOME_CANVAS_ITEM (label);
416 
417 	if ((item->flags & GNOME_CANVAS_ITEM_REALIZED)) {
418 		GdkColor text;
419 		GtkWidget *widget;
420 
421 		widget = GTK_WIDGET (GNOME_CANVAS_ITEM (label)->canvas);
422 
423 		e_utils_get_theme_color_color (widget, "theme_text_color,theme_fg_color", E_UTILS_DEFAULT_THEME_TEXT_COLOR, &text);
424 
425 		if (label->has_focus) {
426 			GdkColor outline, fill;
427 
428 			e_utils_get_theme_color_color (widget, "theme_selected_bg_color", E_UTILS_DEFAULT_THEME_SELECTED_BG_COLOR, &outline);
429 			e_utils_get_theme_color_color (widget, "theme_bg_color", E_UTILS_DEFAULT_THEME_BG_COLOR, &fill);
430 
431 			gnome_canvas_item_set (
432 				label->rect,
433 				"outline_color_gdk", &outline,
434 				"fill_color_gdk", &fill,
435 				NULL);
436 
437 			gnome_canvas_item_set (
438 				label->field,
439 				"fill_color_gdk", &text,
440 				NULL);
441 
442 			gnome_canvas_item_set (
443 				label->fieldname,
444 				"fill_color_gdk", &text,
445 				NULL);
446 		}
447 		else {
448 			gnome_canvas_item_set (
449 				label->rect,
450 				"outline_color_gdk", NULL,
451 				"fill_color_gdk", NULL,
452 				NULL);
453 
454 			gnome_canvas_item_set (
455 				label->field,
456 				"fill_color_gdk", &text,
457 				NULL);
458 
459 			gnome_canvas_item_set (
460 				label->fieldname,
461 				"fill_color_gdk", &text,
462 				NULL);
463 		}
464 	}
465 }
466 
467 static void
e_minicard_label_style_updated(EMinicardLabel * label)468 e_minicard_label_style_updated (EMinicardLabel *label)
469 {
470 	set_colors (label);
471 }
472 
473 static void
e_minicard_label_reflow(GnomeCanvasItem * item,gint flags)474 e_minicard_label_reflow (GnomeCanvasItem *item,
475                          gint flags)
476 {
477 	EMinicardLabel *e_minicard_label = E_MINICARD_LABEL (item);
478 
479 	gint old_height;
480 	gdouble text_height;
481 	gdouble left_width;
482 
483 	old_height = e_minicard_label->height;
484 
485 	g_object_get (
486 		e_minicard_label->fieldname,
487 		"text_height", &text_height,
488 		NULL);
489 
490 	e_minicard_label->height = text_height;
491 
492 	g_object_get (
493 		e_minicard_label->field,
494 		"text_height", &text_height,
495 		NULL);
496 
497 	if (e_minicard_label->height < text_height)
498 		e_minicard_label->height = text_height;
499 	e_minicard_label->height += 3;
500 
501 	gnome_canvas_item_set (
502 		e_minicard_label->rect,
503 		"x2", (gdouble) e_minicard_label->width - 1,
504 		"y2", (gdouble) e_minicard_label->height - 1,
505 		NULL);
506 
507 	gnome_canvas_item_set (
508 		e_minicard_label->fieldname,
509 		"clip_height", (gdouble) e_minicard_label->height - 3,
510 		NULL);
511 
512 	if (e_minicard_label->max_field_name_length != -1 && ((e_minicard_label->width / 2) - 4 > e_minicard_label->max_field_name_length))
513 		left_width = e_minicard_label->max_field_name_length;
514 	else
515 		left_width = e_minicard_label->width / 2 - 4;
516 
517 	e_canvas_item_move_absolute (e_minicard_label->field, left_width + 6, 1);
518 
519 	if (old_height != e_minicard_label->height)
520 		e_canvas_item_request_parent_reflow (item);
521 }
522 
523 GnomeCanvasItem *
e_minicard_label_new(GnomeCanvasGroup * parent)524 e_minicard_label_new (GnomeCanvasGroup *parent)
525 {
526 	return gnome_canvas_item_new (
527 		parent, e_minicard_label_get_type (), NULL);
528 }
529 
530