]> Pileus Git - ~andy/gtk/blob - tests/testiconview-keynav.c
Updated Indonesian translation
[~andy/gtk] / tests / testiconview-keynav.c
1 /* testiconview-keynav.c
2  * Copyright (C) 2010  Red Hat, Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * Author: Matthias Clasen
20  */
21
22 /*
23  * This example demonstrates how to use the keynav-failed signal to
24  * extend arrow keynav over adjacent icon views. This can be used when
25  * grouping items.
26  */
27
28 #include <gtk/gtk.h>
29
30 static GtkTreeModel *
31 get_model (void)
32 {
33   static GtkListStore *store;
34   GtkTreeIter iter;
35
36   if (store)
37     return (GtkTreeModel *) g_object_ref (store);
38
39   store = gtk_list_store_new (1, G_TYPE_STRING);
40
41   gtk_list_store_append (store, &iter);
42   gtk_list_store_set (store, &iter, 0, "One", -1);
43   gtk_list_store_append (store, &iter);
44   gtk_list_store_set (store, &iter, 0, "Two", -1);
45   gtk_list_store_append (store, &iter);
46   gtk_list_store_set (store, &iter, 0, "Three", -1);
47   gtk_list_store_append (store, &iter);
48   gtk_list_store_set (store, &iter, 0, "Four", -1);
49   gtk_list_store_append (store, &iter);
50   gtk_list_store_set (store, &iter, 0, "Five", -1);
51   gtk_list_store_append (store, &iter);
52   gtk_list_store_set (store, &iter, 0, "Six", -1);
53   gtk_list_store_append (store, &iter);
54   gtk_list_store_set (store, &iter, 0, "Seven", -1);
55   gtk_list_store_append (store, &iter);
56   gtk_list_store_set (store, &iter, 0, "Eight", -1);
57
58   return (GtkTreeModel *) store;
59 }
60
61 static gboolean
62 visible_func (GtkTreeModel *model,
63               GtkTreeIter  *iter,
64               gpointer      data)
65 {
66   gboolean first = GPOINTER_TO_INT (data);
67   gboolean visible;
68   GtkTreePath *path;
69
70   path = gtk_tree_model_get_path (model, iter);
71
72   if (gtk_tree_path_get_indices (path)[0] < 4)
73     visible = first;
74   else
75     visible = !first;
76
77   gtk_tree_path_free (path);
78
79   return visible;
80 }
81
82 GtkTreeModel *
83 get_filter_model (gboolean first)
84 {
85   GtkTreeModelFilter *model;
86
87   model = (GtkTreeModelFilter *)gtk_tree_model_filter_new (get_model (), NULL);
88
89   gtk_tree_model_filter_set_visible_func (model, visible_func, GINT_TO_POINTER (first), NULL);
90
91   return (GtkTreeModel *) model;
92 }
93
94 static GtkWidget *
95 get_view (gboolean first)
96 {
97   GtkWidget *view;
98
99   view = gtk_icon_view_new_with_model (get_filter_model (first));
100   gtk_icon_view_set_text_column (GTK_ICON_VIEW (view), 0);
101   gtk_widget_set_size_request (view, 0, -1);
102
103   return view;
104 }
105
106 typedef struct
107 {
108   GtkWidget *header1;
109   GtkWidget *view1;
110   GtkWidget *header2;
111   GtkWidget *view2;
112 } Views;
113
114 static gboolean
115 keynav_failed (GtkWidget        *view,
116                GtkDirectionType  direction,
117                Views            *views)
118 {
119   GtkTreePath *path;
120   GtkTreeModel *model;
121   GtkTreeIter iter;
122   gint col;
123   GtkTreePath *sel;
124
125   if (view == views->view1 && direction == GTK_DIR_DOWN)
126     {
127       if (gtk_icon_view_get_cursor (GTK_ICON_VIEW (views->view1), &path, NULL))
128         {
129           col = gtk_icon_view_get_item_column (GTK_ICON_VIEW (views->view1), path);
130           gtk_tree_path_free (path);
131
132           sel = NULL;
133           model = gtk_icon_view_get_model (GTK_ICON_VIEW (views->view2));
134           gtk_tree_model_get_iter_first (model, &iter);
135           do {
136             path = gtk_tree_model_get_path (model, &iter);
137             if (gtk_icon_view_get_item_column (GTK_ICON_VIEW (views->view2), path) == col)
138               {
139                 sel = path;
140                 break;
141               }
142           } while (gtk_tree_model_iter_next (model, &iter));
143
144           gtk_icon_view_set_cursor (GTK_ICON_VIEW (views->view2), sel, NULL, FALSE);
145           gtk_tree_path_free (sel);
146         }
147       gtk_widget_grab_focus (views->view2);
148       return TRUE;
149     }
150
151   if (view == views->view2 && direction == GTK_DIR_UP)
152     {
153       if (gtk_icon_view_get_cursor (GTK_ICON_VIEW (views->view2), &path, NULL))
154         {
155           col = gtk_icon_view_get_item_column (GTK_ICON_VIEW (views->view2), path);
156           gtk_tree_path_free (path);
157
158           sel = NULL;
159           model = gtk_icon_view_get_model (GTK_ICON_VIEW (views->view1));
160           gtk_tree_model_get_iter_first (model, &iter);
161           do {
162             path = gtk_tree_model_get_path (model, &iter);
163             if (gtk_icon_view_get_item_column (GTK_ICON_VIEW (views->view1), path) == col)
164               {
165                 if (sel)
166                   gtk_tree_path_free (sel);
167                 sel = path;
168               }
169             else
170               gtk_tree_path_free (path);
171           } while (gtk_tree_model_iter_next (model, &iter));
172
173           gtk_icon_view_set_cursor (GTK_ICON_VIEW (views->view1), sel, NULL, FALSE);
174           gtk_tree_path_free (sel);
175         }
176       gtk_widget_grab_focus (views->view1);
177       return TRUE;
178     }
179
180   return FALSE;
181 }
182
183 static gboolean
184 focus_out (GtkWidget     *view,
185            GdkEventFocus *event,
186            gpointer       data)
187 {
188   gtk_icon_view_unselect_all (GTK_ICON_VIEW (view));
189
190   return FALSE;
191 }
192
193 static gboolean
194 focus_in (GtkWidget     *view,
195           GdkEventFocus *event,
196           gpointer       data)
197 {
198   GtkTreePath *path;
199
200   if (!gtk_icon_view_get_cursor (GTK_ICON_VIEW (view), &path, NULL))
201     {
202       path = gtk_tree_path_new_from_indices (0, -1);
203       gtk_icon_view_set_cursor (GTK_ICON_VIEW (view), path, NULL, FALSE);
204     }
205
206   gtk_icon_view_select_path (GTK_ICON_VIEW (view), path);
207   gtk_tree_path_free (path);
208
209   return FALSE;
210 }
211
212 #define CSS \
213   "GtkWindow {\n" \
214   "  background-color: @base_color;\n" \
215   "}\n"
216
217 static void
218 set_styles (void)
219 {
220   GtkCssProvider *provider;
221   GdkScreen *screen;
222
223   provider = gtk_css_provider_new ();
224
225   if (!gtk_css_provider_load_from_data (provider, CSS, -1, NULL))
226     {
227       g_assert_not_reached ();
228     }
229
230   screen = gdk_display_get_default_screen (gdk_display_get_default ());
231
232   gtk_style_context_add_provider_for_screen (screen, GTK_STYLE_PROVIDER (provider),
233                                              GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
234 }
235
236 int
237 main (int argc, char *argv[])
238 {
239   GtkWidget *window;
240   GtkWidget *vbox;
241   Views views;
242
243   gtk_init (&argc, &argv);
244
245   set_styles ();
246
247   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
248   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
249   gtk_container_add (GTK_CONTAINER (window), vbox);
250
251   views.header1 = g_object_new (GTK_TYPE_LABEL,
252                                 "label", "<b>Group 1</b>",
253                                 "use-markup", TRUE,
254                                 "xalign", 0.0,
255                                 NULL);
256   views.view1 = get_view (TRUE);
257   views.header2 = g_object_new (GTK_TYPE_LABEL,
258                                 "label", "<b>Group 2</b>",
259                                 "use-markup", TRUE,
260                                 "xalign", 0.0,
261                                 NULL);
262   views.view2 = get_view (FALSE);
263
264   g_signal_connect (views.view1, "keynav-failed",
265                     G_CALLBACK (keynav_failed), &views);
266   g_signal_connect (views.view2, "keynav-failed",
267                     G_CALLBACK (keynav_failed), &views);
268   g_signal_connect (views.view1, "focus-in-event",
269                     G_CALLBACK (focus_in), NULL);
270   g_signal_connect (views.view1, "focus-out-event",
271                     G_CALLBACK (focus_out), NULL);
272   g_signal_connect (views.view2, "focus-in-event",
273                     G_CALLBACK (focus_in), NULL);
274   g_signal_connect (views.view2, "focus-out-event",
275                     G_CALLBACK (focus_out), NULL);
276
277   gtk_container_add (GTK_CONTAINER (vbox), views.header1);
278   gtk_container_add (GTK_CONTAINER (vbox), views.view1);
279   gtk_container_add (GTK_CONTAINER (vbox), views.header2);
280   gtk_container_add (GTK_CONTAINER (vbox), views.view2);
281
282   gtk_widget_show_all (window);
283
284   gtk_main ();
285
286   return 0;
287 }
288