r877: Fix files that were missing from a make dist tarball.
[cinelerra_cv.git] / guicast / bcpan.C
blob14014a90418fcae1d073019702c72fc09d2f07f7
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         // there are two modes of operation...
107         if (popup)
108         {       if (popup->is_event_win() && get_button_down() && get_buttonpress() == 1)
109                 { 
110                         active = 1;
111                         x_origin = popup->get_cursor_x();
112                         y_origin = popup->get_cursor_y();
113                         stick_x_origin = stick_x;
114                         stick_y_origin = stick_y;
115                         return 1;
116                 } else
117                 {
118                         deactivate();
119                         return 0;
120                 }
121         }
122         if(is_event_win() && get_button_down() && get_buttonpress() == 1)
123         {
124                 hide_tooltip();
125                 activate();
126                 active = 1;
127                 x_origin = get_cursor_x();
128                 y_origin = get_cursor_y();
129                 stick_x_origin = stick_x;
130                 stick_y_origin = stick_y;
131                 draw_popup();
132                 return 1;
133         }
134         return 0;
137 int BC_Pan::cursor_motion_event()
139         if(popup && get_button_down() && get_buttonpress() == 1)
140         {
141                 stick_x = stick_x_origin + get_cursor_x() - x_origin;
142                 stick_y = stick_y_origin + get_cursor_y() - y_origin;
143                 CLAMP(stick_x, 0, virtual_r * 2);
144                 CLAMP(stick_y, 0, virtual_r * 2);
145                 stick_to_values();
146                 draw_popup();
147                 handle_event();
148                 return 1;
149         }
150         return 0;
153 int BC_Pan::button_release_event()
155         if(popup)
156         {
157                 hide_tooltip();
158                 deactivate();
159                 draw();
160                 return 1;
161         }
162         return 0;
165 int BC_Pan::repeat_event(int64_t duration)
167         if(duration == top_level->get_resources()->tooltip_delay &&
168                 tooltip_text[0] != 0 &&
169                 highlighted &&
170                 !active &&
171                 !tooltip_done)
172         {
173                 show_tooltip();
174                 tooltip_done = 1;
175                 return 1;
176         }
177         return 0;
180 int BC_Pan::cursor_enter_event()
182         if(is_event_win() && !highlighted)
183         {
184                 tooltip_done = 0;
185                 highlighted = 1;
186                 draw();
187         }
188         return 0;
191 int BC_Pan::cursor_leave_event()
193         if(highlighted)
194         {
195                 highlighted = 0;
196                 hide_tooltip();
197                 draw();
198         }
199         return 0;
204 int BC_Pan::deactivate()
206         if(popup) delete popup;
207         popup = 0;
208         active = 0;
209         return 0;
212 int BC_Pan::activate(int popup_x, int popup_y)
214         int x, y;
215         Window tempwin;
217         active = 0;
218         if (popup_x < 0 || popup_y < 0)
219         {
220                 XTranslateCoordinates(top_level->display, 
221                         win, 
222                         top_level->rootwin, 
223                         0, 
224                         0, 
225                         &x, 
226                         &y, 
227                         &tempwin);
229                 x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
230                 y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
231                 if (x < 0) x = 0;
232         } else
233         {
234                 XTranslateCoordinates(top_level->display, 
235                         top_level->win, 
236                         top_level->rootwin, 
237                         popup_x, 
238                         popup_y, 
239                         &x, 
240                         &y, 
241                         &tempwin);
242                 x -= images[PAN_POPUP]->get_w() / 2;
243                 y -= images[PAN_POPUP]->get_h() / 2;
244                 if (x < 0) x = 0;
245         }
246         
247         
248         if (popup) delete popup;
249         popup = new BC_Popup(this, 
250                                 x, 
251                                 y, 
252                                 images[PAN_POPUP]->get_w(), 
253                                 images[PAN_POPUP]->get_h(), 
254                                 0, 
255                                 0, 
256                                 images[PAN_POPUP]);
257         draw_popup();
258         flush();
259         return 0;
262 int BC_Pan::update(int x, int y)
264         if(x != stick_x ||
265                 y != stick_y)
266         {
267                 stick_x = x;
268                 stick_y = y;
269                 stick_to_values();
270                 draw();
271         }
272         return 0;
275 void BC_Pan::draw_popup()
277         popup->draw_background(0, 0, popup->get_w(), popup->get_h());
279         int x1, y1;
280         float rotate_angle;
281         float scale = (float)(popup->get_w() - 
282                 get_resources()->pan_data[PAN_CHANNEL]->get_w()) / 
283                 (virtual_r * 2);
284         set_color(get_resources()->pan_text_color);
285         set_font(SMALLFONT);
287         for(int i = 0; i < total_values; i++)
288         {
289                 x1 = (int)(value_x[i] * scale);
290                 y1 = (int)(value_y[i] * scale);
291                 rotate_angle = value_positions[i];
292                 rotate_angle = -rotate_angle;
293                 while(rotate_angle < 0) rotate_angle += 360;
294                 rotater->rotate(temp_channel, 
295                         get_resources()->pan_data[PAN_CHANNEL], 
296                         rotate_angle, 
297                         0);
298                 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup, 
299                         temp_channel, 
300                         PIXMAP_ALPHA);
301                 popup->draw_pixmap(temp_pixmap, x1, y1);
302                 delete temp_pixmap;
304                 char string[BCTEXTLEN];
305                 float value = values[i] + 0.005;
306                 sprintf(string, "%.1f", value);
307                 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
308         }
309         
310         x1 = (int)(stick_x * scale);
311         y1 = (int)(stick_y * scale);
312         popup->draw_pixmap(images[PAN_STICK], x1, y1);
313         popup->flash();
316 #define PICON_W 6
317 #define PICON_H 6
319 void BC_Pan::draw()
321         draw_top_background(parent_window, 0, 0, w, h);
322         
323         draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
324         get_channel_positions(value_x, 
325                 value_y, 
326                 value_positions,
327                 virtual_r,
328                 total_values);
330 // draw channels
331         int x1, y1, x2, y2, w, h, j;
332         float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
333         set_color(RED);
335         for(int i = 0; i < total_values; i++)
336         {
337 // printf("BC_Pan::draw 1 %d %d %d %d\n", 
338 //      i, 
339 //      value_positions[i], 
340 //      value_x[i], 
341 //      value_y[i]);
342                 x1 = (int)(value_x[i] * scale);
343                 y1 = (int)(value_y[i] * scale);
344 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
345                 CLAMP(x1, 0, get_w() - PICON_W);
346                 CLAMP(y1, 0, get_h() - PICON_H);
347                 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
348 //              draw_box(x1, y1, PICON_W, PICON_H);
349         }
351 // draw stick
352         set_color(GREEN);
353         x1 = (int)(stick_x * scale);
354         y1 = (int)(stick_y * scale);
356 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
357         CLAMP(x1, 0, get_w() - PICON_W);
358         CLAMP(y1, 0, get_h() - PICON_H);
360         draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
361 //      x2 = x1 + PICON_W;
362 //      y2 = y1 + PICON_H;
363 //      draw_line(x1, y1, x2, y2);
364 //      draw_line(x2, y1, x1, y2);
366         flash();
369 int BC_Pan::stick_to_values()
371         return stick_to_values(values,
372                 total_values, 
373                 value_positions, 
374                 stick_x, 
375                 stick_y,
376                 virtual_r,
377                 maxvalue);
380 int BC_Pan::stick_to_values(float *values,
381                 int total_values, 
382                 int *value_positions, 
383                 int stick_x, 
384                 int stick_y,
385                 int virtual_r,
386                 float maxvalue)
388 // find shortest distance to a channel
389         float shortest = 2 * virtual_r, test_distance;
390         int i;
391         int *value_x = new int[total_values];
392         int *value_y = new int[total_values];
394         get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
395         for(i = 0; i < total_values; i++)
396         {
397                 if((test_distance = distance(stick_x, 
398                         value_x[i], 
399                         stick_y, 
400                         value_y[i])) < shortest)
401                         shortest = test_distance;
402         }
404 // get values for channels
405         if(shortest == 0)
406         {
407                 for(i = 0; i < total_values; i++)
408                 {
409                         if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
410                                 values[i] = maxvalue;
411                         else
412                                 values[i] = 0;
413                 }
414         }
415         else
416         {
417                 for(i = 0; i < total_values; i++)
418                 {
419                         values[i] = shortest;
420                         values[i] -= (float)(distance(stick_x, 
421                                 value_x[i], 
422                                 stick_y, 
423                                 value_y[i]) - shortest);
424                         if(values[i] < 0) values[i] = 0;
425                         values[i] = values[i] / shortest * maxvalue;
426                 }
427         }
429         for(i = 0; i < total_values; i++)
430         {
431                 values[i] = Units::quantize10(values[i]);
432         }
434         delete [] value_x;
435         delete [] value_y;
436         return 0;
440 float BC_Pan::distance(int x1, int x2, int y1, int y2)
442         return hypot(x2 - x1, y2 - y1);
445 int BC_Pan::change_channels(int new_channels, int *value_positions)
447         delete values;
448         delete this->value_positions;
449         delete value_x;
450         delete value_y;
451         
452         values = new float[new_channels];
453         this->value_positions = new int[new_channels];
454         value_x = new int[new_channels];
455         value_y = new int[new_channels];
456         total_values = new_channels;
457         for(int i = 0; i < new_channels; i++)
458         {
459                 this->value_positions[i] = value_positions[i];
460         }
461         get_channel_positions(value_x, 
462                 value_y, 
463                 value_positions,
464                 virtual_r,
465                 total_values);
466         stick_to_values();
467         draw();
468         return 0;
471 int BC_Pan::get_channel_positions(int *value_x, 
472         int *value_y, 
473         int *value_positions,
474         int virtual_r,
475         int total_values)
477         for(int i = 0; i < total_values; i++)
478         {
479                 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
480         }
481         return 0;
484 int BC_Pan::get_total_values()
486         return total_values;
489 float BC_Pan::get_value(int channel)
491         return values[channel];
494 int BC_Pan::get_stick_x() 
496         return stick_x; 
499 int BC_Pan::get_stick_y() 
501         return stick_y; 
504 float* BC_Pan::get_values()
506         return values;
509 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
511         float radians = (float)a / 360 * 2 * M_PI;
513         y = (int)(sin(radians) * virtual_r);
514         x = (int)(cos(radians) * virtual_r);
515         x += virtual_r;
516         y = virtual_r - y;
517         return 0;
520 void BC_Pan::calculate_stick_position(int total_values, 
521         int *value_positions, 
522         float *values, 
523         float maxvalue, 
524         int virtual_r,
525         int &stick_x,
526         int &stick_y)
528 // If 2 channels have positive values, use weighted average
529         int channel1 = -1;
530         int channel2 = -1;
532         for(int i = 0; i < total_values; i++)
533         {
534                 if(values[i] > 0.001)
535                 {
536                         if(channel1 < 0) channel1 = i;
537                         else
538                         if(channel2 < 0) channel2 = i;
539                         else
540                                 break;
541                 }
542         }
544         if(channel1 >= 0 && channel2 >= 0)
545         {
546                 int x1, y1, x2, y2;
547                 rdtoxy(x1, y1, value_positions[channel1], virtual_r);
548                 rdtoxy(x2, y2, value_positions[channel2], virtual_r);
549                 stick_x = (x1 + x2) / 2;
550                 stick_y = (y1 + y2) / 2;
551         }
552         else
553         {
555 // use highest value as location of stick
556                 float highest_value = 0;
557                 int angle = 0;
558                 int i, j;
560                 for(i = 0; i < total_values; i++)
561                 {
562                         if(values[i] > highest_value)
563                         {
564                                 highest_value = values[i];
565                                 angle = value_positions[i];
566                         }
567                 }
568                 rdtoxy(stick_x, stick_y, angle, virtual_r);
569         }