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