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