updated debian/changelog in anticipation of 0.8
[simple-launcher] / sla-list.cc
1 // This file is a part of Simple Launcher
2 //
3 // Copyright (C) 2006, 2007, 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 static GtkWidget *gtk_button_new_stock_image_only(const gchar *stock_id) {
31   GtkWidget *button = gtk_button_new();
32   GtkWidget *image = gtk_image_new_from_stock(stock_id, GTK_ICON_SIZE_BUTTON);
33
34   gtk_container_add(GTK_CONTAINER(button), image);
35
36   return button;
37 }
38
39 SLAList::SLAList(int icon_size, LauncherItems& items): myWidget(NULL), myStore(NULL), myView(NULL), mySelection(NULL), myItems(items) {
40   GtkTreeViewColumn *column;
41   GtkCellRenderer *renderer;
42
43   myStore = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_INT);
44
45   myView = GTK_TREE_VIEW(gtk_tree_view_new_with_model(GTK_TREE_MODEL(myStore)));
46   gtk_tree_view_set_headers_visible(myView, FALSE);
47   g_object_set(myView, "allow-checkbox-mode", FALSE, NULL);
48
49   mySelection = gtk_tree_view_get_selection(myView);
50   gtk_tree_selection_set_mode(mySelection, GTK_SELECTION_SINGLE);
51
52   renderer = gtk_cell_renderer_pixbuf_new();
53   g_object_set(renderer, "yalign", 0.0, NULL);
54   gtk_cell_renderer_set_fixed_size(renderer, icon_size+4, -1);
55   column = GTK_TREE_VIEW_COLUMN(gtk_tree_view_column_new_with_attributes("", renderer, "pixbuf", 0, NULL));
56
57   gtk_tree_view_insert_column(myView, column, -1);
58
59   renderer = gtk_cell_renderer_text_new();
60   g_object_set(renderer, "yalign", 0.0, NULL);
61   column = gtk_tree_view_column_new();
62   gtk_tree_view_column_pack_start(column, renderer, TRUE);
63   gtk_tree_view_column_set_cell_data_func(column, renderer, _renderText, this, NULL);
64   gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_FIXED);
65   gtk_tree_view_column_set_expand(column, TRUE);
66
67   gtk_tree_view_insert_column(myView, column, -1);
68
69   renderer = gtk_cell_renderer_toggle_new();
70   g_object_set(renderer, "activatable", TRUE, NULL);
71   g_signal_connect(renderer, "toggled", G_CALLBACK(_toggleBool), this);
72   column = gtk_tree_view_column_new();
73   gtk_tree_view_column_pack_start(column, renderer, TRUE);
74   gtk_tree_view_column_set_cell_data_func(column, renderer, _renderBool, this, NULL);
75
76   gtk_tree_view_insert_column(myView, column, -1);
77
78   GtkWidget *swindow = gtk_scrolled_window_new(NULL, NULL);
79
80   gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(swindow), GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
81   gtk_container_add(GTK_CONTAINER(swindow), GTK_WIDGET(myView));
82
83   gtk_widget_set_size_request(swindow, 500, 300);
84
85   GtkWidget *move_up = gtk_button_new_stock_image_only(GTK_STOCK_GO_UP),
86             *move_down = gtk_button_new_stock_image_only(GTK_STOCK_GO_DOWN);
87   GtkTable *table = GTK_TABLE(gtk_table_new(4, 1, FALSE));
88   gtk_table_attach(table, move_up, 0, 1, 1, 2, (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), GTK_EXPAND, 0, 0);
89   gtk_table_attach(table, move_down, 0, 1, 2, 3, (GtkAttachOptions)(GTK_EXPAND|GTK_FILL), GTK_EXPAND, 0, 0);
90
91   g_signal_connect(move_up, "clicked", G_CALLBACK(_moveUp), this);
92   g_signal_connect(move_down, "clicked", G_CALLBACK(_moveDown), this);
93
94   myWidget = gtk_hbox_new(FALSE, 0);
95   gtk_box_pack_start(GTK_BOX(myWidget), swindow, FALSE, FALSE, 0);
96   gtk_box_pack_start(GTK_BOX(myWidget), GTK_WIDGET(table), FALSE, FALSE, 0);
97
98   gtk_widget_show_all(myWidget);
99
100   for (LauncherItems::Names::const_iterator it = myItems.myNames.begin(); it != myItems.myNames.end(); ++it) {
101     LauncherItem *item = myItems.myItems[*it];
102     GtkTreeIter iter;
103
104     gtk_list_store_append(myStore, &iter);
105     gtk_list_store_set(myStore, &iter, 0, item->getIcon(icon_size), 1, it-myItems.myNames.begin(), -1);
106   }
107 }
108
109 SLAList::~SLAList() {
110   // FIXME: do something! :)
111 }
112
113 void SLAList::_renderText(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer self) {
114   ((SLAList *)self)->renderText(column, cell, model, iter);
115 }
116
117 void SLAList::_renderBool(GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, gpointer self) {
118   ((SLAList *)self)->renderBool(column, cell, model, iter);
119 }
120
121 void SLAList::_toggleBool(GtkCellRendererToggle *renderer, const gchar *path, void *self) {
122   ((SLAList *)self)->toggleBool(renderer, path);
123 }
124
125 void SLAList::_moveUp(GtkButton *button, void *self) {
126   ((SLAList *)self)->moveUp(button);
127 }
128
129 void SLAList::_moveDown(GtkButton *button, void *self) {
130   ((SLAList *)self)->moveDown(button);
131 }
132
133 void SLAList::renderText(GtkTreeViewColumn *, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter) {
134   int index;
135
136   gtk_tree_model_get(GTK_TREE_MODEL(myStore), iter, 1, &index, -1);
137
138   LauncherItem *item = myItems[index];
139 #if 1
140   if (gtk_tree_selection_iter_is_selected(mySelection, iter)) {
141     gchar *text = g_markup_printf_escaped("%s\n<small>%s</small>", item->getName().c_str(), item->getComment().c_str());
142     g_object_set(cell, "markup", text, NULL);
143     g_free(text);
144   } else {
145 #endif
146     g_object_set(cell, "text", item->getName().c_str(), NULL);
147 #if 1
148   }
149 #endif
150 }
151
152 void SLAList::renderBool(GtkTreeViewColumn *, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter) {
153   int index;
154
155   gtk_tree_model_get(GTK_TREE_MODEL(myStore), iter, 1, &index, -1);
156
157   g_object_set(cell, "active", myItems[index]->isEnabled(), NULL);
158 }
159
160 void SLAList::toggleBool(GtkCellRendererToggle *renderer, const gchar *spath) {
161   GtkTreeIter iter;
162
163   if (gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(myStore), &iter, spath)) {
164     int index;
165
166     gtk_tree_model_get(GTK_TREE_MODEL(myStore), &iter, 1, &index, -1);
167     myItems[index]->toggle();
168   }
169 }
170
171 void SLAList::moveUp(GtkButton *) {
172   GtkTreeModel *dummy;
173   GtkTreeIter current;
174
175   if (gtk_tree_selection_get_selected(mySelection, &dummy, &current)) {
176     GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(myStore), &current);
177
178     // FIXME: we kinda expexted path to be non-NULL here :)
179     if (gtk_tree_path_prev(path)) {
180       GtkTreeIter next;
181
182       if (gtk_tree_model_get_iter(GTK_TREE_MODEL(myStore), &next, path)) {
183         swap(current, next);
184       }
185     }
186
187     gtk_tree_path_free(path);
188   }
189 }
190
191 void SLAList::moveDown(GtkButton *) {
192   GtkTreeModel *dummy;
193   GtkTreeIter current;
194
195   if (gtk_tree_selection_get_selected(mySelection, &dummy, &current)) {
196     GtkTreePath *path = gtk_tree_model_get_path(GTK_TREE_MODEL(myStore), &current);
197     GtkTreeIter next;
198
199     // FIXME: we kinda expexted path to be non-NULL here :)
200     gtk_tree_path_next(path);
201
202     if (gtk_tree_model_get_iter(GTK_TREE_MODEL(myStore), &next, path)) {
203       swap(current, next);
204     }
205
206     gtk_tree_path_free(path);
207   }
208 }
209
210 void SLAList::swap(GtkTreeIter& a, GtkTreeIter& b) {
211   int i1, i2;
212
213   gtk_tree_model_get(GTK_TREE_MODEL(myStore), &a, 1, &i1, -1);
214   gtk_tree_model_get(GTK_TREE_MODEL(myStore), &b, 1, &i2, -1);
215
216   myItems.swap(i1, i2);
217
218   gtk_list_store_set(myStore, &a, 1, i2, -1);
219   gtk_list_store_set(myStore, &b, 1, i1, -1);
220
221   gtk_list_store_swap(myStore, &a, &b);
222 }
223
224 // vim:ts=2:sw=2:et