Exemplo n.º 1
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);
}
Exemplo n.º 2
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);
}