00001 #include "bcpan.h"
00002 #include "bcpixmap.h"
00003 #include "bcpopup.h"
00004 #include "bcresources.h"
00005 #include "clip.h"
00006 #include "colors.h"
00007 #include "fonts.h"
00008 #include "rotateframe.h"
00009 #include "units.h"
00010 #include "vframe.h"
00011
00012 #include <math.h>
00013 #include <string.h>
00014
00015 BC_Pan::BC_Pan(int x,
00016 int y,
00017 int virtual_r,
00018 float maxvalue,
00019 int total_values,
00020 int *value_positions,
00021 int stick_x,
00022 int stick_y,
00023 float *values)
00024 : BC_SubWindow(x, y, -1, -1, -1)
00025 {
00026 this->virtual_r = virtual_r;
00027 this->maxvalue = maxvalue;
00028 this->total_values = total_values;
00029 this->values = new float[total_values];
00030 memcpy(this->values, values, sizeof(float) * total_values);
00031 this->value_positions = new int[total_values];
00032 memcpy(this->value_positions, value_positions, sizeof(int) * total_values);
00033 this->value_x = new int[total_values];
00034 this->value_y = new int[total_values];
00035 this->stick_x = stick_x;
00036 this->stick_y = stick_y;
00037 get_channel_positions(value_x,
00038 value_y,
00039 value_positions,
00040 virtual_r,
00041 total_values);
00042 if(stick_x < 0 || stick_y < 0)
00043 calculate_stick_position(total_values,
00044 value_positions,
00045 values,
00046 maxvalue,
00047 virtual_r,
00048 this->stick_x,
00049 this->stick_y);
00050 highlighted = 0;
00051 popup = 0;
00052 active = 0;
00053 memset(images, 0, sizeof(BC_Pixmap*) * PAN_IMAGES);
00054 }
00055
00056 BC_Pan::~BC_Pan()
00057 {
00058
00059 delete [] values;
00060
00061 delete [] value_positions;
00062
00063 delete [] value_x;
00064
00065 delete [] value_y;
00066
00067 if(popup) delete popup;
00068
00069 delete temp_channel;
00070
00071 delete rotater;
00072 for(int i = 0; i < PAN_IMAGES; i++)
00073 if(images[i]) delete images[i];
00074
00075 }
00076
00077 int BC_Pan::initialize()
00078 {
00079 set_images(get_resources()->pan_data);
00080
00081 BC_SubWindow::initialize();
00082 temp_channel = new VFrame(0,
00083 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
00084 get_resources()->pan_data[PAN_CHANNEL]->get_h(),
00085 get_resources()->pan_data[PAN_CHANNEL]->get_color_model());
00086 rotater = new RotateFrame(1,
00087 get_resources()->pan_data[PAN_CHANNEL]->get_w(),
00088 get_resources()->pan_data[PAN_CHANNEL]->get_h());
00089 draw();
00090 return 0;
00091 }
00092
00093 void BC_Pan::set_images(VFrame **data)
00094 {
00095 for(int i = 0; i < PAN_IMAGES; i++)
00096 {
00097 if(images[i]) delete images[i];
00098 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
00099 }
00100 w = images[PAN_UP]->get_w();
00101 h = images[PAN_UP]->get_h();
00102 }
00103
00104 int BC_Pan::button_press_event()
00105 {
00106
00107 if (popup)
00108 { if (popup->is_event_win() && get_button_down() && get_buttonpress() == 1)
00109 {
00110 active = 1;
00111 x_origin = popup->get_cursor_x();
00112 y_origin = popup->get_cursor_y();
00113 stick_x_origin = stick_x;
00114 stick_y_origin = stick_y;
00115 return 1;
00116 } else
00117 {
00118 deactivate();
00119 return 0;
00120 }
00121 }
00122 if(is_event_win() && get_button_down() && get_buttonpress() == 1)
00123 {
00124 hide_tooltip();
00125 activate();
00126 active = 1;
00127 x_origin = get_cursor_x();
00128 y_origin = get_cursor_y();
00129 stick_x_origin = stick_x;
00130 stick_y_origin = stick_y;
00131 draw_popup();
00132 return 1;
00133 }
00134 return 0;
00135 }
00136
00137 int BC_Pan::cursor_motion_event()
00138 {
00139 if(popup && get_button_down() && get_buttonpress() == 1)
00140 {
00141 stick_x = stick_x_origin + get_cursor_x() - x_origin;
00142 stick_y = stick_y_origin + get_cursor_y() - y_origin;
00143 CLAMP(stick_x, 0, virtual_r * 2);
00144 CLAMP(stick_y, 0, virtual_r * 2);
00145 stick_to_values();
00146 draw_popup();
00147 handle_event();
00148 return 1;
00149 }
00150 return 0;
00151 }
00152
00153 int BC_Pan::button_release_event()
00154 {
00155 if(popup)
00156 {
00157 hide_tooltip();
00158 deactivate();
00159 draw();
00160 return 1;
00161 }
00162 return 0;
00163 }
00164
00165 int BC_Pan::repeat_event(int64_t duration)
00166 {
00167 if(duration == top_level->get_resources()->tooltip_delay &&
00168 tooltip_text[0] != 0 &&
00169 highlighted &&
00170 !active &&
00171 !tooltip_done)
00172 {
00173 show_tooltip();
00174 tooltip_done = 1;
00175 return 1;
00176 }
00177 return 0;
00178 }
00179
00180 int BC_Pan::cursor_enter_event()
00181 {
00182 if(is_event_win() && !highlighted)
00183 {
00184 tooltip_done = 0;
00185 highlighted = 1;
00186 draw();
00187 }
00188 return 0;
00189 }
00190
00191 int BC_Pan::cursor_leave_event()
00192 {
00193 if(highlighted)
00194 {
00195 highlighted = 0;
00196 hide_tooltip();
00197 draw();
00198 }
00199 return 0;
00200 }
00201
00202
00203
00204 int BC_Pan::deactivate()
00205 {
00206 if(popup) delete popup;
00207 popup = 0;
00208 active = 0;
00209 return 0;
00210 }
00211
00212 int BC_Pan::activate(int popup_x, int popup_y)
00213 {
00214 int x, y;
00215 Window tempwin;
00216
00217 active = 0;
00218 if (popup_x < 0 || popup_y < 0)
00219 {
00220 XTranslateCoordinates(top_level->display,
00221 win,
00222 top_level->rootwin,
00223 0,
00224 0,
00225 &x,
00226 &y,
00227 &tempwin);
00228
00229 x -= (images[PAN_POPUP]->get_w() - get_w()) / 2;
00230 y -= (images[PAN_POPUP]->get_h() - get_h()) / 2;
00231 if (x < 0) x = 0;
00232 } else
00233 {
00234 XTranslateCoordinates(top_level->display,
00235 top_level->win,
00236 top_level->rootwin,
00237 popup_x,
00238 popup_y,
00239 &x,
00240 &y,
00241 &tempwin);
00242 x -= images[PAN_POPUP]->get_w() / 2;
00243 y -= images[PAN_POPUP]->get_h() / 2;
00244 if (x < 0) x = 0;
00245 }
00246
00247
00248 if (popup) delete popup;
00249 popup = new BC_Popup(this,
00250 x,
00251 y,
00252 images[PAN_POPUP]->get_w(),
00253 images[PAN_POPUP]->get_h(),
00254 0,
00255 0,
00256 images[PAN_POPUP]);
00257 draw_popup();
00258 flush();
00259 return 0;
00260 }
00261
00262 int BC_Pan::update(int x, int y)
00263 {
00264 if(x != stick_x ||
00265 y != stick_y)
00266 {
00267 stick_x = x;
00268 stick_y = y;
00269 stick_to_values();
00270 draw();
00271 }
00272 return 0;
00273 }
00274
00275 void BC_Pan::draw_popup()
00276 {
00277 popup->draw_background(0, 0, popup->get_w(), popup->get_h());
00278
00279 int x1, y1;
00280 float rotate_angle;
00281 float scale = (float)(popup->get_w() -
00282 get_resources()->pan_data[PAN_CHANNEL]->get_w()) /
00283 (virtual_r * 2);
00284 set_color(get_resources()->pan_text_color);
00285 set_font(SMALLFONT);
00286
00287 for(int i = 0; i < total_values; i++)
00288 {
00289 x1 = (int)(value_x[i] * scale);
00290 y1 = (int)(value_y[i] * scale);
00291 rotate_angle = value_positions[i];
00292 rotate_angle = -rotate_angle;
00293 while(rotate_angle < 0) rotate_angle += 360;
00294 rotater->rotate(temp_channel,
00295 get_resources()->pan_data[PAN_CHANNEL],
00296 rotate_angle,
00297 0);
00298 BC_Pixmap *temp_pixmap = new BC_Pixmap(popup,
00299 temp_channel,
00300 PIXMAP_ALPHA);
00301 popup->draw_pixmap(temp_pixmap, x1, y1);
00302 delete temp_pixmap;
00303
00304 char string[BCTEXTLEN];
00305 float value = values[i] + 0.005;
00306 sprintf(string, "%.1f", value);
00307 popup->draw_text(x1, y1 + get_text_height(SMALLFONT), string);
00308 }
00309
00310 x1 = (int)(stick_x * scale);
00311 y1 = (int)(stick_y * scale);
00312 popup->draw_pixmap(images[PAN_STICK], x1, y1);
00313 popup->flash();
00314 }
00315
00316 #define PICON_W 6
00317 #define PICON_H 6
00318
00319 void BC_Pan::draw()
00320 {
00321 draw_top_background(parent_window, 0, 0, w, h);
00322
00323 draw_pixmap(images[highlighted ? PAN_HI : PAN_UP]);
00324 get_channel_positions(value_x,
00325 value_y,
00326 value_positions,
00327 virtual_r,
00328 total_values);
00329
00330
00331 int x1, y1, x2, y2, w, h, j;
00332 float scale = (float)(get_w() - PICON_W) / (virtual_r * 2);
00333 set_color(RED);
00334
00335 for(int i = 0; i < total_values; i++)
00336 {
00337
00338
00339
00340
00341
00342 x1 = (int)(value_x[i] * scale);
00343 y1 = (int)(value_y[i] * scale);
00344
00345 CLAMP(x1, 0, get_w() - PICON_W);
00346 CLAMP(y1, 0, get_h() - PICON_H);
00347 draw_pixmap(images[PAN_CHANNEL_SMALL], x1, y1);
00348
00349 }
00350
00351
00352 set_color(GREEN);
00353 x1 = (int)(stick_x * scale);
00354 y1 = (int)(stick_y * scale);
00355
00356
00357 CLAMP(x1, 0, get_w() - PICON_W);
00358 CLAMP(y1, 0, get_h() - PICON_H);
00359
00360 draw_pixmap(images[PAN_STICK_SMALL], x1, y1);
00361
00362
00363
00364
00365
00366 flash();
00367 }
00368
00369 int BC_Pan::stick_to_values()
00370 {
00371 return stick_to_values(values,
00372 total_values,
00373 value_positions,
00374 stick_x,
00375 stick_y,
00376 virtual_r,
00377 maxvalue);
00378 }
00379
00380 int BC_Pan::stick_to_values(float *values,
00381 int total_values,
00382 int *value_positions,
00383 int stick_x,
00384 int stick_y,
00385 int virtual_r,
00386 float maxvalue)
00387 {
00388
00389 float shortest = 2 * virtual_r, test_distance;
00390 int i;
00391 int *value_x = new int[total_values];
00392 int *value_y = new int[total_values];
00393
00394 get_channel_positions(value_x, value_y, value_positions, virtual_r, total_values);
00395 for(i = 0; i < total_values; i++)
00396 {
00397 if((test_distance = distance(stick_x,
00398 value_x[i],
00399 stick_y,
00400 value_y[i])) < shortest)
00401 shortest = test_distance;
00402 }
00403
00404
00405 if(shortest == 0)
00406 {
00407 for(i = 0; i < total_values; i++)
00408 {
00409 if(distance(stick_x, value_x[i], stick_y, value_y[i]) == shortest)
00410 values[i] = maxvalue;
00411 else
00412 values[i] = 0;
00413 }
00414 }
00415 else
00416 {
00417 for(i = 0; i < total_values; i++)
00418 {
00419 values[i] = shortest;
00420 values[i] -= (float)(distance(stick_x,
00421 value_x[i],
00422 stick_y,
00423 value_y[i]) - shortest);
00424 if(values[i] < 0) values[i] = 0;
00425 values[i] = values[i] / shortest * maxvalue;
00426 }
00427 }
00428
00429 for(i = 0; i < total_values; i++)
00430 {
00431 values[i] = Units::quantize10(values[i]);
00432 }
00433
00434 delete [] value_x;
00435 delete [] value_y;
00436 return 0;
00437 }
00438
00439
00440 float BC_Pan::distance(int x1, int x2, int y1, int y2)
00441 {
00442 return hypot(x2 - x1, y2 - y1);
00443 }
00444
00445 int BC_Pan::change_channels(int new_channels, int *value_positions)
00446 {
00447 delete values;
00448 delete this->value_positions;
00449 delete value_x;
00450 delete value_y;
00451
00452 values = new float[new_channels];
00453 this->value_positions = new int[new_channels];
00454 value_x = new int[new_channels];
00455 value_y = new int[new_channels];
00456 total_values = new_channels;
00457 for(int i = 0; i < new_channels; i++)
00458 {
00459 this->value_positions[i] = value_positions[i];
00460 }
00461 get_channel_positions(value_x,
00462 value_y,
00463 value_positions,
00464 virtual_r,
00465 total_values);
00466 stick_to_values();
00467 draw();
00468 return 0;
00469 }
00470
00471 int BC_Pan::get_channel_positions(int *value_x,
00472 int *value_y,
00473 int *value_positions,
00474 int virtual_r,
00475 int total_values)
00476 {
00477 for(int i = 0; i < total_values; i++)
00478 {
00479 rdtoxy(value_x[i], value_y[i], value_positions[i], virtual_r);
00480 }
00481 return 0;
00482 }
00483
00484 int BC_Pan::get_total_values()
00485 {
00486 return total_values;
00487 }
00488
00489 float BC_Pan::get_value(int channel)
00490 {
00491 return values[channel];
00492 }
00493
00494 int BC_Pan::get_stick_x()
00495 {
00496 return stick_x;
00497 }
00498
00499 int BC_Pan::get_stick_y()
00500 {
00501 return stick_y;
00502 }
00503
00504 float* BC_Pan::get_values()
00505 {
00506 return values;
00507 }
00508
00509 int BC_Pan::rdtoxy(int &x, int &y, int a, int virtual_r)
00510 {
00511 float radians = (float)a / 360 * 2 * M_PI;
00512
00513 y = (int)(sin(radians) * virtual_r);
00514 x = (int)(cos(radians) * virtual_r);
00515 x += virtual_r;
00516 y = virtual_r - y;
00517 return 0;
00518 }
00519
00520 void BC_Pan::calculate_stick_position(int total_values,
00521 int *value_positions,
00522 float *values,
00523 float maxvalue,
00524 int virtual_r,
00525 int &stick_x,
00526 int &stick_y)
00527 {
00528
00529 int channel1 = -1;
00530 int channel2 = -1;
00531
00532 for(int i = 0; i < total_values; i++)
00533 {
00534 if(values[i] > 0.001)
00535 {
00536 if(channel1 < 0) channel1 = i;
00537 else
00538 if(channel2 < 0) channel2 = i;
00539 else
00540 break;
00541 }
00542 }
00543
00544 if(channel1 >= 0 && channel2 >= 0)
00545 {
00546 int x1, y1, x2, y2;
00547 rdtoxy(x1, y1, value_positions[channel1], virtual_r);
00548 rdtoxy(x2, y2, value_positions[channel2], virtual_r);
00549 stick_x = (x1 + x2) / 2;
00550 stick_y = (y1 + y2) / 2;
00551 }
00552 else
00553 {
00554
00555
00556 float highest_value = 0;
00557 int angle = 0;
00558 int i, j;
00559
00560 for(i = 0; i < total_values; i++)
00561 {
00562 if(values[i] > highest_value)
00563 {
00564 highest_value = values[i];
00565 angle = value_positions[i];
00566 }
00567 }
00568 rdtoxy(stick_x, stick_y, angle, virtual_r);
00569 }
00570
00571 }
00572