minor fixes
[colorize.git] / gui / main.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 <getopt.h>
7 #include "../src/mark.h"
8 #ifdef WITH_OPENCV
9 #include "../src/opticalflow.h"
10 #endif
11 #include "main.h"
12 #include "menu.h"
13 #include "toolbar.h"
14 #include "image.h"
15 #include "palette.h"
16 #include "timeline.h"
17 #include "colorize.h"
18 #include "diag_bc.h"
19 #include "diag_level.h"
20 #include "fill.h"
21 #ifdef WITH_OPENCV
22 #include "diag_flow.h"
23 #endif
24
25 #define CC_APP_TITLE "Colorize GTK"
26 GtkWidget *main_window;
27 GtkWidget *img_scroll;
28 GtkWidget *img_drawing_area = NULL;
29 GtkWidget *timeline_drawing_area;
30 GtkWidget *timeline_scroll;
31 GtkWidget *palette_treeview = NULL;
32 GtkLabel *img_label;
33 GtkToggleButton *show_marked_button, *show_highlighted_button, *show_preview_button, *show_colorized_button;
34 #ifdef WITH_OPENCV
35 GtkToggleButton *show_flow_button;
36 #endif
37 int button_down = 0, button_down_x = -1000, button_down_y = -1000, shift_pressed = 0, ctrl_pressed = 0, button_num = 1;
38 int last_x = 0, last_y = 0; /* where mouse is over scrolled view */
39 int brush_size;
40 int mark = 1, highlight = 0, preview = 0, rendered = 0, draw_mode = 1, move_mode = 0, fill_mode = 0, pick_mode = 0, flowview = 0;
41 int mouse_over_palette_area = 0, mouse_over_drawing_area = 0, mouse_over_timeline_area = 0;
42 char output_prefix[256] = "";
43 #define min(x,y) ((x < y) ? x : y)
44 #define abs(x,y) ((x < y) ? y - x : x - y)
45
46 /* error requester */
47 void printerror(const char *fmt, ...)
48 {
49         char buffer[4096];
50         va_list args;
51
52         va_start(args,fmt);
53         vsprintf(buffer,fmt,args);
54         buffer[sizeof(buffer)-1]=0;
55         va_end(args);
56
57         GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
58                 GTK_DIALOG_DESTROY_WITH_PARENT,
59                 GTK_MESSAGE_ERROR,
60                 GTK_BUTTONS_CLOSE,
61                 "%s", buffer);
62         gtk_dialog_run (GTK_DIALOG (dialog));
63         gtk_widget_destroy (dialog);
64 }
65
66 static int already_destroyed = 0;
67
68 /* exit program and save current mask / palette */
69 void main_destroy(void)
70 {
71         if (anything_modified) {
72                 int ret;
73                 GtkWidget *dialog = gtk_message_dialog_new (GTK_WINDOW(main_window),
74                         GTK_DIALOG_DESTROY_WITH_PARENT,
75                         GTK_MESSAGE_ERROR,
76                         GTK_BUTTONS_OK_CANCEL,
77                         "Image has been changed, really quit?");
78                 ret = gtk_dialog_run(GTK_DIALOG (dialog));
79                 gtk_widget_destroy(dialog);
80                 if (ret != GTK_RESPONSE_OK)
81                         return;
82         }
83         already_destroyed = 1;
84         gtk_main_quit();
85 }
86
87
88 static void destroy(GtkWidget *widget, gpointer data)
89 {
90         if (!already_destroyed)
91                 main_destroy();
92 }
93
94 /*
95  * keypress
96  */
97
98 /* event handler for main window keys */
99 static gboolean on_key_press(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
100 {
101         int frame;
102
103 //      if (mouse_over_palette_area)
104         if (!mouse_over_drawing_area && !mouse_over_timeline_area)
105                 return FALSE;
106
107         switch (event->keyval) {
108         case GDK_q:
109         case GDK_w:
110                 if (event->state & GDK_CONTROL_MASK) {
111                         main_destroy();
112                         return TRUE;
113                 }
114                 break;
115         case GDK_Right:
116         case GDK_Up:
117                 frame = timeline_selected + 1;
118                 if ((event->state & GDK_SHIFT_MASK) || event->keyval == GDK_Up) {
119                         while(frame < timeline_frames && frame_list[frame].marked == 0 && frame_list[frame].keyframe == 0)
120                                 frame++;
121                 }
122                 if (frame < timeline_frames)
123                         timeline_select_and_save(timeline_selected, frame);
124                 return TRUE;
125         case GDK_Left:
126         case GDK_Down:
127                 frame = timeline_selected - 1;
128                 if ((event->state & GDK_SHIFT_MASK) || event->keyval == GDK_Down) {
129                         while(frame >= 0 && frame_list[frame].marked == 0 && frame_list[frame].keyframe == 0)
130                                 frame--;
131                 }
132                 if (frame >= 0)
133                         timeline_select_and_save(timeline_selected, frame);
134                 return TRUE;
135         case GDK_Home:
136                 frame = 0;
137                 timeline_select_and_save(timeline_selected, frame);
138                 return TRUE;
139         case GDK_End:
140                 frame = timeline_frames - 1;
141                 timeline_select_and_save(timeline_selected, frame);
142                 return TRUE;
143         case GDK_u:
144         case GDK_z:
145                 undo_event(NULL);
146                 return TRUE;
147         case GDK_r:
148                 redo_event(NULL);
149                 return TRUE;
150         case GDK_c:
151                 if (event->state & GDK_CONTROL_MASK) {
152                         copy_event(NULL);
153                         return TRUE;
154                 }
155                 break;
156         case GDK_v:
157                 if (event->state & GDK_CONTROL_MASK) {
158                         paste_event(NULL);
159                         return TRUE;
160                 }
161                 break;
162         case GDK_k:
163                 toggle_keyframe();
164                 return TRUE;
165         case GDK_Shift_L:
166         case GDK_Shift_R:
167                 shift_pressed = 1;
168                 break;
169         case GDK_Control_L:
170         case GDK_Control_R:
171                 ctrl_pressed = 1;
172                 break;
173 //      default:
174 //              printf("press %x\n", event->keyval);
175         }
176
177         return FALSE;
178 }
179
180 /* event handler for main window keys */
181 static gboolean on_key_release(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
182 {
183         switch (event->keyval) {
184         case GDK_Shift_L:
185         case GDK_Shift_R:
186                 shift_pressed = 0;
187                 break;
188         case GDK_Control_L:
189         case GDK_Control_R:
190                 ctrl_pressed = 0;
191                 break;
192 //      default:
193 //              printf("release %x\n", event->keyval);
194         }
195
196         return FALSE;
197 }
198
199 /*
200  * image area
201  */
202
203 /* events if mouse is over palette area */
204 static gboolean enter_palette_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
205 {
206         mouse_over_palette_area = 1;
207         return FALSE;
208 }
209 static gboolean leave_palette_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
210 {
211         mouse_over_palette_area = 0;
212         return FALSE;
213 }
214
215 /* events if mouse is over image area */
216 static gboolean enter_drawing_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
217 {
218         mouse_over_drawing_area = 1;
219         return FALSE;
220 }
221 static gboolean leave_drawing_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
222 {
223         mouse_over_drawing_area = 0;
224         return FALSE;
225 }
226
227 /* events if mouse is over timeline area */
228 static gboolean enter_timeline_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
229 {
230         mouse_over_timeline_area = 1;
231         return FALSE;
232 }
233 static gboolean leave_timeline_area(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
234 {
235         mouse_over_timeline_area = 0;
236         timeline_point(-1, -1);
237         return FALSE;
238 }
239
240 /* ugly non-bresenham.... */
241 static void draw_line(int x, int y, int paint)
242 {
243         double step_x = 0, step_y = 0;
244
245         if (abs(x,button_down_x) > abs(y,button_down_y)) {
246                 while(42) {
247                         if (button_down_x < x) {
248                                 step_x++;
249                                 step_y += (double)(button_down_y - y) / (double)(button_down_x - x);
250                         } else {
251                                 step_x--;
252                                 step_y -= (double)(button_down_y - y) / (double)(button_down_x - x);
253                         }
254                         paint_brush(button_down_x+step_x, button_down_y+step_y, brush_size, paint);
255                         draw_image(button_down_x+step_x-(brush_size*img_scale_x/16)+1, button_down_y+step_y-(brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
256                         if (x == button_down_x+step_x)
257                                 break;
258                 }
259         } else {
260                 while(42) {
261                         if (y == button_down_y) /* no move at all */
262                                 break;
263                         if (button_down_y < y) {
264                                 step_y++;
265                                 step_x += (double)(button_down_x - x) / (double)(button_down_y - y);
266                         } else {
267                                 step_y--;
268                                 step_x -= (double)(button_down_x - x) / (double)(button_down_y - y);
269                         }
270                         paint_brush(button_down_x+step_x, button_down_y+step_y, brush_size, paint);
271                         draw_image(button_down_x+step_x-(brush_size*img_scale_x/16)+1, button_down_y+(step_y-brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
272                         if (y == button_down_y+step_y)
273                                 break;
274                 }
275         }
276         paint_brush(x, y, brush_size, paint);
277         draw_image(x-(brush_size*img_scale_x/16)+1, y-(brush_size*img_scale_y/16)+1, brush_size*2*img_scale_x/16, brush_size*2*img_scale_y/16);
278         button_down_x = x;
279         button_down_y = y;
280 }
281
282 /* notify movement of mouse inside image area */
283 static gint motion_notify_event( GtkWidget *widget,
284                                  GdkEventMotion *event )
285 {
286         int x, y;
287         GdkModifierType state;
288
289         if (event->is_hint)
290                 gdk_window_get_pointer (event->window, &x, &y, &state);
291         else
292         {
293                 x = event->x;
294                 y = event->y;
295                 state = event->state;
296         }
297         last_x = x;
298         last_y = y;
299
300         if ((state & (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK))) {
301                 if (mark || highlight) {
302                         if (button_down && pick_mode) {
303                                 pick_color(x, y);
304                         }
305                         if (button_down && !pick_mode) {
306                                 if (move_mode) {
307                                         move_mark((x-button_down_x)*16/img_scale_x, (y-button_down_y)*16/img_scale_y);
308                                         draw_image(0, 0, -1, -1);
309                                 } else
310                                 if (draw_mode) {
311                                         draw_line(x, y, button_num == 1);
312                                 }
313                         }
314                 }
315         } else {
316                 if (button_down && pick_mode)
317                         release_pick_mode();
318                 button_down = 0;
319         }
320                                                                                    
321         return TRUE;
322 }
323
324 /* button press event inside image area */
325 static gint button_press_event (GtkWidget *widget, GdkEventButton *event)
326 {
327         int x,y;
328
329         x = event->x;
330         y = event->y;
331         button_num = event->button;
332
333         if (mark || highlight) {
334                 if (pick_mode) {
335                         pick_color(x, y);
336                 } else
337                 if (fill_mode) {
338                         if (button_down)
339                                 return TRUE;
340                         copy_mark_to_undo();
341                         fill(x, y, event->button != 1);
342                         draw_image(0, 0, -1, -1);
343                 } else
344                 if (move_mode) {
345                         if (button_down)
346                                 return TRUE;
347                         copy_mark_to_undo();
348                         button_down_x = x;
349                         button_down_y = y;
350                 } else
351                 if (draw_mode) {
352                         if (!button_down)
353                                 copy_mark_to_undo();
354                         /* if not shift, draw a dot and not a line */
355                         if (!shift_pressed || button_down_x == -1000) {
356                                 button_down_x = x;
357                                 button_down_y = y;
358                         }
359                         draw_line(x, y, button_num == 1);
360                 }
361                 button_down = 1;
362         }
363         return TRUE;
364 }
365
366 static gint scroll_event (GtkWidget *widget, GdkEventScroll *event)
367 {
368         if (!ctrl_pressed)
369                 return FALSE;
370
371 #if 0
372 int x,y;
373 GtkAdjustment *hadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(img_scroll));
374 GtkAdjustment *vadjustment = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(img_scroll));
375
376 x = last_x;
377 y = last_y;
378 printf("mouse over pixmap: %d, %d\n", x, y);
379 x -= (int)gtk_adjustment_get_value(hadjustment);
380 y -= (int)gtk_adjustment_get_value(vadjustment);
381 printf("mouse over widget: %d, %d\n", x, y);
382
383
384
385
386 GdkDrawable *draw = gtk_widget_get_window(img_drawing_area);
387 int window_width, window_height;
388 gdk_drawable_get_size (draw, &window_width, &window_height);
389
390 /* we need to calculate an offset, since the drawing area is now larger */
391 x -= (window_width - img_width*img_scale_x/16) / 2;
392 y -= (window_height - img_height*img_scale_y/16) / 2;
393
394 x = x*16/img_scale_x;
395 y = y*16/img_scale_y;
396
397 printf("real coordinates: %d, %d\n", x, y);
398
399 if (x < 0 || x >= img_width || y < 0 || y >= img_height)
400         return FALSE;
401
402 #endif
403
404
405
406         switch (event->direction) {
407         case GDK_SCROLL_UP:
408                 zoom_in_event(NULL);
409                 return TRUE;
410         case GDK_SCROLL_DOWN:
411                 zoom_out_event(NULL);
412                 return TRUE;
413         default:
414                 return FALSE;
415         }
416 }
417
418 /* redraw event of image area */
419 static gint img_expose_event (GtkWidget *widget, GdkEventExpose *event)
420 {
421         draw_image(event->area.x, event->area.y, event->area.width, event->area.height);
422
423         return FALSE;
424 }
425
426 /*
427  * timeline
428  */
429
430 /* mouse move event inside timeline */
431 static gint timeline_motion_notify_event( GtkWidget *widget,
432                                  GdkEventMotion *event )
433 {
434         int x, y;
435         GdkModifierType state;
436
437         if (event->is_hint)
438                 gdk_window_get_pointer (event->window, &x, &y, &state);
439         else
440         {
441                 x = event->x;
442                 y = event->y;
443                 state = event->state;
444         }
445
446         timeline_point(x, y);
447
448         if ((state & GDK_BUTTON1_MASK)) {
449                 timeline_clicked(x, y);
450
451         }
452                                                                                    
453         return TRUE;
454 }
455
456 /* button press event inside timeline area */
457 static gint timeline_press_event (GtkWidget *widget, GdkEventButton *event)
458 {
459         int x,y;
460
461         x = event->x;
462         y = event->y;
463         timeline_clicked(x, y);
464
465         return TRUE;
466 }
467
468 /* redraw event of timeline area */
469 static gint timeline_expose_event (GtkWidget *widget, GdkEventExpose *event)
470 {
471         draw_timeline(event->area.x, event->area.y, event->area.width, event->area.height);
472
473         return FALSE;
474 }
475
476 /*
477  * colorselection
478  */
479
480 GtkWidget *colorseldlg = NULL;
481 GtkColorSelection *colorsel;
482 /* color selection's buttons have been pressed */
483 void color_response(GtkDialog *dialog, gint response_id, gpointer user_data)
484 {
485         GdkColor ncolor;
486
487         switch (response_id) {
488         case GTK_RESPONSE_CANCEL:
489                 gtk_color_selection_get_previous_color(colorsel, &ncolor);
490 new_color:
491                 anything_modified = 1;
492
493                 mark_palette[mark_selected].r = ncolor.red / 256;
494                 mark_palette[mark_selected].g = ncolor.green / 256;
495                 mark_palette[mark_selected].b = ncolor.blue / 256;
496                 update_color(mark_selected);
497                 draw_image(0, 0, -1, -1);
498                 break;
499         case GTK_RESPONSE_OK:
500                 gtk_color_selection_get_current_color(colorsel, &ncolor);
501                 goto new_color;
502         }
503 }
504
505 /*
506  * palette
507  */
508
509 /* palette entry has been clicked */
510 void palette_change(GtkTreeSelection *selection, gpointer data)
511 {
512         GtkTreeModel     *model;
513         GtkTreeIter       iter;
514
515         if (gtk_tree_selection_get_selected(selection, &model, &iter))
516         {
517                 gchar *name;
518
519                 gtk_tree_model_get (model, &iter, 0/*column*/, &name, -1);
520                 mark_selected = atoi(name) - 1;
521                 g_free(name);
522
523                 if (colorseldlg) {
524                         GdkColor color;
525
526                         color.red = mark_palette[mark_selected].r * 256 + 128;
527                         color.green = mark_palette[mark_selected].g * 256 + 128;
528                         color.blue = mark_palette[mark_selected].b * 256 + 128;
529
530                         if (colorseldlg) {
531                                 gtk_color_selection_set_previous_color (colorsel, &color);
532                                 gtk_color_selection_set_current_color (colorsel, &color);
533                         }
534                 }
535
536                 /* set current color for bightness+contrast window */
537                 bc_set_current();
538
539                 /* set current levels in window */
540                 level_set_current();
541
542                 if (highlight || preview)
543                         draw_image(0, 0, -1, -1);
544         }
545 }
546
547 /* name of palette entry has been entered */
548 void palette_edited(GtkCellRendererText *renderer, gchar *path, gchar *new_text, GtkTreeView *treeview)
549 {
550         anything_modified = 1;
551
552         /* copy string */
553         strncpy(mark_palette[mark_selected].name, new_text, sizeof(mark_palette[mark_selected].name));
554         mark_palette[mark_selected].name[sizeof(mark_palette[mark_selected].name)-1] = '\0';
555
556         /* store string */
557         GtkTreeIter iter;
558         GtkTreeModel *model;
559
560         model = gtk_tree_view_get_model (treeview);
561         if (gtk_tree_model_get_iter_from_string (model, &iter, path))
562                 gtk_list_store_set (GTK_LIST_STORE (model), &iter, 2/*column*/, mark_palette[mark_selected].name, -1);
563
564         if (preview)
565                 draw_image(0, 0, -1, -1);
566 }
567
568 /*
569  * commandline help
570  */
571 static void print_help(const char *app)
572 {
573         printf("Colorize version %s\n\n",
574 #include "../version.h"
575         );
576         printf("Usage: %s [options] [<image file>]\n", app);
577         printf("        Run colorize editor optionally with given image file.\n");
578         printf("\nOptions:\n");
579         printf(" -h --help                           This help\n");
580         printf(" -O --output-prefix <path>/<prefix>  Store rendered image using this prefix instead of \"colorized_\"\n");
581 }
582
583 /*
584  * command line options
585  */
586 static int handle_options(int argc, char **argv)
587 {
588         int skip_args = 0;
589
590         while (1) {
591                 int option_index = 0, c;
592                 static struct option long_options[] = {
593                         {"help", 0, 0, 'h'},
594                         {"output-prefix", 1, 0, 'O'},
595                         {0, 0, 0, 0},
596                 };
597
598                 c = getopt_long(argc, argv, "hO:", long_options, &option_index);
599
600                 if (c == -1)
601                         break;
602
603                 switch (c) {
604                 case 'h':
605                         print_help(argv[0]);
606                         exit(0);
607                 case 'O':
608                         strcpy(output_prefix, optarg);
609                         skip_args += 2;
610                         break;
611                 default:
612                         break;
613                 }
614         }
615
616         return skip_args;
617 }
618
619 /*
620  * creation of main window
621  */
622
623 int main(int argc, char *argv[])
624 {
625         GtkWidget *vbox, *tool_bar;
626         GtkWidget *paned;
627         GtkWidget *pal_scroll;
628         GtkWidget *menu_bar;
629         GtkTreeSelection *selection;
630         GtkTreeViewColumn *palette_column;
631         GtkCellRenderer *palette_renderer;
632         int skip_args;
633
634         skip_args = handle_options(argc, argv);
635         argc -= skip_args;
636         argv += skip_args;
637
638 //      g_thread_init(NULL); (not required, it is done automatically)
639         gdk_threads_init();
640         gdk_threads_enter();
641         gtk_init(&argc, &argv);
642
643         main_window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
644         gtk_widget_set_size_request(GTK_WIDGET(main_window), 400, 200);
645         gtk_window_set_default_size(GTK_WINDOW(main_window), 800, 500);
646         gtk_window_set_title(GTK_WINDOW(main_window), CC_APP_TITLE " Version "
647 #include "../version.h"
648         );
649         g_signal_connect(main_window, "delete-event", G_CALLBACK(destroy), NULL);
650         g_signal_connect(main_window, "destroy", G_CALLBACK(destroy), NULL);
651         g_signal_connect(main_window, "key-press-event", G_CALLBACK(on_key_press), NULL);
652         g_signal_connect(main_window, "key-release-event", G_CALLBACK(on_key_release), NULL);
653
654
655         gtk_container_set_border_width (GTK_CONTAINER (main_window), 2);
656
657         /* create vbox (complete window) */
658         vbox = gtk_vbox_new(FALSE, 0);
659         gtk_container_add(GTK_CONTAINER(main_window), vbox);
660         gtk_widget_show(vbox);
661
662         /* add menu to vbox (top of vbox) */
663         menu_bar = gtk_menu_bar_new();
664         gtk_box_pack_start(GTK_BOX(vbox), menu_bar, FALSE, FALSE, 2);
665         gtk_widget_show(menu_bar);
666         create_menus(menu_bar);
667
668         /* add tool_bar to vbox (bottom part of palette box) */
669         tool_bar = gtk_hbox_new(FALSE, 0);
670         gtk_box_pack_start(GTK_BOX(vbox), tool_bar, FALSE, FALSE, 2);
671         gtk_widget_show(tool_bar);
672         create_toolbar(tool_bar);
673
674         /* add paned view to vbox (middle part of vbox) */
675         paned = gtk_hpaned_new ();
676         gtk_widget_show(paned);
677         gtk_box_pack_start(GTK_BOX(vbox), paned, TRUE, TRUE, 2);
678         gtk_paned_set_position(GTK_PANED (paned), 250);
679
680         /* add palette treeview to hbox (top part of palette box) */
681         palette_treeview = gtk_tree_view_new();
682         gtk_widget_set_size_request(palette_treeview, 250, 400);
683         g_signal_connect(palette_treeview, "enter_notify_event", G_CALLBACK(enter_palette_area), NULL);
684         g_signal_connect(palette_treeview, "leave_notify_event", G_CALLBACK(leave_palette_area), NULL);
685         gtk_widget_set_events(palette_treeview, GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK);
686         gtk_widget_show(palette_treeview);
687
688         pal_scroll = gtk_scrolled_window_new(NULL, NULL);
689         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(pal_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
690         gtk_widget_show(pal_scroll);
691         gtk_container_add(GTK_CONTAINER(pal_scroll), palette_treeview);
692
693         palette_renderer = gtk_cell_renderer_text_new();
694         g_object_set(G_OBJECT(palette_renderer), "editable", FALSE, NULL);
695         palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "text", 0/*column*/, NULL);
696         gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 0/*column*/);
697
698         palette_renderer = gtk_cell_renderer_pixbuf_new();
699         palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "pixbuf", 1/*column*/, NULL);
700         gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 1/*column*/);
701
702         palette_renderer = gtk_cell_renderer_text_new();
703         g_object_set(G_OBJECT(palette_renderer), "editable", TRUE, NULL);
704         g_signal_connect(palette_renderer, "edited", (GCallback) palette_edited, palette_treeview);
705         palette_column = gtk_tree_view_column_new_with_attributes("", palette_renderer, "text", 2/*column*/, NULL);
706         gtk_tree_view_insert_column(GTK_TREE_VIEW(palette_treeview), GTK_TREE_VIEW_COLUMN(palette_column), 2/*column*/);
707
708         create_palette();
709
710         selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(palette_treeview));
711         g_signal_connect(selection, "changed", G_CALLBACK(palette_change), NULL);
712         gtk_paned_pack1 (GTK_PANED (paned), pal_scroll, FALSE, TRUE);
713
714         /* add drawing area (right of hbox) */
715         img_drawing_area = gtk_drawing_area_new ();
716         gtk_signal_connect(GTK_OBJECT(img_drawing_area), "motion_notify_event", (GtkSignalFunc)motion_notify_event, NULL);
717         gtk_signal_connect(GTK_OBJECT (img_drawing_area), "button_press_event", (GtkSignalFunc)button_press_event, NULL);
718         gtk_signal_connect(GTK_OBJECT (img_drawing_area), "scroll_event", (GtkSignalFunc)scroll_event, NULL);
719         gtk_signal_connect(GTK_OBJECT (img_drawing_area), "expose_event", (GtkSignalFunc)img_expose_event, NULL); 
720         g_signal_connect(img_drawing_area, "enter_notify_event", G_CALLBACK(enter_drawing_area), NULL);
721         g_signal_connect(img_drawing_area, "leave_notify_event", G_CALLBACK(leave_drawing_area), NULL);
722         gtk_widget_set_events(img_drawing_area, GDK_EXPOSURE_MASK
723                 | GDK_ENTER_NOTIFY_MASK
724                 | GDK_LEAVE_NOTIFY_MASK
725                 | GDK_BUTTON_PRESS_MASK
726                 | GDK_SCROLL_MASK
727                 | GDK_POINTER_MOTION_MASK
728                 | GDK_POINTER_MOTION_HINT_MASK);
729         gtk_widget_show(img_drawing_area);
730
731         img_scroll = gtk_scrolled_window_new(NULL, NULL);
732         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(img_scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
733         gtk_widget_show(img_scroll);
734         gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(img_scroll), img_drawing_area);
735         gtk_paned_pack2 (GTK_PANED (paned), img_scroll, TRUE, TRUE);
736
737 #if 0
738         /* add horizontal seperation to vbox */
739         separator = gtk_hseparator_new();
740         gtk_widget_show(separator);
741         gtk_box_pack_start(GTK_BOX(vbox), separator, FALSE, FALSE, 3);
742 #endif
743
744         /* add timeline (bottom of vbox) */
745         timeline_drawing_area = gtk_drawing_area_new ();
746         gtk_widget_set_size_request(timeline_drawing_area, 10, 10);
747         gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "motion_notify_event", (GtkSignalFunc)timeline_motion_notify_event, NULL);
748         gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "button_press_event", (GtkSignalFunc)timeline_press_event, NULL);
749         gtk_signal_connect(GTK_OBJECT(timeline_drawing_area), "expose_event", (GtkSignalFunc)timeline_expose_event, NULL); 
750         g_signal_connect(timeline_drawing_area, "enter_notify_event", G_CALLBACK(enter_timeline_area), NULL);
751         g_signal_connect(timeline_drawing_area, "leave_notify_event", G_CALLBACK(leave_timeline_area), NULL);
752         gtk_widget_set_events(timeline_drawing_area, GDK_EXPOSURE_MASK
753                 | GDK_ENTER_NOTIFY_MASK
754                 | GDK_LEAVE_NOTIFY_MASK
755                 | GDK_BUTTON_PRESS_MASK
756                 | GDK_POINTER_MOTION_MASK
757                 | GDK_POINTER_MOTION_HINT_MASK);
758         gtk_widget_show(timeline_drawing_area);
759         timeline_scroll = gtk_scrolled_window_new(NULL, NULL);
760         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(timeline_scroll), GTK_POLICY_ALWAYS, GTK_POLICY_NEVER);
761 //      gtk_widget_show(timeline_scroll);
762         gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(timeline_scroll), timeline_drawing_area);
763         gtk_box_pack_start(GTK_BOX(vbox), timeline_scroll, FALSE, FALSE, 0);
764
765         create_timeline(NULL);
766
767         /* label */
768         img_label = GTK_LABEL(gtk_label_new(NULL));
769         gtk_widget_show(GTK_WIDGET(img_label));
770         gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(img_label), FALSE, FALSE, 0);
771
772         /* show window */
773         gtk_widget_show(main_window);
774
775         /* enable some button/menu */
776         set_menu_toggel_by_label(TOGGLE_LABEL_MARK, mark);
777         set_button_toggel_by_label(TOGGLE_LABEL_MARK, mark);
778
779         if (argc > 1) {
780                 create_timeline(argv[1]);
781                 if (frame_list)
782                         create_image(frame_list[timeline_selected].filename, 1);
783         }
784
785         colorize_preview_init();
786         gtk_main();
787         colorize_preview_terminate();
788         gdk_threads_leave();
789
790         // FIXME: destroy
791
792         return 0;
793 }
794