00001 #include "bcbutton.h"
00002 #include "bcmeter.h"
00003 #include "bcpixmap.h"
00004 #include "bcresources.h"
00005 #include "bcwindow.h"
00006 #include "colors.h"
00007 #include "fonts.h"
00008 #include "vframe.h"
00009 #include <string.h>
00010
00011
00012 #define METER_NORMAL 0
00013 #define METER_GREEN 1
00014 #define METER_RED 2
00015 #define METER_YELLOW 3
00016 #define METER_WHITE 4
00017 #define METER_OVER 5
00018
00019
00020 #define METER_LEFT 0
00021 #define METER_MID 1
00022 #define METER_RIGHT 3
00023
00024
00025 BC_Meter::BC_Meter(int x,
00026 int y,
00027 int orientation,
00028 int pixels,
00029 int min,
00030 int max,
00031 int mode,
00032 int use_titles,
00033 long over_delay,
00034 long peak_delay)
00035 : BC_SubWindow(x, y, -1, -1)
00036 {
00037 this->use_titles = use_titles;
00038 this->over_delay = over_delay;
00039 this->peak_delay = peak_delay;
00040 this->min = min;
00041 this->max = max;
00042 this->mode = mode;
00043 this->orientation = orientation;
00044 this->pixels = pixels;
00045 for(int i = 0; i < TOTAL_METER_IMAGES; i++) images[i] = 0;
00046 db_titles.set_array_delete();
00047 }
00048
00049 BC_Meter::~BC_Meter()
00050 {
00051 db_titles.remove_all_objects();
00052 title_pixels.remove_all();
00053 tick_pixels.remove_all();
00054 for(int i = 0; i < TOTAL_METER_IMAGES; i++) delete images[i];
00055 }
00056
00057 int BC_Meter::get_title_w()
00058 {
00059 return get_resources()->meter_title_w;
00060 }
00061
00062 int BC_Meter::get_meter_w()
00063 {
00064 return get_resources()->ymeter_images[0]->get_w() + 2;
00065 }
00066
00067
00068 int BC_Meter::set_delays(int over_delay, int peak_delay)
00069 {
00070 this->over_delay = over_delay;
00071 this->peak_delay = peak_delay;
00072 return 0;
00073 }
00074
00075 int BC_Meter::initialize()
00076 {
00077 peak_timer = 0;
00078 level_pixel = peak_pixel = 0;
00079 over_timer = 0;
00080 over_count = 0;
00081 peak = level = -100;
00082
00083 if(orientation == METER_VERT)
00084 {
00085 set_images(get_resources()->ymeter_images);
00086 h = pixels;
00087 w = images[0]->get_w();
00088 if(use_titles) w += get_title_w();
00089 }
00090 else
00091 {
00092 set_images(get_resources()->xmeter_images);
00093 h = images[0]->get_h();
00094 w = pixels;
00095 if(use_titles) h += get_title_w();
00096 }
00097
00098
00099 get_divisions();
00100
00101 BC_SubWindow::initialize();
00102 draw_titles();
00103 draw_face();
00104 return 0;
00105 }
00106
00107 void BC_Meter::set_images(VFrame **data)
00108 {
00109 for(int i = 0; i < TOTAL_METER_IMAGES; i++) delete images[i];
00110 for(int i = 0; i < TOTAL_METER_IMAGES; i++)
00111 images[i] = new BC_Pixmap(parent_window, data[i], PIXMAP_ALPHA);
00112 }
00113
00114 int BC_Meter::reposition_window(int x, int y, int pixels)
00115 {
00116 if(pixels < 0) pixels = this->pixels;
00117 this->pixels = pixels;
00118 if(orientation == METER_VERT)
00119 BC_SubWindow::reposition_window(x, y, get_w(), pixels);
00120 else
00121 BC_SubWindow::reposition_window(x, y, pixels, get_h());
00122
00123
00124 get_divisions();
00125
00126
00127
00128
00129
00130 draw_titles();
00131 draw_face();
00132 return 0;
00133 }
00134
00135 int BC_Meter::reset()
00136 {
00137 level = min;
00138 peak = min;
00139 level_pixel = peak_pixel = 0;
00140 peak_timer = 0;
00141 over_timer = 0;
00142 over_count = 0;
00143 draw_face();
00144 return 0;
00145 }
00146
00147 int BC_Meter::button_press_event()
00148 {
00149 if(cursor_inside() && is_event_win())
00150 {
00151 reset_over();
00152 return 1;
00153 }
00154 return 0;
00155 }
00156
00157
00158 int BC_Meter::reset_over()
00159 {
00160 over_timer = 0;
00161 return 0;
00162 }
00163
00164 int BC_Meter::change_format(int mode, int min, int max)
00165 {
00166 this->mode = mode;
00167 this->min = min;
00168 this->max = max;
00169 reposition_window(get_x(), get_y(), pixels);
00170 return 0;
00171 }
00172
00173 int BC_Meter::level_to_pixel(float level)
00174 {
00175 int result;
00176 if(mode == METER_DB)
00177 {
00178 result = (int)(pixels *
00179 (level - min) /
00180 (max - min));
00181 if(level <= min) result = 0;
00182 }
00183 else
00184 {
00185
00186 result = 0;
00187 }
00188
00189 return result;
00190 }
00191
00192
00193 void BC_Meter::get_divisions()
00194 {
00195 int i;
00196 int j, j_step;
00197 int division, division_step;
00198 char string[BCTEXTLEN];
00199 char *new_string;
00200
00201
00202 db_titles.remove_all_objects();
00203 title_pixels.remove_all();
00204 tick_pixels.remove_all();
00205
00206 low_division = 0;
00207 medium_division = 0;
00208 high_division = pixels;
00209
00210 int current_pixel;
00211
00212 for(int current = min; current <= max; current++)
00213 {
00214 if(orientation == METER_VERT)
00215 {
00216
00217 current_pixel = (pixels - METER_MARGIN * 2 - 2) *
00218 (current - min) /
00219 (max - min) + 2;
00220 tick_pixels.append(current_pixel);
00221
00222
00223 if(current == min ||
00224 current == max ||
00225 current == 0 ||
00226 (current - min > 4 && max - current > 4 && !(current % 5)))
00227 {
00228 int title_pixel = (pixels -
00229 METER_MARGIN * 2) *
00230 (current - min) /
00231 (max - min);
00232 sprintf(string, "%d", labs(current));
00233 new_string = new char[strlen(string) + 1];
00234 strcpy(new_string, string);
00235 db_titles.append(new_string);
00236 title_pixels.append(title_pixel);
00237 }
00238 }
00239 else
00240 {
00241 current_pixel = (pixels - METER_MARGIN * 2) *
00242 (current - min) /
00243 (max - min);
00244 tick_pixels.append(current_pixel);
00245
00246 }
00247
00248
00249 if(current == -20)
00250 {
00251 low_division = current_pixel;
00252 }
00253 else
00254 if(current == -5)
00255 {
00256 medium_division = current_pixel;
00257 }
00258 else
00259 if(current == 0)
00260 {
00261 high_division = current_pixel;
00262 }
00263 }
00264
00265
00266
00267 }
00268
00269 void BC_Meter::draw_titles()
00270 {
00271 if(!use_titles) return;
00272
00273 set_font(get_resources()->meter_font);
00274
00275 if(orientation == METER_HORIZ)
00276 {
00277 draw_top_background(parent_window, 0, 0, get_w(), get_title_w());
00278
00279 for(int i = 0; i < db_titles.total; i++)
00280 {
00281 draw_text(0, title_pixels.values[i], db_titles.values[i]);
00282 }
00283
00284 flash(0, 0, get_w(), get_title_w());
00285 }
00286 else
00287 if(orientation == METER_VERT)
00288 {
00289 draw_top_background(parent_window, 0, 0, get_title_w(), get_h());
00290
00291
00292 for(int i = 0; i < db_titles.total; i++)
00293 {
00294 int title_y = pixels -
00295 title_pixels.values[i];
00296 if(i == 0)
00297 title_y -= get_text_descent(SMALLFONT_3D);
00298 else
00299 if(i == db_titles.total - 1)
00300 title_y += get_text_ascent(SMALLFONT_3D);
00301 else
00302 title_y += get_text_ascent(SMALLFONT_3D) / 2;
00303
00304 set_color(get_resources()->meter_font_color);
00305 draw_text(0,
00306 title_y,
00307 db_titles.values[i]);
00308 }
00309
00310 for(int i = 0; i < tick_pixels.total; i++)
00311 {
00312
00313 int tick_y = pixels - tick_pixels.values[i] - METER_MARGIN;
00314 set_color(get_resources()->meter_font_color);
00315 draw_line(get_title_w() - 10 - 1, tick_y, get_title_w() - 1, tick_y);
00316 if(get_resources()->meter_3d)
00317 {
00318 set_color(BLACK);
00319 draw_line(get_title_w() - 10, tick_y + 1, get_title_w(), tick_y + 1);
00320 }
00321 }
00322
00323 flash(0, 0, get_title_w(), get_h());
00324 }
00325 }
00326
00327 int BC_Meter::region_pixel(int region)
00328 {
00329 VFrame **reference_images = get_resources()->xmeter_images;
00330 int result;
00331
00332 if(region == METER_RIGHT)
00333 result = region * reference_images[0]->get_w() / 4;
00334 else
00335 result = region * reference_images[0]->get_w() / 4;
00336
00337 return result;
00338 }
00339
00340 int BC_Meter::region_pixels(int region)
00341 {
00342 int x1;
00343 int x2;
00344 int result;
00345 VFrame **reference_images = get_resources()->xmeter_images;
00346
00347 x1 = region * reference_images[0]->get_w() / 4;
00348 x2 = (region + 1) * reference_images[0]->get_w() / 4;
00349 if(region == METER_MID)
00350 result = (x2 - x1) * 2;
00351 else
00352 result = x2 - x1;
00353 return result;
00354 }
00355
00356 void BC_Meter::draw_face()
00357 {
00358 VFrame **reference_images = get_resources()->xmeter_images;
00359 int level_pixel = level_to_pixel(level);
00360 int peak_pixel2 = level_to_pixel(peak);
00361 int peak_pixel1 = peak_pixel2 - 2;
00362 int left_pixel = region_pixel(METER_MID);
00363 int right_pixel = pixels - region_pixels(METER_RIGHT);
00364 int pixel = 0;
00365 int image_number = 0, region = 0;
00366 int in_span, in_start;
00367 int x = use_titles ? get_title_w() : 0;
00368 int w = use_titles ? this->w - get_title_w() : this->w;
00369
00370 draw_top_background(parent_window, x, 0, w, h);
00371
00372
00373 while(pixel < pixels)
00374 {
00375
00376 if(pixel < level_pixel ||
00377 (pixel >= peak_pixel1 && pixel < peak_pixel2))
00378 {
00379 if(pixel < low_division)
00380 image_number = METER_GREEN;
00381 else
00382 if(pixel < medium_division)
00383 image_number = METER_YELLOW;
00384 else
00385 if(pixel < high_division)
00386 image_number = METER_RED;
00387 else
00388 image_number = METER_WHITE;
00389 }
00390 else
00391 {
00392 image_number = METER_NORMAL;
00393 }
00394
00395
00396 if(pixel < left_pixel)
00397 {
00398 region = METER_LEFT;
00399 in_start = pixel + region_pixel(region);
00400 in_span = region_pixels(region) - (in_start - region_pixel(region));
00401 }
00402 else
00403 if(pixel < right_pixel)
00404 {
00405 region = METER_MID;
00406 in_start = region_pixel(region);
00407 in_span = region_pixels(region);
00408 }
00409 else
00410 {
00411 region = METER_RIGHT;
00412 in_start = (pixel - right_pixel) + region_pixel(region);
00413 in_span = region_pixels(region) - (in_start - region_pixel(region));;
00414 }
00415
00416
00417 if(in_span > 0)
00418 {
00419
00420 if(pixel < level_pixel && pixel + in_span > level_pixel)
00421 in_span = level_pixel - pixel;
00422 else
00423 if(pixel < peak_pixel1 && pixel + in_span > peak_pixel1)
00424 in_span = peak_pixel1 - pixel;
00425 else
00426 if(pixel < peak_pixel2 && pixel + in_span > peak_pixel2)
00427 in_span = peak_pixel2 - pixel;
00428
00429
00430 if(image_number == METER_GREEN && pixel + in_span > low_division)
00431 in_span = low_division - pixel;
00432 else
00433 if(image_number == METER_YELLOW && pixel + in_span > medium_division)
00434 in_span = medium_division - pixel;
00435 else
00436 if(image_number == METER_RED && pixel + in_span > high_division)
00437 in_span = high_division - pixel;
00438
00439
00440 if(pixel < left_pixel && pixel + in_span > left_pixel)
00441 in_span = left_pixel - pixel;
00442 else
00443 if(pixel < right_pixel && pixel + in_span > right_pixel)
00444 in_span = right_pixel - pixel;
00445
00446
00447
00448 if(orientation == METER_HORIZ)
00449 draw_pixmap(images[image_number],
00450 pixel,
00451 x,
00452 in_span + 1,
00453 get_h(),
00454 in_start,
00455 0);
00456 else
00457 draw_pixmap(images[image_number],
00458 x,
00459 get_h() - pixel - in_span,
00460 get_w(),
00461 in_span + 1,
00462 0,
00463 images[image_number]->get_h() - in_start - in_span);
00464
00465 pixel += in_span;
00466 }
00467 else
00468 {
00469
00470 break;
00471 }
00472 }
00473
00474 if(over_timer)
00475 {
00476 if(orientation == METER_HORIZ)
00477 draw_pixmap(images[METER_OVER],
00478 10,
00479 2);
00480 else
00481 draw_pixmap(images[METER_OVER],
00482 x + 2,
00483 get_h() - 100);
00484
00485 over_timer--;
00486 }
00487
00488 if(orientation == METER_HORIZ)
00489 flash(0, 0, pixels, get_h());
00490 else
00491 flash(x, 0, w, pixels);
00492 flush();
00493 }
00494
00495 int BC_Meter::update(float new_value, int over)
00496 {
00497 peak_timer++;
00498
00499 if(mode == METER_DB)
00500 {
00501 if(new_value == 0)
00502 level = min;
00503 else
00504 level = db.todb(new_value);
00505 }
00506
00507 if(level > peak || peak_timer > peak_delay)
00508 {
00509 peak = level;
00510 peak_timer = 0;
00511 }
00512
00513
00514
00515 if(over) over_timer = over_delay;
00516
00517
00518 draw_face();
00519 return 0;
00520 }