56
58
static GdkColor colors[] = {
60
{ 0x0, 0x0000, 0x0000, 0x0000 },
57
61
/* light palette */
58
62
{ 0x0, 0xfc00, 0xe900, 0x4f00 }, /* butter */
59
63
{ 0x0, 0xfc00, 0xaf00, 0x3e00 }, /* orange */
242
get_list_foreach (gpointer key,
246
*list = g_list_prepend (*list, key);
250
get_list (GHashTable *table)
254
g_hash_table_foreach (table, (GHFunc) get_list_foreach, &list);
259
246
giggle_graph_renderer_render (GtkCellRenderer *cell,
260
247
GdkWindow *window,
261
248
GtkWidget *widget,
267
254
GiggleGraphRendererPrivate *priv;
268
255
GiggleGraphRendererPathState *path_state;
269
256
GiggleRevision *revision;
270
GHashTable *paths_state;
273
261
gint cur_pos, pos;
274
GList *children, *paths, *path;
277
265
priv = GIGGLE_GRAPH_RENDERER (cell)->_priv;
279
g_return_if_fail (priv->revision != NULL);
267
if (!priv->revision) {
281
271
cr = gdk_cairo_create (window);
282
272
x = cell_area->x;
285
275
revision = priv->revision;
286
276
size = PANGO_PIXELS (pango_font_description_get_size (widget->style->font_desc));
278
table = g_hash_table_new (g_direct_hash, g_direct_equal);
288
279
paths_state = g_object_get_qdata (G_OBJECT (revision), revision_paths_state_quark);
289
280
children = giggle_revision_get_children (revision);
290
281
cur_pos = GPOINTER_TO_INT (g_hash_table_lookup (priv->paths_info, revision));
291
path_state = g_hash_table_lookup (paths_state, GINT_TO_POINTER (cur_pos));
292
paths = path = get_list (paths_state);
293
282
cairo_set_line_width (cr, LINE_WIDTH (size));
295
284
/* paint paths */
297
pos = GPOINTER_TO_INT (path->data);
298
path_state = g_hash_table_lookup (paths_state, GINT_TO_POINTER (pos));
285
for (i = 0; i < paths_state->len; i++) {
286
path_state = & g_array_index (paths_state, GiggleGraphRendererPathState, i);
287
g_hash_table_insert (table, GINT_TO_POINTER ((gint) path_state->n_path), path_state);
288
pos = path_state->n_path;
300
if (path_state->lower_color &&
290
if (path_state->lower_n_color != INVALID_COLOR &&
301
291
(pos != cur_pos || giggle_revision_get_parents (revision))) {
302
gdk_cairo_set_source_color (cr, path_state->lower_color);
292
gdk_cairo_set_source_color (cr, &colors[path_state->lower_n_color]);
303
293
cairo_move_to (cr, x + (pos * PATH_SPACE (size)), y + (h / 2));
304
294
cairo_line_to (cr, x + (pos * PATH_SPACE (size)), y + h);
305
295
cairo_stroke (cr);
308
if (path_state->upper_color) {
309
gdk_cairo_set_source_color (cr, path_state->upper_color);
298
if (path_state->upper_n_color != INVALID_COLOR) {
299
gdk_cairo_set_source_color (cr, &colors[path_state->upper_n_color]);
310
300
cairo_move_to (cr, x + (pos * PATH_SPACE (size)), y);
311
301
cairo_line_to (cr, x + (pos * PATH_SPACE (size)), y + (h / 2));
312
302
cairo_stroke (cr);
318
306
/* paint connections between paths */
319
307
while (children) {
320
308
pos = GPOINTER_TO_INT (g_hash_table_lookup (priv->paths_info, children->data));
321
path_state = g_hash_table_lookup (paths_state, GINT_TO_POINTER (pos));
309
path_state = g_hash_table_lookup (table, GINT_TO_POINTER (pos));
323
if (path_state->upper_color) {
324
gdk_cairo_set_source_color (cr, path_state->upper_color);
311
if (path_state->upper_n_color != INVALID_COLOR) {
312
gdk_cairo_set_source_color (cr, &colors[path_state->upper_n_color]);
325
313
cairo_move_to (cr,
326
314
x + (cur_pos * PATH_SPACE (size)),
343
331
cairo_stroke (cr);
345
333
/* paint internal circle */
346
path_state = g_hash_table_lookup (paths_state, GINT_TO_POINTER (cur_pos));
347
gdk_cairo_set_source_color (cr, path_state->lower_color);
334
path_state = g_hash_table_lookup (table, GINT_TO_POINTER (cur_pos));
335
gdk_cairo_set_source_color (cr, &colors[path_state->lower_n_color]);
349
337
x + (cur_pos * PATH_SPACE (size)),
388
376
gpointer user_data)
390
GiggleGraphRendererPathState *path_state;
391
GHashTable *table = (GHashTable *) user_data;
393
path_state = g_new0 (GiggleGraphRendererPathState, 1);
394
path_state->lower_color = value;
395
path_state->upper_color = value;
396
g_hash_table_insert (table, key, path_state);
378
GiggleGraphRendererPathState path_state;
380
gint n_color, n_path;
382
array = (GArray *) user_data;
383
n_color = GPOINTER_TO_INT (value);
384
n_path = GPOINTER_TO_INT (key);
386
path_state.n_path = n_path;
387
path_state.lower_n_color = n_color;
388
path_state.upper_n_color = n_color;
390
g_array_append_val (array, path_state);
394
get_initial_status (GHashTable *visible_paths)
399
size = g_hash_table_size (visible_paths);
400
array = g_array_sized_new (FALSE, TRUE, sizeof (GiggleGraphRendererPathState), size);
402
g_hash_table_foreach (visible_paths, (GHFunc) get_initial_status_foreach, array);
400
get_initial_status (GHashTable *paths,
401
GHashTable *visible_paths)
408
free_paths_state (GArray *array)
403
g_hash_table_foreach (visible_paths, (GHFunc) get_initial_status_foreach, paths);
410
g_array_free (array, FALSE);
409
416
GHashTable *visible_paths,
412
GiggleGraphRendererPathState *path_state;
419
GiggleGraphRendererPathState path_state;
413
420
GiggleGraphRendererPrivate *priv;
414
GHashTable *paths_state;
416
424
gboolean current_path_reused = FALSE;
417
425
gboolean update_color;
420
428
priv = renderer->_priv;
421
429
children = giggle_revision_get_children (revision);
422
430
update_color = (g_list_length (children) > 1);
423
paths_state = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
424
get_initial_status (paths_state, visible_paths);
431
paths_state = get_initial_status (visible_paths);
426
433
while (children) {
427
path_state = g_new0 (GiggleGraphRendererPathState, 1);
428
n_path = GPOINTER_TO_INT (g_hash_table_lookup (priv->paths_info, children->data));
434
rev = GIGGLE_REVISION (children->data);
435
n_path = GPOINTER_TO_INT (g_hash_table_lookup (priv->paths_info, rev));
431
438
/* there wasn't a path for this revision, choose one */
436
443
find_free_path (visible_paths, &priv->n_paths, &n_path);
439
g_hash_table_insert (priv->paths_info, children->data, GINT_TO_POINTER (n_path));
440
path_state->lower_color = g_hash_table_lookup (visible_paths, GINT_TO_POINTER (n_path));
446
g_hash_table_insert (priv->paths_info, rev, GINT_TO_POINTER (n_path));
447
path_state.lower_n_color =
448
GPOINTER_TO_INT (g_hash_table_lookup (visible_paths, GINT_TO_POINTER (n_path)));
442
450
if (update_color) {
443
*n_color = NEXT_COLOR (*n_color);
444
path_state->upper_color = &colors[*n_color];
451
path_state.upper_n_color = *n_color = NEXT_COLOR (*n_color);
446
path_state->upper_color = path_state->lower_color;
453
path_state.upper_n_color = path_state.lower_n_color;
449
path_state->lower_color = g_hash_table_lookup (visible_paths, GINT_TO_POINTER (n_path));
450
path_state->upper_color = path_state->lower_color;
456
path_state.lower_n_color =
457
GPOINTER_TO_INT (g_hash_table_lookup (visible_paths, GINT_TO_POINTER (n_path)));
459
path_state.upper_n_color = path_state.lower_n_color;
453
g_hash_table_insert (visible_paths, GINT_TO_POINTER (n_path), path_state->upper_color);
454
g_hash_table_insert (paths_state, GINT_TO_POINTER (n_path), path_state);
462
path_state.n_path = n_path;
463
g_hash_table_insert (visible_paths, GINT_TO_POINTER (n_path), GINT_TO_POINTER ((gint) path_state.upper_n_color));
464
g_array_append_val (paths_state, path_state);
456
466
children = children->next;
460
470
/* current path is a dead end, remove it from the visible paths table */
461
471
n_path = GPOINTER_TO_INT (g_hash_table_lookup (priv->paths_info, revision));
462
472
g_hash_table_remove (visible_paths, GINT_TO_POINTER (n_path));
463
path_state = g_hash_table_lookup (paths_state, GINT_TO_POINTER (n_path));
464
path_state->upper_color = NULL;
474
for (i = 0; i < paths_state->len; i++) {
475
path_state = g_array_index (paths_state, GiggleGraphRendererPathState, i);
477
if (path_state.n_path == n_path) {
478
path_state.upper_n_color = INVALID_COLOR;
479
((GiggleGraphRendererPathState *) paths_state->data)[i] = path_state;
467
485
g_object_set_qdata_full (G_OBJECT (revision), revision_paths_state_quark,
468
paths_state, (GDestroyNotify) g_hash_table_destroy);
486
paths_state, (GDestroyNotify) free_paths_state);
505
523
gtk_tree_model_iter_nth_child (model, &iter, NULL, n_children);
506
524
gtk_tree_model_get (model, &iter, column, &revision, -1);
508
if (!giggle_revision_get_parents (revision)) {
509
n_color = NEXT_COLOR (n_color);
510
find_free_path (visible_paths, &priv->n_paths, &n_path);
511
g_hash_table_insert (priv->paths_info, revision, GINT_TO_POINTER (n_path));
512
g_hash_table_insert (visible_paths, GINT_TO_POINTER (n_path), &colors[n_color]);
527
if (!giggle_revision_get_parents (revision)) {
528
n_color = NEXT_COLOR (n_color);
529
find_free_path (visible_paths, &priv->n_paths, &n_path);
530
g_hash_table_insert (priv->paths_info, revision, GINT_TO_POINTER (n_path));
531
g_hash_table_insert (visible_paths, GINT_TO_POINTER (n_path), GINT_TO_POINTER (n_color));
534
giggle_graph_renderer_calculate_revision_state (renderer, revision, visible_paths, &n_color);
535
g_object_unref (revision);
515
giggle_graph_renderer_calculate_revision_state (renderer, revision, visible_paths, &n_color);
516
g_object_unref (revision);
519
539
g_hash_table_destroy (visible_paths);