]> Pileus Git - ~andy/gtk/blob - examples/plugman.c
11a821008be214dd021efce6d23fdcbbe1fbba44
[~andy/gtk] / examples / plugman.c
1 #include <stdlib.h>
2 #include <gtk/gtk.h>
3
4 static void
5 activate_toggle (GSimpleAction *action,
6                  GVariant      *parameter,
7                  gpointer       user_data)
8 {
9   GVariant *state;
10
11   state = g_action_get_state (G_ACTION (action));
12   g_action_change_state (G_ACTION (action), g_variant_new_boolean (!g_variant_get_boolean (state)));
13   g_variant_unref (state);
14 }
15
16 static void
17 change_fullscreen_state (GSimpleAction *action,
18                          GVariant      *state,
19                          gpointer       user_data)
20 {
21   if (g_variant_get_boolean (state))
22     gtk_window_fullscreen (user_data);
23   else
24     gtk_window_unfullscreen (user_data);
25
26   g_simple_action_set_state (action, state);
27 }
28
29 static GtkClipboard *
30 get_clipboard (GtkWidget *widget)
31 {
32   return gtk_widget_get_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
33 }
34
35 static void
36 window_copy (GSimpleAction *action,
37              GVariant      *parameter,
38              gpointer       user_data)
39 {
40   GtkWindow *window = GTK_WINDOW (user_data);
41   GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text");
42
43   gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
44                                   get_clipboard ((GtkWidget*) text));
45 }
46
47 static void
48 window_paste (GSimpleAction *action,
49               GVariant      *parameter,
50               gpointer       user_data)
51 {
52   GtkWindow *window = GTK_WINDOW (user_data);
53   GtkTextView *text = g_object_get_data ((GObject*)window, "plugman-text");
54   
55   gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
56                                    get_clipboard ((GtkWidget*) text),
57                                    NULL,
58                                    TRUE);
59
60 }
61
62 static GActionEntry win_entries[] = {
63   { "copy", window_copy, NULL, NULL, NULL },
64   { "paste", window_paste, NULL, NULL, NULL },
65   { "fullscreen", activate_toggle, NULL, "false", change_fullscreen_state }
66 };
67
68 static void
69 new_window (GApplication *app,
70             GFile        *file)
71 {
72   GtkWidget *window, *grid, *scrolled, *view;
73
74   window = gtk_application_window_new (GTK_APPLICATION (app));
75   gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
76   g_action_map_add_action_entries (G_ACTION_MAP (window), win_entries, G_N_ELEMENTS (win_entries), window);
77   gtk_window_set_title (GTK_WINDOW (window), "Plugman");
78
79   grid = gtk_grid_new ();
80   gtk_container_add (GTK_CONTAINER (window), grid);
81
82   scrolled = gtk_scrolled_window_new (NULL, NULL);
83   gtk_widget_set_hexpand (scrolled, TRUE);
84   gtk_widget_set_vexpand (scrolled, TRUE);
85   view = gtk_text_view_new ();
86
87   g_object_set_data ((GObject*)window, "plugman-text", view);
88
89   gtk_container_add (GTK_CONTAINER (scrolled), view);
90
91   gtk_grid_attach (GTK_GRID (grid), scrolled, 0, 0, 1, 1);
92
93   if (file != NULL)
94     {
95       gchar *contents;
96       gsize length;
97
98       if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
99         {
100           GtkTextBuffer *buffer;
101
102           buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
103           gtk_text_buffer_set_text (buffer, contents, length);
104           g_free (contents);
105         }
106     }
107
108   gtk_widget_show_all (GTK_WIDGET (window));
109 }
110
111 static void
112 plug_man_activate (GApplication *application)
113 {
114   new_window (application, NULL);
115 }
116
117 static void
118 plug_man_open (GApplication  *application,
119                 GFile        **files,
120                 gint           n_files,
121                 const gchar   *hint)
122 {
123   gint i;
124
125   for (i = 0; i < n_files; i++)
126     new_window (application, files[i]);
127 }
128
129 typedef GtkApplication PlugMan;
130 typedef GtkApplicationClass PlugManClass;
131
132 G_DEFINE_TYPE (PlugMan, plug_man, GTK_TYPE_APPLICATION)
133
134 static void
135 plug_man_finalize (GObject *object)
136 {
137   G_OBJECT_CLASS (plug_man_parent_class)->finalize (object);
138 }
139
140 static void
141 show_about (GSimpleAction *action,
142             GVariant      *parameter,
143             gpointer       user_data)
144 {
145   gtk_show_about_dialog (NULL,
146                          "program-name", "Plugman",
147                          "title", "About Plugman",
148                          "comments", "A cheap Bloatpad clone.",
149                          NULL);
150 }
151
152
153 static void
154 quit_app (GSimpleAction *action,
155           GVariant      *parameter,
156           gpointer       user_data)
157 {
158   GList *list, *next;
159   GtkWindow *win;
160
161   g_print ("Going down...\n");
162
163   list = gtk_application_get_windows (GTK_APPLICATION (g_application_get_default ()));
164   while (list)
165     {
166       win = list->data;
167       next = list->next;
168
169       gtk_widget_destroy (GTK_WIDGET (win));
170
171       list = next;
172     }
173 }
174
175 static gboolean is_red_plugin_enabled;
176
177 static gboolean
178 red_plugin_enabled (void)
179 {
180   return is_red_plugin_enabled;
181 }
182
183 static GMenuModel *
184 find_plugin_menu (void)
185 {
186   GMenuModel *menubar;
187   GMenuModel *menu;
188   gint i, j;
189   const gchar *label, *id;
190
191   menubar = g_application_get_menubar (g_application_get_default ());
192   for (i = 0; i < g_menu_model_get_n_items (menubar); i++)
193     {
194        if (g_menu_model_get_item_attribute (menubar, i, "label", "s", &label) &&
195            g_strcmp0 (label, "_Edit") == 0)
196          {
197             menu = g_menu_model_get_item_link (menubar, i, "submenu");
198             for (j = 0; j < g_menu_model_get_n_items (menu); j++)
199               {
200                 if (g_menu_model_get_item_attribute (menu, j, "id", "s", &id) &&
201                     g_strcmp0 (id, "plugins") == 0)
202                   {
203                     return g_menu_model_get_item_link (menu, j, "section");
204                   }
205               }
206          }
207     }
208
209   return NULL;
210 }
211
212 static void
213 red_action (GAction  *action,
214             GVariant *parameter,
215             gpointer  data)
216 {
217   g_print ("Here is where we turn the text red\n");
218 }
219
220 static void
221 enable_red_plugin (void)
222 {
223   GMenu *plugin_menu;
224   GAction *action;
225
226   g_print ("Enabling 'Red' plugin\n");
227
228   action = (GAction *)g_simple_action_new ("red-action", NULL);
229   g_signal_connect (action, "activate", G_CALLBACK (red_action), NULL);
230   g_action_map_add_action (G_ACTION_MAP (g_application_get_default ()), action);
231   g_print ("Actions of 'Red' plugin added\n");
232
233   plugin_menu = find_plugin_menu ();
234   if (plugin_menu)
235     {
236       GMenu *section;
237       GMenuItem *item;
238
239       section = g_menu_new ();
240       g_menu_insert (section, 0, "Turn text red", "app.red-action");
241       item = g_menu_item_new_section (NULL, (GMenuModel*)section);
242       g_menu_item_set_attribute (item, "id", "s", "red");
243       g_menu_append_item (plugin_menu, item);
244       g_object_unref (item);
245       g_object_unref (section);
246       g_print ("Menus of 'Red' plugin added\n");
247     }
248   else
249     g_warning ("Plugin menu not found\n");
250
251   is_red_plugin_enabled = TRUE;
252 }
253
254 static void
255 disable_red_plugin (void)
256 {
257   GMenuModel *plugin_menu;
258
259   g_print ("Disabling 'Red' plugin\n");
260
261   g_action_map_remove_action (G_ACTION_MAP (g_application_get_default ()), "app.red-action");
262
263   plugin_menu = find_plugin_menu ();
264   if (plugin_menu)
265     {
266       const gchar *id;
267       gint i;
268
269       for (i = 0; i < g_menu_model_get_n_items (plugin_menu); i++)
270         {
271            if (g_menu_model_get_item_attribute (plugin_menu, i, "id", "s", &id) &&
272                g_strcmp0 (id, "red") == 0)
273              {
274                g_menu_remove (plugin_menu, i);
275                g_print ("Menus of 'Red' plugin removed\n");
276              }
277         }
278     }
279   else
280     g_warning ("Plugin menu not found\n");
281
282   is_red_plugin_enabled = FALSE;
283 }
284
285 static void
286 enable_or_disable_red_plugin (void)
287 {
288   if (red_plugin_enabled ())
289     disable_red_plugin ();
290   else
291     enable_red_plugin ();
292 }
293
294
295 static void
296 configure_plugins (GSimpleAction *action,
297                    GVariant      *parameter,
298                    gpointer       user_data)
299 {
300   GtkBuilder *builder;
301   GtkWidget *dialog;
302   GtkWidget *red;
303   GError *error = NULL;
304
305   builder = gtk_builder_new ();
306   gtk_builder_add_from_string (builder,
307                                "<interface>"
308                                "  <object class='GtkDialog' id='plugin-dialog'>"
309                                "    <property name='border-width'>12</property>"
310                                "    <property name='title'>Plugins</property>"
311                                "    <child internal-child='vbox'>"
312                                "      <object class='GtkBox' id='content-area'>"
313                                "        <property name='visible'>True</property>"
314                                "        <child>"
315                                "          <object class='GtkCheckButton' id='red-plugin'>"
316                                "            <property name='label'>Red Plugin - turn your text red</property>"
317                                "            <property name='visible'>True</property>"
318                                "          </object>"
319                                "        </child>"
320                                "      </object>"
321                                "    </child>"
322                                "    <child internal-child='action_area'>"
323                                "      <object class='GtkButtonBox' id='action-area'>"
324                                "        <property name='visible'>True</property>"
325                                "        <child>"
326                                "          <object class='GtkButton' id='close-button'>"
327                                "            <property name='label'>Close</property>"
328                                "            <property name='visible'>True</property>"
329                                "          </object>"
330                                "        </child>"
331                                "      </object>"
332                                "    </child>"
333                                "    <action-widgets>"
334                                "      <action-widget response='-5'>close-button</action-widget>"
335                                "    </action-widgets>"
336                                "  </object>"
337                                "</interface>", -1, &error);
338   if (error)
339     {
340       g_warning ("%s", error->message);
341       g_error_free (error);
342       return;
343     }
344
345   dialog = (GtkWidget *)gtk_builder_get_object (builder, "plugin-dialog");
346   red = (GtkWidget *)gtk_builder_get_object (builder, "red-plugin");
347   gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (red), red_plugin_enabled ());
348   g_signal_connect (red, "toggled", G_CALLBACK (enable_or_disable_red_plugin), NULL);
349
350   g_signal_connect (dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL);
351
352   gtk_window_present (GTK_WINDOW (dialog));
353 }
354
355 static GActionEntry app_entries[] = {
356   { "about", show_about, NULL, NULL, NULL },
357   { "quit", quit_app, NULL, NULL, NULL },
358   { "plugins", configure_plugins, NULL, NULL, NULL },
359 };
360
361 static void
362 plug_man_startup (GApplication *application)
363 {
364   GtkBuilder *builder;
365
366   G_APPLICATION_CLASS (plug_man_parent_class)
367     ->startup (application);
368
369   g_action_map_add_action_entries (G_ACTION_MAP (application), app_entries, G_N_ELEMENTS (app_entries), application);
370
371   builder = gtk_builder_new ();
372   gtk_builder_add_from_string (builder,
373                                "<interface>"
374                                "  <menu id='app-menu'>"
375                                "    <section>"
376                                "      <item label='_About Plugman' action='app.about'/>"
377                                "    </section>"
378                                "    <section>"
379                                "      <item label='_Quit' action='app.quit' accel='<Primary>q'/>"
380                                "    </section>"
381                                "  </menu>"
382                                "  <menu id='menubar'>"
383                                "    <submenu label='_Edit'>"
384                                "      <section>"
385                                "        <item label='_Copy' action='win.copy'/>"
386                                "        <item label='_Paste' action='win.paste'/>"
387                                "      </section>"
388                                "      <section id='plugins'>"
389                                "      </section>"
390                                "      <section>"
391                                "        <item label='Plugins' action='app.plugins'/>"
392                                "      </section>"
393                                "    </submenu>"
394                                "    <submenu label='_View'>"
395                                "      <section>"
396                                "        <item label='_Fullscreen' action='win.fullscreen'/>"
397                                "      </section>"
398                                "    </submenu>"
399                                "  </menu>"
400                                "</interface>", -1, NULL);
401   g_application_set_app_menu (application, G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
402   g_application_set_menubar (application, G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
403   g_object_unref (builder);
404 }
405
406 static void
407 plug_man_init (PlugMan *app)
408 {
409 }
410
411 static void
412 plug_man_class_init (PlugManClass *class)
413 {
414   GApplicationClass *application_class = G_APPLICATION_CLASS (class);
415   GObjectClass *object_class = G_OBJECT_CLASS (class);
416
417   application_class->startup = plug_man_startup;
418   application_class->activate = plug_man_activate;
419   application_class->open = plug_man_open;
420
421   object_class->finalize = plug_man_finalize;
422
423 }
424
425 PlugMan *
426 plug_man_new (void)
427 {
428   g_type_init ();
429
430   return g_object_new (plug_man_get_type (),
431                        "application-id", "org.gtk.Test.plugman",
432                        "flags", G_APPLICATION_HANDLES_OPEN,
433                        NULL);
434 }
435
436 int
437 main (int argc, char **argv)
438 {
439   PlugMan *plug_man;
440   int status;
441
442   plug_man = plug_man_new ();
443   gtk_application_add_accelerator (GTK_APPLICATION (plug_man),
444                                    "F11", "win.fullscreen", NULL);
445   status = g_application_run (G_APPLICATION (plug_man), argc, argv);
446   g_object_unref (plug_man);
447
448   return status;
449 }