Add support for GTK 3
[grits] / src / grits-demo.c
1 /*
2  * Copyright (C) 2009-2010 Andy Spencer <andy753421@gmail.com>
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program 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
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <config.h>
19 #include <gtk/gtk.h>
20 #include <gdk/gdkkeysyms.h>
21
22 #include "grits.h"
23
24 #include "compat.h"
25
26 static GritsPrefs   *prefs;
27 static GritsPlugins *plugins;
28 static GritsViewer  *viewer;
29
30
31 /*************
32  * Callbacks *
33  *************/
34 static gboolean on_delete(GtkWidget *widget, GdkEvent *event, gpointer data)
35 {
36         gtk_main_quit();
37         return TRUE;
38 }
39
40 static void on_offline(GtkToggleAction *action, gpointer _)
41 {
42         gboolean active = gtk_toggle_action_get_active(action);
43         grits_viewer_set_offline(viewer, active);
44 }
45
46 static void on_plugin(GtkToggleAction *action, GtkWidget *notebook)
47 {
48         const gchar *name = gtk_action_get_name(GTK_ACTION(action));
49         gboolean active = gtk_toggle_action_get_active(action);
50         if (active) {
51                 GritsPlugin *plugin = grits_plugins_enable(plugins, name,
52                                 GRITS_VIEWER(viewer), prefs);
53                 GtkWidget *config = grits_plugin_get_config(plugin);
54                 if (config) {
55                         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), config,
56                                         gtk_label_new(name));
57                         gtk_widget_show_all(config);
58                 }
59         } else {
60                 grits_plugins_disable(plugins, name);
61                 guint n_pages = gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook));
62                 for (int i = 0; i < n_pages; i++) {
63                         GtkWidget *body = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook), i);
64                         if (!body) continue;
65                         GtkWidget *tab = gtk_notebook_get_tab_label(GTK_NOTEBOOK(notebook), body);
66                         if (!tab) continue;
67                         const gchar *tab_name = gtk_label_get_text(GTK_LABEL(tab));
68                         if (tab_name && g_str_equal(name, tab_name))
69                                 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), i);
70                 }
71                 gtk_widget_queue_draw(GTK_WIDGET(viewer));
72         }
73 }
74
75
76 /******************
77  * Static UI Data *
78  ******************/
79 static const gchar menu_xml[] =
80         "<ui>"
81         "  <menubar name='Menu' >"
82         "    <menu name='File'          action='File' >"
83         "      <menuitem name='Offline' action='Offline' />"
84         "      <menuitem name='Quit'    action='Quit' />"
85         "    </menu>"
86         "    <menu name='Plugins'       action='Plugins' >"
87         "      <placeholder name='PluginsItems' />"
88         "    </menu>"
89         "  </menubar>"
90         "</ui>"
91 ;
92
93 static GtkActionEntry action_data[] =
94 {
95         /* name, stock id, label, accel, tooltip, callback */
96         {"File",    NULL, "_File"},
97         {"Plugins", NULL, "_Plugins"},
98         {"Quit", GTK_STOCK_QUIT, "_Quit", "q", NULL,
99                 G_CALLBACK(gtk_main_quit)},
100 };
101 static GtkToggleActionEntry toggle_action_data[] =
102 {
103         /* name, stock id, label, accel, tooltip, callback, is_active */
104         {"Offline", GTK_STOCK_DISCONNECT, "_Offline", NULL, NULL,
105                 G_CALLBACK(on_offline), FALSE},
106 };
107
108
109 /***********
110  * Helpers *
111  ***********/
112 static GtkUIManager *setup_actions()
113 {
114         GtkUIManager   *manager = gtk_ui_manager_new();
115         GtkActionGroup *actions = gtk_action_group_new("Actions");
116         gtk_action_group_add_actions(actions, action_data,
117                         G_N_ELEMENTS(action_data), NULL);
118         gtk_action_group_add_toggle_actions(actions, toggle_action_data,
119                         G_N_ELEMENTS(toggle_action_data), NULL);
120         gtk_ui_manager_insert_action_group(manager, actions, 0);
121         gtk_ui_manager_add_ui_from_string(manager, menu_xml, sizeof(menu_xml)-1, NULL);
122         g_object_unref(actions);
123         return manager;
124 }
125
126 static GtkWidget *setup_window(GtkUIManager *manager, GtkWidget **_notebook)
127 {
128         GtkWidget *window   = gtk_window_new(GTK_WINDOW_TOPLEVEL);
129         GtkWidget *menu     = gtk_ui_manager_get_widget(manager, "/Menu");
130         GtkWidget *notebook = gtk_notebook_new();
131         GtkWidget *vbox     = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
132         gtk_container_add(GTK_CONTAINER(window), vbox);
133         gtk_box_pack_start(GTK_BOX(vbox), menu,               FALSE, TRUE, 0);
134         gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(viewer), TRUE,  TRUE, 0);
135         gtk_box_pack_start(GTK_BOX(vbox), notebook,           FALSE, TRUE, 0);
136         g_signal_connect(window, "delete-event", G_CALLBACK(on_delete), NULL);
137         gtk_window_add_accel_group(GTK_WINDOW(window),
138                         gtk_ui_manager_get_accel_group(manager));
139         gtk_widget_set_size_request(GTK_WIDGET(viewer), 400, 300);
140         *_notebook = notebook;
141         return window;
142 }
143
144 static void setup_plugins(GtkUIManager *manager, GtkNotebook *notebook)
145 {
146         GtkActionGroup *actions = gtk_action_group_new("Plugins");
147         gtk_ui_manager_insert_action_group(manager, actions, 1);
148         guint merge_id = gtk_ui_manager_new_merge_id(manager);
149         for (GList *cur = grits_plugins_available(plugins); cur; cur = cur->next) {
150                 gchar *name = cur->data;
151                 GtkToggleAction *action = gtk_toggle_action_new(name, name, NULL, NULL);
152                 g_signal_connect(action, "toggled", G_CALLBACK(on_plugin), notebook);
153                 gtk_action_group_add_action(actions, GTK_ACTION(action));
154                 gtk_ui_manager_add_ui(manager, merge_id, "/Menu/Plugins", name, name,
155                                 GTK_UI_MANAGER_AUTO, TRUE);
156                 if (grits_prefs_get_boolean_v(prefs, "plugins", name, NULL))
157                         gtk_toggle_action_set_active(action, TRUE);
158         }
159 }
160
161 static void restore_states(GtkUIManager *manager)
162 {
163         GtkAction *action = gtk_ui_manager_get_action(manager, "/Menu/File/Offline");
164         gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action),
165                         grits_viewer_get_offline(viewer));
166 }
167
168 int main(int argc, char **argv)
169 {
170         gtk_init(&argc, &argv);
171
172         prefs   = grits_prefs_new(NULL, NULL);
173         plugins = grits_plugins_new(g_getenv("GRITS_PLUGIN_PATH"), prefs);
174         viewer  = grits_opengl_new(plugins, prefs);
175
176         GtkWidget    *notebook = NULL;
177         GtkUIManager *manager  = setup_actions();
178         GtkWidget    *window   = setup_window(manager, &notebook);
179         gtk_widget_show_all(window);
180         setup_plugins(manager, GTK_NOTEBOOK(notebook));
181         restore_states(manager);
182         gtk_ui_manager_ensure_update(manager);
183
184         gtk_main();
185
186         grits_plugins_free(plugins);
187         g_object_unref(prefs);
188
189         g_debug("GritsDemo: main - refs=%d,%d",
190                         G_OBJECT(manager)->ref_count,
191                         G_OBJECT(window)->ref_count);
192         g_object_unref(manager);
193         gtk_widget_destroy(window);
194
195         prefs   = NULL;
196         plugins = NULL;
197         viewer  = NULL;
198
199         //gdk_display_close(gdk_display_get_default());
200
201         return 0;
202 }