r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / guicast / bcpan.C
blobe5699411ba340d56bc76cd2906c6c1d8049fda85
1 #include "bcpan.h"
2 #include "bcpixmap.h"
3 #include "bcpopup.h"
4 #include "bcresources.h"
5 #include "clip.h"
6 #include "colors.h"
7 #include "fonts.h"
8 #include "rotateframe.h"
9 #include "units.h"
10 #include "vframe.h"
12 #include <math.h>
13 #include <string.h>
15 BC_Pan::BC_Pan(int x, 
16                 int y, 
17                 int virtual_r, 
18                 float maxvalue, 
19                 int total_values, 
20                 int *value_positions, 
21                 int stick_x, 
22                 int stick_y,
23                 float *values)
24  : BC_SubWindow(x, y, -1, -1, -1)
26         this->virtual_r = virtual_r;
27         this->maxvalue = maxvalue;
28         this->total_values = total_values;
29         this->values = new float[total_values];
30         memcpy(this->values, values, sizeof(float) * total_values);
31         this->value_positions = new int[total_values];
32         memcpy(this->value_positions, value_positions, sizeof(int) * total_values);
33         this->value_x = new int[total_values];
34         this->value_y = new int[total_values];
35         this->stick_x = stick_x;
36         this->stick_y = stick_y;
37         get_channel_positions(value_x, 
38                 value_y, 
39                 value_positions,
40                 virtual_r,
41                 total_values);
42         if(stick_x < 0 || stick_y < 0)
43                 calculate_stick_position(total_values, 
44                         value_positions, 
45                         values, 
46                         maxvalue, 
47                         virtual_r,
48                         this->stick_x,
49                         this->stick_y);
50         highlighted = 0;
51         popup = 0;
52         active = 0;
53         memset(images, 0, sizeof(BC_Pixmap*) * PAN_IMAGES);
56 BC_Pan::~BC_Pan()
58 //printf("BC_Pan::~BC_Pan 1\n");
59         delete [] values;
60 //printf("BC_Pan::~BC_Pan 1\n");
61         delete [] value_positions;
62 //printf("BC_Pan::~BC_Pan 1\n");
63         delete [] value_x;
64 //printf("BC_Pan::~BC_Pan 1\n");
65         delete [] value_y;
66 //printf("BC_Pan::~BC_Pan 1\n");
67         if(popup) delete popup;
68 //printf("BC_Pan::~BC_Pan 1\n");
69         delete temp_channel;
70 //printf("BC_Pan::~BC_Pan 1\n");
71         delete rotater;
72         for(int i = 0; i < PAN_IMAGES; i++)
73                 if(images[i]) delete images[i];
74 //printf("BC_Pan::~BC_Pan 2\n");
77 int BC_Pan::initialize()
79         set_images(get_resources()->pan_data);
81         BC_SubWindow::initialize();
82         temp_channel = new VFrame(0, 
83                 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
84                 get_resources()->pan_data[PAN_CHANNEL]->get_h(),
85                 get_resources()->pan_data[PAN_CHANNEL]->get_color_model());
86         rotater = new RotateFrame(1,
87                 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
88                 get_resources()->pan_data[PAN_CHANNEL]->get_h());
89         draw();
90         return 0;
93 void BC_Pan::set_images(VFrame **data)
95         for(int i = 0; i < PAN_IMAGES; i++)
96         {
97                 if(images[i]) delete images[i];
98                 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
99         }
100         w = images[PAN_UP]->get_w();
101         h = images[PAN_UP]->get_h();
104 int BC_Pan::button_press_event()
106         if(is_event_win() && get_buttonpress() == 1)
107         {
108                 hide_tooltip();
109                 activate();
110                 x_origin = get_cursor_x();
111                 y_origin = get_cursor_y();
112                 stick_x_origin = stick_x;
113                 stick_y_origin = stick_y;
114                 draw_popup();
115                 return 1;
116         }
117         return 0;
120 int BC_Pan::cursor_motion_event()
122         if(active)
123         {
124                 stick_x = stick_x_origin + get_cursor_x() - x_origin;
125                 stick_y = stick_y_origin + get_cursor_y() - y_origin;
126                 CLAMP(stick_x, 0, virtual_r * 2);
127                 CLAMP(stick_y, 0, virtual_r * 2);
128                 stick_to_values();
129                 draw_popup();
130                 handle_event();
131                 return 1;
132         }
133         return 0;
136 int BC_Pan::button_release_event()
138         if(active)
139         {
140                 hide_tooltip();
141                 deactivate();
142                 draw();
143                 return 1;
144         }
145         return 0;
148 int BC_Pan::repeat_event(int64_t duration)
150         if(duration == top_level->get_resources()->tooltip_delay &&
151                 tooltip_text[0] != 0 &&
152                 highlighted &&
153                 !active &&
154                 !tooltip_done)
155         {
156                 show_tooltip();
157                 tooltip_done = 1;
158                 return 1;
159         }
160         return 0;
163 int BC_Pan::cursor_enter_event()
165         if(is_event_win() && !highlighted)
166         {
167                 tooltip_done = 0;
168                 highlighted = 1;
169                 draw();
170         }
171         return 0;
174 int BC_Pan::cursor_leave_event()
176         if(highlighted)
177         {
178                 highlighted = 0;
179                 hide_tooltip();
180                 draw();
181         }
182         return 0;
187 int BC_Pan::deactivate()
189         if(popup) delete popup;
190         popup = 0;
191         active = 0;
192         return 0;
195 int BC_Pan::activate()
197         int x, y;
198         Window tempwin;
200         active = 1;
201         XTranslateCoordinates(top_level->display, 
202                         win, 
203                         top_level->rootwin, 
204                         0, 
205                         0, 
206                         &x, 
207                         &y, 
208                         &tempwin);
210         x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
211         y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
213         popup = new BC_Popup(this, 
214                                 x, 
215                                 y, 
216                                 images[PAN_POPUP]->get_w(), 
217                                 images[PAN_POPUP]->get_h(), 
218                                 0, 
219                                 0, 
220                                 images[PAN_POPUP]);
221         flush();
222         return 0;
225 int BC_Pan::update(int x, int y)
227         if(x != stick_x ||
228                 y != stick_y)
229         {
230                 stick_x = x;
231                 stick_y = y;
232                 stick_to_values();
233                 draw();
234         }
235         return 0;
238 void BC_Pan::draw_popup()
240         popup->draw_background(0, 0, popup->get_w(), popup->get_h());
242         int x1, y1;
243         float rotate_angle;
244         float scale = (float)(popup->get_w() - 
245                 get_resources()->pan_data[PAN_CHANNEL]->get_w()) / 
246                 (virtual_r * 2);
247         set_color(get_resources()->pan_text_color);
248         set_font(SMALLFONT);
250         for(int i = 0; i < total_values; i++)
251         {
252                 x1 = (int)(value_x[i] * scale);
253                 y1 = (int)(value_y[i] * scale);
254                 rotate_angle = value_positions[i];
255                 rotate_angle = -rotate_angle;
256                 while(rotate_angle < 0) rotate_angle += 360;
257                 rotater->rotate(temp_channel, 
258                         get_resources()->pan_data[PAN_CHANNEL], 
259                         rotate_angle, 
260                         0);
261                 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup, 
262                         temp_channel, 
263                         PIXMAP_ALPHA);
264                 popup->draw_pixmap(temp_pixmap, x1, y1);
265                 delete temp_pixmap;
267                 char string[BCTEXTLEN];
268                 float value = values[i] + 0.005;
269                 sprintf(string, "%.1f", value);
270                 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
271         }
272         
273         x1 = (int)(stick_x * scale);
274         y1 = (int)(stick_y * scale);
275         popup->draw_pixmap(images[PAN_STICK], x1, y1);
276         popup->flash();
279 #define PICON_W 6
280 #define PICON_H 6
282 void BC_Pan::draw()
284         draw_top_background(parent_window, 0, 0, w, h);
285         
286         draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
287         get_channel_positions(value_x, 
288                 value_y, 
289                 value_positions,
290                 virtual_r,
291                 total_values);
293 // draw channels
294         int x1, y1, x2, y2, w, h, j;
295         float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
296         set_color(RED);
298         for(int i = 0; i < total_values; i++)
299         {
300 // printf("BC_Pan::draw 1 %d %d %d %d\n", 
301 //      i, 
302 //      value_positions[i], 
303 //      value_x[i], 
304 //      value_y[i]);
305                 x1 = (int)(value_x[i] * scale);
306                 y1 = (int)(value_y[i] * scale);
307 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
308                 CLAMP(x1, 0, get_w() - PICON_W);
309                 CLAMP(y1, 0, get_h() - PICON_H);
310                 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
311 //              draw_box(x1, y1, PICON_W, PICON_H);
312         }
314 // draw stick
315         set_color(GREEN);
316         x1 = (int)(stick_x * scale);
317         y1 = (int)(stick_y * scale);
319 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
320         CLAMP(x1, 0, get_w() - PICON_W);
321         CLAMP(y1, 0, get_h() - PICON_H);
323         draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
324 //      x2 = x1 + PICON_W;
325 //      y2 = y1 + PICON_H;
326 //      draw_line(x1, y1, x2, y2);
327 //      draw_line(x2, y1, x1, y2);
329         flash();
332 int BC_Pan::stick_to_values()
334         return stick_to_values(values,
335                 total_values, 
336                 value_positions, 
337                 stick_x, 
338                 stick_y,
339                 virtual_r,
340                 maxvalue);
343 int BC_Pan::stick_to_values(float *values,
344                 int total_values, 
345                 int *value_positions, 
346                 int stick_x, 
347                 int stick_y,
348                 int virtual_r,
349                 float maxvalue)
351 // find shortest distance to a channel
352         float shortest = 2 * virtual_r, test_distance;
353         int i;
354         int *value_x = new int[total_values];
355         int *value_y = new int[total_values];
357         get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
358         for(i = 0; i < total_values; i++)
359         {
360                 if((test_distance = distance(stick_x, 
361                         value_x[i], 
362                         stick_y, 
363                         value_y[i])) < shortest)
364                         shortest = test_distance;
365         }
367 // get values for channels
368         if(shortest == 0)
369         {
370                 for(i = 0; i < total_values; i++)
371                 {
372                         if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
373                                 values[i] = maxvalue;
374                         else
375                                 values[i] = 0;
376                 }
377         }
378         else
379         {
380                 for(i = 0; i < total_values; i++)
381                 {
382                         values[i] = shortest;
383                         values[i] -= (float)(distance(stick_x, 
384                                 value_x[i], 
385                                 stick_y, 
386                                 value_y[i]) - shortest);
387                         if(values[i] < 0) values[i] = 0;
388                         values[i] = values[i] / shortest * maxvalue;
389                 }
390         }
392         for(i = 0; i < total_values; i++)
393         {
394                 values[i] = Units::quantize10(values[i]);
395         }
397         delete [] value_x;
398         delete [] value_y;
399         return 0;
403 float BC_Pan::distance(int x1, int x2, int y1, int y2)
405         return hypot(x2 - x1, y2 - y1);
408 int BC_Pan::change_channels(int new_channels, int *value_positions)
410         delete values;
411         delete this->value_positions;
412         delete value_x;
413         delete value_y;
414         
415         values = new float[new_channels];
416         this->value_positions = new int[new_channels];
417         value_x = new int[new_channels];
418         value_y = new int[new_channels];
419         total_values = new_channels;
420         for(int i = 0; i < new_channels; i++)
421         {
422                 this->value_positions[i] = value_positions[i];
423         }
424         get_channel_positions(value_x, 
425                 value_y, 
426                 value_positions,
427                 virtual_r,
428                 total_values);
429         stick_to_values();
430         draw();
431         return 0;
434 int BC_Pan::get_channel_positions(int *value_x, 
435         int *value_y, 
436         int *value_positions,
437         int virtual_r,
438         int total_values)
440         for(int i = 0; i < total_values; i++)
441         {
442                 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
443         }
444         return 0;
447 int BC_Pan::get_total_values()
449         return total_values;
452 float BC_Pan::get_value(int channel)
454         return values[channel];
457 int BC_Pan::get_stick_x() 
459         return stick_x; 
462 int BC_Pan::get_stick_y() 
464         return stick_y; 
467 float* BC_Pan::get_values()
469         return values;
472 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
474         float radians = (float)a / 360 * 2 * M_PI;
476         y = (int)(sin(radians) * virtual_r);
477         x = (int)(cos(radians) * virtual_r);
478         x += virtual_r;
479         y = virtual_r - y;
480         return 0;
483 void BC_Pan::calculate_stick_position(int total_values, 
484         int *value_positions, 
485         float *values, 
486         float maxvalue, 
487         int virtual_r,
488         int &stick_x,
489         int &stick_y)
491 // use highest value as location of stick
492         float highest_value = 0;
493         int angle = 0;
494         int i, j;
496         for(i = 0; i < total_values; i++)
497         {
498                 if(values[i] > highest_value)
499                 {
500                         highest_value = values[i];
501                         angle = value_positions[i];
502                 }
503         }
505         rdtoxy(stick_x, stick_y, angle, virtual_r);