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