00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <glib.h>
00034
00035
00036
00037
00038 #include "ergtk_log.h"
00039 #include "ergtkcellrenderertext.h"
00040
00041
00042
00043
00044
00045
00046
00047 typedef enum
00048 {
00049 PROP_NOT_USED = 0,
00050 PROP_FONT,
00051 PROP_HEIGHT,
00052 PROP_TEXT,
00053 PROP_COLOR,
00054 NUM_PROPS
00055 } prop_t;
00056
00057
00058 typedef struct
00059 {
00060 guint n_lines;
00061
00062 struct
00063 {
00064 gchar *font;
00065 guint height;
00066 gchar *text;
00067 gchar *color;
00068 } details[ ERGTK_CELL_RENDERER_TEXT_MAX_LINES ];
00069
00070 } erGtkCellRendererTextPrivate;
00071
00072
00073
00074
00075
00076
00077 static const gchar *PROPNAME_FONT = "font";
00078 static const gchar *PROPNAME_HEIGHT = "height";
00079 static const gchar *PROPNAME_TEXT = "text";
00080 static const gchar *PROPNAME_COLOR = "foreground";
00081
00082
00083
00084
00085
00086
00087 static GtkCellRendererTextClass* g_parent_class = NULL;
00088
00089
00090
00091
00092
00093
00094
00095
00096 static void get_property_impl ( GObject *object,
00097 guint param_id,
00098 GValue *value,
00099 GParamSpec *pspec );
00100
00101 static void set_property_impl ( GObject *object,
00102 guint param_id,
00103 const GValue *value,
00104 GParamSpec *pspec );
00105
00106 static void get_size_impl(GtkCellRenderer *cell,
00107 GtkWidget *widget,
00108 GdkRectangle *cell_area,
00109 gint *x_offset,
00110 gint *y_offset,
00111 gint *width,
00112 gint *height);
00113
00114 static void render_impl (GtkCellRenderer *cell,
00115 GdkWindow *window,
00116 GtkWidget *widget,
00117 GdkRectangle *background_area,
00118 GdkRectangle *cell_area,
00119 GdkRectangle *expose_area,
00120 guint flags);
00121
00122
00123
00124
00125
00126
00127 static void ergtk_cell_renderer_text_class_init (erGtkCellRendererTextClass *klass);
00128 static void ergtk_cell_renderer_text_init (erGtkCellRendererText *thiz);
00129 static void ergtk_cell_renderer_text_finalize (GObject *obj);
00130
00131
00132
00133
00134
00135
00136
00137 GType ergtk_cell_renderer_text_get_type (void)
00138 {
00139 static GType class_type = 0;
00140
00141 if (class_type == 0)
00142 {
00143 static const GTypeInfo class_info =
00144 {
00145 sizeof(erGtkCellRendererTextClass),
00146 NULL,
00147 NULL,
00148 (GClassInitFunc) ergtk_cell_renderer_text_class_init,
00149 NULL,
00150 NULL,
00151 sizeof(erGtkCellRendererText),
00152 0,
00153 (GInstanceInitFunc) ergtk_cell_renderer_text_init,
00154 NULL
00155 };
00156
00157 class_type = g_type_register_static( GTK_TYPE_CELL_RENDERER_TEXT,
00158 "erGtkCellRendererText",
00159 &class_info,
00160 0 );
00161 }
00162
00163 return class_type;
00164 }
00165
00166
00167
00168 static void ergtk_cell_renderer_text_class_init (erGtkCellRendererTextClass* klass)
00169 {
00170 GObjectClass *object_class = (GObjectClass *) klass;
00171 GtkCellRendererClass *cell_renderer_class = (GtkCellRendererClass *) klass;
00172
00173 gint line;
00174 GParamSpec *pspec;
00175 GString *prop_name = g_string_new("");
00176 GString *prop_ext = g_string_new("");
00177
00178
00179 g_parent_class = g_type_class_peek_parent(klass);
00180
00181
00182 cell_renderer_class->render = render_impl;
00183 cell_renderer_class->get_size = get_size_impl;
00184 object_class->get_property = get_property_impl;
00185 object_class->set_property = set_property_impl;
00186 object_class->finalize = ergtk_cell_renderer_text_finalize;
00187
00188
00189 g_type_class_add_private (klass, sizeof(erGtkCellRendererTextPrivate));
00190
00191
00192 for ( line = 0 ; line < ERGTK_CELL_RENDERER_TEXT_MAX_LINES ; line++ )
00193 {
00194 g_string_printf(prop_ext, "-%d", line);
00195
00196
00197 g_string_assign(prop_name, PROPNAME_FONT);
00198 g_string_append(prop_name, prop_ext->str);
00199 pspec = g_param_spec_string( prop_name->str,
00200 prop_name->str,
00201 "Font definition for n-th line",
00202 "",
00203 G_PARAM_READWRITE | G_PARAM_CONSTRUCT );
00204 g_object_class_install_property( object_class, PROP_FONT + (line * NUM_PROPS), pspec);
00205
00206
00207 g_string_assign(prop_name, PROPNAME_HEIGHT);
00208 g_string_append(prop_name, prop_ext->str);
00209 pspec = g_param_spec_uint( prop_name->str,
00210 prop_name->str,
00211 "Line height for n-th line",
00212 0,
00213 200,
00214 10,
00215 G_PARAM_READWRITE | G_PARAM_CONSTRUCT );
00216 g_object_class_install_property( object_class, PROP_HEIGHT + (line * NUM_PROPS), pspec);
00217
00218
00219 g_string_assign(prop_name, PROPNAME_TEXT);
00220 g_string_append(prop_name, prop_ext->str);
00221 pspec = g_param_spec_string( prop_name->str,
00222 prop_name->str,
00223 "Text for n-th line",
00224 "",
00225 G_PARAM_READWRITE | G_PARAM_CONSTRUCT );
00226 g_object_class_install_property( object_class, PROP_TEXT + (line * NUM_PROPS), pspec);
00227
00228
00229 g_string_assign(prop_name, PROPNAME_COLOR);
00230 g_string_append(prop_name, prop_ext->str);
00231 pspec = g_param_spec_string( prop_name->str,
00232 prop_name->str,
00233 "Color for n-th line",
00234 "black",
00235 G_PARAM_READWRITE | G_PARAM_CONSTRUCT );
00236 g_object_class_install_property( object_class, PROP_COLOR + (line * NUM_PROPS), pspec);
00237 }
00238
00239
00240 if (prop_name) { g_string_free(prop_name, TRUE); }
00241 if (prop_ext ) { g_string_free(prop_ext , TRUE); }
00242 }
00243
00244
00245
00246 static void ergtk_cell_renderer_text_init (erGtkCellRendererText *thiz)
00247 {
00248 g_return_if_fail( IS_ERGTK_CELL_RENDERER_TEXT(thiz) );
00249
00250 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(thiz);
00251
00252 gint line;
00253
00254
00255
00256
00257 priv->n_lines = 1;
00258 for ( line = 0 ; line < ERGTK_CELL_RENDERER_TEXT_MAX_LINES ; line++ )
00259 {
00260 priv->details[line].font = NULL;
00261 priv->details[line].text = NULL;
00262 priv->details[line].color = NULL;
00263 }
00264 }
00265
00266
00267
00268 static void ergtk_cell_renderer_text_finalize (GObject *obj)
00269 {
00270 g_return_if_fail( IS_ERGTK_CELL_RENDERER_TEXT(obj) );
00271
00272 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(obj);
00273
00274 gint line;
00275
00276
00277
00278 for ( line = 0 ; line < ERGTK_CELL_RENDERER_TEXT_MAX_LINES ; line++ )
00279 {
00280 g_free(priv->details[line].font);
00281 g_free(priv->details[line].text);
00282 g_free(priv->details[line].color);
00283 }
00284
00285
00286
00287 ((GObjectClass*)g_parent_class)->finalize( obj );
00288 }
00289
00290
00291
00292 GtkCellRenderer *ergtk_cell_renderer_text_new (const guint n_lines)
00293 {
00294 erGtkCellRendererText *thiz = (erGtkCellRendererText*) g_object_new(ERGTK_CELL_RENDERER_TEXT_TYPE, NULL);
00295 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(thiz);
00296
00297 priv->n_lines = MIN( n_lines, ERGTK_CELL_RENDERER_TEXT_MAX_LINES );
00298
00299 return (GtkCellRenderer*) thiz;
00300 }
00301
00302
00303
00304 static void get_property_impl ( GObject *object,
00305 guint param_id,
00306 GValue *value,
00307 GParamSpec *pspec )
00308 {
00309 g_return_if_fail( IS_ERGTK_CELL_RENDERER_TEXT(object) );
00310
00311 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(object);
00312
00313 const gint line = param_id / NUM_PROPS;
00314 const prop_t prop = param_id % NUM_PROPS;
00315
00316 if ( prop == PROP_NOT_USED
00317 || line >= ERGTK_CELL_RENDERER_TEXT_MAX_LINES )
00318 {
00319 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
00320 return;
00321 }
00322
00323 switch (prop)
00324 {
00325 case PROP_FONT:
00326 g_value_set_string (value, priv->details[line].font);
00327 break;
00328
00329 case PROP_HEIGHT:
00330 g_value_set_uint (value, priv->details[line].height);
00331 break;
00332
00333 case PROP_TEXT:
00334 g_value_set_string (value, priv->details[line].text);
00335 break;
00336
00337 case PROP_COLOR:
00338 g_value_set_string (value, priv->details[line].color);
00339 break;
00340
00341 default:
00342 ;
00343 }
00344 }
00345
00346
00347
00348 static void set_property_impl ( GObject *object,
00349 guint param_id,
00350 const GValue *value,
00351 GParamSpec *pspec )
00352 {
00353 g_return_if_fail( IS_ERGTK_CELL_RENDERER_TEXT(object) );
00354
00355 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(object);
00356
00357 guint u;
00358 gchar **cpp;
00359 const gint line = param_id / NUM_PROPS;
00360 const prop_t prop = param_id % NUM_PROPS;
00361
00362 if ( prop == PROP_NOT_USED
00363 || line >= ERGTK_CELL_RENDERER_TEXT_MAX_LINES )
00364 {
00365 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
00366 return;
00367 }
00368
00369 switch (prop)
00370 {
00371 case PROP_FONT:
00372 cpp = &(priv->details[line].font);
00373 g_free(*cpp);
00374 *cpp = g_strdup(g_value_get_string(value));
00375 LOGPRINTF("font[%d] set to [%s]", line, *cpp);
00376 break;
00377
00378 case PROP_HEIGHT:
00379 u = g_value_get_uint(value);
00380 priv->details[line].height = u;
00381 LOGPRINTF("height[%d] set to [%u]", line, u);
00382 break;
00383
00384 case PROP_TEXT:
00385 cpp = &(priv->details[line].text);
00386 g_free(*cpp);
00387 *cpp = g_strdup(g_value_get_string(value));
00388 LOGPRINTF("text[%d] set to [%s]", line, *cpp);
00389 break;
00390
00391 case PROP_COLOR:
00392 g_free(priv->details[line].color);
00393 priv->details[line].color = g_strdup(g_value_get_string(value));
00394 break;
00395
00396 default:
00397 ;
00398 }
00399 }
00400
00401
00402
00403 static void get_size_impl(GtkCellRenderer *cell,
00404 GtkWidget *widget,
00405 GdkRectangle *cell_area,
00406 gint *x_offset,
00407 gint *y_offset,
00408 gint *width,
00409 gint *height)
00410 {
00411 static const int FIXED_HEIGHT = 60;
00412 static const int MIN_WIDTH = 100;
00413 gint calc_width = cell->xpad * 2 + MIN_WIDTH;
00414 gint calc_height = cell->ypad * 2 + FIXED_HEIGHT;
00415
00416 if (cell_area && cell_area->width > calc_width) calc_width = cell_area->width;
00417
00418 if (width) *width = calc_width;
00419 if (height) *height = calc_height;
00420
00421 if (cell_area) {
00422 if (x_offset) {
00423 *x_offset = cell->xalign * (cell_area->width - calc_width);
00424 *x_offset = MAX (*x_offset, 0);
00425 }
00426
00427 if (y_offset) {
00428 *y_offset = cell->yalign * (cell_area->height - calc_height);
00429 *y_offset = MAX (*y_offset, 0);
00430 }
00431 }
00432 }
00433
00434
00435
00436
00437 static void render_impl (GtkCellRenderer *cell,
00438 GdkWindow *window,
00439 GtkWidget *widget,
00440 GdkRectangle *background_area,
00441 GdkRectangle *cell_area,
00442 GdkRectangle *expose_area,
00443 guint flags)
00444 {
00445 g_return_if_fail( IS_ERGTK_CELL_RENDERER_TEXT(cell) );
00446
00447 erGtkCellRendererText *thiz = (erGtkCellRendererText *) cell;
00448 erGtkCellRendererTextPrivate *priv = ERGTK_CELL_RENDERER_TEXT_GET_PRIVATE(thiz);
00449
00450 guint line;
00451 gint height;
00452 gboolean ok;
00453 const gint max_y = cell_area->y + cell_area->height;
00454 GdkRectangle sub_cell_area = *cell_area;
00455 GdkRectangle sub_expose_area;
00456 const gchar *font;
00457 const gchar *text;
00458 const gchar *color;
00459 gchar *font_default = NULL;
00460
00461
00462 g_object_get( thiz,
00463 PROPNAME_FONT, &font_default,
00464 NULL );
00465
00466
00467
00468
00469 flags &= ~GTK_CELL_RENDERER_SELECTED;
00470
00471
00472 for ( line = 0 ; line < priv->n_lines ; line++ )
00473 {
00474
00475 font = priv->details[line].font;
00476 if ( font == NULL
00477 || font[0] == '\0' )
00478 {
00479 font = font_default;
00480 }
00481 text = priv->details[line].text;
00482 if ( text == NULL )
00483 {
00484 text = "";
00485 }
00486 color = priv->details[line].color;
00487 if (color == NULL) color = "black";
00488 g_object_set( thiz,
00489 PROPNAME_FONT, font,
00490 PROPNAME_TEXT, text,
00491 PROPNAME_COLOR, color,
00492 NULL );
00493 LOGPRINTF("line [%d] font [%s] text [%s] color [%s] flags [%d]", line, font, text, color, flags);
00494
00495
00496
00497
00498 height = priv->details[line].height;
00499
00500
00501 sub_cell_area.y = MIN( sub_cell_area.y, max_y );
00502 sub_cell_area.height = MIN( height, (max_y - sub_cell_area.y) );
00503 if ( sub_cell_area.height > 0 )
00504 {
00505 sub_expose_area = *expose_area;
00506 ok = gdk_rectangle_intersect( &sub_cell_area, &sub_expose_area, &sub_expose_area );
00507 if (ok)
00508 {
00509 g_parent_class->parent_class.render( cell,
00510 window,
00511 widget,
00512 background_area,
00513 &sub_cell_area,
00514 &sub_expose_area,
00515 flags );
00516 }
00517 }
00518
00519
00520 sub_cell_area.y += sub_cell_area.height;
00521 }
00522
00523
00524 g_object_set( thiz,
00525 PROPNAME_FONT, font_default,
00526 NULL );
00527
00528
00529 g_free(font_default);
00530
00531 }
00532
00533