83af9c9b36eed50ba6d8af0bfba717d23e1b6cef
[tbo.git] / src / tbo-window.c
1 /*
2  * This file is part of TBO, a gnome comic editor
3  * Copyright (C) 2010  Daniel Garcia Moreno <dani@danigm.net>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19
20 #include <stdio.h>
21 #include <malloc.h>
22 #include <gtk/gtk.h>
23 #include <glib/gi18n.h>
24 #include <gdk/gdkkeysyms.h>
25 #include "tbo-types.h"
26 #include "tbo-window.h"
27 #include "comic.h"
28 #include "page.h"
29 #include "ui-menu.h"
30 #include "tbo-toolbar.h"
31 #include "tbo-drawing.h"
32 #include "tbo-tool-selector.h"
33
34 static int NWINDOWS = 0;
35 static gboolean KEY_BINDER = TRUE;
36
37 static gboolean
38 notebook_switch_page_cb (GtkNotebook     *notebook,
39                          GtkNotebookPage *page,
40                          guint            page_num,
41                          TboWindow        *tbo)
42 {
43     tbo_comic_set_current_page_nth (tbo->comic, page_num);
44     tbo_window_set_current_tab_page (tbo, FALSE);
45     tbo_toolbar_update (tbo->toolbar);
46     tbo_window_update_status (tbo, 0, 0);
47     tbo_drawing_adjust_scroll (TBO_DRAWING (tbo->drawing));
48     return FALSE;
49 }
50
51 static gboolean
52 on_key_cb (GtkWidget    *widget,
53            GdkEventKey  *event,
54            TboWindow    *tbo)
55 {
56     TboToolBase *tool;
57     TboDrawing *drawing = TBO_DRAWING (tbo->drawing);
58
59     tool = tbo_toolbar_get_selected_tool (tbo->toolbar);
60     if (tool)
61         tool->on_key (tool, widget, event);
62
63     tbo_window_update_status (tbo, 0, 0);
64
65     if (KEY_BINDER)
66     {
67         switch (event->keyval)
68         {
69             case GDK_plus:
70                 tbo_drawing_zoom_in (drawing);
71                 break;
72             case GDK_minus:
73                 tbo_drawing_zoom_out (drawing);
74                 break;
75             case GDK_1:
76                 tbo_drawing_zoom_100 (drawing);
77                 break;
78             case GDK_2:
79                 tbo_drawing_zoom_fit (drawing);
80                 break;
81             case GDK_s:
82                 tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_SELECTOR);
83                 break;
84             case GDK_t:
85                 tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_TEXT);
86                 break;
87             case GDK_d:
88                 tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_DOODLE);
89                 break;
90             case GDK_b:
91                 tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_BUBBLE);
92                 break;
93             case GDK_f:
94                 tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_FRAME);
95                 break;
96             default:
97                 break;
98         }
99     }
100     return FALSE;
101 }
102
103 static gboolean
104 on_move_cb (GtkWidget     *widget,
105            GdkEventMotion *event,
106            TboWindow      *tbo)
107 {
108     tbo_window_update_status (tbo, (int)event->x, (int)event->y);
109     return FALSE;
110 }
111
112 TboWindow *
113 tbo_window_new (GtkWidget *window, GtkWidget *dw_scroll,
114                 GtkWidget *scroll2,
115                 GtkWidget *notebook, GtkWidget *toolarea,
116                 GtkWidget *status, GtkWidget *vbox, Comic *comic)
117 {
118     TboWindow *tbo;
119     GList *list;
120
121     tbo = malloc (sizeof (TboWindow));
122     tbo->window = window;
123     tbo->dw_scroll = dw_scroll;
124     tbo->scroll2 = scroll2;
125     list = gtk_container_get_children (GTK_CONTAINER (dw_scroll));
126     tbo->drawing = GTK_WIDGET (list->data);
127     tbo->status = status;
128     tbo->vbox = vbox;
129     tbo->comic = comic;
130     tbo->toolarea = toolarea;
131     tbo->notebook = notebook;
132     tbo->path = NULL;
133
134     return tbo;
135 }
136
137 void 
138 tbo_window_free (TboWindow *tbo)
139 {
140     tbo_comic_free (tbo->comic);
141     gtk_widget_destroy (tbo->window);
142     if (tbo->path)
143         free (tbo->path);
144     free (tbo);
145 }
146
147 void
148 tbo_window_set_path (TboWindow *tbo, const char *path)
149 {
150     if (tbo->path)
151         free (tbo->path);
152     tbo->path = malloc (255 * sizeof (char));
153     snprintf (tbo->path, 255, "%s", path);
154 }
155
156 gboolean 
157 tbo_window_free_cb (GtkWidget *widget, GdkEventExpose *event,
158                     TboWindow *tbo)
159 {
160     tbo_window_free (tbo);
161     NWINDOWS--;
162     if (!NWINDOWS)
163         gtk_main_quit ();
164     return FALSE;
165 }
166
167 GdkPixbuf *create_pixbuf (const gchar * filename)
168 {
169    GdkPixbuf *pixbuf;
170    GError *error = NULL;
171    pixbuf = gdk_pixbuf_new_from_file(filename, &error);
172    if(!pixbuf) {
173       fprintf(stderr, "%s\n", error->message);
174       g_error_free(error);
175    }
176
177    return pixbuf;
178 }
179
180 GtkWidget *
181 create_darea (TboWindow *tbo)
182 {
183     GtkWidget *scrolled;
184     GtkWidget *darea;
185
186     scrolled = gtk_scrolled_window_new (NULL, NULL);
187     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
188     darea = tbo_drawing_new_with_params (tbo->comic);
189     gtk_container_add (GTK_CONTAINER (scrolled), darea);
190     tbo_drawing_init_dnd (TBO_DRAWING (darea), tbo);
191
192     g_signal_connect_after (darea, "motion_notify_event", G_CALLBACK (on_move_cb), tbo);
193     gtk_widget_show_all (scrolled);
194
195     return scrolled;
196 }
197
198 TboWindow *
199 tbo_new_tbo (int width, int height)
200 {
201     TboWindow *tbo;
202     Comic *comic;
203     GtkWidget *window;
204     GtkWidget *container;
205     GtkWidget *tool_paned;
206     GtkWidget *menu;
207     TboToolbar *toolbar;
208     GtkWidget *scrolled;
209     GtkWidget *scrolled2;
210     GtkWidget *darea;
211     GtkWidget *status;
212     GtkWidget *hpaned;
213     GtkWidget *notebook;
214
215     NWINDOWS++;
216
217     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
218     gtk_window_set_default_size (GTK_WINDOW (window), width, height);
219     gtk_window_set_icon (GTK_WINDOW (window), create_pixbuf (DATA_DIR "/icon.png"));
220
221     // El contenedor principal
222     container = gtk_vbox_new (FALSE, 0);
223     gtk_container_add (GTK_CONTAINER (window), container);
224
225     comic = tbo_comic_new (_("Untitled"), width, height);
226     gtk_window_set_title (GTK_WINDOW (window), comic->title);
227     scrolled = gtk_scrolled_window_new (NULL, NULL);
228     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
229     darea = tbo_drawing_new_with_params (comic);
230     gtk_container_add (GTK_CONTAINER (scrolled), darea);
231     notebook = gtk_notebook_new ();
232     gtk_notebook_set_scrollable (GTK_NOTEBOOK (notebook), TRUE);
233     gtk_notebook_append_page (GTK_NOTEBOOK (notebook), scrolled, NULL);
234
235     hpaned = gtk_hpaned_new ();
236     tool_paned = gtk_vbox_new (FALSE, 0);
237     scrolled2 = gtk_scrolled_window_new (NULL, NULL);
238     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled2), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
239     gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrolled2), tool_paned);
240
241     gtk_paned_set_position (GTK_PANED (hpaned), width - 200);
242     gtk_paned_pack1 (GTK_PANED (hpaned), notebook, TRUE, FALSE);
243     gtk_paned_pack2 (GTK_PANED (hpaned), scrolled2, TRUE, FALSE);
244
245     status = gtk_statusbar_new ();
246
247     tbo = tbo_window_new (window, scrolled, scrolled2, notebook, tool_paned, status, container, comic);
248
249     // Generando la barra de herramientas de la aplicacion
250     toolbar = TBO_TOOLBAR (tbo_toolbar_new_with_params (tbo));
251     tbo->toolbar = toolbar;
252
253     // drag & drop
254     tbo_drawing_init_dnd (TBO_DRAWING (darea), tbo);
255
256     // key press event
257     g_signal_connect (tbo->notebook, "switch-page", G_CALLBACK (notebook_switch_page_cb), tbo);
258     g_signal_connect (tbo->window, "key_press_event", G_CALLBACK (on_key_cb), tbo);
259     g_signal_connect (window, "delete-event", G_CALLBACK (tbo_window_free_cb), tbo);
260
261     // Generando el menu de la aplicacion
262     menu = generate_menu (tbo);
263
264     gtk_box_pack_start (GTK_BOX (container), menu, FALSE, FALSE, 0);
265     gtk_box_pack_start (GTK_BOX (container), toolbar->toolbar, FALSE, FALSE, 0);
266
267     gtk_container_add (GTK_CONTAINER (container), hpaned);
268
269     gtk_box_pack_start (GTK_BOX (container), status, FALSE, FALSE, 0);
270
271     gtk_widget_show_all (window);
272     tbo_toolbar_set_selected_tool (toolbar, TBO_TOOLBAR_SELECTOR);
273
274     tbo_window_update_status (tbo, 0, 0);
275     return tbo;
276 }
277
278 void
279 tbo_window_update_status (TboWindow *tbo, int x, int y)
280 {
281     char buffer[200];
282     snprintf (buffer, 200, _("page: %d of %d [ %5d,%5d ] | frames: %d"),
283                     tbo_comic_page_index (tbo->comic),
284                     tbo_comic_len (tbo->comic),
285                     x, y,
286                     tbo_page_len (tbo_comic_get_current_page (tbo->comic)));
287     gtk_statusbar_push (GTK_STATUSBAR (tbo->status), 0, buffer);
288     tbo_toolbar_update (tbo->toolbar);
289 }
290
291 gboolean
292 remove_cb (GtkWidget *widget, gpointer data)
293 {
294     gtk_widget_destroy (widget);
295     return FALSE;
296 }
297
298 void
299 tbo_empty_tool_area (TboWindow *tbo)
300 {
301     gtk_container_foreach (GTK_CONTAINER (tbo->toolarea), (GtkCallback)remove_cb, NULL);
302 }
303
304 void
305 tbo_window_set_key_binder (TboWindow *tbo, gboolean keyb)
306 {
307     KEY_BINDER = keyb;
308     if (keyb)
309         tbo_menu_enable_accel_keys (tbo);
310     else
311         tbo_menu_disable_accel_keys (tbo);
312 }
313
314 void
315 tbo_window_set_current_tab_page (TboWindow *tbo, gboolean setit)
316 {
317     int nth;
318
319     nth = tbo_comic_page_index (tbo->comic);
320     if (setit)
321         gtk_notebook_set_current_page (GTK_NOTEBOOK (tbo->notebook), nth);
322     tbo->dw_scroll = gtk_notebook_get_nth_page (GTK_NOTEBOOK (tbo->notebook), nth);
323     tbo->drawing = gtk_bin_get_child (GTK_BIN (tbo->dw_scroll));
324
325     tbo_toolbar_set_selected_tool (tbo->toolbar, TBO_TOOLBAR_SELECTOR);
326     tbo_tool_selector_set_selected (TBO_TOOL_SELECTOR (tbo->toolbar->selected_tool), NULL);
327     tbo_tool_selector_set_selected_obj (TBO_TOOL_SELECTOR (tbo->toolbar->selected_tool), NULL);
328 }