.
1 /*
2 Copyright (C) 2014 2015 Johan Mattsson
3
4 This library is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 3 of the
7 License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13 */
14
15 using Cairo;
16
17 namespace BirdFont {
18
19 /** Interface for events from native window to the current tab. */
20 public class TabContent : GLib.Object {
21
22 static Text text_input_label;
23 static LineTextArea text_input;
24 static Button text_input_button;
25 static bool text_input_visible = false;
26 static TextListener text_callback;
27 static ImageSurface? pause_surface = null;
28
29 static const int TEXT_INPUT_HEIGHT = 51;
30
31 static double last_press_time = 0;
32
33 public static void zoom_in () {
34 if (MenuTab.has_suppress_event ()) {
35 }
36
37 GlyphCanvas.current_display.zoom_in ();
38 }
39
40 public static void zoom_out () {
41 if (MenuTab.has_suppress_event ()) {
42 return;
43 }
44
45 GlyphCanvas.current_display.zoom_out ();
46 }
47
48 public static void move_view (double x, double y) {
49 if (MenuTab.has_suppress_event ()) {
50 return;
51 }
52
53 GlyphCanvas.current_display.move_view (x, y);
54 }
55
56 public static bool has_scrollbar () {
57 if (MenuTab.has_suppress_event ()) {
58 return false;
59 }
60
61 return GlyphCanvas.current_display.has_scrollbar ();
62 }
63
64 public static void scroll_to (double percent) {
65 if (MenuTab.has_suppress_event ()) {
66 return;
67 }
68
69 GlyphCanvas.current_display.scroll_to (percent);
70 }
71
72 public static void draw (WidgetAllocation allocation, Context cr) {
73 AbstractMenu menu;
74 Dialog dialog;
75
76 if (unlikely (MenuTab.has_suppress_event ())) {
77 cr.save ();
78 Theme.color (cr, "Background 1");
79 cr.rectangle (0, 0, allocation.width, allocation.height);
80 cr.fill ();
81
82 if (pause_surface != null) {
83 cr.scale (1.0 / Screen.get_scale (), 1.0 / Screen.get_scale ());
84 cr.set_source_surface ((!) pause_surface, 0, 0);
85 cr.paint ();
86 }
87
88 cr.restore ();
89 } else {
90 menu = MainWindow.get_menu ();
91 dialog = MainWindow.get_dialog ();
92
93 GlyphCanvas.set_allocation (allocation);
94 MainWindow.get_current_glyph ().resized (allocation);
95 GlyphCanvas.current_display.draw (allocation, cr);
96
97 if (dialog.visible) {
98 dialog.allocation = allocation;
99 dialog.draw (cr);
100 } else if (menu.show_menu) {
101 menu.draw (allocation, cr);
102 }
103
104 if (FontDisplay.dirty_scrollbar) {
105 GlyphCanvas.current_display.update_scrollbar ();
106 FontDisplay.dirty_scrollbar = false;
107 }
108
109 if (text_input_visible) {
110 draw_text_input (allocation, cr);
111 }
112 }
113 }
114
115 public static void create_pause_surface () {
116 Context cr;
117 WidgetAllocation alloc;
118
119 if (MenuTab.has_suppress_event ()) {
120 warning ("Background surface already created.");
121 return;
122 }
123
124 alloc = GlyphCanvas.get_allocation ();
125 pause_surface = Screen.create_background_surface (alloc.width, alloc.height);
126 cr = new Context ((!) pause_surface);
127 cr.scale (Screen.get_scale (), Screen.get_scale ());
128 draw (alloc, cr);
129 }
130
131 public static void key_press (uint keyval) {
132 if (MenuTab.has_suppress_event () || MainWindow.get_dialog ().visible) {
133 return;
134 }
135
136 unichar c = (unichar) keyval;
137
138 if (unlikely (!c.validate ())) {
139 warning ("Invalid unichar: $(keyval)");
140 return;
141 }
142
143 KeyBindings.add_modifier_from_keyval (keyval);
144
145 if (!text_input_visible) {
146 MainWindow.get_menu ().process_key_binding_events (keyval);
147 GlyphCanvas.current_display.key_press (keyval);
148 } else {
149 text_input.key_press (keyval);
150 }
151 }
152
153 public static void key_release (uint keyval) {
154 if (MenuTab.has_suppress_event () || MainWindow.get_dialog ().visible) {
155 return;
156 }
157
158 unichar c = (unichar) keyval;
159
160 if (unlikely (!c.validate ())) {
161 warning ("Invalid unichar: $(keyval)");
162 return;
163 }
164
165 KeyBindings.remove_modifier_from_keyval (keyval);
166
167 if (!text_input_visible) {
168 GlyphCanvas.current_display.key_release (keyval);
169 }
170 }
171
172 public static void motion_notify (double x, double y) {
173 Toolbox toolbox;
174
175 if (MenuTab.has_suppress_event ()) {
176 return;
177 }
178
179 if (!text_input_visible) {
180 GlyphCanvas.current_display.motion_notify (x, y);
181 } else {
182 text_input.motion (x, y);
183 GlyphCanvas.redraw ();
184 }
185
186 toolbox = MainWindow.get_toolbox ();
187 toolbox.hide_tooltip ();
188 }
189
190 public static void button_release (int button, double x, double y) {
191 if (MenuTab.has_suppress_event ()) {
192 return;
193 }
194
195 if (MainWindow.get_dialog ().visible) {
196 MainWindow.get_dialog ().button_release (button, x, y);
197 } else if (MainWindow.get_menu ().show_menu) {
198 MainWindow.get_menu ().button_release (button, x, y);
199 } else if (text_input_visible) {
200 text_input_button.button_release (button, x, y);
201 text_input.button_release (button, x, y);
202 GlyphCanvas.redraw ();
203 } else {
204 GlyphCanvas.current_display.button_release (button, x, y);
205 }
206 }
207
208 public static void button_press (uint button, double x, double y) {
209 if (MenuTab.has_suppress_event ()) {
210 return;
211 }
212
213 last_press_time = GLib.get_real_time ();
214
215 if (MainWindow.get_dialog ().visible) {
216 MainWindow.get_dialog ().button_press (button, x, y);
217 } else if (!MainWindow.get_menu ().show_menu) {
218 if (text_input_visible) {
219 text_input.button_press (button, x, y);
220 text_input_button.button_press (button, x, y);
221
222 if (y > TEXT_INPUT_HEIGHT) {
223 hide_text_input ();
224 }
225 } else {
226 GlyphCanvas.current_display.button_press (button, x, y);
227 }
228 }
229 }
230
231 public static void double_click (uint button, double ex, double ey) {
232 if (MenuTab.has_suppress_event ()) {
233 return;
234 }
235
236 if (!MainWindow.get_menu ().show_menu) {
237 GlyphCanvas.current_display.double_click (button, ex, ey);
238 }
239 }
240
241 public static void scroll_wheel_pixel_delta (double x, double y,
242 double pixeldelta_x, double pixeldelta_y) {
243
244 if (MenuTab.has_suppress_event ()) {
245 return;
246 }
247
248 if (!MainWindow.get_menu ().show_menu) {
249 GlyphCanvas.current_display.scroll_wheel (x, y, pixeldelta_x, pixeldelta_y);
250 }
251 }
252
253 public static void scroll_wheel_up (double x, double y) {
254 if (MenuTab.has_suppress_event ()) {
255 return;
256 }
257
258 if (!MainWindow.get_menu ().show_menu) {
259 GlyphCanvas.current_display.scroll_wheel (x, y, 0, 15);
260 }
261 }
262
263 public static void scroll_wheel_down (double x, double y) {
264 if (MenuTab.has_suppress_event ()) {
265 return;
266 }
267
268 if (!MainWindow.get_menu ().show_menu) {
269 GlyphCanvas.current_display.scroll_wheel (x, y, 0, -15);
270 }
271 }
272
273 public static void magnify (double magnification) {
274 if (MenuTab.has_suppress_event ()) {
275 return;
276 }
277
278 if (!MainWindow.get_menu ().show_menu) {
279 GlyphCanvas.current_display.magnify (magnification);
280 }
281 }
282
283 public static void tap_down (int finger, int x, int y) {
284 if (MenuTab.has_suppress_event ()) {
285 return;
286 }
287
288 if (!MainWindow.get_menu ().show_menu) {
289 GlyphCanvas.current_display.tap_down (finger, x, y);
290 }
291 }
292
293 public static void tap_up (int finger, int x, int y) {
294 if (MenuTab.has_suppress_event ()) {
295 return;
296 }
297
298 if (!MainWindow.get_menu ().show_menu) {
299 GlyphCanvas.current_display.tap_up (finger, x, y);
300 }
301 }
302
303 public static void tap_move (int finger, int x, int y) {
304 if (MenuTab.has_suppress_event ()) {
305 return;
306 }
307
308 if (!MainWindow.get_menu ().show_menu) {
309 GlyphCanvas.current_display.tap_move (finger, x, y);
310 }
311 }
312
313 public static void undo () {
314 if (MenuTab.has_suppress_event ()) {
315 return;
316 }
317
318 GlyphCanvas.current_display.undo ();
319 }
320
321 public static void redo () {
322 if (MenuTab.has_suppress_event ()) {
323 return;
324 }
325
326 GlyphCanvas.current_display.redo ();
327 }
328
329 public static string path_to_uri (string path) {
330 string uri = path;
331 string wp;
332
333 // wine uri hack
334 if (BirdFont.win32) {
335 wp = wine_to_unix_path (uri);
336
337 if (SearchPaths.find_file (wp, "").query_exists ()) {
338 uri = wp;
339 }
340
341 if (uri.index_of ("\\") > -1) {
342 uri = uri.replace ("\\", "/");
343 }
344 }
345
346 if (uri.index_of ("/") == 0) {
347 uri = @"file://$uri";
348 } else {
349 uri = @"file:///$uri";
350 }
351
352 return uri;
353 }
354
355 public static void draw_text_input (WidgetAllocation allocation, Context cr) {
356 cr.save ();
357
358 Theme.color (cr, "Default Background");
359 cr.rectangle (0, 0, allocation.width, TEXT_INPUT_HEIGHT);
360 cr.fill ();
361 cr.restore ();
362
363 Theme.text_color (text_input_label, "Button Foreground");
364
365 text_input_label.widget_x = 10;
366 text_input_label.widget_y = 17;
367
368 text_input.allocation = allocation;
369 text_input.layout ();
370 text_input.widget_x = text_input_label.get_extent () + 20;
371 text_input.widget_y = 10;
372 text_input.width = allocation.width
373 - text_input_button.get_width ()
374 - text_input_label.get_extent ()
375 - 40;
376
377 text_input_button.allocation = allocation;
378 text_input_button.widget_x = text_input.widget_x + text_input.width + 10;
379 text_input_button.widget_y = 10;
380
381 text_input_label.draw (cr);
382 text_input.draw (cr);
383 text_input_button.draw (cr);
384 }
385
386 public static void show_text_input (TextListener tl) {
387 text_callback = tl;
388
389 text_input_label = new Text (tl.label);
390 text_input = new LineTextArea (20 * MainWindow.units);
391 text_input_button = new Button (tl.button_label);
392
393 text_input.carret_is_visible = true;
394
395 text_input.set_text (tl.default_text);
396 text_input.text_changed.connect ((text) => {
397 tl.signal_text_input (text);
398 });
399
400 text_input.enter.connect ((text) => {
401 tl.signal_submit (text);
402 text_input_visible = false;
403 GlyphCanvas.redraw ();
404 });
405
406 text_input_button.action.connect (() => {
407 tl.signal_submit (text_input.get_text ());
408 });
409
410 text_input_visible = true;
411 GlyphCanvas.redraw ();
412 }
413
414 public static void hide_text_input () {
415 text_input_visible = false;
416 text_callback = new TextListener ("", "", "");
417 }
418
419 public static void reset_modifier () {
420 TabContent.key_release (Key.CTRL_RIGHT);
421 TabContent.key_release (Key.CTRL_LEFT);
422 TabContent.key_release (Key.SHIFT_LEFT);
423 TabContent.key_release (Key.SHIFT_RIGHT);
424 TabContent.key_release (Key.ALT_LEFT);
425 TabContent.key_release (Key.ALT_RIGHT);
426 TabContent.key_release (Key.LOGO_LEFT);
427 TabContent.key_release (Key.LOGO_RIGHT);
428
429 if (MainWindow.get_current_display () is Glyph) {
430 TabContent.key_release ((uint) ' ');
431 }
432 }
433 }
434
435 }
436