// ====================================================================== // File: Flv_Table.cxx - Flv_Table implementation // Program: Flv_Table - FLTK Table Widget // Version: 0.1.0 // Started: 11/21/99 // // Copyright (C) 1999 Laurence Charlton // // Description: // Flv_Table implements a table/grid. No data is stored // in the widget. Supports headers/footers for rows and columns, // natively supports a single row height and column width per table. // Row and column grids can be turned on and off. Supports no scroll // bars as well as horizontal/vertical automatic or always on scroll bars. // Also support cell selection and row selection modes. In row selection // mode it acts like a pumped-up list widget. // Uses absolute cell references. // // row -1 is defined as the row header // row -2 is defined as the row footer // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 3 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this library. If not, see . // ====================================================================== #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifndef IN_GIAC #include #else #include "first.h" #endif #ifdef HAVE_LIBFLTK #include "Flv_Table.H" #include #include #include #define DOcb(x) ((callback_when() & (x))==(x)) // Resizing constants #define FUDGE 2 #define MOVE_X 1 #define MOVE_Y 2 #define MOVE_XY (MOVE_X|MOVE_Y) #ifndef max #define max(a,b) ((a)>(b)?(a):(b)) #endif #ifndef min #define min(a,b) ((a)<(b)?(a):(b)) #endif static Fl_Cursor last_cursor = FL_CURSOR_DEFAULT; static int drag_col=-4, drag_row=-4, anchor_left, anchor_top; Flv_Table::Flv_Table( int X, int Y, int W, int H, const char *l ) :Flv_List(X,Y,W,H,l){ edit_col = -1; vcol = 0; vcols = 0; vcol_width = 40; vmove_on_enter = FLV_MOVE_ON_ENTER_COL_ROW; vselect_col = 0; vbuttons = FLV_BUTTON1 | FLV_BUTTON2 | FLV_BUTTON3; click_fill = false; } Flv_Table::~Flv_Table() { } // Probbably won't need to over-ride this for future table widgets void Flv_Table::draw_row( int Offset, int &X, int &Y, int &, int &H, int R ) { int c, cw, CX, FW; int dX, dY, dW, dH; int TX, TY, TW, TH; Flv_Style s; // Calculate clipping height client_area(dX,dY,dW,dH); FW = (col_footer()?col_width(-2):0); CX = X; // Draw column header if (col_header()) { cw = col_width(-1); // Column width TX = CX; TY = Y; TW = cw; TH = H; draw_cell( 0, TX, TY, TW, TH, R, -1 ); CX += cw; dX += cw; dW -= cw; } dW -= FW; // Draw column footer if (FW) { TX = dX+dW; TY = Y; TW = FW; TH = H; draw_cell( 0, TX, TY, TW, TH, R, -2 ); } fl_clip( dX, Y, dW, H ); // Clip data area for (c=0; cdraw(X,Y,W,H,s.background()); // Normally you would use the next line to get the client area to draw bt->inset( X, Y, W, H ); #else draw_box( bt, X, Y, W, H, s.background() ); // Normally you would use the next lines to get the client area to draw X+= (Fl::box_dx(bt)); Y+= (Fl::box_dy(bt)); W-= (Fl::box_dw(bt)); H-= (Fl::box_dh(bt)); #endif // Drawing selection rectangle for cell if (R>-1 && C>-1 && R==row() && C==col() && !select_row() && (Fl::focus()==this || persist_select())) { fl_color( fl_contrast(text_color(), selection_color()) ); fl_rect( X, Y, W, H); } X+=s.x_margin(); Y+=s.y_margin(); W-=s.x_margin()*2; H-=s.y_margin()*2; X += Offset; // Get set-up to draw text fl_font( s.font(), s.font_size() ); if (!active()) s.foreground( fl_inactive(s.foreground()) ); fl_color(s.foreground()); } bool Flv_Table::get_cell_bounds( int &X, int &Y, int &W, int &H, int R, int C ) { int x, y, w, h, r, rh, B, cx; X = Y = W = H = 0; cell_area(x,y,w,h); B = y+h; for (r=top_row(); rB) break; } if (r!=R) return false; Y = y; H = row_height(R); if (Y+H>B) H = B-Y; cx = x - row_offset(); for (r=0; rx+w) break; } rh = col_width(r); if (r!=C || cx+rhx+w) rh = (x+w)-X; if (rh>w) rh = w; if (rh<0) rh = 0; W = rh; return true; } void Flv_Table::draw(void) { int r, rh, rw; int X, Y, W, H, B, FW; int CX, CY, CW, CH; Flv_Style s; int t, c; char buf[30]; // Initially verify we aren't on a locked cell r = row(); c = col(); while(!select_locked()) { get_style(s,r,c); if (!s.locked()) { row(r); col(c); break; } c++; if (c==cols()) { c = 0; r++; if (r==rows()) break; } } // Make sure we have an editor if editing! // if (!veditor && vediting) // switch_editor(row(),col()); // We need to know what the row width will be // so we'll calculate that and then let normal drawing // take over. if (!feature_test(FLVF_MULTI_SELECT)) select_start_col(vcol); for (c=cols(), rw=t=0; t0) { fl_color( dead_space_color() ); fl_rectf( X+rw-row_offset(), Y, B, H ); } B = Y + H; fl_clip( X, Y, W, H ); // Draw rows for ( r=top_row(); Ycolor() ); else fl_color( FL_WHITE ); fl_rectf( X, Y, W, B-Y ); } fl_pop_clip(); } void Flv_Table::add_selection_style( Flv_Style &s, int R, int C ) { if (!multi_select()) // If not multi row selection { select_start_row( row() ); select_start_col( col() ); } if (R>-1 && C>-1) if ( (select_row() && row_selected(R)) || (!select_row() && cell_selected(R,C)) ) { s.background( selection_color() ); s.foreground( selection_text_color()); } } void Flv_Table::cell_area(int &X, int &Y, int &W, int &H ) { client_area(X,Y,W,H); if (label() && *label()) { Y += row_height(FLV_TITLE); H -= row_height(FLV_TITLE); } if (row_header()) { Y += row_height(FLV_ROW_HEADER); H -= row_height(FLV_ROW_HEADER); } if (row_footer()) { H -= row_height(FLV_ROW_FOOTER); } if (col_header()) { X += col_width(FLV_COL_HEADER); W -= col_width(FLV_COL_HEADER); } if (col_footer()) { W -= col_width(FLV_COL_FOOTER); } } bool Flv_Table::cell_selected(int R, int C) { return (col_selected(C) && row_selected(R)); } int Flv_Table::col_width(int C) // Get column width { int fw = vcol_width; Flv_Style *cols; if (global_style.width_defined()) fw = global_style.width(); cols = col_style.find(C); if (cols) if (cols->width_defined()) fw = cols->width(); return fw; } int Flv_Table::col_width(int n, int c) // Set column width { int cw = col_width(c); if (c<-3) c=-3; if (c>=vcols) c=vcols-1; if (n<0) n=0; if (n!=cw) { col_style[c].width(n); damage(FL_DAMAGE_CHILD); } return col_width(c); } void Flv_Table::get_style( Flv_Style &s, int R, int C ) { Flv_Style *rows, *cols, *cells; Flv_List::get_style( s, R ); rows = row_style.skip_to(R); if (R!=-3) { cols = col_style.skip_to(C); if (cols) s = *cols; } if (C<0 || R<0) // Headers/Labels have different default { // Note: we can still override at cell level if (parent()) s.background( parent()->color() ); else s.background( FL_WHITE ); s.frame(FL_THIN_UP_BOX); s.border( FLVB_NONE ); s.border_spacing(0); } cells = (rows?rows->cell_style.skip_to(C):NULL); if (cells) s = *cells; } int Flv_Table::handle(int event) { int stat=0, x, y, X,Y,W,H, r, c; Flv_Style s; switch(event) { case FL_RELEASE: case FL_DRAG: if (!vediting || !veditor) break; case FL_PUSH: if (Fl::event_button1()==0) break; if (drag_row!=-4 || drag_col!=-4) break; x = Fl::event_x(); y = Fl::event_y(); if (!vediting) { if (edit_when()==FLV_EDIT_MANUAL) break; r = row(); c = col(); if (r<0 || c<0) break; cell_area(X,Y,W,H); stat = internal_handle(event); if (stat && r==row() && c==col() && x>=X && x=Y && yx() || yy() || x>veditor->x()+veditor->w() || y>veditor->y()+veditor->h()) break; stat = veditor->handle(event); if (stat) { veditor->draw(); return 1; } break; } if (event==FL_SHORTCUT && vediting) { if (Fl::event_key()==FL_Enter) { end_edit(); // Save editor/ quit editing Fl::focus(this); // take_focus(); internal_handle(FL_KEYBOARD); damage(FL_DAMAGE_CHILD); return 1; } switch( Fl::event_key() ) { case FL_Shift_L: case FL_Shift_R: case FL_Control_L: case FL_Control_R: case FL_Meta_L: case FL_Meta_R: case FL_Alt_L: case FL_Alt_R: break; default: stat = internal_handle(FL_KEYBOARD); } } else { stat = internal_handle(event); if (!stat) { // Jump start editing if automatic if (event==FL_KEYBOARD && !vediting && edit_when()==FLV_EDIT_AUTOMATIC ) { switch( Fl::event_key() ) { case FL_Shift_L: case FL_Shift_R: case FL_Control_L: case FL_Control_R: case FL_Meta_L: case FL_Meta_R: case FL_Alt_L: case FL_Alt_R: break; default: start_edit(); if (veditor) { stat = veditor->handle(event); if (stat) { Fl::focus(veditor); // veditor->take_focus(); veditor->draw(); return 1; } } cancel_edit(); } } } } if (veditor && Fl::focus()==this) { Fl::focus(veditor); // veditor->take_focus(); veditor->handle(FL_FOCUS); } if (stat && veditor) veditor->draw(); return stat; } int Flv_Table::internal_handle(int event) { int TX, TY, r, c, cd, rd; Flv_Style s; static int LX, LY; switch( event ) { case FL_KEYBOARD: break; case FL_ENTER: case FL_LEAVE: vclicks = 0; return Fl_Group::handle(event); case FL_FOCUS: case FL_UNFOCUS: return 1; case FL_MOVE: TY = Fl::event_y(); TX = Fl::event_x(); if ( LX-TX<-3 || LX-TX>3 || LY-TY<-3 || LY-TY>3 ) { LX = TX; LY = TY; vclicks = 0; } check_cursor(); return Fl_Group::handle(event); case FL_RELEASE: drag_row = drag_col = -4; Fl_Group::handle(event); return 1; case FL_DRAG: vclicks=0; if (check_resize()) return 1; case FL_PUSH: // Dragging not clicking if (drag_row!=-4 || drag_col != -4) return 1; r = 0; if (Fl::event_button1() && (buttons() & FLV_BUTTON1)) r=1; if (Fl::event_button2() && (buttons() & FLV_BUTTON2)) r=1; if (Fl::event_button3() && (buttons() & FLV_BUTTON3)) r=1; if (r==0) { vclicks = 0; return 0; } // Determine if col was clicked and highlight it TY = Fl::event_y(); TX = Fl::event_x(); r = get_row(TX,TY); c = get_col(TX,TY); if (r==-4 && c==-4) { vclicks = 0; return Fl_Group::handle(event); } if ( LX-TX>-3 && LX-TX<3 && LY-TY>-3 && LY-TY<3) vclicks++; else { vclicks=1; LX = TX; LY = TY; } damage(FL_DAMAGE_CHILD); rd = (r>row()?1:r==row()?0:-1); cd = (c>col()?1:c==col()?0:-1); if (r>=0) row(r); if (c>=0) col(c); if (!multi_select() || (event==FL_PUSH && !Fl::event_state(FL_SHIFT))) { select_start_row(row()); select_start_col(col()); } // At least one header clicked if (r<0 || c<0) { if (r>-4 && c>-4 && r<0 && c<0 && r!=-3) { if ( DOcb(FLVEcb_ALL_CLICKED) ) { vwhy_event = FLVE_ALL_CLICKED; do_callback(this, user_data()); vwhy_event = 0; } return 1; } if ( c>=0 || r==-3 ) { vwhy_event = 0; switch( r ) { case -3: if (DOcb(FLVEcb_TITLE_CLICKED)) vwhy_event = FLVE_TITLE_CLICKED; break; case -2: if (DOcb(FLVEcb_ROW_FOOTER_CLICKED)) vwhy_event = FLVE_ROW_FOOTER_CLICKED; break; case -1: if (DOcb(FLVEcb_ROW_HEADER_CLICKED)) vwhy_event = FLVE_ROW_HEADER_CLICKED; break; } if (vwhy_event) { do_callback(this, user_data()); vwhy_event = 0; return 1; } } if ( r>=0 ) { vwhy_event = 0; switch( c ) { case -2: if (DOcb(FLVEcb_COL_FOOTER_CLICKED)) vwhy_event = FLVE_COL_FOOTER_CLICKED; break; case -1: if (DOcb(FLVEcb_COL_HEADER_CLICKED)) vwhy_event = FLVE_COL_HEADER_CLICKED; break; } if (vwhy_event) { do_callback(this, user_data()); vwhy_event = 0; return 1; } } return 0; } if (event==FL_PUSH && (rd || cd)) { // Skip over locked cells while(!select_locked()) { get_style(s,r,c); if (!s.locked()) { if (r!=row() || c!=col()) vclicks=0; row(r); col(c); break; } r += rd; c += cd; if ( r<0 || r>=rows() || c<0 || c>=cols() ) break; } } if (event==FL_PUSH) { if (DOcb(FLVEcb_CLICKED)) { vwhy_event = FLVE_CLICKED; do_callback(this, user_data()); vwhy_event = 0; } if (vclicks>=vmax_clicks) vclicks=0; } return 1; default: return Fl_Group::handle(event); } switch(Fl::event_key()) { case FL_Enter: switch( vmove_on_enter) { case FLV_MOVE_ON_ENTER_ROW_COL: if (!move_row(1)) { row(0); col(col()+1); if (!select_locked()) { get_style(s,r,col()); if (!s.locked()) move_row(1); } } return 1; case FLV_MOVE_ON_ENTER_COL_ROW: if (!move_col(1)) { col(0); row(row()+1); if (!select_locked()) { get_style(s,r,col()); if (!s.locked()) move_row(1); } } return 1; } return 0; case FL_Up: if (Fl::event_state(FL_CTRL)) move_row(-row()); else move_row(-1); break; case FL_Down: if (Fl::event_state(FL_CTRL)) move_row(rows()); else move_row(1); break; case FL_Page_Down: if (Fl::event_state(FL_CTRL)) move_row( rows() ); else move_row(page_size()); break; case FL_Page_Up: if (Fl::event_state(FL_CTRL)) move_row(-row()); else move_row(-page_size()); break; case FL_Home: // Adjust rows before columns so we redraw everything if (Fl::event_state(FL_CTRL)) move_row(-rows()); move_col(-cols()); break; case FL_End: // Adjust rows before columns so we redraw everything if (Fl::event_state(FL_CTRL)) move_row(rows()); move_col(cols()); break; case FL_Right: if (select_row()) return 0; if (Fl::event_state(FL_CTRL)) move_col(cols()); else move_col(1); break; case FL_Left: if (select_row()) return 0; if (Fl::event_state(FL_CTRL)) move_col(-col()); else move_col(-1); break; default: return Fl_Group::handle(event); } if (!multi_select() || !Fl::event_state(FL_SHIFT)) { select_start_col(col()); select_start_row(row()); } return 1; } int Flv_Table::row(int n) { int X,Y,W,H; if (n>=rows()) n=rows()-1; if (n<0) n=0; if (n!=vrow) { vrow = n; client_area(X,Y,W,H); update_top_row(H); end_edit(); if (edit_when()==FLV_EDIT_ALWAYS) switch_editor( row(), col() ); vlast_row = vrow; if (DOcb(FLVEcb_ROW_CHANGED)) { vwhy_event = FLVE_ROW_CHANGED; do_callback(this, user_data()); vwhy_event = 0; } damage(FL_DAMAGE_CHILD); } return vrow; } int Flv_Table::col( int n ) { Flv_Style s; if (n>=vcols) n=vcols-1; if (n<0) n=0; if (n!=vcol) { vcol = n; end_edit(); if (edit_when()==FLV_EDIT_ALWAYS) switch_editor( row(), col() ); adjust_for_cell(); if (DOcb(FLVEcb_COL_CHANGED)) { vwhy_event = FLVE_COL_CHANGED; do_callback(this, user_data()); vwhy_event = 0; } damage(FL_DAMAGE_CHILD); } return vcol; } bool Flv_Table::col_resizable(int c) // Get/set column locked status { Flv_Style *s; bool l=true; if (global_style.resizable_defined()) l = global_style.resizable(); s = col_style.find(c); if (s) if (s->resizable_defined()) l = s->resizable(); return l; } bool Flv_Table::col_resizable( bool n, int c) { col_style[c].resizable(n); return n; } int Flv_Table::cols( int n ) { if (n>=0 && n!=vcols) { vcols = n; if (vcol>=vcols) col(vcols-1); if (vselect_col>vcol) select_start_col(vcol); update_width(); if (DOcb(FLVEcb_COLS_CHANGED)) { vwhy_event = FLVE_COLS_CHANGED; do_callback(this, user_data()); vwhy_event = 0; } damage(FL_DAMAGE_CHILD); } return vcols; } bool Flv_Table::col_selected(int n) { if (vselect_col=y && y>Y+rh){ return -1; } X+=cw; W-=cw; } if (col_footer()){ cw = col_width(-2); if (X+W>=x && x>=X+W-cw){ return -2; } W -= cw; } rw = row_width(); if (!rw) rw = W; if ( x=X+W || y=Y+H || x>X-row_offset()+rw){ return -4; } Offset = row_offset(); for (CX=X, t=0; t=CX-Offset && x=CX+(4*cw)/5-Offset); return t; } } return -4; // In grey area at bottom? } int Flv_Table::select_start_col(int n) { if (n>=vcols) n=vcols-1; if (n<0) n=0; if (n!=vselect_col) { vselect_col = n; if (DOcb(FLVEcb_SELECTION_CHANGED)) { vwhy_event = FLVE_SELECTION_CHANGED; do_callback(this, user_data()); vwhy_event = 0; } damage(FL_DAMAGE_CHILD); } return vselect_col; } void Flv_Table::update_width() { int rw, n; for (rw=n=0; no) row_offset(o); else { client_area(X,Y,W,H); if (col_footer()) W -= col_width(-2); if (col_header()) W -= col_width(-2); cw = col_width(col()); if (o+cw-row_offset()>W) { row_offset(o+cw-W); damage(FL_DAMAGE_CHILD); } } } bool Flv_Table::check_resize(void) { int ex, ey, v; int X, Y, W, H; if (drag_row<-3 && drag_col<-2) return false; client_area(X,Y,W,H); ex = Fl::event_x(); ey = Fl::event_y(); if (drag_row==-3) { v = ey-anchor_top; if (v<2) v=2; row_style[drag_row].height(v); damage(FL_DAMAGE_CHILD); return true; } if (label() && *label()) { Y += row_height(-3); H -= row_height(-3); } if (drag_col>-3) { if (drag_col==-2) { v = anchor_left - ex + col_width(drag_col); if (col_header()) { X += col_width(-1); W -= col_width(-1); } if (v>W-1) { v = W-1; anchor_left = X+W-v; } if (v<2) { v=2; anchor_left = X+W-2; } col_style[drag_col].width(v); damage(FL_DAMAGE_CHILD); if (v!=W-1 && v!=2) anchor_left = ex; } else { v = ex-anchor_left; if (drag_col==-1) { // Make sure it's in the grid if (col_footer()) W-=col_width(-2); if (v > W-1 ) v = W-1; } if (v<2) v=2; col_width(v,drag_col); damage(FL_DAMAGE_CHILD); } } // Resize row if (drag_row>-4) { if (drag_row==-2) { v = anchor_top - ey + row_height(drag_row); if (row_header()) { H-=row_height(-1); Y+=row_height(-1); } if (v>H-1) { v = H-1; anchor_top = Y+H-v; } if (v<2) { v = 2; anchor_top = Y+H-2; } row_style[drag_row].height(v); damage(FL_DAMAGE_CHILD); if (v!=2 && v!=H-1) anchor_top = ey; } else { v = ey-anchor_top; if (drag_row==-1) { if (row_footer()) H-=row_height(-2); if (v>H-1) v = H-1; } if (v<2) v=2; row_height(v,drag_row); damage(FL_DAMAGE_CHILD); } } return true; } // See if we can resize, if so change cursor void Flv_Table::check_cursor(void){ int X, Y, W, H, R, ey, ex, move=0, WW, size; int v; bool resize, inh, inv; Fl_Cursor cursor; // Assume total miss drag_row = drag_col = -4; cursor = FL_CURSOR_DEFAULT; ex = Fl::event_x(); ey = Fl::event_y(); client_area(X,Y,W,H); inh = (ex>=X && ex=Y && ey=Y-FUDGE && ey<=Y+FUDGE && inh); if (resize){ if (row_resizable(-3)){ drag_row = -3; anchor_top = Y-size; move |= MOVE_Y; } } } // Trival tests to see if we're in region resize = full_resize(); if (!resize){ if (row_header()){ size = row_height(-1); resize |= (ey>=Y && ey<=Y+size+FUDGE && inh); } if (!resize){ if (row_footer()){ size = row_height(-2); resize |= (ey<=Y+H && ey>=Y+H-size-FUDGE && inh); } if (!resize){ if (col_header()){ size = col_width(-1); resize |= (ex>=X && ex<=X+size+FUDGE && inh); } if (!resize){ if (col_footer()){ size = col_width(-2); resize |= (ex<=X+W && ex>=X+W-size-FUDGE && inh); } } } } } if (!resize){ // In general region? if (cursor!=last_cursor) { fl_cursor(cursor,FL_BLACK,FL_WHITE); last_cursor = cursor; } return; } // ================================================================== // Sweep columns WW = X; if (col_header()) { size = col_width(-1); if (ex>=WW+size-FUDGE && ex<=WW+size+FUDGE && inv){ if (col_resizable(-1) && (move & MOVE_Y)==0){ drag_col = -1; anchor_left = WW; move |= MOVE_X; } } WW += size; X += size; W -= size; } if (col_footer()){ size = col_width(-2); if (ex>=X+W-size-FUDGE && ex<=X+W-size+FUDGE && inv){ if (col_resizable(-2)) { drag_col = -2; anchor_left = ex; move |= MOVE_X; } } W -= size; } if ( (move & MOVE_X)==0 ){ R = X-row_offset()+row_width()+FUDGE; // Right edge of row for (WW-=row_offset(),v=0 ; WW=WW+size-FUDGE && ex<=WW+size+FUDGE && inv){ if (col_resizable(v)){ drag_col = v; anchor_left = WW; move |= MOVE_X; // Moving col } break; } } } if (col_header()){ X-=col_width(-1); W+=col_width(-1); } if (col_footer()) W+=col_width(-2); // ================================================================== // Sweep rows WW = Y; if (row_header()){ size = row_height(-1); if (ey>=WW+size-FUDGE && ey<=WW+size+FUDGE && inh){ if (row_resizable(-1)){ drag_row = -1; anchor_top = WW; move |= MOVE_Y; } } WW += size; Y += size; H -= size; } if (row_footer()) { size = row_height(-2); if (ey>=Y+H-size-FUDGE && ey<=Y+H-size+FUDGE && inh){ if (row_resizable(-2)){ drag_row = -2; anchor_top = ey; move |= MOVE_Y; } } H -= size; } // end if(row_footer()) if ( (move & MOVE_Y)==0 ){ for (v=top_row(); v=Y+H) break; if (ey>=WW+size-FUDGE && ey<=WW+size+FUDGE && inh){ if (row_resizable(v)){ drag_row = v; anchor_top = WW; move |= MOVE_Y; // Moving } break; } } // end for } // end if move & MOVE_Y switch( move ){ case MOVE_X: cursor = FL_CURSOR_WE; drag_row=-4; break; case MOVE_Y: cursor = FL_CURSOR_NS; drag_col=-4; break; case MOVE_XY: cursor = FL_CURSOR_NWSE; break; default: drag_row = drag_col = -4; cursor = FL_CURSOR_DEFAULT; break; } if (cursor!=last_cursor){ fl_cursor(cursor,FL_BLACK,FL_WHITE); last_cursor = cursor; } } bool Flv_Table::move_row( int amount ) { Flv_Style s; int r = row(); if (!amount) return true; r += amount; if (r>=rows()) r = rows()-1; if (r<0) r = 0; while(!select_locked()) { get_style(s,r,col()); if (!s.locked()) break; r += (amount<0?-1:1); if ( r<0 || r>=rows() ) return false; } if (r!=row()) { row(r); return true; } return false; } bool Flv_Table::move_col( int amount ) { Flv_Style s; int c = col(); if (!amount) return true; c += amount; if (c>=cols()) c = cols()-1; if (c<0) c = 0; while(!select_locked()) { get_style(s,row(),c); if (!s.locked()) break; c += (amount<0?-1:1); if ( c<0 || c>=rows() ) return false; } if (c!=col()) { col(c); return true; } return false; } int Flv_Table::edit_when( int v ) { int wfocused = (Fl::focus()==veditor); if (v!=vedit_when) { vedit_when = v; if (vedit_when!=FLV_EDIT_ALWAYS) end_edit(); else start_edit(); } if (wfocused && !vediting) { Fl::focus(this); // take_focus(); redraw(); } return vedit_when; } void Flv_Table::start_edit(void) // Start editing { if (!vediting) { vediting = true; switch_editor( row(), col() ); } } void Flv_Table::end_edit(void) { int wfocused = (Fl::focus()==veditor); if (veditor) switch_editor(-1,-1); if (wfocused && !vediting) { Fl::focus(this); // take_focus(); redraw(); } } void Flv_Table::cancel_edit(void) // Cancel editing { int wfocused = (Fl::focus()==veditor); if (veditor) { veditor->hide(); veditor->draw(); } veditor = NULL; edit_row = -1; edit_col = -1; vediting = false; // switch_editor(-1, -1); if (wfocused && !vediting) { Fl::focus(this); // take_focus(); redraw(); } } void Flv_Table::switch_editor( int nr, int nc ) { Flv_Style s; int x, y, w, h, wfocused; char buf[30]; wfocused = (Fl::focus()==veditor); if (veditor) { if (edit_row>-1 && edit_col>-1) save_editor( veditor, edit_row, edit_col ); edit_row=-1; edit_col=-1; veditor->hide(); veditor->draw(); veditor = NULL; } if (edit_when()==FLV_EDIT_ALWAYS) { vediting = true; if (nr<0) nr = row(); if (nc<0) nc = col(); } if (nr>-1 && nc>-1 && vediting) { get_style( s, nr, nc ); if (s.editor_defined() && !s.locked()) { veditor = s.editor(); if (veditor) { edit_row = nr; edit_col = nc; veditor->hide(); get_cell_bounds(x,y,w,h,nr,nc); position_editor(veditor, x,y,w,h, s); load_editor( veditor, nr, nc ); veditor->show(); Fl::focus(veditor); // veditor->take_focus(); veditor->handle(FL_FOCUS); veditor->damage(FL_DAMAGE_ALL); veditor->draw(); } } } if (!veditor) { vediting=false; edit_row=-1; edit_col=-1; } if (!veditor && wfocused) { Fl::focus(this); // take_focus(); handle(FL_FOCUS); } } #endif