示例#1
0
// Resize FLTK override
//     Handle resize events if user resizes parent window.
//
void Fl_Table::resize(int X, int Y, int W, int H)
{
    // Tell group to resize, and recalc our own widget as well
    Fl_Group::resize(X, Y, W, H);
    table_resized();
    redraw();
}
示例#2
0
// Set number of cols
void Fl_Table_Copy::cols(int val) {
  _cols = val;
  {
    int default_w = ( _colwidths.size() > 0 ) ? _colwidths[_colwidths.size()-1] : 80;
    int now_size = _colwidths.size();
    _colwidths.size(val);			// enlarge or shrink as needed
    while ( now_size < val ) {
      _colwidths[now_size++] = default_w;	// fill new
    }
  }
  table_resized();
  redraw();
}
示例#3
0
// Set number of cols
void Fl_Table::cols(int val)
{
    _cols = val;
    {
	int default_w = ( _colwidths.size() > 0 ) ? _colwidths[_colwidths.size()-1] : 80;
	while ( val > (int)_colwidths.size() )
	    { _colwidths.push_back(default_w); }	// enlarge
	while ( val < (int)_colwidths.size() )
	    { _colwidths.pop_back(); }			// shrink
    }
    table_resized();
    redraw();
}
示例#4
0
// Set height of a row
void Fl_Table::row_height(int row, int height)
{
    if ( row < 0 ) return;
    if ( row < (int)_rowheights.size() && _rowheights[row] == height ) 
        { return; }		// OPTIMIZATION: no change? avoid redraw
    // Add row heights, even if none yet
    while ( row >= (int)_rowheights.size() )
        { _rowheights.push_back(height); }
    _rowheights[row] = height;
    table_resized();
    if ( row <= botrow )	// OPTIMIZATION: only redraw if onscreen or above screen
	{ redraw(); }

    // ROW RESIZE CALLBACK
    if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED )
	{ do_callback(CONTEXT_RC_RESIZE, row, 0); }
}
示例#5
0
// Set number of rows
void Fl_Table::rows(int val)
{
    int oldrows = _rows;
    _rows = val;
    {
	int default_h = ( _rowheights.size() > 0 ) ? _rowheights.back() : 25;
	while ( val > (int)_rowheights.size() )
	    { _rowheights.push_back(default_h); }	// enlarge
	while ( val < (int)_rowheights.size() )
	    { _rowheights.pop_back(); }			// shrink
    }
    table_resized();

    // OPTIMIZATION: redraw only if change is visible.
    if ( val >= oldrows && oldrows > botrow )
        { /* NO REDRAW */ }
    else
        { redraw(); }
}
示例#6
0
// Set width of a column
void Fl_Table::col_width(int col, int width)
{
    if ( col < 0 ) return;
    if ( col < (int)_colwidths.size() && _colwidths[col] == width ) 
        { return; }		// OPTIMIZATION: no change? avoid redraw

    // Add column widths, even if none yet
    while ( col >= (int)_colwidths.size() )
        { _colwidths.push_back(width); }

    _colwidths[col] = width;
    table_resized();
    if ( col <= rightcol )	// OPTIMIZATION: only redraw if onscreen or to the left
	{ redraw(); }

    // COLUMN RESIZE CALLBACK
    if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED )
	{ do_callback(CONTEXT_RC_RESIZE, 0, col); }
}
示例#7
0
// Set number of rows
void Fl_Table_Copy::rows(int val) {
  int oldrows = _rows;
  _rows = val;
  {
    int default_h = ( _rowheights.size() > 0 ) ? _rowheights.back() : 25;
    int now_size = _rowheights.size();
    _rowheights.size(val);			// enlarge or shrink as needed
    while ( now_size < val ) {
      _rowheights[now_size++] = default_h;	// fill new
    }
  }
  table_resized();
  
  // OPTIMIZATION: redraw only if change is visible.
  if ( val >= oldrows && oldrows > botrow ) {
    // NO REDRAW
  } else {
    redraw();
  }
}
示例#8
0
// Set width of a column
void Fl_Table_Copy::col_width(int col, int width)
{
  if ( col < 0 ) return;
  if ( col < (int)_colwidths.size() && _colwidths[col] == width ) {
    return;			// OPTIMIZATION: no change? avoid redraw
  }
  // Add column widths, even if none yet
  int now_size = (int)_colwidths.size();
  if ( col >= now_size ) {
    _colwidths.size(col+1);
    while (now_size < col) {
      _colwidths[now_size++] = width;
    }
  }
  _colwidths[col] = width;
  table_resized();
  if ( col <= rightcol ) {	// OPTIMIZATION: only redraw if onscreen or to the left
    redraw();
  }
  // COLUMN RESIZE CALLBACK
  if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) {
    do_callback(CONTEXT_RC_RESIZE, 0, col);
  }
}
示例#9
0
// Ctor
Fl_Table_Copy::Fl_Table_Copy(int X, int Y, int W, int H, const char *l) : Fl_Group(X,Y,W,H,l) {
  _rows             = 0;
  _cols             = 0;
  _row_header_w     = 40;
  _col_header_h     = 18;
  _row_header       = 0;
  _col_header       = 0;
  _row_header_color = color();
  _col_header_color = color();
  _row_resize       = 0;
  _col_resize       = 0;
  _row_resize_min   = 1;
  _col_resize_min   = 1;
  _redraw_toprow    = -1;
  _redraw_botrow    = -1;
  _redraw_leftcol   = -1;
  _redraw_rightcol  = -1;
  table_w           = 0;
  table_h           = 0;
  toprow            = 0;
  botrow            = 0;
  leftcol           = 0;
  rightcol          = 0;
  toprow_scrollpos  = -1;
  leftcol_scrollpos = -1;
  _last_cursor      = FL_CURSOR_DEFAULT;
  _resizing_col     = -1;
  _resizing_row     = -1;
  _dragging_x       = -1;
  _dragging_y       = -1;
  _last_row         = -1;
  _auto_drag        = 0;
  current_col	    = -1;
  current_row       = -1;
  select_row        = -1;
  select_col        = -1;
#if FLTK_ABI_VERSION >= 10301
  _scrollbar_size   = 0;
#endif  
#if FLTK_ABI_VERSION >= 10303
  flags_            = 0;	// TABCELLNAV off
#endif
  
  //MK
  _showVScrollbar = true;
  
  box(FL_THIN_DOWN_FRAME);
  
  vscrollbar = new Fl_Scrollbar(x()+w()-Fl::scrollbar_size(), y(),
                                Fl::scrollbar_size(), h()-Fl::scrollbar_size());
  vscrollbar->type(FL_VERTICAL);
  vscrollbar->callback(scroll_cb, (void*)this);
  
  hscrollbar = new Fl_Scrollbar(x(), y()+h()-Fl::scrollbar_size(),
                                w(), Fl::scrollbar_size());
  hscrollbar->type(FL_HORIZONTAL);
  hscrollbar->callback(scroll_cb, (void*)this);
  
  table = new Fl_Scroll(x(), y(), w(), h());
  table->box(FL_NO_BOX);
  table->type(0);		// don't show Fl_Scroll's scrollbars -- use our own
  table->hide();		// hide unless children are present
  table->end();
  
  table_resized();
  redraw();
  
  Fl_Group::end();		// end the group's begin()
  
  table->begin();		// leave with fltk children getting added to the scroll
}
示例#10
0
// Handle FLTK events
int Fl_Table_Copy::handle(int event) {
  PRINTEVENT;
  int ret = Fl_Group::handle(event);	// let FLTK group handle events first
  // Which row/column are we over?
  int R, C;  				// row/column being worked on
  ResizeFlag resizeflag;		// which resizing area are we over? (0=none)
  TableContext context = cursor2rowcol(R, C, resizeflag);
  if (ret) {
    if (Fl::event_inside(hscrollbar) || Fl::event_inside(vscrollbar)) return 1;
    if ( context != CONTEXT_ROW_HEADER &&		// mouse not in row header (STR#2742)
         context != CONTEXT_COL_HEADER &&		// mouse not in col header (STR#2742)
         Fl::focus() != this && 			// we don't have focus?
         contains(Fl::focus())) {			// focus is a child?
      return 1;
    }
  }
  // Make snapshots of realtime event states *before* we service user's cb,
  // which may do things like post popup menus that return with unexpected button states.
  int _event_button = Fl::event_button();
  int _event_clicks = Fl::event_clicks();
  int _event_x      = Fl::event_x();
  int _event_y      = Fl::event_y();
  int _event_key    = Fl::event_key();
#if FLTK_ABI_VERSION >= 10303
  int _event_state  = Fl::event_state();
#endif
  Fl_Widget *_focus = Fl::focus();
  switch ( event ) {
    case FL_PUSH:
      // Single left-click on table? do user's callback with CONTEXT_TABLE
      if (_event_button == 1 && !_event_clicks) {
        if (_focus == this) {
          take_focus();
          do_callback(CONTEXT_TABLE, -1, -1);
          ret = 1;
        }
        damage_zone(current_row, current_col, select_row, select_col, R, C);
        if (context == CONTEXT_CELL) {
          current_row = select_row = R;
          current_col = select_col = C;
          _selecting = CONTEXT_CELL;
        } else {
	  // Clear selection if not resizing row/col
	  if ( !resizeflag ) {
            current_row = select_row = -1;
            current_col = select_col = -1;
	  }
        }
      }
      // A click on table with user's callback defined?
      //     Need this for eg. right click to pop up a menu
      //
      if ( Fl_Widget::callback() &&		// callback defined?
          resizeflag == RESIZE_NONE ) {		// not resizing?
        do_callback(context, R, C);		// do callback with context (cell, header, etc)
      }
      // Handle selection if handling a left-click
      //    Use snapshot of _event_button we made before servicing user's cb's
      //    to avoid checking realtime state of buttons which may have changed
      //    during the user's callbacks.
      //
      switch ( context ) {
        case CONTEXT_CELL:
          // FL_PUSH on a cell?
          ret = 1;				// express interest in FL_RELEASE
          break;
          
        case CONTEXT_NONE:
          // FL_PUSH on table corner?
          if ( _event_button == 1 && _event_x < x() + row_header_width()) {
            current_col = 0;
            select_col = cols() - 1;
            current_row = 0;
            select_row = rows() - 1;				
            damage_zone(current_row, current_col, select_row, select_col);
            ret = 1;
          }
          break;
          
        case CONTEXT_COL_HEADER:
          // FL_PUSH on a column header?
          if ( _event_button == 1) {
            // Resizing? Handle it
            if ( resizeflag ) {
              // Start resize if left click on column border.
              //    "ret=1" ensures we get drag events from now on.
              //    (C-1) is used if mouse is over the left hand side 
              //    of cell, so we resize the next column on the left.
              //
              _resizing_col = ( resizeflag & RESIZE_COL_LEFT ) ? C-1 : C; 
              _resizing_row = -1;
              _dragging_x = _event_x;
              ret = 1;
            } else {
              // Not resizing? Select the column
	      if ( Fl::focus() != this && contains(Fl::focus()) ) return 0;	// STR #3018 - item 1
              current_col = select_col = C;
              current_row = 0;
              select_row = rows() - 1;
              _selecting = CONTEXT_COL_HEADER;
              damage_zone(current_row, current_col, select_row, select_col);
              ret = 1;
            }
          }
          break;
          
        case CONTEXT_ROW_HEADER:
          // FL_PUSH on a row header?
          if ( _event_button == 1 ) {
            // Resizing? Handle it
            if ( resizeflag ) {
              // Start resize if left mouse clicked on row border.
              //    "ret = 1" ensures we get drag events from now on.
              //    (R-1) is used if mouse is over the top of the cell,
              //    so that we resize the row above.
              //
              _resizing_row = ( resizeflag & RESIZE_ROW_ABOVE ) ? R-1 : R; 
              _resizing_col = -1;
              _dragging_y = _event_y; 
              ret = 1;
            } else {
              // Not resizing? Select the row
	      if ( Fl::focus() != this && contains(Fl::focus()) ) return 0;	// STR #3018 - item 1
              current_row = select_row = R;
              current_col = 0;
              select_col = cols() - 1;
              _selecting = CONTEXT_ROW_HEADER;
              damage_zone(current_row, current_col, select_row, select_col);
              ret = 1;
            }
          }
          break;
          
        default:
          ret = 0;		// express disinterest
          break;
      }
      _last_row = R;
      break;
      
    case FL_DRAG:
      if (_auto_drag == 1) {
        ret = 1;
        break;
      } 
      if ( _resizing_col > -1 ) {
        // Dragging column?
        //
        //    Let user drag even /outside/ the row/col widget.
        //    Don't allow column width smaller than 1.
        //    Continue to show FL_CURSOR_WE at all times during drag.
        //
        int offset = _dragging_x - _event_x;
        int new_w = col_width(_resizing_col) - offset;
        if ( new_w < _col_resize_min ) new_w = _col_resize_min;
        col_width(_resizing_col, new_w);
        _dragging_x = _event_x;
        table_resized();
        redraw();
        change_cursor(FL_CURSOR_WE);
        ret = 1;
        if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) {
          do_callback(CONTEXT_RC_RESIZE, R, C);
        }
      }
      else if ( _resizing_row > -1 ) {
        // Dragging row?
        //
        //    Let user drag even /outside/ the row/col widget.
        //    Don't allow row width smaller than 1.
        //    Continue to show FL_CURSOR_NS at all times during drag.
        //
        int offset = _dragging_y - _event_y;
        int new_h = row_height(_resizing_row) - offset;
        if ( new_h < _row_resize_min ) new_h = _row_resize_min;
        row_height(_resizing_row, new_h);
        _dragging_y = _event_y;
        table_resized();
        redraw();
        change_cursor(FL_CURSOR_NS);
        ret = 1;
        if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED ) {
          do_callback(CONTEXT_RC_RESIZE, R, C);
        }
      } else {
        if (_event_button == 1 && 
            _selecting == CONTEXT_CELL &&
            context == CONTEXT_CELL) {
          // Dragging a cell selection?
	  if ( _event_clicks ) break;			// STR #3018 - item 2
          if (select_row != R || select_col != C) {
            damage_zone(current_row, current_col, select_row, select_col, R, C);
          }
          select_row = R;
          select_col = C;
          ret = 1;
        }
        else if (_event_button == 1 && 
                 _selecting == CONTEXT_ROW_HEADER && 
                 context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) {
          if (select_row != R) {
            damage_zone(current_row, current_col, select_row, select_col, R, C);
          }
          select_row = R;
          ret = 1;
        }
        else if (_event_button == 1 && 
                 _selecting == CONTEXT_COL_HEADER 
                 && context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) {
          if (select_col != C) {
            damage_zone(current_row, current_col, select_row, select_col, R, C);
          }
          select_col = C;
          ret = 1;
        }
      }
      // Enable autodrag if not resizing, and mouse has moved off table edge
      if ( _resizing_row < 0 && _resizing_col < 0 && _auto_drag == 0 && 
          ( _event_x > x() + w() - 20 ||
            _event_x < x() + row_header_width() || 
            _event_y > y() + h() - 20 ||
            _event_y < y() + col_header_height()
           ) ) {
            _start_auto_drag();
          }
      break;
      
    case FL_RELEASE:
      _stop_auto_drag();
      switch ( context ) {
        case CONTEXT_ROW_HEADER:		// release on row header
        case CONTEXT_COL_HEADER:		// release on col header
        case CONTEXT_CELL:			// release on a cell
        case CONTEXT_TABLE:			// release on dead zone
          if ( _resizing_col == -1 &&		// not resizing a column
              _resizing_row == -1 &&		// not resizing a row
              Fl_Widget::callback() && 		// callback defined
              when() & FL_WHEN_RELEASE && 	// on button release
              _last_row == R ) {		// release on same row PUSHed?
            // Need this for eg. left clicking on a cell to select it
            do_callback(context, R, C);
          }
          break;
          
        default:
          break;
      }
      if ( _event_button == 1 ) {
        change_cursor(FL_CURSOR_DEFAULT);
        _resizing_col = -1;
        _resizing_row = -1;
        ret = 1;
      }
      break;
      
    case FL_MOVE:
      if ( context == CONTEXT_COL_HEADER && 		// in column header?
          resizeflag ) {				// resize + near boundary?
        change_cursor(FL_CURSOR_WE);			// show resize cursor
      }
      else if ( context == CONTEXT_ROW_HEADER && 	// in row header?
               resizeflag ) {				// resize + near boundary?
        change_cursor(FL_CURSOR_NS);			// show resize cursor
      } else {
        change_cursor(FL_CURSOR_DEFAULT);		// normal cursor
      }
      ret = 1;
      break;
      
    case FL_ENTER:		// See FLTK event docs on the FL_ENTER widget
      if (!ret) take_focus();
      ret = 1;
      //FALLTHROUGH
      
    case FL_LEAVE:		// We want to track the mouse if resizing is allowed.
      if ( resizeflag ) {
        ret = 1;
      }
      if ( event == FL_LEAVE ) {
        _stop_auto_drag();
        change_cursor(FL_CURSOR_DEFAULT);
      }
      break;
      
    case FL_FOCUS:
      Fl::focus(this);
      //FALLTHROUGH
      
    case FL_UNFOCUS:
      _stop_auto_drag();
      ret = 1;
      break;
      
    case FL_KEYBOARD: {
      ret = 0;
      int is_row = select_row;
      int is_col = select_col;
      switch(_event_key) {
        case FL_Home:
          ret = move_cursor(0, -1000000);
          break;
        case FL_End:
          ret = move_cursor(0, 1000000);
          break;
        case FL_Page_Up:
          ret = move_cursor(-(botrow - toprow - 1), 0);
          break;
        case FL_Page_Down:
          ret = move_cursor(botrow - toprow - 1 , 0);
          break;
        case FL_Left:
          ret = move_cursor(0, -1);
          break;
        case FL_Right:
          ret = move_cursor(0, 1);
          break;
        case FL_Up:
          ret = move_cursor(-1, 0);
          break;
        case FL_Down:
          ret = move_cursor(1, 0);
          break;
	case FL_Tab:
#if FLTK_ABI_VERSION >= 10303
	  if ( !tab_cell_nav() ) break;		// not navigating cells? let fltk handle it (STR#2862)
	  if ( _event_state & FL_SHIFT ) {
            ret = move_cursor(0, -1, 0);	// shift-tab -> left
	  } else {
	    ret = move_cursor(0, 1, 0);		// tab -> right
	  }
          break;
#else
          break;				// without tab_cell_nav(), Fl_Table_Copy should default to navigating widgets, not cells
#endif
      }
      if (ret && Fl::focus() != this) {
        do_callback(CONTEXT_TABLE, -1, -1);
        take_focus();
      }
      //if (!ret && Fl_Widget::callback() && when() & FL_WHEN_NOT_CHANGED  )
      if ( Fl_Widget::callback() && 
          (
           ( !ret && when() & FL_WHEN_NOT_CHANGED ) || 
           ( is_row!= select_row || is_col!= select_col ) 
           )
          ) {
        do_callback(CONTEXT_CELL, select_row, select_col); 
        //damage_zone(current_row, current_col, select_row, select_col);
        ret = 1;
      }
      break;
    }
      
    default:
      change_cursor(FL_CURSOR_DEFAULT);
      break;
  }
  return(ret);
}
示例#11
0
// Draw the entire Fl_Table_Copy
//    Override the draw() routine to draw the table.
//    Then tell the group to draw over us.
//
void Fl_Table_Copy::draw() {   
#if FLTK_ABI_VERSION >= 10301
    // NEW
    int scrollsize = _scrollbar_size ? _scrollbar_size : Fl::scrollbar_size();
#else
    // OLD
    int scrollsize = Fl::scrollbar_size();
#endif
  // Check if scrollbar size changed
  if ( ( vscrollbar && (scrollsize != vscrollbar->w()) ) || 
       ( hscrollbar && (scrollsize != hscrollbar->h()) ) ) {
    // handle size change, min/max, table dim's, etc
    table_resized();
  }

  draw_cell(CONTEXT_STARTPAGE, 0, 0,	 	// let user's drawing routine
            tix, tiy, tiw, tih);		// prep new page
  
  // Let fltk widgets draw themselves first. Do this after
  // draw_cell(CONTEXT_STARTPAGE) in case user moves widgets around.
  // Use window 'inner' clip to prevent drawing into table border.
  // (unfortunately this clips FLTK's border, so we must draw it explicity below)
  //
  fl_push_clip(wix, wiy, wiw, wih);
  {
    Fl_Group::draw();
  }
  fl_pop_clip();
  
  // Explicitly draw border around widget, if any
  draw_box(box(), x(), y(), w(), h(), color());
  
  // If Fl_Scroll 'table' is hidden, draw its box
  //    Do this after Fl_Group::draw() so we draw over scrollbars
  //    that leak around the border.
  //
  if ( ! table->visible() ) {
    if ( damage() & FL_DAMAGE_ALL || damage() & FL_DAMAGE_CHILD ) {
      draw_box(table->box(), tox, toy, tow, toh, table->color());
    }
  } 
  // Clip all further drawing to the inner widget dimensions
  fl_push_clip(wix, wiy, wiw, wih);
  {
    // Only redraw a few cells?
    if ( ! ( damage() & FL_DAMAGE_ALL ) && _redraw_leftcol != -1 ) {
      fl_push_clip(tix, tiy, tiw, tih);
      for ( int c = _redraw_leftcol; c <= _redraw_rightcol; c++ ) {
        for ( int r = _redraw_toprow; r <= _redraw_botrow; r++ ) { 
          _redraw_cell(CONTEXT_CELL, r, c);
        }
      }
      fl_pop_clip();
    }
    if ( damage() & FL_DAMAGE_ALL ) {
      int X,Y,W,H;
      // Draw row headers, if any
      if ( row_header() ) {
        get_bounds(CONTEXT_ROW_HEADER, X, Y, W, H);
        fl_push_clip(X,Y,W,H);
        for ( int r = toprow; r <= botrow; r++ ) {
          _redraw_cell(CONTEXT_ROW_HEADER, r, 0);
        }
        fl_pop_clip();
      }
      // Draw column headers, if any
      if ( col_header() ) {
        get_bounds(CONTEXT_COL_HEADER, X, Y, W, H);
        fl_push_clip(X,Y,W,H);
        for ( int c = leftcol; c <= rightcol; c++ ) {
          _redraw_cell(CONTEXT_COL_HEADER, 0, c);
        }
        fl_pop_clip();
      } 
      // Draw all cells.
      //    This includes cells partially obscured off edges of table.
      //    No longer do this last; you might think it would be nice
      //    to draw over dead zones, but on redraws it flickers. Avoid
      //    drawing over deadzones; prevent deadzones by sizing columns.
      //
      fl_push_clip(tix, tiy, tiw, tih); {
        for ( int r = toprow; r <= botrow; r++ ) {
          for ( int c = leftcol; c <= rightcol; c++ ) {
            _redraw_cell(CONTEXT_CELL, r, c); 
          }
        }
      }
      fl_pop_clip(); 
      // Draw little rectangle in corner of headers
      if ( row_header() && col_header() ) {
        fl_rectf(wix, wiy, row_header_width(), col_header_height(), color());
      }
      
      // Table has a boxtype? Close those few dead pixels
      if ( table->box() ) {
        if ( col_header() ) {
          fl_rectf(tox, wiy, Fl::box_dx(table->box()), col_header_height(), color());
        }
        if ( row_header() ) {
          fl_rectf(wix, toy, row_header_width(), Fl::box_dx(table->box()), color());
        }
      }
      
      // Table width smaller than window? Fill remainder with rectangle
      if ( table_w < tiw ) {
        fl_rectf(tix + table_w, tiy, tiw - table_w, tih, color()); 
        // Col header? fill that too
        if ( col_header() ) {
          fl_rectf(tix + table_w, 
                   wiy, 
                   // get that corner just right..
                   (tiw - table_w + Fl::box_dw(table->box()) - 
                    Fl::box_dx(table->box())),
                   col_header_height(),
                   color());
        }
      } 
      // Table height smaller than window? Fill remainder with rectangle
      if ( table_h < tih ) {
        fl_rectf(tix, tiy + table_h, tiw, tih - table_h, color()); 
        if ( row_header() ) {
          // NOTE:
          //     Careful with that lower corner; don't use tih; when eg. 
          //     table->box(FL_THIN_UPFRAME) and hscrollbar hidden, 
          //     leaves a row of dead pixels.
          //
          fl_rectf(wix, tiy + table_h, row_header_width(), 
                   (wiy+wih) - (tiy+table_h) - 
                   ( hscrollbar->visible() ? scrollsize : 0),
                   color());
        }
      }
    } 
    // Both scrollbars? Draw little box in lower right
    if ( vscrollbar->visible() && hscrollbar->visible() ) {
      fl_rectf(vscrollbar->x(), hscrollbar->y(), 
               vscrollbar->w(), hscrollbar->h(), color());
    } 
    draw_cell(CONTEXT_ENDPAGE, 0, 0,		// let user's drawing
              tix, tiy, tiw, tih);		// routines cleanup
    
    _redraw_leftcol = _redraw_rightcol = _redraw_toprow = _redraw_botrow = -1;
  }
  fl_pop_clip();
}
示例#12
0
// Handle FLTK events
int Fl_Table::handle(int event)
{
    PRINTEVENT;

    int ret = Fl_Group::handle(event);	// let FLTK group handle events first

    if (ret) {
	if (Fl::event_inside(hscrollbar) || Fl::event_inside(vscrollbar)) return 1;
	if (Fl::focus() != this && contains(Fl::focus())) return 1;
    }
 
    // Which row/column are we over?
    int R, C;  				// row/column being worked on
    ResizeFlag resizeflag;		// which resizing area are we over? (0=none)
    TableContext context = cursor2rowcol(R, C, resizeflag);

    switch ( event )
    {
	case FL_PUSH:
            if (Fl::event_button() == 1 && !Fl::event_clicks())
	    {
                if (Fl::focus() != this)
		{
		    take_focus();
		    do_callback(CONTEXT_TABLE, -1, -1);
		    ret = 1;
		}
                damage_zone(current_row, current_col, select_row, select_col, R, C);
		if (context == CONTEXT_CELL) 
		{
		    current_row = select_row = R;
		    current_col = select_col = C;
		    _selecting = CONTEXT_CELL;
		}
		else 
		{
		    current_row = select_row = -1;
		    current_col = select_col = -1;
		}
            }
	    // Need this for eg. right click to pop up a menu
	    if ( Fl_Widget::callback() &&		// callback defined?
		 resizeflag == RESIZE_NONE )		// not resizing?
		    { do_callback(context, R, C); }	// do callback

	    switch ( context )
	    {
	        case CONTEXT_CELL:
		    // FL_PUSH on a cell?
		    ret = 1; 			// express interest in FL_RELEASE
		    break;

		case CONTEXT_NONE:
		    // FL_PUSH on table corner?
		    if ( Fl::event_button() == 1 && 
		         Fl::event_x() < x() + row_header_width()) 
		    {
			current_col = 0;
			select_col = cols() - 1;
			current_row = 0;
			select_row = rows() - 1;				
			damage_zone(current_row, current_col, select_row, select_col);
			ret = 1;
		    }
		    break;

		case CONTEXT_COL_HEADER:
		    // FL_PUSH on a column header?
		    if ( Fl::event_button() == 1)
		    {
		        // Resizing? Handle it
		        if ( resizeflag )
			{
			    // Start resize if left click on column border.
			    //    "ret=1" ensures we get drag events from now on.
			    //    (C-1) is used if mouse is over the left hand side 
			    //    of cell, so we resize the next column on the left.
			    //
			    _resizing_col = ( resizeflag & RESIZE_COL_LEFT ) ? C-1 : C; 
			    _resizing_row = -1;
			    _dragging_x = Fl::event_x(); 
			    ret = 1;
			}
			else
			{
			    // Not resizing? Select the column
			    current_col = select_col = C;
			    current_row = 0;
			    select_row = rows() - 1;
			    _selecting = CONTEXT_COL_HEADER;
			    damage_zone(current_row, current_col, 
			    		select_row, select_col);
			    ret = 1;
			}
		    }
		    break;

		case CONTEXT_ROW_HEADER:
		    // FL_PUSH on a row header?
		    if ( Fl::event_button() == 1 )
		    {
		        // Resizing? Handle it
			if ( resizeflag )
			{
			    // Start resize if left mouse clicked on row border.
			    //    "ret = 1" ensures we get drag events from now on.
			    //    (R-1) is used if mouse is over the top of the cell,
			    //    so that we resize the row above.
			    //
			    _resizing_row = ( resizeflag & RESIZE_ROW_ABOVE ) ? R-1 : R; 
			    _resizing_col = -1;
			    _dragging_y = Fl::event_y(); 
			    ret = 1;
			} 
			else
			{
			    // Not resizing? Select the row
			    current_row = select_row = R;
			    current_col = 0;
			    select_col = cols() - 1;
			    _selecting = CONTEXT_ROW_HEADER;
			    damage_zone(current_row, current_col, 
			    		select_row, select_col);
			    ret = 1;
			}
		    }
		    break;

		default:
		    ret = 0;		// express disinterest
		    break;
	    }
	    _last_row = R;
	    break;

        case FL_DRAG:
            if (_auto_drag == 1) {
		ret = 1;
		break;
	    }

	    if ( _resizing_col > -1 )
	    {
		// Dragging column?
		//
		//    Let user drag even /outside/ the row/col widget.
		//    Don't allow column width smaller than 1.
		//    Continue to show FL_CURSOR_WE at all times during drag.
		//
		int offset = _dragging_x - Fl::event_x();
		int new_w = col_width(_resizing_col) - offset;
		if ( new_w < _col_resize_min ) new_w = _col_resize_min;
		col_width(_resizing_col, new_w);
		_dragging_x = Fl::event_x();
		table_resized();
		redraw();
		change_cursor(FL_CURSOR_WE);
		ret = 1;
		if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED )
		    { do_callback(CONTEXT_RC_RESIZE, R, C); }
	    }
	    else if ( _resizing_row > -1 )
	    {
		// Dragging row?
		//
		//    Let user drag even /outside/ the row/col widget.
		//    Don't allow row width smaller than 1.
		//    Continue to show FL_CURSOR_NS at all times during drag.
		//
		int offset = _dragging_y - Fl::event_y();
		int new_h = row_height(_resizing_row) - offset;
		if ( new_h < _row_resize_min ) new_h = _row_resize_min;
		row_height(_resizing_row, new_h);
		_dragging_y = Fl::event_y();
		table_resized();
		redraw();
		change_cursor(FL_CURSOR_NS);
		ret = 1;
		if ( Fl_Widget::callback() && when() & FL_WHEN_CHANGED )
		    { do_callback(CONTEXT_RC_RESIZE, R, C); }
	    } else {
                if (Fl::event_button() == 1 && _selecting == CONTEXT_CELL 
			&& context == CONTEXT_CELL) 
		{
                    if (select_row != R || select_col != C)
                        damage_zone(current_row, current_col, select_row, select_col, R, C);
                    select_row = R;
                    select_col = C;
                    ret = 1;
                } else if (Fl::event_button() == 1 && _selecting == CONTEXT_ROW_HEADER 
			&& context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) 
		{
                   if (select_row != R)
                        damage_zone(current_row, current_col, select_row, select_col, R, C);
		    select_row = R;
                    ret = 1;
		} else if (Fl::event_button() == 1 && _selecting == CONTEXT_COL_HEADER 
			&& context & (CONTEXT_ROW_HEADER|CONTEXT_COL_HEADER|CONTEXT_CELL)) 
		{
                    if (select_col != C)
                        damage_zone(current_row, current_col, select_row, select_col, R, C);
		    select_col = C;
                    ret = 1;
		}
            }
	    // Enable autodrag if not resizing, and mouse has moved off table edge
	    if ( _resizing_row < 0 && _resizing_col < 0 && _auto_drag == 0 && 
	        ( Fl::event_x() > x() + w() - 20 ||
                  Fl::event_x() < x() + row_header_width() || 
		  Fl::event_y() > y() + h() - 20 ||
                  Fl::event_y() < y() + col_header_height()
		) )
            {
                _start_auto_drag();
            }
	    break;

	case FL_RELEASE:
            _stop_auto_drag();
	    switch ( context )
	    {
		case CONTEXT_ROW_HEADER:	// release on row header
		case CONTEXT_COL_HEADER:	// release on col header
		case CONTEXT_CELL:		// release on a cell
		case CONTEXT_TABLE:		// release on dead zone
		    if ( _resizing_col == -1 &&		// not resizing a column
			 _resizing_row == -1 &&		// not resizing a row
		         Fl_Widget::callback() && 	// callback defined
			 when() & FL_WHEN_RELEASE && 	// on button release
			 _last_row == R )		// release on same row PUSHed?
		    {
			// Need this for eg. left clicking on a cell to select it
			do_callback(context, R, C);
		    }
		    break;

		default:
		    break;
	    }

	    if ( Fl::event_button() == 1 )
	    {
		change_cursor(FL_CURSOR_DEFAULT);
		_resizing_col = -1;
		_resizing_row = -1;
		ret = 1;
	    }
	    break;

	case FL_MOVE:
	    if ( context == CONTEXT_COL_HEADER && 	// in column header?
	         resizeflag )				// resize + near boundary?
		{ change_cursor(FL_CURSOR_WE); }	// show resize cursor
	    else if ( context == CONTEXT_ROW_HEADER && 	// in row header?
	         resizeflag )				// resize + near boundary?
		{ change_cursor(FL_CURSOR_NS); }	// show resize cursor
	    else
		{ change_cursor(FL_CURSOR_DEFAULT); }	// normal cursor
	    ret = 1;
	    break;

	case FL_ENTER:		// See FLTK event docs on the FL_ENTER widget
	     if (!ret) take_focus();
	     ret = 1;
	     //FALLTHROUGH

	case FL_LEAVE:		// We want to track the mouse if resizing is allowed.
	    if ( resizeflag )
		{ ret = 1; }
	    if ( event == FL_LEAVE ) 
	    {
	        _stop_auto_drag();
	    	change_cursor(FL_CURSOR_DEFAULT);
	    }
	    break;

        case FL_FOCUS:
	    Fl::focus(this);
	    //FALLTHROUGH

        case FL_UNFOCUS:
	    _stop_auto_drag();
	    ret = 1;
	    break;

	case FL_KEYBOARD:
	    ret = 0;
	    switch(Fl::event_key()) {
		case FL_Home:
		    ret = move_cursor(0, -1000000); break;
		case FL_End:
		    ret = move_cursor(0, 1000000); break;
		case FL_Page_Up:
		    ret = move_cursor(-(botrow - toprow - 1), 0); break;
		case FL_Page_Down:
		    ret = move_cursor(botrow - toprow - 1 , 0); break;
		case FL_Left:
		    ret = move_cursor(0, -1); break;
		case FL_Right:
		    ret = move_cursor(0, 1); break;
		case FL_Up:
		    ret = move_cursor(-1, 0); break;
		case FL_Down:
		    ret = move_cursor(1, 0); break;
	    }
	    if (ret && Fl::focus() != this) {
		do_callback(CONTEXT_TABLE, -1, -1);
		take_focus();
	    }
	    if (!ret && Fl_Widget::callback() && when() & FL_WHEN_NOT_CHANGED  ) { 
		do_callback(CONTEXT_CELL, select_row, select_col); 
		//damage_zone(current_row, current_col, select_row, select_col);
		ret = 1;
	    }
	    break;

	default:
	    change_cursor(FL_CURSOR_DEFAULT);
	    break;
    }
    return(ret);
}