.
1 /*
2 Copyright (C) 2012 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 using Math;
17
18 namespace BirdFont {
19
20 public class Expander : GLib.Object {
21
22 private static const double HEADLINE_MARGIN = 6;
23
24 public double x = 7;
25 public double y = 5;
26 public double scroll = 0;
27
28 public double w = 6;
29 public double h = 5;
30
31 public double margin = 0;
32
33 protected double opacity = 0;
34
35 protected bool active = false;
36
37 public Gee.ArrayList<Tool> tool;
38
39 bool persist = false;
40 bool unique = false;
41
42 double content_height = 0;
43
44 string? headline;
45
46 public Expander (string? headline = null) {
47 this.headline = headline;
48 tool = new Gee.ArrayList<Tool> ();
49 }
50
51 public void set_headline (string? h) {
52 headline = h;
53 }
54
55 public double get_content_height () {
56 return content_height;
57 }
58
59 /** Returns true if tools can be used with the current canvas after
60 * they have been selectes and false if they are a commands to be executed.
61 */
62 public bool is_persistent () {
63 return persist;
64 }
65
66 /** Returns true if all other tools in thid expander should be deselected
67 * when a tool is selected.
68 */
69 public bool is_unique () {
70 return unique;
71 }
72
73 public void set_persistent (bool p) {
74 persist = p;
75 }
76
77 public void set_unique (bool u) {
78 unique = u;
79 }
80
81 public void update_tool_position () {
82 double scale = Toolbox.get_scale ();
83 double margin_small = 5 * scale;
84 double xt = x;
85 double yt = y + scroll + margin_small;
86 bool new_row = false;
87 bool has_visible_tools = false;
88 Tool previous;
89 bool first_row;
90
91 foreach (Tool t in tool) {
92 if (t.tool_is_visible ()) {
93 has_visible_tools = true;
94 break;
95 }
96 }
97
98 if (!has_visible_tools) {
99 content_height = 0;
100 return;
101 }
102
103 foreach (Tool t in tool) {
104 if (t is ZoomBar) {
105 t.w = Toolbox.allocation_width * scale;
106 t.h = 7 * scale;
107 } else if (t is LabelTool) {
108 t.w = Toolbox.allocation_width * scale;
109 t.h = 15 * scale;
110 } else if (t is FontName) {
111 t.w = Toolbox.allocation_width * scale;
112 t.h = 20 * scale;
113 } else if (t is KerningRange) {
114 t.w = Toolbox.allocation_width * scale;
115 t.h = 17 * scale;
116 } else {
117 t.w = 33 * scale;
118 t.h = (33 / 1.11) * scale;
119 }
120 }
121
122 if (tool.size > 0) {
123 content_height = tool.get (0).h + margin_small;
124 } else {
125 content_height = 0;
126 }
127
128 if (headline != null && tool.size > 0) {
129 yt += 17 * scale + HEADLINE_MARGIN;
130 content_height += 17 * scale + HEADLINE_MARGIN;
131 }
132
133 if (tool.size > 0) {
134 previous = tool.get (0);
135 first_row = true;
136 foreach (Tool t in tool) {
137 if (t.tool_is_visible ()) {
138 new_row = xt + t.w > Toolbox.allocation_width - 7 * scale;
139
140 if (new_row && !first_row) {
141 content_height += previous.h + margin_small;
142 xt = x;
143 yt += previous.h + 7 * scale;
144 }
145
146 t.x = xt;
147 t.y = yt;
148
149 xt += t.w + 7 * scale;
150
151 previous = t;
152 first_row = false;
153 }
154 }
155 }
156 }
157
158 public void set_scroll (double scroll) {
159 this.scroll = scroll;
160 }
161
162 public void set_offset (double ty) {
163 y = ty;
164 update_tool_position ();
165 }
166
167 public void add_tool (Tool t, int position = -1) {
168 if (position < 0) {
169 tool.add (t);
170 } else {
171 return_if_fail (position <= tool.size);
172 tool.insert (position, t);
173 }
174
175 update_tool_position ();
176
177 t.select_action.connect ((selected) => {
178 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin));
179
180 if (is_unique ()) {
181 foreach (var deselected in tool) {
182 if (selected.get_id () != deselected.get_id ()) {
183 deselected.set_selected (false);
184 }
185 }
186 }
187
188 if (!selected.new_selection && selected.persistent) {
189 if (is_persistent ()) {
190 selected.set_selected (true);
191 } else {
192 selected.set_selected (false);
193 }
194 }
195
196 if (!is_persistent () && !selected.persistent) {
197 var time = new TimeoutSource(200);
198 time.set_callback(() => {
199 selected.set_selected (false);
200 MainWindow.get_toolbox ().redraw ((int) x, (int) y, (int) w + 300, (int) (h + margin));
201 return false;
202 });
203 time.attach(null);
204 }
205
206 selected.new_selection = false;
207 });
208 }
209
210 public bool is_over (double xp, double yp) {
211 double yt = y + scroll + 2;
212 return yt - 7 <= yp <= yt + 7 && xp < 17;
213 }
214
215 public bool set_active (bool a) {
216 bool r = (active != a);
217 opacity = (a) ? 1 : 0;
218 active = a;
219 return r;
220 }
221
222 public void draw (int wd, int hd, Context cr) {
223 double yt = y + scroll + 2;
224 Text title;
225
226 if (tool.size > 0) {
227 if (headline != null) {
228 title = new Text ();
229 title.set_text ((!) headline);
230 title.use_cache (true);
231 Theme.text_color (title, "Foreground 2");
232 title.set_font_size (17 * Toolbox.get_scale ());
233 title.draw_at_baseline (cr, x, yt + HEADLINE_MARGIN + 13 * Toolbox.get_scale ());
234 }
235 }
236 }
237
238 public void draw_content (int w, int h, Context cr) {
239 cr.save ();
240 foreach (Tool t in tool) {
241 if (t.tool_is_visible ()) {
242 t.draw (cr);
243 }
244 }
245 cr.restore ();
246 }
247
248 }
249
250 }
251