Move GTK menu bar and functions into seperate file
[colorize.git] / gui / menu.c
1 #include <gtk/gtk.h>
2 #include <gdk/gdkkeysyms.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6 #include "../src/mark.h"
7 #ifdef WITH_OPENCV
8 #include "../src/opticalflow.h"
9 #endif
10 #include "main.h"
11 #include "menu.h"
12 #include "image.h"
13 #include "palette.h"
14 #include "timeline.h"
15 #include "colorize.h"
16 #include "brightcontrast.h"
17 #include "level.h"
18 #include "fill.h"
19 #ifdef WITH_OPENCV
20 #include "flow.h"
21 #endif
22
23 /*
24  * menus
25  */
26
27 static void open_event(gpointer priv)
28 {
29         GtkWidget *dialog;
30         char *filename = NULL;
31         
32         if (anything_modified) {
33                 int ret;
34                 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
35                         GTK_DIALOG_DESTROY_WITH_PARENT,
36                         GTK_MESSAGE_ERROR,
37                         GTK_BUTTONS_OK_CANCEL,
38                         "Image has been changed, really open new image?");
39                 ret = gtk_dialog_run(GTK_DIALOG (dialog));
40                 gtk_widget_destroy(dialog);
41                 if (ret != GTK_RESPONSE_OK)
42                         return;
43         }
44
45         dialog = gtk_file_chooser_dialog_new("Select first grey image",
46                 GTK_WINDOW(main_window),
47                 GTK_FILE_CHOOSER_ACTION_OPEN,
48                 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
49                 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
50                 NULL);
51
52         if (frame_list)
53                 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(dialog), frame_list[timeline_selected].filename);
54         if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
55                 filename = strdup(gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)));
56         }
57
58         gtk_widget_destroy(dialog);
59
60         if (filename) {
61 // do not save          timeline_select_and_save(timeline_selected, timeline_selected);
62                 
63                 create_timeline(filename);
64                 if (frame_list)
65                         create_image(frame_list[timeline_selected].filename, 1);
66                 free(filename);
67         }
68
69 }
70
71 static void save_event(gpointer priv)
72 {
73         timeline_select_and_save(timeline_selected, timeline_selected);
74 }
75
76 static void exit_event(gpointer priv)
77 {
78         main_destroy();
79 }
80
81 static void color_changed(GtkWidget *widget, GtkColorSelection *colorsel)
82 {
83 }
84
85 void undo_event(gpointer priv)
86 {
87         copy_undo_to_mark(0);
88         draw_image(0, 0, -1, -1);
89 }
90
91 void redo_event(gpointer priv)
92 {
93         copy_undo_to_mark(1);
94         draw_image(0, 0, -1, -1);
95 }
96
97 void copy_event(gpointer priv)
98 {
99         copy_color(mark_selected + 1);
100 }
101
102 static void copy_all_event(gpointer priv)
103 {
104         copy_color(0);
105 }
106
107 void paste_event(gpointer priv)
108 {
109         copy_mark_to_undo();
110         paste_color();
111         draw_image(0, 0, -1, -1);
112 }
113
114 static void color_destroy(GtkWidget *widget, gpointer data)
115 {
116         colorseldlg = NULL;
117 }
118
119 void palette_event(gpointer priv)
120 {
121         GdkColor color;
122
123         if (colorseldlg) {
124                 gtk_widget_destroy(colorseldlg);
125                 colorseldlg = NULL;
126                 return;
127         }
128
129         color.red = mark_palette[mark_selected].r * 256 + 128;
130         color.green = mark_palette[mark_selected].g * 256 + 128;
131         color.blue = mark_palette[mark_selected].b * 256 + 128;
132
133         colorseldlg = gtk_color_selection_dialog_new("Select Color");
134         colorsel = GTK_COLOR_SELECTION (GTK_COLOR_SELECTION_DIALOG (colorseldlg)->colorsel);
135         gtk_color_selection_set_previous_color (colorsel, &color);
136         gtk_color_selection_set_current_color (colorsel, &color);
137         g_signal_connect(G_OBJECT(colorsel), "color_changed", G_CALLBACK(color_changed), (gpointer)colorsel);
138         g_signal_connect(G_OBJECT(colorseldlg), "response", G_CALLBACK(color_response), NULL);
139         g_signal_connect(G_OBJECT(colorseldlg), "destroy", G_CALLBACK(color_destroy), NULL);
140
141
142         gtk_widget_show(colorseldlg);
143 }
144
145 static void keyframe_event(gpointer priv)
146 {
147         toggle_keyframe();
148 }
149
150 static void erase_event(gpointer priv)
151 {
152         printerror("Use RIGHT mouse button to erase!");
153 }
154
155 static void clear_event(gpointer priv)
156 {
157         copy_mark_to_undo();
158         erase_mark(0);
159         draw_image(0, 0, -1, -1);
160 }
161
162 static void clear_color_event(gpointer priv)
163 {
164         copy_mark_to_undo();
165         erase_mark(mark_selected + 1);
166         draw_image(0, 0, -1, -1);
167 }
168
169 void zoom_in_event(gpointer priv)
170 {
171         if (img_scale_x < 64) {
172                 int aspect = img_scale_y / img_scale_x;
173                 img_scale_x += 4;
174                 img_scale_y = img_scale_x * aspect;
175                 create_or_reset_pixbuf(0);
176         }
177 }
178
179 void zoom_out_event(gpointer priv)
180 {
181         if (img_scale_x > 4) {
182                 int aspect = img_scale_y / img_scale_x;
183                 img_scale_x -= 4;
184                 img_scale_y = img_scale_x * aspect;
185                 create_or_reset_pixbuf(0);
186         }
187 }
188
189 static void zoom_100_event(gpointer priv)
190 {
191         img_scale_x = 16;
192         img_scale_y = 16;
193         create_or_reset_pixbuf(0);
194 }
195
196 static void zoom_field_event(gpointer priv)
197 {
198         if (gtk_check_menu_item_get_active((GtkCheckMenuItem *)priv))
199                 img_scale_y = img_scale_x*2;
200         else
201                 img_scale_y = img_scale_x;
202         create_or_reset_pixbuf(1);
203 }
204
205 static void show_highlighted_event(gpointer priv)
206 {
207         highlight = gtk_check_menu_item_get_active((GtkCheckMenuItem *)priv);
208         set_button_toggel_by_label(TOGGLE_LABEL_HIGHLIGHT, highlight);
209 }
210
211 static void show_preview_event(gpointer priv)
212 {
213         preview = gtk_check_menu_item_get_active((GtkCheckMenuItem *)priv);
214         set_button_toggel_by_label(TOGGLE_LABEL_PREVIEW, preview);
215 }
216
217 void colorize_event(gpointer priv)
218 {
219         if (rendered) {
220                 printerror("Disable colorized view first.");
221                 return;
222         }
223 #ifdef WITH_OPENCV
224         if (flowview) {
225                 printerror("Disable flow view first.");
226                 return;
227         }
228 #endif
229         if (img_mark_buffer)
230                 colorize_image();
231 }
232
233 static void show_colorized_event(gpointer priv)
234 {
235         if (timeline_frames > 1)
236                 rendered = gtk_check_menu_item_get_active((GtkCheckMenuItem *)priv);
237         else
238                 rendered = 0;
239         gtk_check_menu_item_set_active((GtkCheckMenuItem *)priv, rendered);
240         set_button_toggel_by_label(TOGGLE_LABEL_RENDERED, rendered);
241 }
242
243 #ifdef WITH_OPENCV
244 static void show_flow_event(gpointer priv)
245 {
246         if (flow_enable && timeline_frames > 1)
247                 flowview = gtk_check_menu_item_get_active((GtkCheckMenuItem *)priv);
248         else
249                 flowview = 0;
250         gtk_check_menu_item_set_active((GtkCheckMenuItem *)priv, flowview);
251         set_button_toggel_by_label(TOGGLE_LABEL_FLOWVIEW, flowview);
252 }
253 #endif
254
255 static void dummy_event(gpointer priv)
256 {
257 }
258
259
260
261 struct my_menu_item {
262         enum toggle_label label;
263         GtkWidget *widget;
264         const char *text;
265         void (*handler)(gpointer priv);
266         gchar *stock;
267 };
268
269 struct my_menu {
270         const char *text;
271         struct my_menu_item *items;
272 };
273
274 struct my_menu_item file_menu_items[] = {
275         { TOGGLE_LABEL_NONE, NULL, "Open", open_event, GTK_STOCK_OPEN },
276         { TOGGLE_LABEL_NONE, NULL, "Save", save_event, GTK_STOCK_SAVE },
277         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
278         { TOGGLE_LABEL_NONE, NULL, "Exit", exit_event, GTK_STOCK_QUIT },
279         { TOGGLE_LABEL_NONE, NULL, NULL, NULL }
280 };
281
282 struct my_menu_item edit_menu_items[] = {
283         { TOGGLE_LABEL_NONE, NULL, "Undo", undo_event, GTK_STOCK_UNDO },
284         { TOGGLE_LABEL_NONE, NULL, "Redo", redo_event, GTK_STOCK_REDO },
285         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
286         { TOGGLE_LABEL_NONE, NULL, "Copy", copy_event, GTK_STOCK_COPY },
287         { TOGGLE_LABEL_NONE, NULL, "Copy All", copy_all_event, NULL },
288         { TOGGLE_LABEL_NONE, NULL, "Paste", paste_event, GTK_STOCK_PASTE },
289         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
290         { TOGGLE_LABEL_NONE, NULL, "Palette", palette_event, NULL },
291         { TOGGLE_LABEL_NONE, NULL, "Bright/Contrast", bc_event, NULL },
292         { TOGGLE_LABEL_NONE, NULL, "Adjust Levels", level_event, NULL },
293 #ifdef WITH_OPENCV
294         { TOGGLE_LABEL_NONE, NULL, "Optical Flow", flow_event, NULL },
295 #endif
296         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
297         { TOGGLE_LABEL_NONE, NULL, "Keyframe", keyframe_event, NULL },
298         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
299         { TOGGLE_LABEL_NONE, NULL, "Erase Tool", erase_event, NULL },
300         { TOGGLE_LABEL_NONE, NULL, "Clear", clear_event, GTK_STOCK_CLEAR },
301         { TOGGLE_LABEL_NONE, NULL, "Clear Color", clear_color_event, NULL },
302         { TOGGLE_LABEL_NONE, NULL, NULL, NULL }
303 };
304
305 struct my_menu_item view_menu_items[] = {
306         { TOGGLE_LABEL_NONE, NULL, "Zoom In", zoom_in_event, GTK_STOCK_ZOOM_IN },
307         { TOGGLE_LABEL_NONE, NULL, "Zoom Out", zoom_out_event, GTK_STOCK_ZOOM_OUT },
308         { TOGGLE_LABEL_NONE, NULL, "Zoom 100", zoom_100_event, GTK_STOCK_ZOOM_100 },
309         { TOGGLE_LABEL_ZOOMFIELDS, NULL, "Zoom Field", zoom_field_event, NULL },
310         { TOGGLE_LABEL_NONE, NULL, "", dummy_event, NULL },
311         { TOGGLE_LABEL_HIGHLIGHT, NULL, "Highlight color", show_highlighted_event, NULL },
312         { TOGGLE_LABEL_PREVIEW, NULL, "Preview color", show_preview_event, NULL },
313         { TOGGLE_LABEL_RENDERED, NULL, "Show colorized", show_colorized_event, NULL },
314 #ifdef WITH_OPENCV
315         { TOGGLE_LABEL_FLOWVIEW, NULL, "Show flow", show_flow_event, NULL },
316 #endif
317         { TOGGLE_LABEL_NONE, NULL, NULL, NULL }
318 };
319
320 struct my_menu_item render_menu_items[] = {
321         { TOGGLE_LABEL_NONE, NULL, "Colorize Image", colorize_event, NULL },
322         { TOGGLE_LABEL_NONE, NULL, NULL, NULL }
323 };
324
325 struct my_menu menus[] = {
326         { "_File", file_menu_items },
327         { "_Edit", edit_menu_items },
328         { "_View", view_menu_items },
329         { "_Render", render_menu_items },
330         { NULL, NULL }
331 };
332
333 /* create menu bar */
334 void create_menus(GtkWidget *menu_bar)
335 {
336         GtkWidget *root_menu;
337         GtkWidget *menu;
338         GtkWidget *menu_item;
339         struct my_menu_item *items;
340         int i, j;
341
342         /* create vbox and add menu_bar */
343         for (i = 0; menus[i].text; i++) {
344                 /* create menu with items */
345                 items = menus[i].items;
346                 menu = gtk_menu_new();
347                 for (j = 0; items[j].text; j++) {
348                         if (!items[j].text[0])
349                                 menu_item = gtk_separator_menu_item_new();
350                         else if (items[j].stock)
351                                 menu_item = gtk_image_menu_item_new_from_stock(items[j].stock, NULL);
352                         else if (items[j].label != TOGGLE_LABEL_NONE)
353                                 menu_item = gtk_check_menu_item_new_with_label(items[j].text);
354                         else
355                                 menu_item = gtk_menu_item_new_with_label(items[j].text);
356                         items[j].widget = menu_item;
357                         gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
358                         g_signal_connect_swapped(menu_item, "activate", G_CALLBACK(items[j].handler), menu_item);
359                         gtk_widget_show(menu_item);
360                 }
361                 /* create root menu and add to menu_bar */
362                 root_menu = gtk_menu_item_new_with_mnemonic(menus[i].text);
363                 gtk_widget_show(root_menu);
364                 gtk_menu_item_set_submenu(GTK_MENU_ITEM(root_menu), menu);
365                 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), root_menu);
366         }
367
368 }
369
370 void set_menu_toggel_by_label(enum toggle_label label, gboolean active)
371 {
372         struct my_menu_item *items;
373         int i, j;
374
375         for (i = 0; menus[i].text; i++) {
376                 items = menus[i].items;
377                 for (j = 0; items[j].text; j++) {
378                         if (items[j].label == label)
379                                 gtk_check_menu_item_set_active((GtkCheckMenuItem *)items[j].widget, active);
380                 }
381         }
382 }