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