]> Pileus Git - ~andy/gtk/blob - examples/bloatpad.c
bloatpad: adjust to G(tk)Application 'quit' change
[~andy/gtk] / examples / bloatpad.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 activate_radio (GSimpleAction *action,
18                 GVariant      *parameter,
19                 gpointer       user_data)
20 {
21   g_action_change_state (G_ACTION (action), parameter);
22 }
23
24 static void
25 change_fullscreen_state (GSimpleAction *action,
26                          GVariant      *state,
27                          gpointer       user_data)
28 {
29   if (g_variant_get_boolean (state))
30     gtk_window_fullscreen (user_data);
31   else
32     gtk_window_unfullscreen (user_data);
33
34   g_simple_action_set_state (action, state);
35 }
36
37 static void
38 change_justify_state (GSimpleAction *action,
39                       GVariant      *state,
40                       gpointer       user_data)
41 {
42   GtkTextView *text = g_object_get_data (user_data, "bloatpad-text");
43   const gchar *str;
44
45   str = g_variant_get_string (state, NULL);
46
47   if (g_str_equal (str, "left"))
48     gtk_text_view_set_justification (text, GTK_JUSTIFY_LEFT);
49   else if (g_str_equal (str, "center"))
50     gtk_text_view_set_justification (text, GTK_JUSTIFY_CENTER);
51   else if (g_str_equal (str, "right"))
52     gtk_text_view_set_justification (text, GTK_JUSTIFY_RIGHT);
53   else
54     /* ignore this attempted change */
55     return;
56
57   g_simple_action_set_state (action, state);
58 }
59
60 static GtkClipboard *
61 get_clipboard (GtkWidget *widget)
62 {
63   return gtk_widget_get_clipboard (widget, gdk_atom_intern_static_string ("CLIPBOARD"));
64 }
65
66 static void
67 window_copy (GSimpleAction *action,
68              GVariant      *parameter,
69              gpointer       user_data)
70 {
71   GtkWindow *window = GTK_WINDOW (user_data);
72   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
73
74   gtk_text_buffer_copy_clipboard (gtk_text_view_get_buffer (text),
75                                   get_clipboard ((GtkWidget*) text));
76 }
77
78 static void
79 window_paste (GSimpleAction *action,
80               GVariant      *parameter,
81               gpointer       user_data)
82 {
83   GtkWindow *window = GTK_WINDOW (user_data);
84   GtkTextView *text = g_object_get_data ((GObject*)window, "bloatpad-text");
85   
86   gtk_text_buffer_paste_clipboard (gtk_text_view_get_buffer (text),
87                                    get_clipboard ((GtkWidget*) text),
88                                    NULL,
89                                    TRUE);
90
91 }
92
93 static GActionEntry win_entries[] = {
94   { "copy", window_copy, NULL, NULL, NULL },
95   { "paste", window_paste, NULL, NULL, NULL },
96   { "fullscreen", activate_toggle, NULL, "false", change_fullscreen_state },
97   { "justify", activate_radio, "s", "'left'", change_justify_state }
98 };
99
100 static void
101 new_window (GApplication *app,
102             GFile        *file)
103 {
104   GtkWidget *window, *grid, *scrolled, *view;
105   GtkWidget *toolbar;
106   GtkToolItem *button;
107   GtkWidget *sw, *box, *label;
108
109   window = gtk_application_window_new (GTK_APPLICATION (app));
110   gtk_window_set_default_size ((GtkWindow*)window, 640, 480);
111   g_action_map_add_action_entries (G_ACTION_MAP (window), win_entries, G_N_ELEMENTS (win_entries), window);
112   gtk_window_set_title (GTK_WINDOW (window), "Bloatpad");
113
114   grid = gtk_grid_new ();
115   gtk_container_add (GTK_CONTAINER (window), grid);
116
117   toolbar = gtk_toolbar_new ();
118   button = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_JUSTIFY_LEFT);
119   gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::left");
120   gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (button));
121
122   button = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_JUSTIFY_CENTER);
123   gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::center");
124   gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (button));
125
126   button = gtk_toggle_tool_button_new_from_stock (GTK_STOCK_JUSTIFY_RIGHT);
127   gtk_actionable_set_detailed_action_name (GTK_ACTIONABLE (button), "win.justify::right");
128   gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (button));
129
130   button = gtk_separator_tool_item_new ();
131   gtk_separator_tool_item_set_draw (GTK_SEPARATOR_TOOL_ITEM (button), FALSE);
132   gtk_tool_item_set_expand (GTK_TOOL_ITEM (button), TRUE);
133   gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (button));
134
135   button = gtk_tool_item_new ();
136   box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
137   gtk_container_add (GTK_CONTAINER (button), box);
138   label = gtk_label_new ("Fullscreen:");
139   gtk_container_add (GTK_CONTAINER (box), label);
140   sw = gtk_switch_new ();
141   gtk_actionable_set_action_name (GTK_ACTIONABLE (sw), "win.fullscreen");
142   gtk_container_add (GTK_CONTAINER (box), sw);
143   gtk_container_add (GTK_CONTAINER (toolbar), GTK_WIDGET (button));
144
145   gtk_grid_attach (GTK_GRID (grid), toolbar, 0, 0, 1, 1);
146
147   scrolled = gtk_scrolled_window_new (NULL, NULL);
148   gtk_widget_set_hexpand (scrolled, TRUE);
149   gtk_widget_set_vexpand (scrolled, TRUE);
150   view = gtk_text_view_new ();
151
152   g_object_set_data ((GObject*)window, "bloatpad-text", view);
153
154   gtk_container_add (GTK_CONTAINER (scrolled), view);
155
156   gtk_grid_attach (GTK_GRID (grid), scrolled, 0, 1, 1, 1);
157
158   if (file != NULL)
159     {
160       gchar *contents;
161       gsize length;
162
163       if (g_file_load_contents (file, NULL, &contents, &length, NULL, NULL))
164         {
165           GtkTextBuffer *buffer;
166
167           buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view));
168           gtk_text_buffer_set_text (buffer, contents, length);
169           g_free (contents);
170         }
171     }
172
173   gtk_widget_show_all (GTK_WIDGET (window));
174 }
175
176 static void
177 bloat_pad_activate (GApplication *application)
178 {
179   new_window (application, NULL);
180 }
181
182 static void
183 bloat_pad_open (GApplication  *application,
184                 GFile        **files,
185                 gint           n_files,
186                 const gchar   *hint)
187 {
188   gint i;
189
190   for (i = 0; i < n_files; i++)
191     new_window (application, files[i]);
192 }
193
194 typedef GtkApplication BloatPad;
195 typedef GtkApplicationClass BloatPadClass;
196
197 G_DEFINE_TYPE (BloatPad, bloat_pad, GTK_TYPE_APPLICATION)
198
199 static void
200 bloat_pad_finalize (GObject *object)
201 {
202   G_OBJECT_CLASS (bloat_pad_parent_class)->finalize (object);
203 }
204
205 static void
206 new_activated (GSimpleAction *action,
207                GVariant      *parameter,
208                gpointer       user_data)
209 {
210   GApplication *app = user_data;
211
212   g_application_activate (app);
213 }
214
215 static void
216 about_activated (GSimpleAction *action,
217                  GVariant      *parameter,
218                  gpointer       user_data)
219 {
220   gtk_show_about_dialog (NULL,
221                          "program-name", "Bloatpad",
222                          "title", "About Bloatpad",
223                          "comments", "Not much to say, really.",
224                          NULL);
225 }
226
227 static void
228 quit_activated (GSimpleAction *action,
229                 GVariant      *parameter,
230                 gpointer       user_data)
231 {
232   GApplication *app = user_data;
233
234   g_application_quit (app);
235 }
236
237 static GActionEntry app_entries[] = {
238   { "new", new_activated, NULL, NULL, NULL },
239   { "about", about_activated, NULL, NULL, NULL },
240   { "quit", quit_activated, NULL, NULL, NULL },
241 };
242
243 static void
244 bloat_pad_startup (GApplication *application)
245 {
246   GtkBuilder *builder;
247
248   G_APPLICATION_CLASS (bloat_pad_parent_class)
249     ->startup (application);
250
251   g_action_map_add_action_entries (G_ACTION_MAP (application), app_entries, G_N_ELEMENTS (app_entries), application);
252
253   builder = gtk_builder_new ();
254   gtk_builder_add_from_string (builder,
255                                "<interface>"
256                                "  <menu id='app-menu'>"
257                                "    <section>"
258                                "      <item>"
259                                "        <attribute name='label' translatable='yes'>_New Window</attribute>"
260                                "        <attribute name='action'>app.new</attribute>"
261                                "        <attribute name='accel'>&lt;Primary&gt;n</attribute>"
262                                "      </item>"
263                                "    </section>"
264                                "    <section>"
265                                "      <item>"
266                                "        <attribute name='label' translatable='yes'>_About Bloatpad</attribute>"
267                                "        <attribute name='action'>app.about</attribute>"
268                                "      </item>"
269                                "    </section>"
270                                "    <section>"
271                                "      <item>"
272                                "        <attribute name='label' translatable='yes'>_Quit</attribute>"
273                                "        <attribute name='action'>app.quit</attribute>"
274                                "        <attribute name='accel'>&lt;Primary&gt;q</attribute>"
275                                "      </item>"
276                                "    </section>"
277                                "  </menu>"
278                                "  <menu id='menubar'>"
279                                "    <submenu>"
280                                "      <attribute name='label' translatable='yes'>_Edit</attribute>"
281                                "      <section>"
282                                "        <item>"
283                                "          <attribute name='label' translatable='yes'>_Copy</attribute>"
284                                "          <attribute name='action'>win.copy</attribute>"
285                                "          <attribute name='accel'>&lt;Primary&gt;c</attribute>"
286                                "        </item>"
287                                "        <item>"
288                                "          <attribute name='label' translatable='yes'>_Parse</attribute>"
289                                "          <attribute name='action'>win.parse</attribute>"
290                                "          <attribute name='accel'>&lt;Primary&gt;v</attribute>"
291                                "        </item>"
292                                "      </section>"
293                                "    </submenu>"
294                                "    <submenu>"
295                                "      <attribute name='label' translatable='yes'>_View</attribute>"
296                                "      <section>"
297                                "        <item>"
298                                "          <attribute name='label' translatable='yes'>_Fullscreen</attribute>"
299                                "          <attribute name='action'>win.fullscreen</attribute>"
300                                "          <attribute name='accel'>F11</attribute>"
301                                "        </item>"
302                                "      </section>"
303                                "    </submenu>"
304                                "  </menu>"
305                                "</interface>", -1, NULL);
306   gtk_application_set_app_menu (GTK_APPLICATION (application), G_MENU_MODEL (gtk_builder_get_object (builder, "app-menu")));
307   gtk_application_set_menubar (GTK_APPLICATION (application), G_MENU_MODEL (gtk_builder_get_object (builder, "menubar")));
308   g_object_unref (builder);
309 }
310
311 static void
312 bloat_pad_init (BloatPad *app)
313 {
314 }
315
316 static void
317 bloat_pad_class_init (BloatPadClass *class)
318 {
319   GApplicationClass *application_class = G_APPLICATION_CLASS (class);
320   GObjectClass *object_class = G_OBJECT_CLASS (class);
321
322   application_class->startup = bloat_pad_startup;
323   application_class->activate = bloat_pad_activate;
324   application_class->open = bloat_pad_open;
325
326   object_class->finalize = bloat_pad_finalize;
327
328 }
329
330 BloatPad *
331 bloat_pad_new (void)
332 {
333   GtkApplication *bloat_pad;
334
335   g_type_init ();
336
337   g_set_application_name ("Bloatpad");
338
339   bloat_pad = g_object_new (bloat_pad_get_type (),
340                             "application-id", "org.gtk.Test.bloatpad",
341                             "flags", G_APPLICATION_HANDLES_OPEN,
342                             "inactivity-timeout", 30000,
343                             "register-session", TRUE,
344                             NULL);
345
346   return bloat_pad;
347 }
348
349 int
350 main (int argc, char **argv)
351 {
352   BloatPad *bloat_pad;
353   int status;
354
355   bloat_pad = bloat_pad_new ();
356
357   gtk_application_add_accelerator (GTK_APPLICATION (bloat_pad),
358                                    "F11", "win.fullscreen", NULL);
359
360   status = g_application_run (G_APPLICATION (bloat_pad), argc, argv);
361
362   g_object_unref (bloat_pad);
363
364   return status;
365 }