Parent Directory | Revision Log
BCT cleanup
1 | harbaum | 127 | /* |
2 | * Copyright (C) 2009 Till Harbaum <till@harbaum.org>. | ||
3 | * | ||
4 | * This file is part of GPXView. | ||
5 | * | ||
6 | * GPXView is free software: you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation, either version 3 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * GPXView is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with GPXView. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | harbaum | 128 | /* |
21 | * This simple breadcrumbtrail replacement is a simple hbox with | ||
22 | * buttons inside | ||
23 | */ | ||
24 | |||
25 | harbaum | 127 | #include "gpxview.h" |
26 | |||
27 | harbaum | 128 | typedef struct { |
28 | GtkWidget *button; | ||
29 | GDestroyNotify destroy; | ||
30 | gpointer id; | ||
31 | } crumb_t; | ||
32 | harbaum | 127 | |
33 | harbaum | 128 | typedef struct { |
34 | GtkWidget *back; | ||
35 | |||
36 | GSList *crumbs; | ||
37 | } bct_priv_t; | ||
38 | |||
39 | static void bct_free(gpointer data, gpointer user_data) { | ||
40 | g_free(data); | ||
41 | harbaum | 127 | } |
42 | harbaum | 128 | |
43 | static gint bct_destroy_event(GtkWidget *widget, gpointer data ) { | ||
44 | bct_priv_t *priv = (bct_priv_t*)data; | ||
45 | |||
46 | g_slist_foreach(priv->crumbs, bct_free, NULL); | ||
47 | g_free(priv); | ||
48 | |||
49 | return FALSE; | ||
50 | } | ||
51 | |||
52 | static void crumb_destroy(bct_priv_t *priv, crumb_t *crumb) { | ||
53 | /* call destroy callback */ | ||
54 | crumb->destroy(crumb->id); | ||
55 | |||
56 | /* destroy it */ | ||
57 | gtk_widget_destroy(crumb->button); | ||
58 | |||
59 | /* remove element from list */ | ||
60 | priv->crumbs = g_slist_remove(priv->crumbs, crumb); | ||
61 | |||
62 | g_free(crumb); | ||
63 | } | ||
64 | |||
65 | static void bct_update(bct_priv_t *priv) { | ||
66 | /* still something in list? */ | ||
67 | if(g_slist_length(priv->crumbs)) { | ||
68 | crumb_t *crumb = g_slist_last(priv->crumbs)->data; | ||
69 | /* disable button now last in chain */ | ||
70 | gtk_widget_set_sensitive(crumb->button, FALSE); | ||
71 | harbaum | 129 | |
72 | GtkWidget *label = gtk_bin_get_child(GTK_BIN(crumb->button)); | ||
73 | gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE); | ||
74 | harbaum | 128 | } |
75 | |||
76 | /* disable back button if crumb trail has 1 item or less */ | ||
77 | if(g_slist_length(priv->crumbs) <= 1) | ||
78 | gtk_widget_set_sensitive(priv->back, FALSE); | ||
79 | } | ||
80 | |||
81 | static void on_back_clicked(GtkButton *button, bct_priv_t *priv) { | ||
82 | crumb_destroy(priv, g_slist_last(priv->crumbs)->data); | ||
83 | bct_update(priv); | ||
84 | } | ||
85 | |||
86 | static void on_crumb_clicked(GtkButton *button, bct_priv_t *priv) { | ||
87 | /* clear crumb trail until we reach the button that was clicked */ | ||
88 | crumb_t *crumb = g_slist_last(priv->crumbs)->data; | ||
89 | while(crumb->button != (GtkWidget*)button) { | ||
90 | crumb_destroy(priv, crumb); | ||
91 | crumb = g_slist_last(priv->crumbs)->data; | ||
92 | } | ||
93 | bct_update(priv); | ||
94 | } | ||
95 | |||
96 | GtkWidget *bct_new(void) { | ||
97 | bct_priv_t *priv = g_new0(bct_priv_t, 1); | ||
98 | |||
99 | GtkWidget *hbox = gtk_hbox_new(FALSE, 0); | ||
100 | g_object_set_data(G_OBJECT(hbox), "priv", priv); | ||
101 | |||
102 | priv->back = gtk_button_new(); | ||
103 | gtk_button_set_image(GTK_BUTTON(priv->back), | ||
104 | gtk_image_new_from_stock(GTK_STOCK_GO_BACK, GTK_ICON_SIZE_BUTTON)); | ||
105 | gtk_widget_set_sensitive(priv->back, FALSE); | ||
106 | g_signal_connect(priv->back, "clicked", | ||
107 | G_CALLBACK(on_back_clicked), priv); | ||
108 | |||
109 | gtk_box_pack_start(GTK_BOX(hbox), priv->back, FALSE, FALSE, 0); | ||
110 | |||
111 | g_signal_connect(G_OBJECT(hbox), "destroy", | ||
112 | G_CALLBACK(bct_destroy_event), priv); | ||
113 | |||
114 | return hbox; | ||
115 | } | ||
116 | |||
117 | void bct_push_text(GtkWidget *bct, const gchar *text, gpointer id, | ||
118 | GDestroyNotify destroy) { | ||
119 | bct_priv_t *priv = g_object_get_data(G_OBJECT(bct), "priv"); | ||
120 | g_return_if_fail (priv); | ||
121 | |||
122 | /* enable last crumb */ | ||
123 | if(g_slist_length(priv->crumbs)) { | ||
124 | crumb_t *crumb = g_slist_last(priv->crumbs)->data; | ||
125 | gtk_widget_set_sensitive(crumb->button, TRUE); | ||
126 | gtk_widget_set_sensitive(priv->back, TRUE); | ||
127 | harbaum | 129 | |
128 | GtkWidget *label = gtk_bin_get_child(GTK_BIN(crumb->button)); | ||
129 | gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); | ||
130 | harbaum | 128 | } |
131 | |||
132 | /* create a new crumb */ | ||
133 | crumb_t *crumb = g_new0(crumb_t, 1); | ||
134 | |||
135 | /* append a new crumb */ | ||
136 | crumb->button = gtk_button_new_with_label(text); | ||
137 | crumb->destroy = destroy; | ||
138 | crumb->id = id; | ||
139 | |||
140 | gtk_box_pack_start(GTK_BOX(bct), crumb->button, FALSE, FALSE, 0); | ||
141 | gtk_widget_set_sensitive(crumb->button, FALSE); | ||
142 | gtk_widget_show(crumb->button); | ||
143 | |||
144 | g_signal_connect(crumb->button, "clicked", | ||
145 | G_CALLBACK(on_crumb_clicked), priv); | ||
146 | |||
147 | /* append to list of crumbs */ | ||
148 | priv->crumbs = g_slist_append(priv->crumbs, crumb); | ||
149 | |||
150 | } |