r854: Merge 2.1:
[cinelerra_cv/ct.git] / guicast / bcpan.C
blob84a1ed8390f552d3dda1d0e38431ae67b8f3e568
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);
228                 x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
229                 y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
230                 if (x < 0) x = 0;
231         } else
232         {
233                 XTranslateCoordinates(top_level->display, 
234                         top_level->win, 
235                         top_level->rootwin, 
236                         popup_x, 
237                         popup_y, 
238                         &x, 
239                         &y, 
240                         &tempwin);
241                 x -= images[PAN_POPUP]->get_w() / 2;
242                 y -= images[PAN_POPUP]->get_h() / 2;
243                 if (x < 0) x = 0;
244         }
245         
246         
247         if (popup) delete popup;
248         popup = new BC_Popup(this, 
249                                 x, 
250                                 y, 
251                                 images[PAN_POPUP]->get_w(), 
252                                 images[PAN_POPUP]->get_h(), 
253                                 0, 
254                                 0, 
255                                 images[PAN_POPUP]);
256         draw_popup();
257         flush();
258         return 0;
261 int BC_Pan::update(int x, int y)
263         if(x != stick_x ||
264                 y != stick_y)
265         {
266                 stick_x = x;
267                 stick_y = y;
268                 stick_to_values();
269                 draw();
270         }
271         return 0;
274 void BC_Pan::draw_popup()
276         popup->draw_background(0, 0, popup->get_w(), popup->get_h());
278         int x1, y1;
279         float rotate_angle;
280         float scale = (float)(popup->get_w() - 
281                 get_resources()->pan_data[PAN_CHANNEL]->get_w()) / 
282                 (virtual_r * 2);
283         set_color(get_resources()->pan_text_color);
284         set_font(SMALLFONT);
286         for(int i = 0; i < total_values; i++)
287         {
288                 x1 = (int)(value_x[i] * scale);
289                 y1 = (int)(value_y[i] * scale);
290                 rotate_angle = value_positions[i];
291                 rotate_angle = -rotate_angle;
292                 while(rotate_angle < 0) rotate_angle += 360;
293                 rotater->rotate(temp_channel, 
294                         get_resources()->pan_data[PAN_CHANNEL], 
295                         rotate_angle, 
296                         0);
297                 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup, 
298                         temp_channel, 
299                         PIXMAP_ALPHA);
300                 popup->draw_pixmap(temp_pixmap, x1, y1);
301                 delete temp_pixmap;
303                 char string[BCTEXTLEN];
304                 float value = values[i] + 0.005;
305                 sprintf(string, "%.1f", value);
306                 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
307         }
308         
309         x1 = (int)(stick_x * scale);
310         y1 = (int)(stick_y * scale);
311         popup->draw_pixmap(images[PAN_STICK], x1, y1);
312         popup->flash();
315 #define PICON_W 6
316 #define PICON_H 6
318 void BC_Pan::draw()
320         draw_top_background(parent_window, 0, 0, w, h);
321         
322         draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
323         get_channel_positions(value_x, 
324                 value_y, 
325                 value_positions,
326                 virtual_r,
327                 total_values);
329 // draw channels
330         int x1, y1, x2, y2, w, h, j;
331         float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
332         set_color(RED);
334         for(int i = 0; i < total_values; i++)
335         {
336 // printf("BC_Pan::draw 1 %d %d %d %d\n", 
337 //      i, 
338 //      value_positions[i], 
339 //      value_x[i], 
340 //      value_y[i]);
341                 x1 = (int)(value_x[i] * scale);
342                 y1 = (int)(value_y[i] * scale);
343 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
344                 CLAMP(x1, 0, get_w() - PICON_W);
345                 CLAMP(y1, 0, get_h() - PICON_H);
346                 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
347 //              draw_box(x1, y1, PICON_W, PICON_H);
348         }
350 // draw stick
351         set_color(GREEN);
352         x1 = (int)(stick_x * scale);
353         y1 = (int)(stick_y * scale);
355 //printf("BC_Pan::draw 2 %d %d\n", x1, y1);
356         CLAMP(x1, 0, get_w() - PICON_W);
357         CLAMP(y1, 0, get_h() - PICON_H);
359         draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
360 //      x2 = x1 + PICON_W;
361 //      y2 = y1 + PICON_H;
362 //      draw_line(x1, y1, x2, y2);
363 //      draw_line(x2, y1, x1, y2);
365         flash();
368 int BC_Pan::stick_to_values()
370         return stick_to_values(values,
371                 total_values, 
372                 value_positions, 
373                 stick_x, 
374                 stick_y,
375                 virtual_r,
376                 maxvalue);
379 int BC_Pan::stick_to_values(float *values,
380                 int total_values, 
381                 int *value_positions, 
382                 int stick_x, 
383                 int stick_y,
384                 int virtual_r,
385                 float maxvalue)
387 // find shortest distance to a channel
388         float shortest = 2 * virtual_r, test_distance;
389         int i;
390         int *value_x = new int[total_values];
391         int *value_y = new int[total_values];
393         get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
394         for(i = 0; i < total_values; i++)
395         {
396                 if((test_distance = distance(stick_x, 
397                         value_x[i], 
398                         stick_y, 
399                         value_y[i])) < shortest)
400                         shortest = test_distance;
401         }
403 // get values for channels
404         if(shortest == 0)
405         {
406                 for(i = 0; i < total_values; i++)
407                 {
408                         if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
409                                 values[i] = maxvalue;
410                         else
411                                 values[i] = 0;
412                 }
413         }
414         else
415         {
416                 for(i = 0; i < total_values; i++)
417                 {
418                         values[i] = shortest;
419                         values[i] -= (float)(distance(stick_x, 
420                                 value_x[i], 
421                                 stick_y, 
422                                 value_y[i]) - shortest);
423                         if(values[i] < 0) values[i] = 0;
424                         values[i] = values[i] / shortest * maxvalue;
425                 }
426         }
428         for(i = 0; i < total_values; i++)
429         {
430                 values[i] = Units::quantize10(values[i]);
431         }
433         delete [] value_x;
434         delete [] value_y;
435         return 0;
439 float BC_Pan::distance(int x1, int x2, int y1, int y2)
441         return hypot(x2 - x1, y2 - y1);
444 int BC_Pan::change_channels(int new_channels, int *value_positions)
446         delete values;
447         delete this->value_positions;
448         delete value_x;
449         delete value_y;
450         
451         values = new float[new_channels];
452         this->value_positions = new int[new_channels];
453         value_x = new int[new_channels];
454         value_y = new int[new_channels];
455         total_values = new_channels;
456         for(int i = 0; i < new_channels; i++)
457         {
458                 this->value_positions[i] = value_positions[i];
459         }
460         get_channel_positions(value_x, 
461                 value_y, 
462                 value_positions,
463                 virtual_r,
464                 total_values);
465         stick_to_values();
466         draw();
467         return 0;
470 int BC_Pan::get_channel_positions(int *value_x, 
471         int *value_y, 
472         int *value_positions,
473         int virtual_r,
474         int total_values)
476         for(int i = 0; i < total_values; i++)
477         {
478                 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
479         }
480         return 0;
483 int BC_Pan::get_total_values()
485         return total_values;
488 float BC_Pan::get_value(int channel)
490         return values[channel];
493 int BC_Pan::get_stick_x() 
495         return stick_x; 
498 int BC_Pan::get_stick_y() 
500         return stick_y; 
503 float* BC_Pan::get_values()
505         return values;
508 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
510         float radians = (float)a / 360 * 2 * M_PI;
512         y = (int)(sin(radians) * virtual_r);
513         x = (int)(cos(radians) * virtual_r);
514         x += virtual_r;
515         y = virtual_r - y;
516         return 0;
519 void BC_Pan::calculate_stick_position(int total_values, 
520         int *value_positions, 
521         float *values, 
522         float maxvalue, 
523         int virtual_r,
524         int &stick_x,
525         int &stick_y)
527 // use highest value as location of stick
528         float highest_value = 0;
529         int angle = 0;
530         int i, j;
532         for(i = 0; i < total_values; i++)
533         {
534                 if(values[i] > highest_value)
535                 {
536                         highest_value = values[i];
537                         angle = value_positions[i];
538                 }
539         }
540         rdtoxy(stick_x, stick_y, angle, virtual_r);