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