// Find X/Y/W/H for cell at R/C // If R or C are out of range, returns -1 // with X/Y/W/H set to zero. // int Fl_Table_Copy::find_cell(TableContext context, int R, int C, int &X, int &Y, int &W, int &H) { if ( row_col_clamp(context, R, C) ) { // row or col out of range? error X=Y=W=H=0; return(-1); } X = col_scroll_position(C) - hscrollbar->value() + tix; Y = row_scroll_position(R) - vscrollbar->value() + tiy; W = col_width(C); H = row_height(R); switch ( context ) { case CONTEXT_COL_HEADER: Y = wiy; H = col_header_height(); return(0); case CONTEXT_ROW_HEADER: X = wix; W = row_header_width(); return(0); case CONTEXT_CELL: return(0); case CONTEXT_TABLE: return(0); // TODO -- HANDLE OTHER CONTEXTS default: fprintf(stderr, "Fl_Table_Copy::find_cell: unknown context %d\n", (int)context); return(-1); } //NOTREACHED }
bool CONTROLS::on_mousemove(float x, float y) { if(gameclient.snap.gameobj && gameclient.snap.gameobj->paused) return false; mouse_pos += vec2(x, y); // TODO: ugly // float camera_max_distance = 200.0f; float follow_factor = config.cl_mouse_followfactor/100.0f; float deadzone = config.cl_mouse_deadzone; float mouse_max = min(camera_max_distance/follow_factor + deadzone, (float)config.cl_mouse_max_distance); //vec2 camera_offset(0, 0); if(gameclient.snap.spectate) { if(gameclient.freeview) { if(mouse_pos.x < 200.0f) mouse_pos.x = 200.0f; if(mouse_pos.y < 200.0f) mouse_pos.y = 200.0f; if(mouse_pos.x > col_width()*32-200.0f) mouse_pos.x = col_width()*32-200.0f; if(mouse_pos.y > col_height()*32-200.0f) mouse_pos.y = col_height()*32-200.0f; } else mouse_pos = gameclient.spectate_pos; target_pos = mouse_pos; } else { float l = length(mouse_pos); if(l > mouse_max) { mouse_pos = normalize(mouse_pos)*mouse_max; l = mouse_max; } //float offset_amount = max(l-deadzone, 0.0f) * follow_factor; //if(l > 0.0001f) // make sure that this isn't 0 //camera_offset = normalize(mouse_pos)*offset_amount; } return true; }
// Recalculate internals after a scroll. // // Call this if table has been scrolled or resized. // Does not handle redraw(). // TODO: Assumes ti[xywh] has already been recalculated. // void Fl_Table::table_scrolled() { // Top row int y, row, voff = vscrollbar->value(); for ( row=y=0; row < _rows; row++ ) { y += row_height(row); if ( y >= voff ) { y -= row_height(row); break; } } _row_position = toprow = ( row >= _rows ) ? (row - 1) : row; toprow_scrollpos = y; // OPTIMIZATION: save for later use // Bottom row voff = vscrollbar->value() + tih; for ( ; row < _rows; row++ ) { y += row_height(row); if ( y >= voff ) { break; } } botrow = ( row >= _rows ) ? (row - 1) : row; // Left column int x, col, hoff = hscrollbar->value(); for ( col=x=0; col < _cols; col++ ) { x += col_width(col); if ( x >= hoff ) { x -= col_width(col); break; } } _col_position = leftcol = ( col >= _cols ) ? (col - 1) : col; leftcol_scrollpos = x; // OPTIMIZATION: save for later use // Right column // Work with data left over from leftcol calculation // hoff = hscrollbar->value() + tiw; for ( ; col < _cols; col++ ) { x += col_width(col); if ( x >= hoff ) { break; } } rightcol = ( col >= _cols ) ? (col - 1) : col; // First tell children to scroll draw_cell(CONTEXT_RC_RESIZE, 0,0,0,0,0,0); }
// Find scroll position of a column (in pixels) long Fl_Table_Copy::col_scroll_position(int col) { int startcol = 0; long scroll = 0; // OPTIMIZATION: // Attempt to use precomputed row scroll position // if ( leftcol_scrollpos != -1 && col >= leftcol ) { scroll = leftcol_scrollpos; startcol = leftcol; } for ( int t=startcol; t<col; t++ ) { scroll += col_width(t); } return(scroll); }
void KlassInfoHisto::print_class_stats(outputStream* st, bool csv_format, const char *columns) { ResourceMark rm; KlassSizeStats sz, sz_sum; int i; julong *col_table = (julong*)(&sz); julong *colsum_table = (julong*)(&sz_sum); int width_table[KlassSizeStats::_num_columns]; bool selected[KlassSizeStats::_num_columns]; _selected_columns = columns; memset(&sz_sum, 0, sizeof(sz_sum)); for (int c=0; c<KlassSizeStats::_num_columns; c++) { selected[c] = is_selected(name_table[c]); } for(i=0; i < elements()->length(); i++) { elements()->at(i)->set_index(i+1); } for (int pass=1; pass<=2; pass++) { if (pass == 2) { print_title(st, csv_format, selected, width_table, name_table); } for(i=0; i < elements()->length(); i++) { KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); const Klass* k = e->klass(); memset(&sz, 0, sizeof(sz)); sz._inst_count = e->count(); sz._inst_bytes = HeapWordSize * e->words(); k->collect_statistics(&sz); sz._total_bytes = sz._ro_bytes + sz._rw_bytes; if (pass == 1) { for (int c=0; c<KlassSizeStats::_num_columns; c++) { colsum_table[c] += col_table[c]; } } else { int super_index = -1; if (k->oop_is_instance()) { Klass* super = ((InstanceKlass*)k)->java_super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { super_index = super_e->index(); } } } if (csv_format) { st->print("%d,%d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);} } st->print(",%s",e->name()); } else { st->print("%5d %5d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], col_table[c]);} } st->print(" %s", e->name()); } if (is_selected("ClassLoader")) { ClassLoaderData* loader_data = k->class_loader_data(); st->print(","); loader_data->print_value_on(st); } st->cr(); } } if (pass == 1) { for (int c=0; c<KlassSizeStats::_num_columns; c++) { width_table[c] = col_width(colsum_table[c], name_table[c]); } } } sz_sum._inst_size = 0; if (csv_format) { st->print(","); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);} } } else { st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);} } st->print(" Total"); if (sz_sum._total_bytes > 0) { st->cr(); st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) { switch (c) { case KlassSizeStats::_index_inst_size: case KlassSizeStats::_index_inst_count: case KlassSizeStats::_index_method_count: PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL st->print(str_fmt(width_table[c]), "-"); PRAGMA_DIAG_POP break; default: { double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; PRAGMA_DIAG_PUSH PRAGMA_FORMAT_NONLITERAL_IGNORED_INTERNAL st->print(perc_fmt(width_table[c]), perc); PRAGMA_DIAG_POP } } } } } }
void KlassInfoHisto::print_class_stats(outputStream* st, bool csv_format, const char *columns) { ResourceMark rm; KlassSizeStats sz, sz_sum; int i; julong *col_table = (julong*)(&sz); julong *colsum_table = (julong*)(&sz_sum); int width_table[KlassSizeStats::_num_columns]; bool selected[KlassSizeStats::_num_columns]; _selected_columns = columns; memset(&sz_sum, 0, sizeof(sz_sum)); for (int c=0; c<KlassSizeStats::_num_columns; c++) { selected[c] = is_selected(name_table[c]); } for(i=0; i < elements()->length(); i++) { elements()->at(i)->set_index(i+1); } // First iteration is for accumulating stats totals in colsum_table[]. // Second iteration is for printing stats for each class. for (int pass=1; pass<=2; pass++) { if (pass == 2) { print_title(st, csv_format, selected, width_table, name_table); } for(i=0; i < elements()->length(); i++) { KlassInfoEntry* e = (KlassInfoEntry*)elements()->at(i); const Klass* k = e->klass(); // Get the stats for this class. memset(&sz, 0, sizeof(sz)); sz._inst_count = e->count(); sz._inst_bytes = HeapWordSize * e->words(); k->collect_statistics(&sz); sz._total_bytes = sz._ro_bytes + sz._rw_bytes; if (pass == 1) { // Add the stats for this class to the overall totals. for (int c=0; c<KlassSizeStats::_num_columns; c++) { colsum_table[c] += col_table[c]; } } else { int super_index = -1; // Print the stats for this class. if (k->is_instance_klass()) { Klass* super = k->super(); if (super) { KlassInfoEntry* super_e = _cit->lookup(super); if (super_e) { super_index = super_e->index(); } } } if (csv_format) { st->print("%ld,%d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, col_table[c]);} } st->print(",%s",e->name()); } else { st->print("%5ld %5d", e->index(), super_index); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], col_table[c]);} } st->print(" %s", e->name()); } if (is_selected("ClassLoader")) { ClassLoaderData* loader_data = k->class_loader_data(); st->print(","); loader_data->print_value_on(st); } st->cr(); } } if (pass == 1) { // Calculate the minimum width needed for the column by accounting for the // column header width and the width of the largest value in the column. for (int c=0; c<KlassSizeStats::_num_columns; c++) { width_table[c] = col_width(colsum_table[c], name_table[c]); } } } sz_sum._inst_size = 0; // Print the column totals. if (csv_format) { st->print(","); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {st->print("," JULONG_FORMAT, colsum_table[c]);} } } else { st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) {print_julong(st, width_table[c], colsum_table[c]);} } st->print(" Total"); if (sz_sum._total_bytes > 0) { st->cr(); st->print(" "); for (int c=0; c<KlassSizeStats::_num_columns; c++) { if (selected[c]) { switch (c) { case KlassSizeStats::_index_inst_size: case KlassSizeStats::_index_inst_count: case KlassSizeStats::_index_method_count: st->print("%*s", width_table[c], "-"); break; default: { double perc = (double)(100) * (double)(colsum_table[c]) / (double)sz_sum._total_bytes; st->print("%*.1f%%", width_table[c]-1, perc); } } } } } } st->cr(); if (!csv_format) { print_title(st, csv_format, selected, width_table, name_table); } }
void UIPartList::set_disk(int diskidx, disk_info_t *info){ _diskidx = diskidx; _info = info; if (_info->mbr.gpt_protect){ col_width(0, 40); col_width(1, 200); col_width(2, 40); col_width(3, 360); col_width(4, 120); col_width(5, 120); col_width(6, 90); rows(_info->gpt.part_count); } else { col_width(0, 40); col_width(1, 300); col_width(2, 40); col_width(3, 40); col_width(4, 120); col_width(5, 120); col_width(6, 90); rows(_info->mbr.part_count); } redraw(); }
// 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); }
// 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); }