RafaMar fixed my comment error
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bctumble.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 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 "bcpixmap.h"
23 #include "bcresources.h"
24 #include "bctextbox.h"
25 #include "bctumble.h"
26 #include "math.h"
27 #include "vframe.h"
28
29
30 #define TUMBLE_UP 0
31 #define TUMBLE_UPHI 1
32 #define TUMBLEBOTTOM_DN 2
33 #define TUMBLETOP_DN 3
34 #define TOTAL_STATES 4
35
36 BC_Tumbler::BC_Tumbler(int x, int y, VFrame **data, int orient)
37  : BC_SubWindow(x, y, 0, 0, -1)
38 {
39         for(int i = 0; i < TOTAL_STATES; i++)
40                 images[i] = 0;
41         status = TUMBLE_UP;
42         repeat_count = 0;
43         this->data = data;
44         this->orient = orient;
45 }
46
47
48 BC_Tumbler::~BC_Tumbler()
49 {
50         for(int i = 0; i < TOTAL_STATES; i ++)
51                 delete images[i];
52 }
53
54
55 int BC_Tumbler::calculate_w(VFrame **data)
56 {
57         VFrame **vfrms = data ? data : BC_WindowBase::get_resources()->tumble_data;
58         return vfrms[0]->get_w();
59 }
60
61 int BC_Tumbler::calculate_h(VFrame **data)
62 {
63         VFrame **vfrms = data ? data : BC_WindowBase::get_resources()->tumble_data;
64         return vfrms[0]->get_h();
65 }
66
67
68 int BC_Tumbler::initialize()
69 {
70 // Get the image
71         set_images(data ? data : get_resources()->tumble_data);
72         w = images[TUMBLE_UP]->get_w();
73         h = images[TUMBLE_UP]->get_h();
74
75 // Create the subwindow
76         BC_SubWindow::initialize();
77
78 // Display the bitmap
79         draw_face(0);
80         return 0;
81 }
82
83 int BC_Tumbler::reposition_window(int x, int y, int w, int h)
84 {
85         BC_WindowBase::reposition_window(x, y);
86         draw_face(0);
87         return 0;
88 }
89
90
91 int BC_Tumbler::update_bitmaps(VFrame **data)
92 {
93         set_images(data);
94         draw_top_background(parent_window, 0, 0, w, h);
95         draw_face(1);
96         return 0;
97 }
98
99 int BC_Tumbler::set_images(VFrame **data)
100 {
101         for(int i = 0; i < TOTAL_STATES; ++i ) {
102                 if( images[i] ) delete images[i];
103                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
104         }
105         return 0;
106 }
107
108 int BC_Tumbler::draw_face(int flush)
109 {
110         draw_top_background(parent_window, 0, 0, w, h);
111         pixmap->draw_pixmap(images[status], 0, 0, w, h, 0, 0);
112         flash(flush);
113         return 0;
114 }
115
116 int BC_Tumbler::repeat_event(int64_t duration)
117 {
118 //printf("BC_Tumbler::repeat_event 1 %d\n", duration);
119         if( duration == top_level->get_resources()->tooltip_delay ) {
120                 if( tooltip_text && tooltip_text[0] != 0 && status == TUMBLE_UPHI ) {
121                         show_tooltip();
122                         return 1;
123                 }
124         }
125         else if( duration == top_level->get_resources()->tumble_duration ) {
126 //printf("BC_Tumbler::repeat_event 2\n");
127 // delay the 1st repeat
128                 if( ++repeat_count > 1 && repeat_count < 5 ) return 0;
129                 if( status == TUMBLETOP_DN ) { handle_up_event(); return 1; }
130                 if( status == TUMBLEBOTTOM_DN) { handle_down_event(); return 1; }
131         }
132         return 0;
133 }
134
135 int BC_Tumbler::cursor_enter_event()
136 {
137         if( top_level->event_win != win ) return 0;
138         if( !top_level->button_down && status == TUMBLE_UP ) {
139                 status = TUMBLE_UPHI;
140                 draw_face(1);
141         }
142         return 0;
143 }
144
145 int BC_Tumbler::cursor_leave_event()
146 {
147         hide_tooltip();
148         if( status == TUMBLE_UPHI ) {
149                 status = TUMBLE_UP;
150                 draw_face(1);
151         }
152         return 0;
153 }
154
155 int BC_Tumbler::button_press_event()
156 {
157         hide_tooltip();
158         if( top_level->event_win != win ) return 0;
159 //printf("BC_Tumbler::button_press_event 1 %d\n", get_buttonpress());
160         if( get_buttonpress() == WHEEL_UP ) {
161                 status = TUMBLETOP_DN;
162                 draw_face(1);
163                 handle_up_event();
164         }
165         else if( get_buttonpress() == WHEEL_DOWN ) {
166                         status = TUMBLEBOTTOM_DN;
167                         draw_face(1);
168                         handle_down_event();
169                 }
170         else {
171                 status = orient == TUMBLER_HORZ ?
172                         top_level->cursor_x > get_w()/2 ? TUMBLETOP_DN : TUMBLEBOTTOM_DN :
173                         top_level->cursor_y < get_h()/2 ? TUMBLETOP_DN : TUMBLEBOTTOM_DN ;
174                 draw_face(1);
175
176                 top_level->set_repeat(top_level->get_resources()->tumble_duration);
177                 repeat_count = 0;
178                 repeat_event(top_level->get_resources()->tumble_duration);
179 //printf("BC_Tumbler::button_press_event 2 %d\n", get_buttonpress());
180         }
181         return 1;
182 }
183
184 int BC_Tumbler::button_release_event()
185 {
186         hide_tooltip();
187         if( top_level->event_win != win ) return 0;
188         if( status == TUMBLEBOTTOM_DN || status == TUMBLETOP_DN ) {
189                 top_level->unset_repeat(top_level->get_resources()->tumble_duration);
190                 status = cursor_inside() ? TUMBLE_UPHI : TUMBLE_UP;
191                 draw_face(1);
192         }
193         return 0;
194 }
195
196 int BC_Tumbler::cursor_motion_event()
197 {
198         if( top_level->event_win != win ) return 0;
199         if( top_level->button_down && !cursor_inside() &&
200             !(status == TUMBLETOP_DN || status == TUMBLEBOTTOM_DN) ) {
201                 status = TUMBLE_UP;
202                 draw_face(1);
203         }
204         return 0;
205 }
206
207
208 BC_ITumbler::BC_ITumbler(BC_TextBox *textbox, int64_t min, int64_t max, int x, int y)
209  : BC_Tumbler(x, y)
210 {
211         this->textbox = textbox;
212         this->min = min;
213         this->max = max;
214         this->increment = 1;
215 }
216
217 BC_ITumbler::~BC_ITumbler()
218 {
219 }
220
221 void BC_ITumbler::set_increment(float value)
222 {
223         this->increment = (int64_t)value;
224         if(increment < 1) increment = 1;
225 }
226
227 int BC_ITumbler::handle_up_event()
228 {
229         int64_t value = atol(textbox->get_text());
230         value += increment;
231         if(value > max) value = max;
232         textbox->update(value);
233         textbox->handle_event();
234         return 1;
235 }
236
237 int BC_ITumbler::handle_down_event()
238 {
239         int64_t value = atol(textbox->get_text());
240         value -= increment;
241         if(value < min) value = min;
242         textbox->update(value);
243         textbox->handle_event();
244         return 1;
245 }
246
247 void BC_ITumbler::set_boundaries(int64_t min, int64_t max)
248 {
249         this->min = min;
250         this->max = max;
251 }
252
253
254 BC_FTumbler::BC_FTumbler(BC_TextBox *textbox,
255         float min,
256         float max,
257         int x,
258         int y)
259  : BC_Tumbler(x, y)
260 {
261         this->textbox = textbox;
262         this->min = min;
263         this->max = max;
264         this->increment = 1.0;
265         this->log_floatincrement = 0;
266 }
267
268 BC_FTumbler::~BC_FTumbler()
269 {
270 }
271
272 int BC_FTumbler::handle_up_event()
273 {
274         float value = atof(textbox->get_text());
275         if (log_floatincrement) {
276                 // round off to to current precision (i.e. 250 -> 200)
277                 float cp = floor(log(value)/log(10) + 0.0001);
278                 value = floor((value/pow(10,cp))+ 0.0001)*pow(10,cp);
279                 value += pow(10,cp);
280         }
281         else
282         value += increment;
283         if(value > max) value = max;
284         textbox->update(value);
285         textbox->handle_event();
286         return 1;
287 }
288
289 int BC_FTumbler::handle_down_event()
290 {
291         float value = atof(textbox->get_text());
292         if (log_floatincrement) {
293                 // round off to to current precision (i.e. 250 -> 200)
294                 float cp = floor(log(value)/log(10));
295                 value = floor(value/pow(10,cp))*pow(10,cp);
296                 // Need to make it so that: [.001 .01 .1 1 10 100] => [.0001 .001 .01 .1 1 10]
297                 cp = floor(log(value)/log(10)-.01);
298                 value -= pow(10,cp);
299         }
300         else
301         value -= increment;
302         if(value < min) value = min;
303         textbox->update(value);
304         textbox->handle_event();
305         return 1;
306 }
307
308 void BC_FTumbler::set_boundaries(float min, float max)
309 {
310         this->min = min;
311         this->max = max;
312 }
313
314 void BC_FTumbler::set_increment(float value)
315 {
316         this->increment = value;
317 }
318
319 void BC_FTumbler::set_log_floatincrement(int value)
320 {
321         this->log_floatincrement = value;
322 }