prevent popup deactivation while button_down
[goodguy/history.git] / cinelerra-5.0 / cinelerra / zoompanel.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 1997-2014 Adam Williams <broadcast at earthling dot net>
5  * 
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * 
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  * 
20  */
21
22 #include "bcsignals.h"
23 #include "clip.h"
24 #include "edl.h"
25 #include "edlsession.h"
26 #include "mwindow.h"
27 #include "mwindowgui.h"
28 #include "theme.h"
29 #include "trackcanvas.h"
30 #include "units.h"
31 #include "vframe.h"
32 #include "zoompanel.h"
33
34
35 ZoomHash::ZoomHash(double value, char *text)
36 {
37         this->value = value;
38         this->text = new char[strlen(text) + 1];
39         strcpy(this->text, text);
40 }
41
42 ZoomHash::~ZoomHash()
43 {
44         delete [] text;
45 }
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 ZoomPanel::ZoomPanel(MWindow *mwindow, 
64         BC_WindowBase *subwindow, 
65         double value, 
66         int x, 
67         int y,
68         int w, 
69         double min,
70         double max,
71         int zoom_type)
72 {
73         this->mwindow = mwindow;
74         this->subwindow = subwindow;
75         this->x = x;
76         this->y = y;
77         this->w = w;
78         this->value = value;
79         this->min = min;
80         this->max = max;
81         this->zoom_type = zoom_type;
82         this->menu_images = 0;
83         this->tumbler_images = 0;
84         this->user_table = 0;
85         this->user_size = 0;
86 }
87
88 ZoomPanel::ZoomPanel(MWindow *mwindow, 
89         BC_WindowBase *subwindow, 
90         double value, 
91         int x, 
92         int y,
93         int w, 
94         double *user_table,
95         int user_size,
96         int zoom_type)
97 {
98         this->mwindow = mwindow;
99         this->subwindow = subwindow;
100         this->x = x;
101         this->y = y;
102         this->w = w;
103         this->value = value;
104         this->min = min;
105         this->max = max;
106         this->zoom_type = zoom_type;
107         this->menu_images = 0;
108         this->tumbler_images = 0;
109         this->user_table = user_table;
110         this->user_size = user_size;
111 }
112
113 ZoomPanel::~ZoomPanel()
114 {
115         delete zoom_text;
116         delete zoom_tumbler;
117         zoom_table.remove_all_objects();
118 }
119
120 void ZoomPanel::calculate_menu()
121 {
122         if(user_size)
123         {
124                 for(int i = 0; i < user_size; i++)
125                 {
126                         zoom_text->add_item(new BC_MenuItem(value_to_text(user_table[i], 0)));
127                         zoom_table.append(new ZoomHash(user_table[i], value_to_text(user_table[i], 0)));
128                 }
129         }
130         else
131         {
132                 for(double zoom = min; zoom <= max; zoom *= 2)
133                 {
134                         zoom_text->add_item(new BC_MenuItem(value_to_text(zoom, 0)));
135                         zoom_table.append(new ZoomHash(zoom, value_to_text(zoom, 0)));
136                 }
137         }
138 }
139
140 int ZoomPanel::calculate_w(int menu_w)
141 {
142         return BC_PopupMenu::calculate_w(menu_w) + BC_Tumbler::calculate_w();
143 }
144
145 void ZoomPanel::update_menu()
146 {
147         while(zoom_text->total_items())
148         {
149                 zoom_text->remove_item(0);
150         }
151
152         zoom_table.remove_all_objects();
153         calculate_menu();
154 }
155
156 void ZoomPanel::set_menu_images(VFrame **data)
157 {
158         this->menu_images = data;
159 }
160
161 void ZoomPanel::set_tumbler_images(VFrame **data)
162 {
163         this->tumbler_images = data;
164 }
165
166 void ZoomPanel::create_objects()
167 {
168         subwindow->add_subwindow(zoom_text = new ZoomPopup(mwindow, 
169                 this, 
170                 x, 
171                 y));
172         x += zoom_text->get_w();
173         subwindow->add_subwindow(zoom_tumbler = new ZoomTumbler(mwindow, 
174                 this, 
175                 x, 
176                 y));
177         calculate_menu();
178 }
179
180 void ZoomPanel::reposition_window(int x, int y)
181 {
182         zoom_text->reposition_window(x, y);
183         x += zoom_text->get_w();
184         zoom_tumbler->reposition_window(x, y);
185 }
186
187
188 int ZoomPanel::get_w()
189 {
190         return zoom_text->get_w() + zoom_tumbler->get_w();
191 }
192
193 double ZoomPanel::get_value()
194 {
195         return value;
196 }
197
198 char* ZoomPanel::get_text()
199 {
200         return zoom_text->get_text();
201 }
202
203 void ZoomPanel::set_text(const char *text)
204 {
205         zoom_text->set_text(text);
206 }
207
208 void ZoomPanel::update(double value)
209 {
210         this->value = value;
211         zoom_text->set_text(value_to_text(value));
212 }
213
214 void ZoomPanel::update(const char *value)
215 {
216         zoom_text->set_text(value);
217 }
218
219
220 char* ZoomPanel::value_to_text(double value, int use_table)
221 {
222         if(use_table)
223         {
224                 for(int i = 0; i < zoom_table.total; i++)
225                 {
226 //printf("ZoomPanel::value_to_text %p\n", zoom_table.values[i]);
227                         if(EQUIV(zoom_table.values[i]->value, value))
228                                 return zoom_table.values[i]->text;
229                 }
230 //printf("ZoomPanel::value_to_text: should never get here\n");
231                 return zoom_table.values[0]->text;
232         }
233
234         switch(zoom_type)
235         {
236                 case ZOOM_PERCENTAGE:
237                         sprintf(string, "%d%%", (int)(value * 100));
238                         break;
239
240                 case ZOOM_FLOAT:
241                         sprintf(string, "%.1f", value);
242                         break;
243
244                 case ZOOM_LONG:
245                         sprintf(string, "%ld", (long)value);
246                         break;
247
248                 case ZOOM_TIME:
249                 {
250 //                      sprintf(string, "%ld", (long)value);
251                         double total_seconds = (double)(mwindow->theme->mcanvas_w - 
252                                         mwindow->theme->patchbay_w -
253                                         BC_ScrollBar::get_span(SCROLL_VERT)) * 
254                                 value / 
255                                 mwindow->edl->session->sample_rate;
256                         Units::totext(string, 
257                                 total_seconds, 
258                                 mwindow->edl->session->time_format, 
259                                 mwindow->edl->session->sample_rate, 
260                                 mwindow->edl->session->frame_rate, 
261                                 mwindow->edl->session->frames_per_foot);
262                         break;
263                 }
264         }
265         return string;
266 }
267
268 double ZoomPanel::text_to_zoom(char *text, int use_table)
269 {
270         if(use_table) {
271                 for(int i = 0; i < zoom_table.total; i++) {
272                         if(!strcasecmp(text, zoom_table.values[i]->text))
273                                 return zoom_table.values[i]->value;
274                 }
275                 return zoom_table.values[0]->value;
276         }
277
278         double result = 1.;
279         switch(zoom_type) {
280                 case ZOOM_PERCENTAGE:
281                         result = atof(text) / 100;
282                         break;
283                 case ZOOM_FLOAT:
284                 case ZOOM_LONG:
285 //              case ZOOM_TIME:
286                         result = atof(text);
287                         break;
288                 case ZOOM_TIME: {
289                         double total_samples = Units::fromtext(text, 
290                                 mwindow->edl->session->sample_rate, 
291                                 mwindow->edl->session->time_format, 
292                                 mwindow->edl->session->frame_rate,
293                                 mwindow->edl->session->frames_per_foot);
294                         total_samples /= mwindow->theme->mcanvas_w - 
295                                 mwindow->theme->patchbay_w -
296                                 BC_ScrollBar::get_span(SCROLL_VERT);
297                         double difference = fabs(total_samples - result);
298                         while(fabs(result - total_samples) <= difference) {
299                                 difference = fabs(result - total_samples);
300                                 result *= 2;
301                         }
302                         break;
303                 }
304         }
305         return result;
306 }
307
308
309
310
311
312
313
314 ZoomPopup::ZoomPopup(MWindow *mwindow, ZoomPanel *panel, int x, int y)
315  : BC_PopupMenu(x, 
316                 y, 
317                 panel->w, 
318                 panel->value_to_text(panel->value, 0), 
319                 1,
320                 panel->menu_images)
321 {
322         this->mwindow = mwindow;
323         this->panel = panel;
324 }
325
326 ZoomPopup::~ZoomPopup()
327 {
328 }
329
330 int ZoomPopup::handle_event()
331 {
332         panel->value = panel->text_to_zoom(get_text());
333         panel->handle_event();
334         return 1;
335 }
336
337
338
339 ZoomTumbler::ZoomTumbler(MWindow *mwindow, ZoomPanel *panel, int x, int y)
340  : BC_Tumbler(x, 
341         y,
342         panel->tumbler_images)
343 {
344         this->mwindow = mwindow;
345         this->panel = panel;
346 }
347
348 ZoomTumbler::~ZoomTumbler()
349 {
350 }
351
352 int ZoomTumbler::handle_up_event()
353 {
354         if(panel->user_table)
355         {
356                 int current_index = 0;
357                 for(current_index = 0; current_index < panel->user_size; current_index++)
358                         if(EQUIV(panel->user_table[current_index], panel->value)) break;
359                 current_index++;
360                 CLAMP(current_index, 0, panel->user_size - 1);
361                 panel->value = panel->user_table[current_index];
362         }
363         else
364         {
365                 panel->value *= 2;
366                 RECLIP(panel->value, panel->min, panel->max);
367         }
368
369         panel->zoom_text->set_text(panel->value_to_text(panel->value));
370         panel->handle_event();
371         return 1;
372 }
373
374 int ZoomTumbler::handle_down_event()
375 {
376         if(panel->user_table)
377         {
378                 int current_index = 0;
379                 for(current_index = 0; current_index < panel->user_size; current_index++)
380                         if(EQUIV(panel->user_table[current_index], panel->value)) break;
381                 current_index--;
382                 CLAMP(current_index, 0, panel->user_size - 1);
383                 panel->value = panel->user_table[current_index];
384         }
385         else
386         {
387                 panel->value /= 2;
388                 RECLIP(panel->value, panel->min, panel->max);
389         }
390         panel->zoom_text->set_text(panel->value_to_text(panel->value));
391         panel->handle_event();
392         return 1;
393 }