2d7b18afc28c430b2984a44b7a8440d127b9262c
[tbo.git] / src / ui-drawing.c
1 #include <stdio.h>
2 #include <cairo.h>
3 #include <gtk/gtk.h>
4 #include <gdk/gdkkeysyms.h>
5 #include <stdlib.h>
6 #include <glib/gi18n.h>
7
8 #include "ui-toolbar.h"
9
10 #include "tbo-window.h"
11 #include "ui-drawing.h"
12
13 #include "comic.h"
14 #include "page.h"
15 #include "frame.h"
16
17 #include "frame-tool.h"
18 #include "selector-tool.h"
19 #include "doodle-tool.h"
20 #include "dnd.h"
21
22
23 Frame *FRAME_VIEW = NULL;
24 float ZOOM_STEP = 0.05;
25 float ZOOM = 1;
26 int DRAWING_W = 0;
27 int DRAWING_H = 0;
28 gboolean KEY_BINDER = TRUE;
29
30 void
31 tbo_drawing_draw_page (cairo_t *cr, Page *page, int w, int h)
32 {
33     Frame *frame;
34     GList *frame_list;
35
36     // white background
37     cairo_set_source_rgb(cr, 1, 1, 1);
38     cairo_rectangle(cr, 0, 0, w, h);
39     cairo_fill(cr);
40
41     for (frame_list = tbo_page_get_frames (page); frame_list; frame_list = frame_list->next)
42     {
43         // draw each frame
44         frame = (Frame *)frame_list->data;
45         tbo_frame_draw (frame, cr);
46     }
47 }
48
49 void
50 tbo_drawing_draw (cairo_t *cr, TboWindow *tbo)
51 {
52     Frame *frame;
53     GList *frame_list;
54     Page *page;
55
56     int w, h;
57
58     w = tbo->comic->width;
59     h = tbo->comic->height;
60     // white background
61     cairo_set_source_rgb(cr, 1, 1, 1);
62     cairo_rectangle(cr, 0, 0, w*ZOOM, h*ZOOM);
63     cairo_fill(cr);
64
65     cairo_scale (cr, ZOOM, ZOOM);
66
67     page = tbo_comic_get_current_page (tbo->comic);
68
69     if (!FRAME_VIEW)
70     {
71         for (frame_list = tbo_page_get_frames (page); frame_list; frame_list = frame_list->next)
72         {
73             // draw each frame
74             frame = (Frame *)frame_list->data;
75             tbo_frame_draw (frame, cr);
76         }
77     }
78     else
79     {
80         tbo_frame_draw_scaled (FRAME_VIEW, cr, w, h);
81     }
82 }
83
84 gboolean
85 on_key_cb (GtkWidget    *widget,
86            GdkEventKey  *event,
87            TboWindow    *tbo)
88 {
89     enum Tool tool;
90     void **data = malloc (sizeof(void *)*3);
91     data[0] = widget;
92     data[1] = event;
93     data[2] = tbo;
94
95     tool = get_selected_tool ();
96     tool_signal (tool, TOOL_KEY, data);
97     free (data);
98
99     update_drawing (tbo);
100     tbo_window_update_status (tbo, 0, 0);
101
102     if (KEY_BINDER)
103     {
104         switch (event->keyval)
105         {
106             case GDK_plus:
107                 tbo_drawing_zoom_in (tbo);
108                 break;
109             case GDK_minus:
110                 tbo_drawing_zoom_out (tbo);
111                 break;
112             case GDK_1:
113                 tbo_drawing_zoom_100 (tbo);
114                 break;
115             case GDK_s:
116                 set_selected_tool_and_action (SELECTOR, tbo);
117                 break;
118             case GDK_t:
119                 set_selected_tool_and_action (TEXT, tbo);
120                 break;
121             case GDK_d:
122                 set_selected_tool_and_action (DOODLE, tbo);
123                 break;
124             case GDK_f:
125                 set_selected_tool_and_action (FRAME, tbo);
126                 break;
127             default:
128                 break;
129         }
130     }
131     return FALSE;
132 }
133
134 gboolean
135 on_expose_cb (GtkWidget      *widget,
136               GdkEventExpose *event,
137               TboWindow       *tbo)
138 {
139     cairo_t *cr;
140     enum Tool tool;
141     GdkWindow *window;
142
143     cr = gdk_cairo_create(GTK_LAYOUT (widget)->bin_window);
144
145     window = gtk_widget_get_parent_window (GTK_WIDGET (widget));
146     gdk_drawable_get_size (GDK_DRAWABLE (window), &DRAWING_W, &DRAWING_H);
147
148     cairo_set_source_rgb (cr, 0, 0, 0);
149     cairo_rectangle (cr, 0, 0, DRAWING_W, DRAWING_H);
150     cairo_fill (cr);
151
152     tbo_drawing_draw (cr, tbo);
153
154     // Update drawing helpers
155     tool = get_selected_tool ();
156     tool_signal (tool, TOOL_DRAWING, cr);
157
158     cairo_destroy(cr);
159
160     return FALSE;
161 }
162
163 gboolean
164 on_move_cb (GtkWidget     *widget,
165            GdkEventMotion *event,
166            TboWindow      *tbo)
167 {
168
169     enum Tool tool;
170     void **data = malloc (sizeof(void *)*3);
171     data[0] = widget;
172     event->x = event->x / ZOOM;
173     event->y = event->y / ZOOM;
174     data[1] = event;
175     data[2] = tbo;
176
177     tool = get_selected_tool ();
178     tool_signal (tool, TOOL_MOVE, data);
179     free (data);
180
181     update_drawing (tbo);
182     tbo_window_update_status (tbo, (int)event->x, (int)event->y);
183     return FALSE;
184 }
185
186 gboolean
187 on_click_cb (GtkWidget    *widget,
188            GdkEventButton *event,
189            TboWindow      *tbo)
190 {
191     enum Tool tool;
192     void **data = malloc (sizeof(void *)*3);
193     data[0] = widget;
194     event->x = event->x / ZOOM;
195     event->y = event->y / ZOOM;
196     data[1] = event;
197     data[2] = tbo;
198
199     tool = get_selected_tool ();
200     tool_signal (tool, TOOL_CLICK, data);
201     free (data);
202
203     update_drawing (tbo);
204     tbo_window_update_status (tbo, (int)event->x, (int)event->y);
205     return FALSE;
206 }
207
208 gboolean
209 on_release_cb (GtkWidget    *widget,
210            GdkEventButton   *event,
211            TboWindow        *tbo)
212 {
213     enum Tool tool;
214     void **data = malloc (sizeof(void *)*3);
215     data[0] = widget;
216     event->x = event->x / ZOOM;
217     event->y = event->y / ZOOM;
218
219     data[1] = event;
220     data[2] = tbo;
221
222     tool = get_selected_tool ();
223     tool_signal (tool, TOOL_RELEASE, data);
224     free (data);
225
226     update_drawing (tbo);
227     tbo_window_update_status (tbo, (int)event->x, (int)event->y);
228     return FALSE;
229 }
230
231 GtkWidget *
232 get_drawing_area (int width, int height)
233 {
234
235     GtkWidget *drawing;
236
237     drawing = gtk_layout_new(NULL, NULL);
238     gtk_layout_set_size (GTK_LAYOUT (drawing), width+2, height+2);
239
240     return drawing;
241 }
242
243 void
244 darea_connect_signals (TboWindow *tbo, GtkWidget *drawing)
245 {
246     gtk_widget_add_events (drawing, GDK_BUTTON_PRESS_MASK |
247                                     GDK_BUTTON_RELEASE_MASK |
248                                     GDK_POINTER_MOTION_MASK);
249
250     g_signal_connect(drawing, "expose-event",
251             G_CALLBACK (on_expose_cb), tbo);
252
253     g_signal_connect (drawing, "button_press_event",
254             G_CALLBACK (on_click_cb), tbo);
255
256     g_signal_connect (drawing, "button_release_event",
257             G_CALLBACK (on_release_cb), tbo);
258
259     g_signal_connect (drawing, "motion_notify_event",
260             G_CALLBACK (on_move_cb), tbo);
261
262     // drag & drop
263     gtk_drag_dest_set (drawing, GTK_DEST_DEFAULT_ALL, TARGET_LIST, N_TARGETS, GDK_ACTION_COPY);
264     g_signal_connect (drawing, "drag-data-received", G_CALLBACK(drag_data_received_handl), tbo);
265 }
266
267 void
268 darea_disconnect_signals (TboWindow *tbo, GtkWidget *drawing)
269 {
270     g_signal_handlers_disconnect_by_func (drawing, G_CALLBACK (on_expose_cb), tbo);
271     g_signal_handlers_disconnect_by_func (drawing, G_CALLBACK (on_click_cb), tbo);
272     g_signal_handlers_disconnect_by_func (drawing, G_CALLBACK (on_release_cb), tbo);
273     g_signal_handlers_disconnect_by_func (drawing, G_CALLBACK (on_move_cb), tbo);
274     g_signal_handlers_disconnect_by_func (drawing, G_CALLBACK(drag_data_received_handl), tbo);
275 }
276
277 void
278 update_drawing (TboWindow *tbo)
279 {
280     gtk_widget_queue_draw_area (tbo->drawing,
281             0, 0,
282             DRAWING_W, DRAWING_H);
283 }
284
285 void
286 set_frame_view (Frame *frame)
287 {
288     FRAME_VIEW = frame;
289 }
290
291 Frame *
292 get_frame_view ()
293 {
294     return FRAME_VIEW;
295 }
296
297 void tbo_drawing_zoom_in (TboWindow *tbo)
298 {
299     ZOOM += ZOOM_STEP;
300     gtk_layout_set_size (GTK_LAYOUT (tbo->drawing), tbo->comic->width*ZOOM, tbo->comic->height*ZOOM);
301     update_drawing (tbo);
302 }
303
304 void tbo_drawing_zoom_out (TboWindow *tbo)
305 {
306     ZOOM -= ZOOM_STEP;
307     gtk_layout_set_size (GTK_LAYOUT (tbo->drawing), tbo->comic->width*ZOOM, tbo->comic->height*ZOOM);
308     update_drawing (tbo);
309 }
310
311 void tbo_drawing_zoom_100 (TboWindow *tbo)
312 {
313     ZOOM = 1;
314     gtk_layout_set_size (GTK_LAYOUT (tbo->drawing), tbo->comic->width*ZOOM, tbo->comic->height*ZOOM);
315     update_drawing (tbo);
316 }
317
318 float
319 tbo_drawing_get_zoom ()
320 {
321     return ZOOM;
322 }
323
324 void
325 set_key_binder (gboolean binder)
326 {
327     KEY_BINDER = binder;
328 }