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