1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * Anjuta
4  * Copyright (C) 2002 Dave Camp
5  *
6  * This program 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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 this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  */
20 
21 /**
22  * SECTION:anjuta-preferences-dialog
23  * @short_description: Preferences dialog
24  * @see_also: #AnjutaPreferences
25  * @stability: Unstable
26  * @include: libanjuta/anjuta-preferences-dialog.h
27  *
28  * Plugins can added preferences page with anjuta_preferences_dialog_add_page().
29  * However, read #AnjutaPreferences for adding proper preferences pages.
30  */
31 
32 #include <config.h>
33 
34 #include <string.h>
35 #include <glib.h>
36 #include <glib/gi18n.h>
37 #include <gtk/gtk.h>
38 #include <gdk-pixbuf/gdk-pixbuf.h>
39 
40 
41 #include <libanjuta/anjuta-cell-renderer-captioned-image.h>
42 #include <libanjuta/anjuta-preferences-dialog.h>
43 
44 #define PREFERENCES_DEFAULT_WIDTH 800
45 #define PREFERENCES_DEFAULT_HEIGHT 400
46 
47 struct _AnjutaPreferencesDialogPrivate {
48 	GtkWidget *treeview;
49 	GtkListStore *store;
50 
51 	GtkWidget *notebook;
52 };
53 
54 enum {
55 	COL_NAME,
56 	COL_TITLE,
57 	COL_PIXBUF,
58 	COL_WIDGET,
59 	LAST_COL
60 };
61 
62 static void anjuta_preferences_dialog_class_init    (AnjutaPreferencesDialogClass *class);
63 static void anjuta_preferences_dialog_init (AnjutaPreferencesDialog      *dlg);
64 
G_DEFINE_TYPE(AnjutaPreferencesDialog,anjuta_preferences_dialog,GTK_TYPE_DIALOG)65 G_DEFINE_TYPE (AnjutaPreferencesDialog, anjuta_preferences_dialog,
66 			   GTK_TYPE_DIALOG)
67 
68 static void
69 anjuta_preferences_dialog_finalize (GObject *obj)
70 {
71 	AnjutaPreferencesDialog *dlg = ANJUTA_PREFERENCES_DIALOG (obj);
72 
73 	if (dlg->priv->store) {
74 		g_object_unref (dlg->priv->store);
75 		dlg->priv->store = NULL;
76 	}
77 
78 	g_free (dlg->priv);
79 
80 	((GObjectClass *) anjuta_preferences_dialog_parent_class)->finalize (obj);
81 }
82 
83 static void
anjuta_preferences_dialog_class_init(AnjutaPreferencesDialogClass * class)84 anjuta_preferences_dialog_class_init (AnjutaPreferencesDialogClass *class)
85 {
86 	GObjectClass *object_class = G_OBJECT_CLASS (class);
87 
88 	object_class->finalize = anjuta_preferences_dialog_finalize;
89 }
90 
91 static void
add_category_columns(AnjutaPreferencesDialog * dlg)92 add_category_columns (AnjutaPreferencesDialog *dlg)
93 {
94 	GtkCellRenderer *renderer;
95 	GtkTreeViewColumn *column;
96 
97 	renderer = anjuta_cell_renderer_captioned_image_new ();
98 	g_object_ref_sink (renderer);
99 	column = gtk_tree_view_column_new_with_attributes (_("Category"),
100 							   renderer,
101 							   "text",
102 							   COL_TITLE,
103 							   "pixbuf",
104 							   COL_PIXBUF,
105 							   NULL);
106 
107 	gtk_tree_view_append_column (GTK_TREE_VIEW (dlg->priv->treeview),
108 				     column);
109 }
110 
111 static void
selection_changed_cb(GtkTreeSelection * selection,AnjutaPreferencesDialog * dlg)112 selection_changed_cb (GtkTreeSelection *selection,
113 		      AnjutaPreferencesDialog *dlg)
114 {
115 	GtkTreeIter iter;
116 
117 	if (gtk_tree_selection_get_selected (selection, NULL, &iter)) {
118 		GtkWidget *widget;
119 
120 		gtk_tree_model_get (GTK_TREE_MODEL (dlg->priv->store), &iter,
121 				    COL_WIDGET, &widget, -1);
122 
123 		gtk_notebook_set_current_page
124 			(GTK_NOTEBOOK (dlg->priv->notebook),
125 			 gtk_notebook_page_num (GTK_NOTEBOOK (dlg->priv->notebook),
126 						widget));
127 
128 	}
129 }
130 
131 static gint
compare_pref_page_func(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer user_data)132 compare_pref_page_func (GtkTreeModel *model,
133 						GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
134 {
135 	gint val;
136 	gchar *name1, *name2;
137 
138 	gtk_tree_model_get (model, a, COL_TITLE, &name1, -1);
139 	gtk_tree_model_get (model, b, COL_TITLE, &name2, -1);
140 
141 	/* FIXME: Make the general page first */
142 	if (strcmp (name1, _("General")) == 0)
143 		return -1;
144 
145 	if (strcmp (name2, _("General")) == 0)
146 		return 1;
147 
148 	val = strcmp (name1, name2);
149 	g_free (name1);
150 	g_free (name2);
151 
152 	return val;
153 }
154 
155 static void
anjuta_preferences_dialog_init(AnjutaPreferencesDialog * dlg)156 anjuta_preferences_dialog_init (AnjutaPreferencesDialog *dlg)
157 {
158 	GtkWidget *hbox;
159 	GtkWidget *scrolled_window;
160 	GtkTreeSelection *selection;
161 	GtkTreeSortable *sortable;
162 
163 	dlg->priv = g_new0 (AnjutaPreferencesDialogPrivate, 1);
164 
165 	gtk_container_set_border_width (GTK_CONTAINER(dlg), 6);
166 
167 	hbox = g_object_new(GTK_TYPE_BOX,
168 	                    "border-width", 6,
169 	                    "spacing", 6,
170 	                    "visible", TRUE,
171 	                    NULL);
172 
173 	dlg->priv->treeview = gtk_tree_view_new ();
174 	gtk_widget_show (dlg->priv->treeview);
175 	gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dlg->priv->treeview),
176 					   FALSE);
177 	dlg->priv->store = gtk_list_store_new (LAST_COL,
178 					       G_TYPE_STRING,
179 					       G_TYPE_STRING,
180 					       GDK_TYPE_PIXBUF,
181 					       GTK_TYPE_WIDGET,
182 					       G_TYPE_INT);
183 	sortable = GTK_TREE_SORTABLE (dlg->priv->store);
184 	gtk_tree_sortable_set_sort_column_id (sortable, COL_TITLE,
185 										  GTK_SORT_ASCENDING);
186 	gtk_tree_sortable_set_sort_func (sortable, COL_TITLE,
187 									 compare_pref_page_func,
188 									 NULL, NULL);
189 
190 	gtk_tree_view_set_model (GTK_TREE_VIEW (dlg->priv->treeview),
191 				 GTK_TREE_MODEL (dlg->priv->store));
192 
193 	add_category_columns (dlg);
194 
195 	scrolled_window = gtk_scrolled_window_new (NULL, NULL);
196 	gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
197 					GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
198 	gtk_scrolled_window_set_shadow_type
199 		(GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
200 
201 	gtk_widget_show (scrolled_window);
202 	gtk_container_add (GTK_CONTAINER (scrolled_window),
203 			   dlg->priv->treeview);
204 	gtk_box_pack_start (GTK_BOX (hbox), scrolled_window,
205 			    FALSE, FALSE, 0);
206 
207 	dlg->priv->notebook = gtk_notebook_new ();
208 	gtk_widget_show (dlg->priv->notebook);
209 	gtk_notebook_set_show_tabs (GTK_NOTEBOOK (dlg->priv->notebook), FALSE);
210 	gtk_notebook_set_show_border (GTK_NOTEBOOK (dlg->priv->notebook),
211 				      FALSE);
212 
213 	gtk_box_pack_start (GTK_BOX (hbox), dlg->priv->notebook,
214 			    TRUE, TRUE, 0);
215 
216 
217 	selection = gtk_tree_view_get_selection
218 		(GTK_TREE_VIEW (dlg->priv->treeview));
219 
220 	gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE);
221 
222 	g_signal_connect (selection, "changed",
223 			  G_CALLBACK (selection_changed_cb), dlg);
224 
225 	gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dlg))), hbox,
226 			    TRUE, TRUE, 0);
227 
228 	gtk_dialog_add_button (GTK_DIALOG (dlg), GTK_STOCK_CLOSE, -7);
229 
230 	gtk_widget_show (hbox);
231 }
232 
233 /**
234  * anjuta_preferences_dialog_new:
235  *
236  * Creates a new #AnjutaPreferencesDialog object.
237  *
238  * Return value: a new #AnjutaPreferencesDialog object.
239  */
240 GtkWidget *
anjuta_preferences_dialog_new(void)241 anjuta_preferences_dialog_new (void)
242 {
243 	return g_object_new (ANJUTA_TYPE_PREFERENCES_DIALOG,
244 	                     "title", _("Anjuta Preferences"),
245 	                     "default-width", PREFERENCES_DEFAULT_WIDTH,
246 	                     "default-height", PREFERENCES_DEFAULT_HEIGHT,
247 	                     NULL);
248 }
249 
250 /**
251  * anjuta_preferences_dialog_add_page:
252  * @dlg: A #AnjutaPreferencesDialog object.
253  * @name: Name of the preferences page.
254  * @title: Title of the page
255  * @icon: Icon file name.
256  * @page: page widget.
257  *
258  * Adds a widget page in preferences dialog. Name and icon appears
259  * on the left icon list where differnt pages are selected.
260  */
261 void
anjuta_preferences_dialog_add_page(AnjutaPreferencesDialog * dlg,const gchar * name,const gchar * title,GdkPixbuf * icon,GtkWidget * page)262 anjuta_preferences_dialog_add_page (AnjutaPreferencesDialog *dlg,
263 									const gchar *name,
264 									const gchar *title,
265 									GdkPixbuf *icon,
266 									GtkWidget *page)
267 {
268 	GtkTreeIter iter;
269 	GtkTreeSelection* selection =
270 		gtk_tree_view_get_selection (GTK_TREE_VIEW (dlg->priv->treeview));
271 	GtkTreeIter first;
272 	gtk_widget_show (page);
273 
274 	gtk_notebook_append_page (GTK_NOTEBOOK (dlg->priv->notebook), page, NULL);
275 
276 	gtk_list_store_append (dlg->priv->store, &iter);
277 
278 	gtk_list_store_set (dlg->priv->store, &iter,
279 			    COL_NAME, name,
280 			    COL_TITLE, title,
281 			    COL_PIXBUF, icon,
282 			    COL_WIDGET, page,
283 			    -1);
284 
285 	gtk_tree_model_get_iter_first (GTK_TREE_MODEL (dlg->priv->store),
286 	                               &first);
287 	gtk_tree_selection_select_iter (selection, &first);
288 }
289 
290 /**
291  * anjuta_preferences_dialog_remove_page:
292  * @dlg: A #AnjutaPreferencesDialog object.g_signal_handler
293  * @title: Name of the preferences page.
294  *
295  * Removes a preferences page.
296  */
297 void
anjuta_preferences_dialog_remove_page(AnjutaPreferencesDialog * dlg,const char * title)298 anjuta_preferences_dialog_remove_page (AnjutaPreferencesDialog *dlg,
299 									   const char *title)
300 {
301 	GtkTreeModel* model = GTK_TREE_MODEL(dlg->priv->store);
302 	GtkTreeIter iter;
303 	GtkWidget *page;
304 
305 	if (gtk_tree_model_get_iter_first(model, &iter))
306 	{
307 		do
308 		{
309 			gchar* page_title;
310 			GObject* page_widget;
311 
312 			gtk_tree_model_get(model, &iter,
313 					COL_TITLE, &page_title,
314 					COL_WIDGET, &page_widget,
315 					-1);
316 
317 			if (g_str_equal(page_title, title))
318 			{
319 				int page_num;
320 
321 				page_num = gtk_notebook_page_num (
322 						GTK_NOTEBOOK(dlg->priv->notebook),
323 						GTK_WIDGET (page_widget));
324 
325 				page = gtk_notebook_get_nth_page (GTK_NOTEBOOK (dlg->priv->notebook),
326 												  page_num);
327 
328 				gtk_notebook_remove_page(
329 						GTK_NOTEBOOK(dlg->priv->notebook), page_num);
330 
331 				gtk_widget_destroy (page);
332 
333 				gtk_list_store_remove(dlg->priv->store, &iter);
334 				return;
335 			}
336 		}
337 		while (gtk_tree_model_iter_next(model, &iter));
338 	}
339 	g_warning("Could not find page to remove");
340 }
341