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