.
1 /*
2 Copyright (C) 2012 2014 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 using Math;
17
18 namespace BirdFont {
19
20 public class Toolbox : GLib.Object {
21 public static ToolCollection current_set;
22
23 public static DrawingTools drawing_tools;
24 public static KerningTools kerning_tools;
25 public static PreviewTools preview_tools;
26 public static OverviewTools overview_tools;
27 public static BackgroundTools background_tools;
28 public static HiddenTools hidden_tools;
29
30 Tool current_tool;
31
32 public Tool press_tool;
33
34 public signal void redraw (int x, int y, int w, int h);
35
36 public static int allocation_width = 0;
37 public static int allocation_height = 0;
38
39 /** Scrolling with scroll wheel */
40 bool scrolling_toolbox = false;
41
42 /** Scroll with touch pad. */
43 bool scrolling_touch = false;
44 double scroll_y = 0;
45
46 public List<ToolCollection> tool_sets = new List<ToolCollection> ();
47
48 static double scale = 1;
49
50 public Toolbox (GlyphCanvas glyph_canvas, TabBar tab_bar) {
51 scale = Toolbox.allocation_width / 160.0;
52
53 current_tool = new Tool ("no_icon");
54 press_tool = new Tool (null);
55
56 drawing_tools = new DrawingTools (glyph_canvas);
57 kerning_tools = new KerningTools ();
58 preview_tools = new PreviewTools ();
59 overview_tools = new OverviewTools ();
60 background_tools = new BackgroundTools ();
61 hidden_tools = new HiddenTools ();
62
63 tool_sets.append (drawing_tools);
64 tool_sets.append (kerning_tools);
65 tool_sets.append (preview_tools);
66 tool_sets.append (overview_tools);
67 tool_sets.append (background_tools);
68 tool_sets.append (hidden_tools); // tools without a button
69
70 current_set = drawing_tools;
71
72 tab_bar.signal_tab_selected.connect ((tab) => {
73 string tab_name = tab.get_display ().get_name ();
74 set_toolbox_from_tab (tab_name, tab);
75 });
76
77 update_expanders ();
78 }
79
80 public static void set_toolbox_from_tab (string tab_name, Tab? t = null) {
81 if (tab_name == "Kerning") {
82 current_set = (ToolCollection) kerning_tools;
83 } else if (tab_name == "Preview") {
84 current_set = (ToolCollection) preview_tools;
85 } else if (tab_name == "Overview") {
86 current_set = (ToolCollection) overview_tools;
87 } else if (tab_name == "Backgrounds") {
88 current_set = (ToolCollection) background_tools;
89 } else if (t != null && ((!) t).get_display () is Glyph) {
90 current_set = (ToolCollection) drawing_tools;
91 } else {
92 current_set = new EmptySet ();
93 }
94
95 MainWindow.get_toolbox ().update_expanders ();
96 redraw_tool_box ();
97 }
98
99 public static Tool get_move_tool () {
100 return DrawingTools.move_tool;
101 }
102
103 public static void set_object_stroke (double width) {
104 DrawingTools.object_stroke.set_value_round (width);
105 redraw_tool_box ();
106 }
107
108 public static void set_allocation (int w, int h) {
109 if (w != allocation_width || allocation_height != h) {
110 allocation_width = w;
111 allocation_height = h;
112 Toolbox.redraw_tool_box ();
113 }
114 }
115
116 public void press (uint button, double x, double y) {
117 if (MenuTab.suppress_event) {
118 warn_if_test ("Event suppressed");
119 return;
120 }
121
122 foreach (Expander exp in current_set.get_expanders ()) {
123 foreach (Tool t in exp.tool) {
124 if (t.tool_is_visible () && t.is_over (x, y)) {
125 t.panel_press_action (t, button, x, y);
126 press_tool = t;
127 }
128 }
129 }
130
131 scrolling_touch = true;
132 scroll_y = y;
133 }
134
135 public void release (uint button, double x, double y) {
136 bool active;
137
138 if (MenuTab.suppress_event) {
139 warn_if_test ("Event suppressed");
140 return;
141 }
142
143 foreach (Expander exp in current_set.get_expanders ()) {
144 foreach (Tool t in exp.tool) {
145 if (t.tool_is_visible ()) {
146 active = t.is_over (x, y);
147
148 if (active) {
149 if (press_tool == t) {
150 select_tool (t);
151 }
152 }
153
154 t.panel_release_action (t, button, x, y);
155 }
156 }
157 }
158
159 scrolling_touch = false;
160 }
161
162 public void scroll_up (double x, double y) {
163 bool action = false;
164
165 if (MenuTab.suppress_event) {
166 warn_if_test ("Event suppressed");
167 return;
168 }
169
170 if (!scrolling_toolbox) {
171 foreach (Expander exp in current_set.get_expanders ()) {
172 foreach (Tool t in exp.tool) {
173 if (t.tool_is_visible () && t.is_over (x, y)) {
174 action = t.scroll_wheel_up_action (t);
175 press_tool = t;
176 }
177 }
178 }
179 }
180
181 if (!action) {
182 scroll_current_set (35);
183 }
184
185 redraw_tool_box ();
186 }
187
188 void scroll_current_set (double d) {
189 current_set.scroll += d;
190
191 if (current_set.scroll > 0) {
192 current_set.scroll = 0;
193 }
194
195 if (current_set.content_height < allocation_height) {
196 current_set.scroll = 0;
197 } else if (current_set.content_height + current_set.scroll < allocation_height) {
198 current_set.scroll = allocation_height - current_set.content_height;
199 }
200
201 update_expanders ();
202 suppress_scroll ();
203 }
204
205 public void scroll_down (double x, double y) {
206 bool action = false;
207
208 if (!scrolling_toolbox) {
209 foreach (Expander exp in current_set.get_expanders ()) {
210 foreach (Tool t in exp.tool) {
211 if (t.tool_is_visible () && t.is_over (x, y)) {
212 action = t.scroll_wheel_down_action (t);
213 press_tool = t;
214 }
215 }
216 }
217 }
218
219 if (!action) {
220 scroll_current_set (-35);
221 }
222
223 redraw_tool_box ();
224 }
225
226 void suppress_scroll () {
227 scrolling_toolbox = true;
228
229 Timeout.add (2000, () => {
230 scrolling_toolbox = false;
231 return false;
232 });
233 }
234
235 public void move (double x, double y) {
236 bool update;
237 bool a;
238 bool consumed = false;
239 bool active;
240
241 foreach (Expander exp in current_set.get_expanders ()) {
242 a = exp.is_over (x, y);
243 update = exp.set_active (a);
244
245 if (update) {
246 redraw ((int) exp.x - 10, (int) exp.y - 10, (int) (exp.x + exp.w + 10), (int) (exp.y + exp.h + 10));
247 }
248
249
250 foreach (Tool t in exp.tool) {
251 if (t.tool_is_visible ()) {
252 active = t.is_over (x, y);
253
254 if (!active && t.is_active ()) {
255 t.move_out_action (t);
256 }
257
258 update = t.set_active (active);
259
260 if (update) {
261 redraw (0, 0, allocation_width, allocation_height);
262 }
263
264 if (t.panel_move_action (t, x, y)) {
265 consumed = true;
266 }
267 }
268 }
269 }
270
271 if (scrolling_touch && !consumed && BirdFont.android) {
272 scroll_current_set (y - scroll_y);
273 scroll_y = y;
274 redraw_tool_box ();
275 }
276 }
277
278 public static void redraw_tool_box () {
279 if (MenuTab.suppress_event) {
280 warn_if_test ("Don't redraw toolbox when background thread is running.");
281 return;
282 }
283
284 Toolbox t = MainWindow.get_toolbox ();
285 if (!is_null (t)) {
286 t.redraw (0, 0, allocation_width, allocation_height);
287 }
288 }
289
290 public void reset_active_tool () {
291 foreach (Expander exp in current_set.get_expanders ()) {
292 foreach (Tool t in exp.tool) {
293 t.set_active (false);
294 }
295 }
296 }
297
298 public Tool? get_active_tool () {
299 foreach (Expander exp in current_set.get_expanders ()) {
300 foreach (Tool t in exp.tool) {
301 if (t.is_active ()) {
302 return t;
303 }
304 }
305 }
306
307 return null;
308 }
309
310 public void set_current_tool (Tool tool) {
311 if (tool.editor_events) {
312 current_tool = tool;
313 }
314 }
315
316 public Tool get_current_tool () {
317 return current_tool;
318 }
319
320 public void select_tool (Tool tool) {
321 bool update;
322
323 foreach (Expander exp in current_set.get_expanders ()) {
324 foreach (Tool t in exp.tool) {
325 if (tool.get_id () == t.get_id ()) {
326 if (!t.tool_is_visible ()) {
327 warning ("Tool is hidden");
328 } else {
329 update = false;
330
331 update = tool.set_selected (true);
332 if (tool.persistent) {
333 update = tool.set_active (true);
334 }
335
336 tool.select_action (tool);
337
338 if (update) {
339 redraw ((int) exp.x - 10, (int) exp.y - 10, allocation_width, (int) (allocation_height - exp.y + 10));
340 }
341
342 set_current_tool (tool);
343 }
344 }
345 }
346
347 }
348 }
349
350 public Tool get_tool (string name) {
351 foreach (ToolCollection tc in tool_sets) {
352 foreach (Expander e in tc.get_expanders ()) {
353 foreach (Tool t in e.tool) {
354 if (t.get_name () == name) {
355 return t;
356 }
357 }
358 }
359 }
360
361 warning ("No tool found for name \"%s\".\n", name);
362
363 return new Tool ("no_icon");
364 }
365
366 public static void set_tool_visible (string name, bool visible) {
367 Toolbox tb = MainWindow.get_toolbox ();
368 Tool t = tb.get_tool (name);
369 t.set_tool_visibility (visible);
370 tb.update_expanders ();
371 Toolbox.redraw_tool_box ();
372 }
373
374 public static void select_tool_by_name (string name) {
375 Toolbox b = MainWindow.get_toolbox ();
376
377 if (is_null (b)) {
378 return;
379 }
380
381 b.select_tool (b.get_tool (name));
382 }
383
384 public static bool set_scale (double s) {
385 scale = s;
386 }
387
388 public static double get_scale () {
389 return scale;
390 }
391
392 public void set_default_tool_size () {
393 foreach (ToolCollection t in tool_sets) {
394 foreach (Expander e in t.get_expanders ()) {
395 e.update_tool_position ();
396 }
397 }
398 }
399
400 public void update_expanders () {
401 double pos;
402
403 foreach (Expander e in current_set.get_expanders ()) {
404 e.set_scroll (current_set.scroll);
405 }
406
407 pos = 4 * get_scale ();
408 foreach (Expander e in current_set.get_expanders ()) {
409 e.set_offset (pos);
410
411 pos += e.get_content_height () + 4 * get_scale ();
412
413 current_set.content_height = pos;
414
415 if (BirdFont.android) {
416 current_set.content_height *= 1.15;
417 }
418 }
419
420 foreach (Expander e in current_set.get_expanders ()) {
421 e.set_active (false);
422 }
423 }
424
425 private void draw_expanders (int w, int h, Context cr) {
426 foreach (Expander e in current_set.get_expanders ()) {
427 e.draw (w, h, cr);
428 e.draw_content (w, h, cr);
429 }
430 }
431
432 public void draw (int w, int h, Context cr) {
433 EmptySet empty_set;
434 ImageSurface bg;
435 double scale_x, scale_y, scale;
436
437 if (current_set is EmptySet) {
438 empty_set = (EmptySet) current_set;
439
440 if (empty_set.background != null) {
441 bg = (!) empty_set.background;
442
443 scale_x = (double) allocation_width / bg.get_width ();
444 scale_y = (double) allocation_height / bg.get_height ();
445
446 scale = fmax (scale_x, scale_y);
447
448 cr.save ();
449 cr.scale (scale, scale);
450 cr.set_source_surface (bg, 0, 0);
451 cr.paint ();
452 cr.restore ();
453
454 draw_expanders (w, h, cr);
455 }
456 } else {
457 cr.save ();
458
459 cr.rectangle (0, 0, w, h);
460 cr.set_line_width (0);
461 Theme.color (cr, "Background 4");
462 cr.fill ();
463
464 draw_expanders (w, h, cr);
465
466 cr.restore ();
467 }
468 }
469
470 public class EmptySet : ToolCollection {
471
472 public ImageSurface? background;
473 Gee.ArrayList<Expander> expanders;
474
475 public EmptySet () {
476 background = Icons.get_icon ("corvus_monedula.png");
477 expanders = new Gee.ArrayList<Expander> ();
478 }
479
480 public override Gee.ArrayList<Expander> get_expanders () {
481 return expanders;
482 }
483 }
484
485 }
486
487 }
488