asset drag/drop to viewers, bluebanana bug, listbox fontlist highlight
[goodguy/history.git] / cinelerra-5.1 / 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, const 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->user_table = 0;
83         this->user_size = 0;
84 }
85
86 ZoomPanel::ZoomPanel(MWindow *mwindow,
87         BC_WindowBase *subwindow,
88         double value,
89         int x,
90         int y,
91         int w,
92         double *user_table,
93         int user_size,
94         int zoom_type)
95 {
96         this->mwindow = mwindow;
97         this->subwindow = subwindow;
98         this->x = x;
99         this->y = y;
100         this->w = w;
101         this->value = value;
102         this->min = min;
103         this->max = max;
104         this->zoom_type = zoom_type;
105         this->user_table = user_table;
106         this->user_size = user_size;
107 }
108
109 ZoomPanel::~ZoomPanel()
110 {
111         delete zoom_text;
112         delete zoom_tumbler;
113         zoom_table.remove_all_objects();
114 }
115
116 void ZoomPanel::calculate_menu()
117 {
118         if(user_size)
119         {
120                 for(int i = 0; i < user_size; i++)
121                 {
122                         zoom_text->add_item(new BC_MenuItem(value_to_text(user_table[i], 0)));
123                         zoom_table.append(new ZoomHash(user_table[i], value_to_text(user_table[i], 0)));
124                 }
125         }
126         else
127         {
128                 for(double zoom = min; zoom <= max; zoom *= 2)
129                 {
130                         zoom_text->add_item(new BC_MenuItem(value_to_text(zoom, 0)));
131                         zoom_table.append(new ZoomHash(zoom, value_to_text(zoom, 0)));
132                 }
133         }
134 }
135
136 int ZoomPanel::calculate_w(int menu_w)
137 {
138         return BC_PopupMenu::calculate_w(menu_w) + BC_Tumbler::calculate_w();
139 }
140
141 void ZoomPanel::update_menu()
142 {
143         while(zoom_text->total_items()) zoom_text->del_item(0);
144
145         zoom_table.remove_all_objects();
146         calculate_menu();
147 }
148
149 void ZoomPanel::create_objects()
150 {
151         subwindow->add_subwindow(zoom_text = new ZoomPopup(mwindow, this, x, y));
152         x += zoom_text->get_w();
153         subwindow->add_subwindow(zoom_tumbler = new ZoomTumbler(mwindow, this, x, y));
154         calculate_menu();
155 }
156
157 void ZoomPanel::reposition_window(int x, int y)
158 {
159         zoom_text->reposition_window(x, y);
160         x += zoom_text->get_w();
161         zoom_tumbler->reposition_window(x, y);
162 }
163
164
165 int ZoomPanel::get_w()
166 {
167         return zoom_text->get_w() + zoom_tumbler->get_w();
168 }
169
170 double ZoomPanel::get_value()
171 {
172         return value;
173 }
174
175 char* ZoomPanel::get_text()
176 {
177         return zoom_text->get_text();
178 }
179
180 void ZoomPanel::set_text(const char *text)
181 {
182         zoom_text->set_text(text);
183 }
184
185 void ZoomPanel::set_tooltip(const char *text)
186 {
187         zoom_text->set_tooltip(text);
188         zoom_tumbler->set_tooltip(text);
189 }
190
191 void ZoomPanel::update(double value)
192 {
193         this->value = value;
194         zoom_text->set_text(value_to_text(value));
195 }
196
197 void ZoomPanel::update(const char *value)
198 {
199         zoom_text->set_text(value);
200 }
201
202
203 char* ZoomPanel::value_to_text(double value, int use_table)
204 {
205         if(use_table)
206         {
207                 for(int i = 0; i < zoom_table.total; i++)
208                 {
209 //printf("ZoomPanel::value_to_text %p\n", zoom_table.values[i]);
210                         if(EQUIV(zoom_table.values[i]->value, value))
211                                 return zoom_table.values[i]->text;
212                 }
213 //printf("ZoomPanel::value_to_text: should never get here\n");
214                 return zoom_table.values[0]->text;
215         }
216
217         switch(zoom_type)
218         {
219                 case ZOOM_PERCENTAGE:
220                         sprintf(string, "%d%%", (int)(value * 100));
221                         break;
222
223                 case ZOOM_FLOAT:
224                         sprintf(string, "%.1f", value);
225                         break;
226
227                 case ZOOM_LONG:
228                         sprintf(string, "%ld", (long)value);
229                         break;
230
231                 case ZOOM_TIME:
232                 {
233 //                      sprintf(string, "%ld", (long)value);
234                         double total_seconds = (double)(mwindow->theme->mcanvas_w -
235                                         mwindow->theme->patchbay_w -
236                                         BC_ScrollBar::get_span(SCROLL_VERT)) *
237                                 value /
238                                 mwindow->edl->session->sample_rate;
239                         Units::totext(string,
240                                 total_seconds,
241                                 mwindow->edl->session->time_format,
242                                 mwindow->edl->session->sample_rate,
243                                 mwindow->edl->session->frame_rate,
244                                 mwindow->edl->session->frames_per_foot);
245                         break;
246                 }
247         }
248         return string;
249 }
250
251 double ZoomPanel::text_to_zoom(char *text, int use_table)
252 {
253         if(use_table) {
254                 for(int i = 0; i < zoom_table.total; i++) {
255                         if(!strcasecmp(text, zoom_table.values[i]->text))
256                                 return zoom_table.values[i]->value;
257                 }
258                 return zoom_table.values[0]->value;
259         }
260
261         double result = 1.;
262         switch(zoom_type) {
263                 case ZOOM_PERCENTAGE:
264                         result = atof(text) / 100;
265                         break;
266                 case ZOOM_FLOAT:
267                 case ZOOM_LONG:
268 //              case ZOOM_TIME:
269                         result = atof(text);
270                         break;
271                 case ZOOM_TIME: {
272                         double total_samples = Units::fromtext(text,
273                                 mwindow->edl->session->sample_rate,
274                                 mwindow->edl->session->time_format,
275                                 mwindow->edl->session->frame_rate,
276                                 mwindow->edl->session->frames_per_foot);
277                         total_samples /= mwindow->theme->mcanvas_w -
278                                 mwindow->theme->patchbay_w -
279                                 BC_ScrollBar::get_span(SCROLL_VERT);
280                         double difference = fabs(total_samples - result);
281                         while(fabs(result - total_samples) <= difference) {
282                                 difference = fabs(result - total_samples);
283                                 result *= 2;
284                         }
285                         break;
286                 }
287         }
288         return result;
289 }
290
291
292
293
294
295
296
297 ZoomPopup::ZoomPopup(MWindow *mwindow, ZoomPanel *panel, int x, int y)
298  : BC_PopupMenu(x, y, panel->w, panel->value_to_text(panel->value, 0),
299         1, mwindow->theme->get_image_set("zoombar_menu", 0))
300 {
301         this->mwindow = mwindow;
302         this->panel = panel;
303 }
304
305 ZoomPopup::~ZoomPopup()
306 {
307 }
308
309 int ZoomPopup::handle_event()
310 {
311         panel->value = panel->text_to_zoom(get_text());
312         panel->handle_event();
313         return 1;
314 }
315
316
317
318 ZoomTumbler::ZoomTumbler(MWindow *mwindow, ZoomPanel *panel, int x, int y)
319  : BC_Tumbler(x, y, mwindow->theme->get_image_set("zoombar_tumbler", 0))
320 {
321         this->mwindow = mwindow;
322         this->panel = panel;
323 }
324
325 ZoomTumbler::~ZoomTumbler()
326 {
327 }
328
329 int ZoomTumbler::handle_up_event()
330 {
331         if(panel->user_table)
332         {
333                 int current_index = 0;
334                 for(current_index = 0; current_index < panel->user_size; current_index++)
335                         if(EQUIV(panel->user_table[current_index], panel->value)) break;
336                 current_index++;
337                 CLAMP(current_index, 0, panel->user_size - 1);
338                 panel->value = panel->user_table[current_index];
339         }
340         else
341         {
342                 panel->value *= 2;
343                 RECLIP(panel->value, panel->min, panel->max);
344         }
345
346         panel->zoom_text->set_text(panel->value_to_text(panel->value));
347         panel->handle_event();
348         return 1;
349 }
350
351 int ZoomTumbler::handle_down_event()
352 {
353         if(panel->user_table)
354         {
355                 int current_index = 0;
356                 for(current_index = 0; current_index < panel->user_size; current_index++)
357                         if(EQUIV(panel->user_table[current_index], panel->value)) break;
358                 current_index--;
359                 CLAMP(current_index, 0, panel->user_size - 1);
360                 panel->value = panel->user_table[current_index];
361         }
362         else
363         {
364                 panel->value /= 2;
365                 RECLIP(panel->value, panel->min, panel->max);
366         }
367         panel->zoom_text->set_text(panel->value_to_text(panel->value));
368         panel->handle_event();
369         return 1;
370 }