MOOS 0.2375
/home/toby/moos-ivp/MOOS-2375-Oct0611/Thirdparty/FLTKVW/Flv_List.cxx
Go to the documentation of this file.
00001 //      ======================================================================
00002 //      File:    Flv_List.cxx - Flv_List implementation
00003 //      Program: Flv_List - FLTK List Widget
00004 //      Version: 0.1.0
00005 //      Started: 11/21/99
00006 //
00007 //      Copyright (C) 1999 Laurence Charlton
00008 //
00009 //      Description:
00010 //      Flv_List implements a scrollable list.  No data is stored
00011 //      in the widget.  Supports headers/footers, natively supports a single
00012 //      row height per list.    Row grids can be turned on and off.  Supports
00013 //      no scroll bars as well as horizontal/vertical automatic or always
00014 //      on scroll bars.
00015 //      Uses absolute row references.
00016 //
00017 //      row -1 is defined as the row header
00018 //      row -2 is defined as the row footer
00019 //
00020 // This library is free software; you can redistribute it and/or
00021 // modify it under the terms of the GNU Library General Public
00022 // License as published by the Free Software Foundation; either
00023 // version 2 of the License, or (at your option) any later version.
00024 //
00025 // This library is distributed in the hope that it will be useful,
00026 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00027 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00028 // Library General Public License for more details.
00029 //
00030 // You should have received a copy of the GNU Library General Public
00031 // License along with this library; if not, write to the Free Software
00032 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00033 // USA.
00034 //
00035 // Please report all bugs and problems to "lcharlto@mail.coin.missouri.edu"
00036 //      ======================================================================
00037 
00038 
00039 
00040 
00041 #include "Flv_List.H"
00042 #include <FL/fl_draw.H>
00043 #include <FL/Fl_Output.H>
00044 #include <stdio.h>
00045 
00046 #define DOcb(x) ((vcallback_when & (x))==(x))
00047 
00048 //      Resizing constants
00049 #define FUDGE 2
00050 #define MOVE_X 1
00051 #define MOVE_Y 2
00052 #define MOVE_XY (MOVE_X|MOVE_Y)
00053 
00054 static void vscrollbar_cb(Fl_Widget* o, void*)
00055 {
00056         Flv_List *s = (Flv_List *)(o->parent());
00057         s->top_row( ((Fl_Scrollbar *)o)->value() );
00058         s->damage(FL_DAMAGE_CHILD);
00059 //      s->select_start_row( ((Fl_Scrollbar *)o)->value() );
00060 }
00061 
00062 static void hscrollbar_cb(Fl_Widget* o, void*)
00063 {
00064         Flv_List *s = (Flv_List *)(o->parent());
00065         s->row_offset( ((Fl_Scrollbar *)o)->value() );
00066 }
00067 
00068 Flv_List::Flv_List( int X, int Y, int W, int H, const char *l ) :
00069         Fl_Group(X,Y,W,H,l),
00070         scrollbar(0,0,0,0,0),
00071         hscrollbar(0,0,0,0,0)
00072 {
00073         int r, rh;
00074 
00075         edit_row=-1;
00076 #ifdef FLTK_2
00077         style(Fl_Output::default_style);
00078 #else
00079         box(FL_THIN_DOWN_BOX);
00080 #endif
00081         fl_font( text_font(), text_size() );
00082         fl_measure("X", r, rh );
00083 
00084 //      Leave global_style & row_style undefined
00085 //      get_default_style(global_style);
00086 
00087         if (parent())
00088                 vdead_space_color = parent()->color();
00089         else
00090                 vdead_space_color = FL_GRAY;
00091 
00092         scrollbar.callback(vscrollbar_cb);
00093         hscrollbar.callback(hscrollbar_cb);
00094         hscrollbar.type(FL_HORIZONTAL);
00095 
00096         vclicks = 0;
00097         vmax_clicks = 2;                                                                //      Double click the most
00098         vcallback_when = 0xffff;                                //      All Events
00099         veditor = NULL;
00100         vediting = false;
00101         vedit_when = FLV_EDIT_MANUAL;
00102   vwhy_event = 0;
00103         vfeature = FLVF_PERSIST_SELECT;
00104         vhas_scrollbars = FLVS_BOTH;
00105         vlast_row = 0;
00106         vrow = 0;
00107         vrow_offset = 0;
00108         vrow_width = 0;
00109         vrows = 0;
00110         vrows_per_page = 0;
00111         vscrollbar_width = 17;
00112         vselect_locked = true;
00113         vselect_row = 0;
00114         vtop_row = 0;
00115 
00116         end();                                                                  //      Don't put other widgets in this one.
00117 }
00118 
00119 Flv_List::~Flv_List()
00120 {
00121         row_style.release();            //      Free any memory allocated
00122 }
00123 
00124 //================================================================
00125 //      Virtual functions
00126 //================================================================
00127 void Flv_List::save_editor( Fl_Widget *, int , int )
00128 {
00129 }
00130 
00131 void Flv_List::load_editor( Fl_Widget *, int , int )
00132 {
00133 }
00134 
00135 void Flv_List::position_editor( Fl_Widget *e, int x, int y, int w, int h, Flv_Style & )
00136 {
00137         e->resize( x, y, w, h );
00138 }
00139 
00140 //      Draw a single row
00141 void Flv_List::draw_row( int Offset, int &X, int &Y, int &W, int &H, int R )
00142 {
00143         Fl_Boxtype bt;
00144         Flv_Style s;
00145 
00146         get_style( s, R );                                              //      Guaranteed to fill in style
00147         if (Fl::focus()==this || persist_select())
00148                 add_selection_style( s, R );    //      Add selection coloring if applicable
00149   if (row_divider())
00150         s.border( s.border()|FLVB_BOTTOM );     //      Be sure bottom is on
00151 
00152         X -= Offset;
00153   
00154   draw_border(s,X,Y,W,H);
00155         bt = s.frame();
00156 
00157   fl_color( s.background() );
00158   fl_rectf(X,Y,W,H );
00159 #ifdef FLTK_2
00160         bt->draw(X,Y,W,H,s.background());
00161         bt->inset( X, Y, W, H );
00162 #else
00163         draw_box( bt, X, Y, W, H, s.background() );
00164         X+= (Fl::box_dx(bt));
00165         Y+= (Fl::box_dy(bt));
00166         W-= (Fl::box_dw(bt));
00167         H-= (Fl::box_dh(bt));
00168 #endif
00169         if (R==row() && (Fl::focus()==this || persist_select()))
00170         {
00171                 fl_color( fl_contrast(FL_BLACK,selection_color()) );
00172                 fl_rect( X, Y, W, H);
00173         }
00174         X+=s.x_margin();
00175         Y+=s.y_margin();
00176         W-=s.x_margin()*2;
00177         H-=s.y_margin()*2;
00178 
00179         fl_font( s.font(), s.font_size() );
00180         if (!active())
00181                 s.foreground( fl_inactive(s.foreground()) );
00182         fl_color( s.foreground() );
00183   X += Offset;
00184         if (R==-3)                                                                              //      Draw title
00185                 fl_draw(label(), X, Y, W, H, s.align() );
00186 }
00187 
00188 //      Handle events
00189 int Flv_List::handle(int event)
00190 {
00191         int t, x, y;
00192         bool bs;
00193 
00194         bs = (vselect_row!=vrow);
00195         switch( event )
00196         {
00197                 case FL_DEACTIVATE:
00198                 case FL_HIDE:
00199                 case FL_LEAVE:
00200                 case FL_ENTER:
00201                 case FL_ACTIVATE:
00202                 case FL_SHOW:
00203                         return 1;
00204 
00205                 case FL_MOVE:
00206                         check_cursor();
00207                         Fl_Group::handle(event);
00208                         return 1;
00209                 case FL_FOCUS:
00210                         Fl::focus(this);
00211                         damage(FL_DAMAGE_CHILD);
00212                         Fl_Group::handle(event);
00213                         return 1;
00214                 case FL_UNFOCUS:
00215                         damage(FL_DAMAGE_CHILD);
00216                         Fl_Group::handle(event);
00217                         return 1;
00218                 case FL_KEYBOARD:
00219                         break;
00220                 case FL_RELEASE:
00221                         Fl_Group::handle(event);
00222                         return 1;
00223                 case FL_DRAG:
00224                         if (check_resize())
00225                                 return 1;
00226                 case FL_PUSH:
00227                         Fl::focus(this);
00228                         damage(FL_DAMAGE_CHILD);
00229                         x = Fl::event_x();
00230                         y = Fl::event_y();
00231                         t = get_row( x, y );
00232 
00233                         //      Row header clicked
00234                         if (t<0)
00235                         {
00236                                 vwhy_event = 0;
00237                                 switch( t )
00238                                 {
00239                                         case -3:
00240                                                 if (DOcb(FLVEcb_TITLE_CLICKED))
00241                                                         vwhy_event = FLVE_TITLE_CLICKED;
00242                                                 break;
00243                                         case -2:
00244                                                 if (DOcb(FLVEcb_ROW_FOOTER_CLICKED))
00245                                                         vwhy_event = FLVE_ROW_FOOTER_CLICKED;
00246                                                 break;
00247                                         case -1:
00248                                                 if (DOcb(FLVEcb_ROW_HEADER_CLICKED))
00249                                                         vwhy_event = FLVE_ROW_HEADER_CLICKED;
00250                                                 break;
00251                                 }
00252                                 if (vwhy_event)
00253                                 {
00254                                         do_callback(this, user_data());
00255                                         vwhy_event = 0;
00256                                 }
00257                                 Fl_Group::handle(event);
00258                                 return 1;
00259                         }
00260                         row(t);
00261 
00262                         if (!multi_select() ||
00263                                         (event==FL_PUSH && !Fl::event_state(FL_SHIFT)))
00264                         {
00265                                 if (bs)
00266                                         vlast_row = vrow;
00267                                 if (vselect_row!=vrow)
00268                                         select_start_row( vrow );
00269                         }
00270                         if (event==FL_PUSH)
00271                         {
00272                                 if (DOcb(FLVEcb_CLICKED))
00273                                 {
00274                                         vwhy_event = FLVE_CLICKED;
00275                                         do_callback(this, user_data());
00276                                         vwhy_event = 0;
00277                                 }
00278                         }
00279                         Fl_Group::handle(event);
00280                         return 1;
00281 
00282                 default:
00283                         return Fl_Group::handle(event);
00284         }
00285 
00286         switch(Fl::event_key())
00287         {
00288 
00289                 case FL_Up:
00290                         if (Fl::event_state(FL_CTRL))
00291                         {
00292                                 if (vrow>0)
00293                                         row(0);
00294                         } else
00295                                 row(vrow-1);
00296                         break;
00297 
00298                 case FL_Down:
00299                         if (Fl::event_state(FL_CTRL))
00300                         {
00301                                 if (vrow<vrows-1)
00302                                         row( vrows-1 );
00303                         } else
00304                         {
00305                                 if (vrow<vrows-1)
00306                                         row (vrow+1);
00307                         }
00308                         break;
00309 
00310                 case FL_Page_Down:
00311                         if (Fl::event_state(FL_CTRL))
00312                         {
00313                                 if (vrow<vrows-1)
00314                                         row(vrows-1);
00315                         } else
00316                         {
00317                                 if (vrow<vrows-1)
00318                                         row(vrow+page_size());
00319                         }
00320                         break;
00321 
00322                 case FL_Page_Up:
00323                         if (Fl::event_state(FL_CTRL))
00324                         {
00325                                 if (vrow>0)
00326                                         row(0);
00327                         } else
00328                                 row( vrow-page_size() );
00329                         break;
00330 
00331                 case FL_Right:
00332                         row_offset(vrow_offset+10);
00333                         break;
00334 
00335                 case FL_Left:
00336                         row_offset(vrow_offset-10);
00337                         break;
00338 
00339                 default:
00340                         return Fl_Group::handle(event);
00341         }
00342         if (!multi_select())
00343         {
00344                 if (bs)
00345                         vlast_row = vrow;
00346                 if (vselect_row!=vrow)
00347                         select_start_row(vrow);
00348         }
00349         if (!Fl::event_state(FL_SHIFT) && vselect_row!=vrow)
00350                 select_start_row(vrow);
00351         Fl_Group::handle(event);
00352         return 1;
00353 }
00354 
00355 int Flv_List::row_height( int r )
00356 {
00357         int rh, x;
00358         Flv_Style *rows;
00359 
00360         if (!global_style.height_defined())
00361         {
00362                 fl_font( text_font(), text_size() );
00363                 fl_measure("X", x, rh );
00364         } else
00365                 rh = global_style.height();
00366         if (r<0)
00367                 rh += 4;
00368         rows = row_style.find(r);
00369         if (rows)
00370                 if (rows->height_defined())
00371                         rh = rows->height();
00372         return rh;
00373 }
00374 
00375 //      H is set to height of drawn row not including any grids
00376 int Flv_List::row_height( int n, int r )
00377 {
00378         if (r>-4 && r<rows())
00379                 row_style[r].height(n);
00380         return row_height(r);
00381         //      Note: this is only the constant value, if row_height(r) is a calculated
00382         //      value, it's the only way we can really determine row height.
00383         //      Don't rely on the value of this function, ALWAYS call row_height(r)
00384 }
00385 
00386 int Flv_List::get_row( int x, int y )
00387 {
00388         int X, Y, W, H;
00389         int rh, rw, t, CY;
00390 
00391         //      Determine if row was clicked and highlight it
00392         client_area(X,Y,W,H);
00393         if (label())
00394         {
00395                 rh = row_height(-3);
00396                 if (Y<=y && y<=Y+rh)
00397                         return -3;
00398                 Y+=rh;
00399                 H-=rh;
00400         }
00401         if (row_header())
00402         {
00403                 rh = row_height(-1);
00404                 if (Y<=y && y<=Y+rh)
00405                         return -1;
00406                 Y+=rh;
00407                 H-=rh;
00408         }
00409         if (row_footer())
00410         {
00411                 rh = row_height(-2);
00412                 if (Y+H>=y && y>Y+H-rh)
00413                         return -2;
00414                 H -= rh;
00415         }
00416         rw = row_width();
00417         if (!rw)
00418                 rw = W;
00419         if ( x<X || x>X+W || y<Y || y>=Y+H || x>X-vrow_offset+rw)
00420                 return -4;                              //      Out of bounds
00421 
00422         for (CY=Y, t=vtop_row;  t<vrows && CY<Y+H;      t++, CY+=rh )
00423         {
00424                 rh = row_height(t);     
00425                 if (CY<=y && y<=CY+rh)
00426                         return t;
00427         }
00428         return -4;              //      In grey area?
00429 }
00430 
00431 //      get trickle down style
00432 void Flv_List::get_style(Flv_Style &s, int R, int )
00433 {
00434         Flv_Style *rows;
00435 
00436         get_default_style(s);                           //      Get default style information
00437         s = global_style;                                               //      Add global style information
00438 
00439 
00440         rows = row_style.skip_to(R);
00441         if (rows) s = *rows;                            //      Add row style information
00442         if (R<0)                                                                                //      Headers/Labels have different default
00443         {                           //  Note: we can still override at cell level
00444                 if (parent())
00445                         s.background( parent()->color() );
00446                 else
00447                         s.background( FL_WHITE );
00448                 s.frame(FL_THIN_UP_BOX);
00449                 s.border( FLVB_NONE );
00450     s.border_spacing(0);
00451         }
00452         if (R==-3)                                                                      //      If title use label information
00453         {
00454                 s.font(label_font());
00455                 s.font_size(label_size());
00456                 s.foreground( label_color() );
00457                 s.align(FL_ALIGN_CLIP);
00458         }
00459         if (rows && R<0)
00460   {
00461                 rows = rows->cell_style.skip_to(0);
00462           if (rows && R<0)
00463           s = *rows;
00464   }
00465 }
00466 
00467 Flv_Feature Flv_List::feature(Flv_Feature v)
00468 {
00469         if (v!=vfeature)
00470         {
00471                 vfeature = v;
00472                 vlast_row = vrow;                                       //      Redraw all!
00473                 if (DOcb(FLVEcb_FEATURE_CHANGED))
00474                 {
00475                         vwhy_event = FLVE_FEATURE_CHANGED;
00476                         do_callback(this, user_data());
00477                         vwhy_event = 0;
00478                 }
00479                 damage(FL_DAMAGE_CHILD);        //      Because features are visible
00480         }
00481         return vfeature;
00482 }
00483 
00484 Flv_Feature Flv_List::feature_add(Flv_Feature v)
00485 {
00486         if ( (vfeature&v)!=v )
00487         {
00488                 vfeature |= v;
00489                 if (DOcb(FLVEcb_FEATURE_CHANGED))
00490                 {
00491                         vwhy_event = FLVE_FEATURE_CHANGED;
00492                         do_callback(this, user_data());
00493                         vwhy_event = 0;
00494                 }
00495                 damage(FL_DAMAGE_CHILD);        //      Because features are visible
00496         }
00497         return vfeature;
00498 }
00499 
00500 Flv_Feature Flv_List::feature_remove(Flv_Feature v)
00501 {
00502         if ( (vfeature&v)!=0 )
00503         {
00504                 vfeature &= (Flv_Feature)(~v);
00505                 if (DOcb(FLVEcb_FEATURE_CHANGED))
00506                 {
00507                         vwhy_event = FLVE_FEATURE_CHANGED;
00508                         do_callback(this, user_data());
00509                         vwhy_event = 0;
00510                 }
00511                 damage(FL_DAMAGE_CHILD);        //      Because features are visible
00512         }
00513         return vfeature;
00514 }
00515 
00516 Flv_ShowScrollbar Flv_List::has_scrollbar( Flv_ShowScrollbar v )
00517 {
00518         if (v!=vhas_scrollbars)
00519         {
00520                 vhas_scrollbars = v;
00521                 damage(FL_DAMAGE_CHILD);
00522         }
00523         return vhas_scrollbars;
00524 }
00525 
00526 int Flv_List::edit_when( int v )
00527 {
00528         if (v!=vedit_when)
00529         {
00530                 vedit_when = v;
00531                 if (vedit_when!=FLV_EDIT_ALWAYS)
00532                         end_edit();
00533                 else
00534                         start_edit();
00535         }
00536         return vedit_when;
00537 }
00538 
00539 int Flv_List::bottom_row(void)
00540 {
00541         int r, rh;
00542         int X, Y, W, H, B;
00543 
00544         client_area( X, Y, W, H );
00545         B = Y + H;
00546 
00547         for ( r=vtop_row; Y<B && r<vrows; r++, Y+=rh )
00548                 rh = row_height(r);
00549         if (r==vrows)
00550                 r = vrows-1;
00551         return r;
00552 }
00553 
00554 int Flv_List::row(int n)
00555 {
00556         int X, Y, W, H;
00557         if (n>=vrows)
00558                 n=vrows-1;
00559         if (n<0)
00560                 n=0;
00561         if (n!=vrow)
00562         {
00563                 vrow = n;
00564                 client_area(X,Y,W,H);
00565                 update_top_row(H);
00566                 vlast_row = vrow;
00567                 if (DOcb(FLVEcb_ROW_CHANGED))
00568                 {
00569                         vwhy_event = FLVE_ROW_CHANGED;
00570                         do_callback(this, user_data());
00571                         vwhy_event = 0;
00572                 }
00573                 damage(FL_DAMAGE_CHILD);
00574         }
00575         return vrow;
00576 }
00577 
00578 bool Flv_List::row_resizable( int r )                                   //      Get/Set row locked status
00579 {
00580         Flv_Style s;
00581         get_style(s,r);
00582         return s.resizable();
00583 }
00584 
00585 bool Flv_List::row_resizable( bool n, int r )
00586 {
00587         row_style[r].resizable(n);
00588         return n;
00589 }
00590 
00591 int Flv_List::row_offset( int n )
00592 {
00593         if (n>vrow_width)
00594                 n = vrow_width;
00595         if (n<0)
00596                 n = 0;
00597         if (n!=vrow_offset)
00598         {
00599                 vrow_offset = n;
00600                 vlast_row = vrow;                       //      Make sure we draw everything
00601                 damage(FL_DAMAGE_CHILD);
00602         }
00603         return vrow_offset;
00604 }
00605 
00606 int Flv_List::rows(int n)
00607 {
00608         if (n>=0 && n!=vrows)
00609         {
00610                 vrows = n;
00611                 if (vrow>=vrows)
00612                         row(vrows-1);
00613                 if (vselect_row>vrow)
00614                         select_start_row(vrow);
00615                 if (DOcb(FLVEcb_ROW_CHANGED))
00616                 {
00617                         vwhy_event = FLVE_ROW_CHANGED;
00618                         do_callback(this, user_data());
00619                         vwhy_event = 0;
00620                 }
00621                 damage(FL_DAMAGE_CHILD);
00622         }
00623         return vrows;
00624 }
00625 
00626 int Flv_List::rows_per_page( int n )
00627 {
00628         if (n!=vrows_per_page && n>=0)
00629                 vrows_per_page = n;
00630         return vrows_per_page;
00631 }
00632 
00633 bool Flv_List::row_selected( int n )
00634 {
00635         if (vselect_row<vrow)
00636                 return (vselect_row<=n && n<=vrow);
00637         else
00638                 return (vrow<=n && n<=vselect_row);
00639 }
00640 
00641 int Flv_List::row_width( int n )
00642 {
00643         if (n>=0 && n!=vrow_width)
00644         {
00645                 vrow_width = n;
00646                 damage(FL_DAMAGE_CHILD);
00647         }
00648         return vrow_width;
00649 }
00650 
00651 int Flv_List::scrollbar_width(int n)
00652 {
00653         if (n!=vscrollbar_width && n>0)
00654         {
00655                 vscrollbar_width = n;
00656                 damage(FL_DAMAGE_CHILD);
00657         }
00658         return vscrollbar_width;
00659 }
00660 
00661 int Flv_List::select_start_row(int n)                   //      Set first selected row
00662 {
00663         if (n>=vrows)   n=vrows-1;
00664         if (n<0) n=0;
00665         if (n!=vselect_row)
00666         {
00667                 vselect_row = n;
00668                 vlast_row = vrow;
00669                 if (DOcb(FLVEcb_SELECTION_CHANGED))
00670                 {
00671                         vwhy_event = FLVE_SELECTION_CHANGED;
00672                         do_callback(this, user_data());
00673                         vwhy_event = 0;
00674                 }
00675                 damage(FL_DAMAGE_CHILD);
00676         }
00677         return vselect_row;
00678 }
00679 
00680 //================================================================
00681 //      Protected functions
00682 //================================================================
00683 void Flv_List::client_area( int &X, int &Y, int &W, int &H )
00684 {
00685         char sv=0, sh=0;
00686         int th, v, rw;
00687 
00688         X = x(); Y = y(); W = w(); H = h();
00689 #ifdef FLTK_2
00690         box()->inset(X,Y,W,H);
00691 #else
00692         Fl_Boxtype b = box();
00693         X += Fl::box_dx(b);
00694         Y += Fl::box_dy(b);
00695         W -= Fl::box_dw(b);
00696         H -= Fl::box_dh(b);
00697 #endif
00698 
00699         rw = vrow_width;
00700         if (rw==0) rw = W;
00701 
00702         if ( (vhas_scrollbars & FLVS_HORIZONTAL_ALWAYS)==FLVS_HORIZONTAL_ALWAYS)
00703                 sh = 1;
00704         else if ( (vhas_scrollbars & FLVS_HORIZONTAL)==FLVS_HORIZONTAL )
00705         {
00706                 if (vrow_width!=0)
00707                 {
00708                         if (rw>W)
00709                                 sh=1;
00710                         else if (rw>W-vscrollbar_width)
00711                                 sh=-1;  //      Turn on if rows won't fit
00712                 }
00713         }
00714         //      We need total height
00715         if ( (vhas_scrollbars & FLVS_VERTICAL_ALWAYS)==FLVS_VERTICAL_ALWAYS )
00716                 sv = 1;
00717         else if ( (vhas_scrollbars & FLVS_VERTICAL)==FLVS_VERTICAL )
00718         {
00719                 th = (label()?row_height(-3):0);
00720                 th += (row_header()?row_height(-1):0);
00721                 th += (row_footer()?row_height(-2):0);
00722                 for (v=0;       th<=H && v<rows();      v++ )
00723                         th += row_height(v);
00724                 if ( th>H)
00725                         sv = 1;
00726                 else if ( th > H-vscrollbar_width )
00727                         sv = -1;        //      Turn on if width in region
00728         }
00729         if (sh<0 && sv>0) sh=1; // Extends to scrollbar obscured region so turn on
00730         if (sv<0 && sh>0) sv=1; // Extends to scrollbar obscured region so turn on
00731 
00732         if (sv>0) W-=vscrollbar_width;
00733         if (sh>0) H-=vscrollbar_width;
00734 }
00735 
00736 void Flv_List::draw_border(Flv_Style &s, int &X, int &Y, int &W, int &H )
00737 {
00738         int t;
00739 
00740   //    Draw outer border if defined
00741         fl_color( s.border_color() );
00742         if (s.left_border())
00743         fl_yxline(X, Y, Y+H-1);
00744   if (s.right_border())
00745         fl_yxline(X+W-1, Y, Y+H-1 );
00746   if (s.left_border())
00747   {
00748         X++;
00749     W--;
00750   }
00751   if (s.right_border())
00752         W--;
00753 
00754   if (s.top_border())
00755                 fl_xyline(X, Y, X+W-1 );
00756   if (s.bottom_border())
00757         fl_xyline(X, Y+H-1, X+W-1 );
00758         if (s.top_border())
00759   {
00760         Y++;
00761     H--;
00762   }
00763   if (s.bottom_border())
00764         H--;
00765 
00766   //    Draw spacing between borders
00767         fl_color( color() );
00768   for (t=0;     t<s.border_spacing();   t++ )
00769   {
00770 
00771                 fl_rect( X, Y, W, H );
00772     if (s.left_border())
00773     {
00774             X++;
00775       W--;
00776                 }
00777     if (s.right_border())
00778         W--;
00779                 if (s.top_border())
00780     {
00781             Y++;
00782       H--;
00783     }
00784     if (s.bottom_border())
00785         H--;
00786   }
00787 
00788   //    Draw inner border if defined
00789         fl_color( s.border_color() );
00790         if (s.inner_left_border())
00791         fl_yxline(X, Y, Y+H-1);
00792   if (s.inner_right_border())
00793         fl_yxline(X+W-1, Y, Y+H-1 );
00794   if (s.inner_left_border())
00795   {
00796         X++;
00797                 W--;
00798   }
00799   if (s.inner_right_border())
00800                 W--;
00801 
00802   if (s.inner_top_border())
00803         fl_xyline(X, Y, X+W-1 );
00804   if (s.inner_bottom_border())
00805         fl_xyline(X, Y+H-1, X+W-1 );
00806   if (s.inner_top_border())
00807   {
00808         Y++;
00809     H--;
00810   }
00811   if (s.inner_bottom_border())
00812         H--;
00813 }
00814 
00815 //      Determine if scrollbars are visible/position and draw
00816 //      them if nessasary, also update X,Y,W,H to be inside box
00817 void Flv_List::draw_scrollbars(int &X, int &Y, int &W, int &H )
00818 {
00819         char sv=0, sh=0;
00820         int th, x, rw;
00821 
00822 
00823         rw = vrow_width;
00824         if (rw==0) rw = W;
00825 
00826         if ( (vhas_scrollbars & FLVS_HORIZONTAL_ALWAYS)==FLVS_HORIZONTAL_ALWAYS)
00827                 sh = 1;
00828         else if ( (vhas_scrollbars & FLVS_HORIZONTAL)==FLVS_HORIZONTAL )
00829         {
00830                 if (vrow_width!=0)
00831                 {
00832                         if (rw>W)
00833                                 sh=1;
00834                         else if (rw>W-vscrollbar_width)
00835                                 sh=-1;  //      Turn on if rows won't fit
00836                 }
00837         }
00838         //      We need total height
00839         if ( (vhas_scrollbars & FLVS_VERTICAL_ALWAYS)==FLVS_VERTICAL_ALWAYS )
00840                 sv = 1;
00841         else if ( (vhas_scrollbars & FLVS_VERTICAL)==FLVS_VERTICAL )
00842         {
00843                 th = (label()?row_height(-3):0);
00844                 th += (row_header()?row_height(-1):0);
00845                 th += (row_footer()?row_height(-2):0);
00846                 for (x=0;       th<=H && x<rows();      x++ )
00847                         th += row_height(x);
00848                 if ( th>H)
00849                         sv = 1;
00850                 else if ( th > H-vscrollbar_width )
00851                         sv = -1;        //      Turn on if width in region
00852         }
00853         if (sh<0 && sv>0) sh=1; // Extends to scrollbar obscured region so turn on
00854         if (sv<0 && sh>0) sv=1; // Extends to scrollbar obscured region so turn on
00855 
00856         if (sv>0) W-=vscrollbar_width;
00857         if (sh>0) H-=vscrollbar_width;
00858 
00859         //      Place scrollbars where they should be
00860         if (sv>0)
00861         {
00862                 scrollbar.damage_resize(X+W,Y,vscrollbar_width,H);
00863                 scrollbar.value( top_row(), page_size()+1,      0, vrows );     //      Fake out page size
00864                 scrollbar.linesize( 1 );
00865                 scrollbar.minimum(0);
00866                 scrollbar.maximum(vrows-1);
00867                 x = H - (vrows*2) - vscrollbar_width*2;
00868                 if (x<vscrollbar_width) x = vscrollbar_width;
00869 #ifdef FLTK_2
00870                 scrollbar.slider_size(x);
00871 #else
00872                 scrollbar.slider_size((double)((double)x/(double)(H-vscrollbar_width*2)));
00873 #endif
00874                 scrollbar.Fl_Valuator::value( top_row() );      //      , 1,    0, vrows );
00875                 if (!scrollbar.visible())
00876                         scrollbar.set_visible();
00877                 draw_child(scrollbar);
00878         } else
00879                 scrollbar.clear_visible();
00880 
00881 
00882         if (rw-vrow_offset<W && rw>W)
00883         {
00884                 vrow_offset = rw - W;
00885                 vlast_row = vrow;       //      Make sure we update the entire widget
00886         }
00887 
00888         if (sh>0)
00889         {
00890                 hscrollbar.damage_resize(X,Y+H,W,vscrollbar_width);
00891                 hscrollbar.value( vrow_offset, 50,      0, vrow_width );        //      Fake out page size
00892                 hscrollbar.linesize( 10 );
00893                 hscrollbar.minimum(0);
00894                 hscrollbar.maximum(vrow_width-W);
00895 #ifdef FLTK_2
00896                 x = W - vrow_width/10 - vscrollbar_width*2;
00897                 if (x<vscrollbar_width) x = vscrollbar_width;
00898                 hscrollbar.slider_size(x);
00899 #else
00900                 x = vrow_width / 10;
00901                 hscrollbar.slider_size( (double)((double)x/(double)(W-vscrollbar_width*2)));
00902 #endif
00903                 hscrollbar.Fl_Valuator::value( vrow_offset );   //      , 1,    0, vrows );
00904                 if (!hscrollbar.visible())
00905                         hscrollbar.set_visible();
00906                 draw_child(hscrollbar);
00907         } else
00908                 hscrollbar.clear_visible();
00909 
00910         if (sh>0 && sv>0)       //      Draw box at ends
00911         {
00912                 if (parent())
00913                         fl_color( parent()->color() );
00914                 else
00915                         fl_color( FL_WHITE );
00916                 fl_rectf( X+W, Y+H, vscrollbar_width, vscrollbar_width );
00917         }
00918 }
00919 
00920 void Flv_List::update_top_row(int H)
00921 {
00922         int rh, r;
00923 
00924         if (vrow<vtop_row)
00925         {
00926                 vtop_row = vrow;
00927                 vlast_row = vrow;       //      Make sure we update the entire widget
00928         } else
00929         {
00930                 if (label())
00931                         H -= row_height(-3);
00932                 if (row_header())
00933                         H -= row_height(-1);
00934                 if (row_footer())
00935                         H -= row_height(-2);
00936                 for (r=vtop_row;        r<=vrow && r<vrows;     r++, H-=rh )
00937                 {
00938                         rh = row_height(r);
00939                         if (rh>H)
00940                                 break;
00941                 }
00942                 if (r<=vrow)            //      Move top row down, so we can see current line
00943                 {
00944                         vlast_row = vrow;       //      Make sure we update the entire widget
00945                         for( ;  r<=vrow;        r++, H -= rh )
00946                         {
00947                                 rh = row_height(r);
00948                                 vtop_row++;
00949                         }
00950                 }
00951                 //      If there're visible rows below the current row
00952 //              if (rh<H)
00953 //              {
00954 //                      //      Finish computing visible rows
00955 //                      for (;  r<vrows;        r++, H-=rh )
00956 //                      {
00957 //                              rh = row_height(r);
00958 //                              if (rh>H)
00959 //                                      break;
00960 //                      }
00961 //              }
00962 //              //      Do we need to move the top row up?
00963 //              if (rh<H)
00964 //              {
00965 //                      //      Too much space at bottom, we need to move top row toward 0
00966 //                      //      If possible.
00967 //                      vlast_row = vrow;       //      Make sure we update the entire widget
00968 //                      for (; vtop_row>0; vtop_row--, H -= rh )
00969 //                      {
00970 //                              rh = row_height(vtop_row);
00971 //                              if (rh>H)
00972 //                                      break;
00973 //                      }
00974 //              }
00975         }
00976 }
00977 
00978 void Flv_List::start_draw(int &X, int &Y, int &W, int &H, int &trow_width )
00979 {
00980         int rh, CX, CY, CW, CH;
00981         label_type(FL_NO_LABEL);
00982 
00983         if (damage()&FL_DAMAGE_ALL)
00984         {
00985 #ifdef FLTK_2
00986                 draw_frame();
00987 #else
00988                 draw_box();
00989 #endif
00990         }
00991 
00992 
00993         //      Get dimension inside box
00994         X = x(); Y = y(); W = w(); H = h();
00995 #ifdef FLTK_2
00996         box()->inset(X,Y,W,H);
00997 #else
00998         Fl_Boxtype b = box();
00999         X += Fl::box_dx(b);
01000         Y += Fl::box_dy(b);
01001         W -= Fl::box_dw(b);
01002         H -= Fl::box_dh(b);
01003 #endif
01004 
01005         draw_scrollbars( X, Y, W, H );  // Place/set values, update bounding box
01006 
01007         trow_width = vrow_width;
01008         if (!trow_width)
01009                 trow_width = W;
01010 
01011         //      Update top row if nessasary
01012 //      update_top_row(H);
01013 
01014         //      Draw Title
01015         if (label())
01016         {
01017                 rh = row_height(-3);
01018                 fl_clip( X, Y, W, rh );
01019     CX=X;       CY=Y;   CW=W;   CH=rh;
01020                 Flv_List::draw_row( 0, CX, CY, CW, CH, -3);
01021                 fl_pop_clip();
01022                 Y += rh;
01023                 H -= rh;
01024         }
01025 
01026         //      Draw header if visible
01027         if (row_header())
01028         {
01029                 rh = row_height(-1);
01030                 fl_clip( X, Y, W, rh );
01031     CX=X;       CY=Y;   CW=trow_width;  CH=rh;
01032                 draw_row( vrow_offset, CX, CY, CW, CH, -1);
01033                 fl_pop_clip();
01034                 Y += rh;
01035                 H -= rh;
01036         }
01037         //      Draw footer
01038         if (row_footer())
01039         {
01040                 rh = row_height(-2);
01041                 H -=rh;
01042                 fl_clip( X, Y+H, W, rh );
01043     CX=X;       CY=Y+H; CW=trow_width;  CH=rh;
01044                 draw_row( vrow_offset, CX, CY, CW, CH, -2 );
01045                 fl_pop_clip();
01046         }
01047 }
01048 
01049 //      Perform actual draw function
01050 void Flv_List::draw()
01051 {
01052         int r, rh, rw;
01053         int X, Y, W, H, B;
01054         int CX, CY, CW, CH;
01055         Flv_Style s;
01056 
01057         //      Initially verify we aren't on a locked cell
01058         r = row();
01059         while(!select_locked())
01060         {
01061                 get_style(s,r);
01062                 if (!s.locked())
01063                 {
01064                         row(r);
01065                         break;
01066                 }
01067                 r++;
01068                 if (r==rows())
01069                         break;
01070         }
01071         //      Make sure we have an editor if editing!
01072         if (vediting && !veditor)
01073                 switch_editor(row());
01074 
01075         start_draw(X,Y,W,H,rw);
01076 
01077         B = W-(rw-vrow_offset);
01078         //      Fill-in area at right of list
01079         if (B>0)
01080         {
01081                 fl_color( dead_space_color() );
01082     CY = Y;     CH = H;
01083     if (row_header())
01084     {
01085         CY -= row_height(-1);
01086       CH += row_height(-1);
01087     }
01088     if (row_footer())
01089         CH += row_height(-2);
01090                 fl_rectf( X+rw-vrow_offset, CY, B, CH );
01091         }
01092 
01093         B = Y + H;
01094         fl_clip( X, Y, W, H );
01095         //      Draw rows
01096         for (   r=vtop_row;     Y<B && r<vrows; r++, Y+=rh )
01097         {
01098                 rh = row_height(r);
01099                 if ( vlast_row==vrow || (vlast_row!=vrow && (r==vlast_row || r==vrow)) )
01100                 {
01101                         fl_clip( X, Y, rw, rh);
01102             CX=X;       CY=Y;   CW=rw;  CH=rh;
01103                         draw_row( vrow_offset, CX, CY, CW, CH, r );
01104                         fl_pop_clip();
01105                 }
01106         }
01107         vlast_row = vrow;
01108 
01109         //      Fill-in area at bottom of list
01110         if (Y<B)
01111         {
01112                 fl_color( dead_space_color() );
01113                 fl_rectf( X, Y, W, B-Y );
01114         }
01115         fl_pop_clip();
01116 }
01117 
01118 int Flv_List::page_size(void)
01119 {
01120         int ps, H;
01121 
01122         if (vrows_per_page)
01123                 ps = vrows_per_page;
01124         else
01125         {
01126                 H = h() - 2 * vscrollbar_width;
01127                 ps=11;
01128                 if (H)
01129                         ps=(H/row_height(0));
01130                 ps--;
01131                 if (ps<1)
01132                   ps=1;
01133         }
01134         return ps;
01135 }
01136 
01137 bool Flv_List::move_row( int amount )
01138 {
01139         int r = row();
01140         Flv_Style s;
01141 
01142         r += amount;
01143         if (r>=rows())
01144                 r = rows()-1;
01145         if (r<0)
01146                 r = 0;
01147 
01148         while(!select_locked())
01149         {
01150                 get_style(s,r);
01151                 if (!s.locked())
01152                         break;
01153                 r += (amount<0?-1:1);
01154                 if ( r<0 || r>=rows() )
01155                         return false;
01156         }
01157         if (r!=row())
01158         {
01159                 row(r);
01160                 return true;
01161         }
01162         return false;
01163 }
01164 
01165 void Flv_List::get_default_style( Flv_Style &s )
01166 {
01167         int r, rh;
01168 
01169         //      Make sure EVERY feature is defined
01170         s.align(FL_ALIGN_LEFT);
01171 #ifdef FLTK_2
01172         s.background(color());
01173 #else
01174         s.background(FL_WHITE);
01175 #endif
01176         s.border(FLVB_NONE);
01177         if (parent())
01178                 s.border_color(parent()->color());
01179         else
01180                 s.border_color(FL_WHITE);
01181         s.border_spacing(0);
01182         s.editor(NULL);                                                         //      No editor
01183         s.font(text_font());
01184         s.font_size(text_size());
01185         s.foreground(text_color());
01186         s.frame(FL_FLAT_BOX);
01187 
01188         fl_font( text_font(), text_size() );
01189         fl_measure("X", r, rh );
01190         s.height(rh);
01191         s.locked(true);
01192         s.resizable(false);
01193         s.width(40);
01194   s.x_margin(2);
01195   s.y_margin(1);
01196 }
01197 
01198 void Flv_List::add_selection_style( Flv_Style &s, int R, int  )
01199 {
01200         if (!multi_select())            //      If not multi row selection
01201                 select_start_row( row() );
01202 
01203         //      Handle row selection
01204         if (row_selected(R))
01205         {
01206                         s.background( selection_color() );
01207                         s.foreground( fl_contrast( text_color(), selection_color() ) );
01208         }
01209 }
01210 
01211 static Fl_Cursor last_cursor = FL_CURSOR_DEFAULT;
01212 static int drag_row=-4, anchor_top;
01213 
01214 bool Flv_List::check_resize(void)
01215 {
01216         int ey, h;
01217         bool w=false;
01218 
01219         ey = Fl::event_y();
01220 
01221         if (drag_row>-4)
01222         {
01223                 if (drag_row==-2)
01224                 {
01225                         h = anchor_top - ey + row_height(drag_row);
01226                         if (h>1)
01227                         {
01228                                 row_style[drag_row].height(h);
01229                                 damage(FL_DAMAGE_CHILD);
01230                                 anchor_top = ey;
01231                                 w = true;
01232                         }
01233                 } else
01234                 {
01235                         h = ey-anchor_top;
01236                         if (h<1) h=1;
01237                         row_style[drag_row].height(h);
01238                         damage(FL_DAMAGE_CHILD);
01239                         w=true;
01240                 }
01241         }
01242         return w;
01243 }
01244 
01245 //      See if we can resize, if so change cursor
01246 void Flv_List::check_cursor(void)
01247 {
01248         int X, Y, W, H, ey, move=0, WW, size;
01249         int v;
01250         Fl_Cursor cursor;
01251 
01252         ey = Fl::event_y();
01253         client_area(X,Y,W,H);
01254 
01255         if (label() && *label())
01256         {
01257                 Y+=row_height(-3);
01258                 H-=row_height(-3);
01259         }
01260 
01261 //      if (full_resize())      //      Trival test first
01262         {
01263                 if (row_header())
01264                 {
01265                         size = row_height(-1);
01266                         if (ey>=Y+size-FUDGE && ey<=Y+size+FUDGE)
01267                         {
01268                                 if (row_resizable(-1))
01269                                 {
01270                                         drag_row = -1;
01271                                         anchor_top = Y;
01272                                         move |= MOVE_Y;         //      Moving
01273                                 }
01274                         }
01275                         Y += size;
01276                         H -= size;
01277                 }
01278                 if (row_footer())
01279                 {
01280                         size = row_height(-2);
01281                         if (ey>=Y+H-size-FUDGE && ey<=Y+H-size+FUDGE)
01282                         {
01283                                 if (row_resizable(-2))
01284                                 {
01285                                         drag_row = -2;
01286                                         anchor_top = ey;
01287                                         move |= MOVE_Y;         //      Moving
01288                                 }
01289                         }
01290                         H -= size;
01291                 }
01292 
01293                 if ((move & MOVE_Y)==0)
01294                 {
01295                         WW = Y;
01296                         for (v=top_row();       v<rows();       WW+=size, v++ )
01297                         {
01298                                 size = row_height(v);
01299                                 if (WW+size+FUDGE>=Y+H)
01300                                         break;
01301                                 if (ey>=WW+size-FUDGE && ey<=WW+size+FUDGE)
01302                                 {
01303                                         if (row_resizable(v))
01304                                         {
01305                                                 drag_row = v;
01306                                                 anchor_top = WW;
01307                                                 move |= MOVE_Y;         //      Moving
01308                                         }
01309                                         break;
01310                                 }
01311                         }
01312                 }
01313         }
01314 
01315         switch( move )
01316         {
01317                 case MOVE_Y:    cursor = FL_CURSOR_NS;                  break;
01318                 default:
01319                         drag_row = -4;
01320                         cursor = FL_CURSOR_DEFAULT;
01321                         break;
01322         }
01323         if (cursor!=last_cursor)
01324         {
01325                 fl_cursor(cursor,FL_BLACK,FL_WHITE);
01326                 last_cursor = cursor;
01327         }
01328 }
01329 
01330 void Flv_List::end_edit(void)
01331 {
01332         switch_editor(-1);
01333 }
01334 
01335 void Flv_List::start_edit(void)                                                                                 //      Start editing
01336 {
01337         if (!vediting)
01338         {
01339                 vediting = true;
01340                 switch_editor( row() );
01341         }
01342 }
01343 
01344 void Flv_List::cancel_edit(void)                                                                                        //      Cancel editing
01345 {
01346         if (veditor)
01347                 veditor->hide();
01348         veditor = NULL;
01349         edit_row = -1;
01350         if (edit_when()!=FLV_EDIT_ALWAYS)
01351                 vediting = false;
01352         switch_editor( row() );
01353 }
01354 
01355 void Flv_List::switch_editor( int nr )
01356 {
01357         Flv_Style s;
01358 
01359         if (veditor)
01360         {
01361                 if (edit_row>-1)
01362                         save_editor( veditor, edit_row );
01363                 edit_row = -1;
01364                 veditor->hide();
01365                 veditor = NULL;
01366         }
01367         if (edit_when()==FLV_EDIT_ALWAYS)
01368                 vediting = true;
01369         if (nr && vediting )
01370         {
01371                 get_style( s, nr );
01372                 if (s.editor_defined() && !s.locked())
01373                 {
01374                         veditor = s.editor();
01375                         if (veditor)
01376                         {
01377                                 edit_row = nr;
01378                                 load_editor( veditor, nr );
01379                                 veditor->damage(FL_DAMAGE_ALL);
01380                                 veditor->hide();
01381                                 veditor->show();
01382                                 Fl::focus(veditor);
01383                         }
01384                 }
01385         }
01386         if (veditor && veditor->parent()!=this)
01387                 veditor->parent(this);
01388 }
01389 
01390 #ifdef FLTK_2
01391 //================================================================
01392 //      Style stuff?
01393 //================================================================
01394 static void revert(Fl_Style* s) {
01395         s->selection_color = FL_BLUE_SELECTION_COLOR;
01396         s->selection_text_color = FL_WHITE;
01397         s->off_color = FL_BLACK;
01398         s->box = FL_THIN_DOWN_BOX;
01399         s->color = FL_GRAY_RAMP+1;
01400 }
01401 
01402 Fl_Style* Flv_List::default_style =
01403                 new Fl_Named_Style("Browser", revert, &Flv_List::default_style);
01404 #endif
01405 
01406 
01407 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines