Main Page | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Class Members | File Members

bcmeter.C

Go to the documentation of this file.
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 // Which source image to replicate
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 // Region of source image to replicate
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 // calibrate the db titles
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 //printf("BC_Meter::reposition_window 1 %d %d %d %d\n", x, y, w, h);
00124         get_divisions();
00125 
00126 //set_color(WHITE);
00127 //draw_box(0, 0, w, h);
00128 //flash();      
00129 //return 0;
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 // Not implemented anymore
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 // Create tick marks and titles in one pass
00212         for(int current = min; current <= max; current++)
00213         {
00214                 if(orientation == METER_VERT)
00215                 {
00216 // Create tick mark
00217                         current_pixel = (pixels - METER_MARGIN * 2 - 2) * 
00218                                 (current - min) /
00219                                 (max - min) + 2;
00220                         tick_pixels.append(current_pixel);
00221 
00222 // Create titles in selected positions
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 // Titles not supported for horizontal
00246                 }
00247 
00248 // Create color divisions
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 // if(orientation == METER_VERT)
00265 // printf("BC_Meter::get_divisions %d %d %d %d\n",
00266 // low_division, medium_division, high_division, pixels);
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 // Titles
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 // Tick marks
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 //printf("BC_Meter::draw_face %d %d\n", w, h);
00372 
00373         while(pixel < pixels)
00374         {
00375 // Select image to draw
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 // Select region of image to duplicate
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 //printf("BC_Meter::draw_face region %d pixel %d pixels %d in_start %d in_span %d\n", region, pixel, pixels, in_start, in_span);
00417                 if(in_span > 0)
00418                 {
00419 // Clip length to peaks
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 // Clip length to color changes
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 // Clip length to regions
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 //printf("BC_Meter::draw_face image_number %d pixel %d pixels %d in_start %d in_span %d\n", image_number, pixel, pixels, in_start, in_span);
00447 //printf("BC_Meter::draw_face %d %d %d %d\n", orientation, region, images[image_number]->get_h() - in_start - in_span);
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 // Sanity check
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);        // db value
00505         }
00506 
00507         if(level > peak || peak_timer > peak_delay)
00508         {
00509                 peak = level;
00510                 peak_timer = 0;
00511         }
00512 
00513 // if(orientation == METER_HORIZ)
00514 // printf("BC_Meter::update %f\n", level);
00515         if(over) over_timer = over_delay;       
00516 // only draw if window is visible
00517 
00518         draw_face();
00519         return 0;
00520 }

Generated on Sun Jan 8 13:26:32 2006 for Guicast-svn by  doxygen 1.4.4