MOOS 0.2375
|
00001 // ====================================================================== 00002 // File: Flv_Style.cxx - Flv_Style implementation 00003 // Program: Flv_Style - FLTK Virtual List/Table Styles Widget 00004 // Version: 0.1.0 00005 // Started: 11/21/99 00006 // 00007 // Copyright (C) 1999 Laurence Charlton 00008 // 00009 // Description: 00010 // The styles classes are basically defined to make life easier while 00011 // working with styles for the virtual classes. 00012 // ====================================================================== 00013 00014 #include <FL/Fl_Widget.H> 00015 #include "Flv_Style.H" 00016 #include <stdio.h> 00017 #ifdef WIN32 00018 #include <memory.h> 00019 #include <string.h> 00020 #else 00021 #include <memory.h> 00022 #endif 00023 00024 #define ADDSIZE 10 00025 00026 // Flv_Style bits 00027 #define STYLE_DEFINE_FONT 0x0001 00028 #define STYLE_DEFINE_FONT_SIZE 0x0002 00029 #define STYLE_DEFINE_FOREGROUND 0x0004 00030 #define STYLE_DEFINE_BACKGROUND 0x0008 00031 #define STYLE_DEFINE_ALIGN 0x0010 00032 #define STYLE_DEFINE_FRAME 0x0020 00033 #define STYLE_DEFINE_RESIZABLE 0x0040 00034 #define STYLE_DEFINE_HEIGHT 0x0080 00035 #define STYLE_DEFINE_WIDTH 0x0100 00036 #define STYLE_DEFINE_LOCKED 0x0200 00037 #define STYLE_DEFINE_BORDER 0x0400 00038 #define STYLE_DEFINE_BORDER_COLOR 0x0800 00039 #define STYLE_DEFINE_BORDER_SPACING 0x1000 00040 #define STYLE_DEFINE_X_MARGIN 0x2000 00041 #define STYLE_DEFINE_Y_MARGIN 0x4000 00042 #define STYLE_DEFINE_EDITOR 0x8000 00043 00044 #define CLEAR(n) vdefined &= ~(n) 00045 #define DEFINED(n) ((vdefined & (n))!= 0) 00046 #define DEFINED2(v,n) ((v.vdefined & (n))!= 0) 00047 00048 Flv_Style::Flv_Style() 00049 { 00050 vdefined = 0; 00051 vvalue = 0; 00052 // I'm not worried about initializing the rest of the private 00053 // variables since they are undefined. 00054 } 00055 00056 Flv_Style::Flv_Style( int value ) 00057 { 00058 vdefined = 0; 00059 vvalue = value; 00060 // I'm not worried about initializing the rest of the private 00061 // variables since they are undefined. 00062 } 00063 00064 // ================================================================== 00065 // Set drawing alignment 00066 const Fl_Align &Flv_Style::align(const Fl_Align &n) 00067 { 00068 valign = n; 00069 vdefined |= STYLE_DEFINE_ALIGN; 00070 return valign; 00071 } 00072 00073 // Undefine drawing alignment 00074 void Flv_Style::clear_align(void) 00075 { 00076 CLEAR(STYLE_DEFINE_ALIGN); 00077 } 00078 00079 // Is drawing alignment defined? 00080 bool Flv_Style::align_defined(void) const 00081 { 00082 return DEFINED(STYLE_DEFINE_ALIGN); 00083 } 00084 00085 // ================================================================== 00086 // Set background color 00087 Fl_Color Flv_Style::background(Fl_Color n) 00088 { 00089 vbackground = n; 00090 vdefined |= STYLE_DEFINE_BACKGROUND; 00091 return vbackground; 00092 } 00093 00094 // Undefine background color 00095 void Flv_Style::clear_background(void) 00096 { 00097 CLEAR(STYLE_DEFINE_BACKGROUND); 00098 } 00099 00100 // Is background defined? 00101 bool Flv_Style::background_defined(void) const 00102 { 00103 return DEFINED(STYLE_DEFINE_BACKGROUND); 00104 } 00105 00106 00107 // ================================================================== 00108 // Set border 00109 int Flv_Style::border(int n) 00110 { 00111 vborder = (unsigned char)n; 00112 vdefined |= STYLE_DEFINE_BORDER; 00113 return vborder; 00114 } 00115 00116 // Undefine border 00117 void Flv_Style::clear_border(void) 00118 { 00119 CLEAR(STYLE_DEFINE_BORDER); 00120 } 00121 00122 // Is border defined? 00123 bool Flv_Style::border_defined(void) const 00124 { 00125 return DEFINED(STYLE_DEFINE_BORDER); 00126 } 00127 00128 // ================================================================== 00129 // Set border_color 00130 Fl_Color Flv_Style::border_color(Fl_Color n) 00131 { 00132 vborder_color = n; 00133 vdefined |= STYLE_DEFINE_BORDER_COLOR; 00134 return vborder_color; 00135 } 00136 00137 // Undefine border_color 00138 void Flv_Style::clear_border_color(void) 00139 { 00140 CLEAR(STYLE_DEFINE_BORDER_COLOR); 00141 } 00142 00143 // Is border_color defined? 00144 bool Flv_Style::border_color_defined(void) const 00145 { 00146 return DEFINED(STYLE_DEFINE_BORDER_COLOR); 00147 } 00148 00149 00150 // ================================================================== 00151 // Set border_spacing 00152 int Flv_Style::border_spacing(int n) 00153 { 00154 vborder_spacing = (unsigned char)n; 00155 vdefined |= STYLE_DEFINE_BORDER_SPACING; 00156 return vborder_spacing; 00157 } 00158 00159 // Undefine border_spacing 00160 void Flv_Style::clear_border_spacing(void) 00161 { 00162 CLEAR(STYLE_DEFINE_BORDER_SPACING); 00163 } 00164 00165 // Is border_spacing defined? 00166 bool Flv_Style::border_spacing_defined(void) const 00167 { 00168 return DEFINED(STYLE_DEFINE_BORDER_SPACING); 00169 } 00170 00171 // ================================================================== 00172 // Set content editor 00173 Fl_Widget *Flv_Style::editor(Fl_Widget *v) 00174 { 00175 veditor = v; 00176 if (Fl::focus()!=v && veditor) 00177 veditor->hide(); 00178 vdefined |= STYLE_DEFINE_EDITOR; 00179 return veditor; 00180 } 00181 00182 // Undefine border_spacing 00183 void Flv_Style::clear_editor(void) 00184 { 00185 CLEAR(STYLE_DEFINE_EDITOR); 00186 } 00187 00188 // Is border_spacing defined? 00189 bool Flv_Style::editor_defined(void) const 00190 { 00191 return DEFINED(STYLE_DEFINE_EDITOR); 00192 } 00193 00194 // ================================================================== 00195 // Set current font 00196 const Fl_Font &Flv_Style::font(const Fl_Font &n) 00197 { 00198 vfont = n; 00199 vdefined |= STYLE_DEFINE_FONT; 00200 return vfont; 00201 } 00202 00203 // Undefine font 00204 void Flv_Style::clear_font(void) 00205 { 00206 CLEAR(STYLE_DEFINE_FONT); 00207 } 00208 00209 // Is font defined 00210 bool Flv_Style::font_defined(void) const 00211 { 00212 return DEFINED(STYLE_DEFINE_FONT); 00213 } 00214 00215 // ================================================================== 00216 // Set font size 00217 int Flv_Style::font_size(int n) 00218 { 00219 if (n < 1) // Clip at 1 as the smallest font size 00220 n = 1; 00221 vfont_size = n; 00222 vdefined |= STYLE_DEFINE_FONT_SIZE; 00223 return vfont_size; 00224 } 00225 00226 // Undefine font size 00227 void Flv_Style::clear_font_size(void) 00228 { 00229 CLEAR(STYLE_DEFINE_FONT_SIZE); 00230 } 00231 00232 // Is font size defined? 00233 bool Flv_Style::font_size_defined(void) const 00234 { 00235 return DEFINED(STYLE_DEFINE_FONT_SIZE); 00236 } 00237 00238 // ================================================================== 00239 // Set foreground color 00240 Fl_Color Flv_Style::foreground(Fl_Color n) 00241 { 00242 vforeground = n; 00243 vdefined |= STYLE_DEFINE_FOREGROUND; 00244 return vforeground; 00245 } 00246 00247 // Undefine foreground color 00248 void Flv_Style::clear_foreground(void) 00249 { 00250 CLEAR(STYLE_DEFINE_FOREGROUND); 00251 } 00252 00253 // Is foreground defined? 00254 bool Flv_Style::foreground_defined(void) const 00255 { 00256 return DEFINED(STYLE_DEFINE_FOREGROUND); 00257 } 00258 00259 // ================================================================== 00260 // Set frame type 00261 const Fl_Boxtype &Flv_Style::frame(const Fl_Boxtype &n) 00262 { 00263 vframe = n; 00264 vdefined |= STYLE_DEFINE_FRAME; 00265 return vframe; 00266 } 00267 00268 // Undefine frame type 00269 void Flv_Style::clear_frame(void) 00270 { 00271 CLEAR(STYLE_DEFINE_FRAME); 00272 } 00273 00274 // Is frame type defined? 00275 bool Flv_Style::frame_defined(void) const 00276 { 00277 return DEFINED(STYLE_DEFINE_FRAME); 00278 } 00279 00280 // ================================================================== 00281 // Set height 00282 int Flv_Style::height(int n ) 00283 { 00284 if (n < 0) 00285 n = 0; 00286 vdefined |= STYLE_DEFINE_HEIGHT; 00287 return (vheight = n); 00288 } 00289 00290 // Undefine row height 00291 void Flv_Style::clear_height(void) 00292 { 00293 CLEAR(STYLE_DEFINE_HEIGHT); 00294 } 00295 00296 // Is row height defined? 00297 bool Flv_Style::height_defined(void) const 00298 { 00299 return DEFINED(STYLE_DEFINE_HEIGHT); 00300 } 00301 00302 // ================================================================== 00303 // Set locked 00304 bool Flv_Style::locked(bool n) 00305 { 00306 vdefined |= STYLE_DEFINE_LOCKED; 00307 return (vlocked = n); 00308 } 00309 00310 // Undefine locked 00311 void Flv_Style::clear_locked(void) 00312 { 00313 CLEAR(STYLE_DEFINE_LOCKED); 00314 } 00315 00316 // Is locked defined? 00317 bool Flv_Style::locked_defined(void) const 00318 { 00319 return DEFINED(STYLE_DEFINE_LOCKED); 00320 } 00321 00322 // ================================================================== 00323 // Set resizable 00324 bool Flv_Style::resizable(bool n) 00325 { 00326 vresizable = n; 00327 vdefined |= STYLE_DEFINE_RESIZABLE; 00328 return vresizable; 00329 } 00330 00331 // Undefine resizable 00332 void Flv_Style::clear_resizable(void) 00333 { 00334 CLEAR(STYLE_DEFINE_RESIZABLE); 00335 } 00336 00337 // Is resizable defined? 00338 bool Flv_Style::resizable_defined(void) const 00339 { 00340 return DEFINED(STYLE_DEFINE_RESIZABLE); 00341 } 00342 00343 // ================================================================== 00344 // Set column width 00345 int Flv_Style::width(int n) 00346 { 00347 if (n < 0) 00348 n = 0; 00349 vdefined |= STYLE_DEFINE_WIDTH; 00350 return (vwidth = n); 00351 } 00352 00353 // Undefine column width 00354 void Flv_Style::clear_width(void) 00355 { 00356 CLEAR(STYLE_DEFINE_WIDTH); 00357 } 00358 00359 // Is column width defined? 00360 bool Flv_Style::width_defined(void) const 00361 { 00362 return DEFINED(STYLE_DEFINE_WIDTH); 00363 } 00364 00365 // ================================================================== 00366 // Set x margin 00367 int Flv_Style::x_margin(int x) 00368 { 00369 if (x<0) 00370 x=0; 00371 if (x!=vx_margin) 00372 { 00373 vdefined |= STYLE_DEFINE_X_MARGIN; 00374 vx_margin = (unsigned char)x; 00375 } 00376 return vx_margin; 00377 } 00378 00379 // Undefine x margin 00380 void Flv_Style::clear_x_margin(void) 00381 { 00382 CLEAR(STYLE_DEFINE_X_MARGIN); 00383 } 00384 00385 // Is x margin defined 00386 bool Flv_Style::x_margin_defined(void) const 00387 { 00388 return DEFINED(STYLE_DEFINE_X_MARGIN); 00389 } 00390 00391 // ================================================================== 00392 // Set y margin 00393 int Flv_Style::y_margin(int y) 00394 { 00395 if (y<0) 00396 y=0; 00397 if (y!=vy_margin) 00398 { 00399 vdefined |= STYLE_DEFINE_Y_MARGIN; 00400 vy_margin = (unsigned char)y; 00401 } 00402 return vy_margin; 00403 } 00404 00405 // Undefine y margin 00406 void Flv_Style::clear_y_margin(void) 00407 { 00408 CLEAR(STYLE_DEFINE_Y_MARGIN); 00409 } 00410 00411 // Is y margin defined 00412 bool Flv_Style::y_margin_defined(void) const 00413 { 00414 return DEFINED(STYLE_DEFINE_Y_MARGIN); 00415 } 00416 00417 // ================================================================== 00418 // Cumulative assignment operator 00419 // This will only assign portions that are defined. 00420 const Flv_Style &Flv_Style::operator=(const Flv_Style &n) 00421 { 00422 if (n.align_defined()) 00423 align(n.valign); 00424 if (n.background_defined()) 00425 background(n.vbackground); 00426 if (n.border_defined()) 00427 border(n.vborder); 00428 if (n.border_color_defined()) 00429 border_color(n.vborder_color); 00430 if (n.border_spacing_defined()) 00431 border_spacing(n.vborder_spacing); 00432 if (n.editor_defined()) 00433 editor(n.veditor); 00434 if (n.font_defined()) 00435 font(n.vfont); 00436 if (n.font_size_defined()) 00437 font_size(n.vfont_size); 00438 if (n.foreground_defined()) 00439 foreground(n.vforeground); 00440 if (n.frame_defined()) 00441 frame(n.vframe); 00442 if (n.height_defined()) 00443 height(n.vheight); 00444 if (n.locked_defined()) 00445 locked(n.vlocked); 00446 if (n.resizable_defined()) 00447 resizable(n.vresizable); 00448 if (n.width_defined()) 00449 width(n.vwidth); 00450 if (n.x_margin_defined()) 00451 x_margin(n.vx_margin); 00452 if (n.y_margin_defined()) 00453 y_margin(n.vy_margin); 00454 00455 00456 // I'm not copying value because it seems meaningless in every context 00457 // I can think of. 00458 00459 // I'm not copying cell_style either for the same reason. It just seems like 00460 // a REALLY bad idea. 00461 return *this; 00462 } 00463 00464 // ********************************************************************** 00465 // Routines for Flv_Style_List 00466 // 00467 // Implemented as a dynamic sparse array 00468 // ********************************************************************** 00469 Flv_Style_List::Flv_Style_List() 00470 { 00471 list = NULL; 00472 vcount = vallocated = vcurrent = 0; 00473 } 00474 00475 void Flv_Style_List::compact(void) 00476 { 00477 int n, t; 00478 00479 // Release memory for any dead items 00480 for (t=0; t<vcount; t++ ) 00481 { 00482 list[t]->cell_style.compact(); // Compact cells! 00483 if (list[t]->cell_style.count()==0 && list[t]->all_clear()) 00484 { 00485 delete list[t]; 00486 list[t] = NULL; 00487 } 00488 } 00489 // Compact list now 00490 for (t=n=0; t<vcount; t++ ) 00491 { 00492 if (list[t]) 00493 list[n++] = list[t]; 00494 else if (vcurrent<=t && vcurrent>0) 00495 vcurrent--; 00496 } 00497 00498 // Make list easy to view, wasted CPU cycles 00499 for (t=n; t<vcount; t++ ) 00500 list[t] = NULL; 00501 00502 vcount = n; // Update count 00503 00504 if (!vcount && list) 00505 { 00506 delete []list; 00507 list = NULL; 00508 vcount = vcurrent = vallocated = 0; 00509 } 00510 } 00511 // Undefine all styles in list 00512 void Flv_Style_List::clear(void) 00513 { 00514 int t; 00515 00516 for (t=0; t<vcount; t++ ) // Make all entries clear 00517 list[t]->clear_all(); 00518 compact(); // Remove dead space thats left 00519 } 00520 00521 // Free memory for all (including cell 00522 void Flv_Style_List::release(void) 00523 { 00524 int t; 00525 for (t = 0; t < vcount; t++ ) 00526 { 00527 list[t]->cell_style.release(); 00528 delete list[t]; 00529 } 00530 if (list) 00531 delete []list; 00532 list = NULL; 00533 vcurrent = vcount = vallocated = 0; 00534 } 00535 00536 Flv_Style *Flv_Style_List::current(void) // Current node 00537 { 00538 if (!list) 00539 return NULL; 00540 return list[vcurrent]; 00541 } 00542 00543 // Find closest match 00544 // It will find the first value >= n 00545 Flv_Style *Flv_Style_List::find( int n ) 00546 { 00547 int t, l, h; 00548 00549 if (!list || vcount == 0) // If list is empty, there will be no matches 00550 return NULL; 00551 00552 // How a about a nice binary search? It will be slower for sequential 00553 // processing and a small number of styles, but worlds faster as the 00554 // number of styles increases. Use skip_to for sequential processing 00555 // and find for random access. 00556 l = 0; 00557 h = vcount-1; 00558 while (l+1 < h) 00559 { 00560 vcurrent = (l+h) / 2; 00561 t = list[vcurrent]->value(); 00562 if (t == n) 00563 return list[vcurrent]; 00564 else if (t < n) 00565 l = vcurrent; 00566 else 00567 h = vcurrent; 00568 } 00569 00570 // This needs cleaning, I fairly certain there's way too much logic here 00571 // While this will work, I think we only need to check one of the values 00572 // but I've been wrong before... :) 00573 vcurrent = l; 00574 t = list[vcurrent]->value(); 00575 if (t == n) 00576 return list[vcurrent]; 00577 if (t < n && vcurrent < vcount-1) 00578 { 00579 vcurrent=h; 00580 t = list[vcurrent]->value(); 00581 if (t == n) 00582 return list[vcurrent]; 00583 } 00584 return NULL; 00585 } 00586 00587 Flv_Style *Flv_Style_List::first(void) // Get first style 00588 { 00589 if (!list) 00590 return NULL; 00591 vcurrent = 0; 00592 return list[vcurrent]; 00593 } 00594 00595 bool Flv_Style_List::insert( Flv_Style *n ) // Add style (if doesn't exist) 00596 { 00597 int t; 00598 // Make sure there is room for a new item 00599 if (vcount == vallocated) 00600 { 00601 Flv_Style **a = new Flv_Style *[vallocated+ADDSIZE]; 00602 if (!a) 00603 return false; 00604 // Wasted CPU cycles, but list is pretty 00605 memset( a, 0, sizeof(Flv_Style *)*(vallocated+ADDSIZE) ); 00606 if (vcount) 00607 memcpy( a, list, sizeof(Flv_Style *)*vcount ); 00608 vallocated += ADDSIZE; 00609 if (list) 00610 delete []list; 00611 list = a; 00612 } 00613 00614 if (vcount) 00615 { 00616 find(n->value()); // Point to insert candidate 00617 if (n->value()==list[vcurrent]->value()) // No duplicates 00618 return false; 00619 if (n->value()>list[vcurrent]->value()) // Insert at end of list 00620 vcurrent++; 00621 } 00622 00623 00624 // Make room for insert if not appending 00625 for (t=vcount; t>vcurrent; t-- ) 00626 list[t] = list[t-1]; 00627 00628 list[vcurrent] = n; 00629 vcount++; 00630 return true; 00631 } 00632 00633 Flv_Style *Flv_Style_List::next(void) // Next style 00634 { 00635 if (!list || vcurrent >= vcount-1) 00636 return NULL; 00637 00638 vcurrent++; 00639 return list[vcurrent]; 00640 } 00641 00642 Flv_Style *Flv_Style_List::prior(void) 00643 { 00644 00645 if (!vcurrent || !list) 00646 return 0; 00647 vcurrent--; 00648 return list[vcurrent]; 00649 } 00650 00651 bool Flv_Style_List::clear_current(void) 00652 { 00653 if (!list) 00654 return false; 00655 00656 if (list[vcurrent]->cell_style.count() == 0) 00657 return release_current(); 00658 list[vcurrent]->clear_all(); 00659 return true; 00660 } 00661 00662 bool Flv_Style_List::release_current(void) // Remove current style 00663 { 00664 if (!list) 00665 return false; 00666 00667 delete list[vcurrent]; 00668 if (vcurrent < vcount-1) 00669 { 00670 memmove(list+vcurrent, list+vcurrent+1, sizeof(Flv_Style *)*(vcount-vcurrent) ); 00671 vcount--; 00672 list[vcount] = NULL; 00673 } 00674 if (vcurrent == vcount) 00675 vcurrent--; 00676 00677 return true; 00678 } 00679 00680 // From n skip up to value v 00681 Flv_Style *Flv_Style_List::skip_to( int v ) 00682 { 00683 int c; 00684 00685 if (!list || !vcount) 00686 return NULL; 00687 00688 // In case we're backing up or starting over 00689 // We're checking vcurrent-1 so if the last search found 00690 // an entry > the desired value, and this search isn't quite 00691 // to the last found value, we don't want to start over, just 00692 // stay where we are. 00693 // Style 1, 2, 3, 7 & 10 defined 00694 // search for 4 (current points to 7) returns false 00695 // search for 5 (stay at seven since 3 is < value, return false) 00696 // If we started at 0 we'd end up here anyway... :) 00697 // search for 7 (stay at seven, we'll find it quick, return true) 00698 if (vcurrent) 00699 { 00700 if (list[vcurrent-1]->value() >= v) 00701 vcurrent = 0; 00702 } 00703 00704 for (; vcurrent < vcount; vcurrent++ ) 00705 { 00706 c = list[vcurrent]->value(); 00707 if (c == v) 00708 return list[vcurrent]; 00709 else if (c > v) 00710 return NULL; 00711 } 00712 vcurrent--; 00713 return NULL; 00714 } 00715 00716 // Note: this could be a little wierd since it's actually returning 00717 // the style with value 'value' instead of list index 'value' 00718 // Plus: it's going to define the style if it doesn't already exist! 00719 // 00720 // If you don't want extraneous styles getting inserted, be sure to 00721 // use the find operator first. (I.e. If your reading a style value 00722 // and the style didn't previously exist, all the style information 00723 // will be undefined! 00724 Flv_Style &Flv_Style_List::operator[](int value) 00725 { 00726 Flv_Style *p; 00727 00728 if (find(value)) // If it exists 00729 return *(list[vcurrent]); // return it 00730 00731 p = new Flv_Style; 00732 p->value(value); 00733 insert(p); 00734 return *p; 00735 } 00736