Parent Directory | Revision Log
Balloon callback extensions
1 | /* |
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 | /* |
21 | * This simple breadcrumbtrail replacement is a simple hbox with |
22 | * buttons inside |
23 | */ |
24 | |
25 | #include "gpxview.h" |
26 | |
27 | typedef struct { |
28 | GtkWidget *button; |
29 | GDestroyNotify destroy; |
30 | gpointer id; |
31 | } crumb_t; |
32 | |
33 | 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 | } |
42 | |
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 | |
72 | // GtkWidget *label = gtk_bin_get_child(GTK_BIN(crumb->button)); |
73 | // gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_NONE); |
74 | } |
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 | |
128 | // GtkWidget *label = gtk_bin_get_child(GTK_BIN(crumb->button)); |
129 | // gtk_label_set_ellipsize(GTK_LABEL(label), PANGO_ELLIPSIZE_END); |
130 | } |
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 | } |