[svn-buildpackage] Tagging simple-launcher (0.7)
[simple-launcher] / sla-list.cc
1 // This file is a part of Simple Launcher
2 //
3 // Copyright (C) 2006, Mikhail Sobolev
4 //
5 // Simple Launcher is free software; you can redistribute it and/or modify it
6 // under the terms of the GNU General Public License version 2 as published by
7 // the Free Software Foundation.
8 //
9 // This program is distributed in the hope that it will be useful, but WITHOUT
10 // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12 // more details.
13 //
14 // You should have received a copy of the GNU General Public License along with
15 // this program; if not, write to the Free Software Foundation, Inc., 51
16 // Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17
18 #include <gtk/gtkscrolledwindow.h>
19 #include <gtk/gtkcellrendererpixbuf.h>
20 #include <gtk/gtkcellrenderertext.h>
21 #include <gtk/gtkcellrenderertoggle.h>
22 #include <gtk/gtktable.h>
23 #include <gtk/gtkbutton.h>
24 #include <gtk/gtktreeselection.h>
25 #include <gtk/gtkhbox.h>
26 #include <gtk/gtkstock.h>
27
28 #include "sla-list.h"
29
30 SLAList::SLAList(int icon_size, LaunchableItems& items): myWidget(0), myStore(0), myView(0), mySelection(0), myItems(items) {
31   GtkTreeViewColumn *column;
32   GtkCellRenderer *renderer;
33
34   myStore = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_INT);
35
36   myView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(myStore)));
37   gtk_tree_view_set_headers_visible(myView, FALSE);
38
39   mySelection = gtk_tree_view_get_selection(myView);
40   gtk_tree_selection_set_mode(mySelection, GTK_SELECTION_SINGLE);
41
42   renderer = gtk_cell_renderer_pixbuf_new();
43   g_object_set(renderer, "yalign", 0.0, 0);
44   gtk_cell_renderer_set_fixed_size(renderer, icon_size+4, -1);
45   column = GTK_TREE_VIEW_COLUMN(gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf", 0, 0));
46
47   gtk_tree_view_insert_column(myView, column, -1);
48
49   renderer = gtk_cell_renderer_text_new();
50   g_object_set(renderer, "yalign", 0.0, 0);
51   column = gtk_tree_view_column_new();
52   gtk_tree_view_column_set_cell_data_func(column, renderer, _renderText, this, 0);
53   gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
54   gtk_tree_view_column_set_expand(column, TRUE);
55
56   gtk_tree_view_insert_column(myView, column, -1);
57
58   renderer = gtk_cell_renderer_toggle_new();
59   g_object_set(renderer, "activatable", TRUE, 0);
60   g_signal_connect(renderer, "toggled", G_CALLBACK(_toggleBool), this);
61   column = gtk_tree_view_column_new();
62   gtk_tree_view_column_set_cell_data_func(column, renderer, _renderBool, this, 0);
63
64   gtk_tree_view_insert_column(myView, column, -1);
65
66   GtkWidget *swindow = gtk_scrolled_window_new(0, 0);
67
68   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
69   gtk_container_add(GTK_CONTAINER(swindow), GTK_WIDGET(myView));
70
71   gtk_widget_set_size_request(swindow, 500, 300);
72
73   GtkWidget *move_up = gtk_button_new_from_stock(GTK_STOCK_GO_UP),
74             *move_down = gtk_button_new_from_stock(GTK_STOCK_GO_DOWN);
75   GtkTable *table = GTK_TABLE(gtk_table_new(4, 1, FALSE));
76   gtk_table_attach(table, move_up, 0, 1, 1, 2, (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), GTK_EXPAND, 0, 0);
77   gtk_table_attach(table, move_down, 0, 1, 2, 3, (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), GTK_EXPAND, 0, 0);
78
79   g_signal_connect(move_up, "clicked", G_CALLBACK(_moveUp), this);
80   g_signal_connect(move_down, "clicked", G_CALLBACK(_moveDown), this);
81
82   myWidget = gtk_hbox_new(FALSE, 0);
83   gtk_box_pack_start(GTK_BOX(myWidget), swindow, FALSE, FALSE, 0);
84   gtk_box_pack_start(GTK_BOX(myWidget), GTK_WIDGET(table), FALSE, FALSE, 0);
85
86   gtk_widget_show_all(myWidget);
87
88   for (LaunchableItems::const_iterator item = myItems.begin(); item != myItems.end(); ++item) {
89     GtkTreeIter iter;
90     
91     gtk_list_store_append(myStore, &iter);
92     gtk_list_store_set(myStore, &iter, 0, item->second->getIcon(icon_size), 1, item-myItems.begin(), -1);
93   }
94 }
95
96 SLAList::~SLAList() {
97   // FIXME: do something! :)
98 }
99
100 void SLAList::_renderText(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer self) {
101   ((SLAList *)self)->renderText(column, cell, model, iter);
102 }
103
104 void SLAList::_renderBool(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer self) {
105   ((SLAList *)self)->renderBool(column, cell, model, iter);
106 }
107
108 void SLAList::_toggleBool(GtkCellRendererToggle *renderer, const gchar *path, void *self) {
109   ((SLAList *)self)->toggleBool(renderer, path);
110 }
111
112 void SLAList::_moveUp(GtkButton *button, void *self) {
113   ((SLAList *)self)->moveUp(button);
114 }
115
116 void SLAList::_moveDown(GtkButton *button, void *self) {
117   ((SLAList *)self)->moveDown(button);
118 }
119
120 void SLAList::renderText(GtkTreeViewColumn *, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter) {
121   int index;
122
123   gtk_tree_model_get(GTK_TREE_MODEL(myStore), iter, 1, &index, -1);
124
125   if (gtk_tree_selection_iter_is_selected(mySelection, iter)) {
126     gchar *text = g_markup_printf_escaped("%s\n<small>%s</small>", myItems[index].second->getName().c_str(), myItems[index].second->getComment().c_str());
127     g_object_set(cell, "markup", text, 0);
128     g_free(text);
129   } else {
130     g_object_set(cell, "text", myItems[index].second->getName().c_str(), 0);
131   }
132 }
133
134 void SLAList::renderBool(GtkTreeViewColumn *, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter) {
135   int index;
136
137   gtk_tree_model_get(GTK_TREE_MODEL(myStore), iter, 1, &index, -1);
138
139   g_object_set(cell, "active", myItems[index].second->isEnabled(), 0);
140 }
141
142 void SLAList::toggleBool(GtkCellRendererToggle *renderer, const gchar *spath) {
143   GtkTreePath *path = gtk_tree_path_new_from_string(spath);
144
145   if (path != 0) {
146     GtkTreeIter iter;
147
148     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(myStore), &iter, path)) {
149       int index;
150
151       gtk_tree_model_get(GTK_TREE_MODEL(myStore), &iter, 1, &index, -1);
152       myItems[index].second->toggle();
153     }
154   }
155 }
156
157 void SLAList::moveUp(GtkButton *) {
158   GtkTreeModel *dummy;
159   GtkTreeIter current;
160
161   if (gtk_tree_selection_get_selected(mySelection, &dummy, &current)) {
162     GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(myStore), &current);
163
164     // FIXME: we kinda expexted path to be non-NULL here :)
165     if (gtk_tree_path_prev(path)) {
166       GtkTreeIter next;
167
168       if (gtk_tree_model_get_iter(GTK_TREE_MODEL(myStore), &next, path)) {
169         swap(current, next);
170       }
171     }
172
173     gtk_tree_path_free(path);
174   }
175 }
176
177 void SLAList::moveDown(GtkButton *) {
178   GtkTreeModel *dummy;
179   GtkTreeIter current;
180
181   if (gtk_tree_selection_get_selected(mySelection, &dummy, &current)) {
182     GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(myStore), &current);
183     GtkTreeIter next;
184
185     // FIXME: we kinda expexted path to be non-NULL here :)
186     gtk_tree_path_next(path);
187
188     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(myStore), &next, path)) {
189       swap(current, next);
190     }
191
192     gtk_tree_path_free(path);
193   }
194 }
195
196 void SLAList::swap(GtkTreeIter& a, GtkTreeIter& b) {
197   int i1, i2;
198
199   gtk_tree_model_get(GTK_TREE_MODEL(myStore), &a, 1, &i1, -1);
200   gtk_tree_model_get(GTK_TREE_MODEL(myStore), &b, 1, &i2, -1);
201
202   std::swap(myItems[i1], myItems[i2]);
203
204   gtk_list_store_set(myStore, &a, 1, i2, -1);
205   gtk_list_store_set(myStore, &b, 1, i1, -1);
206
207   gtk_list_store_swap(myStore, &a, &b);
208 }
209
210 // vim:ts=2:sw=2:et