/** * Copyright Mikael Högdahl - triyana@users.sourceforge.net * * This source is distributed under the terms of the Q Public License version 1.0, * created by Trolltech (www.trolltech.com). */ #include "Fl_Table.h" #include "Fl_Table_Data.h" #include "Fl_Select.h" #include "Fl_Find.h" #include "Fl_Defines.h" #include #include #include #include #include #include #include #include #include #include #include #include #include /** * Callback for vertical scrollbar */ void Fl_Table::cb_ver (Fl_Widget* w, void* o) { ((Fl_Table*)o)->cb_ver(); } /** * Callback for horizontal scrollbar */ void Fl_Table::cb_hor (Fl_Widget* w, void* o) { ((Fl_Table*)o)->cb_hor(); } /** * Create table widget * @param Fl_Table_Data - Data object * @param int - X pos * @param int - Y pos * @param int - Width * @param int - Height */ Fl_Table::Fl_Table (Fl_Window* dlgParent, Fl_Table_Data* data, int x, int y, int w, int h) : Fl_Group (x, y, w, h, 0) { aData = data; aDlgParent = dlgParent; aCurrCol = 0; aCurrRow = 0; aStartCol = 0; aStartRow = 0; aWidth = 0; aVisibleRows = 0; aMaxVisibleRows = 0; aVisibleCols = 0; aWidth = 0; aClipped = 0; *aSearchWord = '\0'; aCase = false; aEditWidget = 0; aDragState = DRAG_NONE; aEventHandler = 0; aFind = new Fl_Find (); begin(); aDummy = new Fl_Input (0, 0, 0, 0); aScrollbarVer = new Fl_Scrollbar (x + w - SCROLL_SIZE, y, SCROLL_SIZE, h - SCROLL_SIZE); aScrollbarHor = new Fl_Scrollbar (x, y + h - SCROLL_SIZE, w - SCROLL_SIZE, SCROLL_SIZE); end(); box (FL_DOWN_BOX); color (FL_WHITE); aScrollbarVer->callback (cb_ver, this); aScrollbarHor->callback (cb_hor, this); aScrollbarHor->type (FL_HORIZONTAL); aScrollbarVer->slider_size (0.08); aScrollbarHor->slider_size (0.08); set_data_size (); Fl::focus (this); remove (aDummy); } /** * Delete table object */ Fl_Table::~Fl_Table () { quit_edit_mode (false); delete aData; delete []aWidth; delete aDummy; delete aFind; } /** * Add new row at the end of table */ void Fl_Table::add () { aData->add (); aCurrRow = aData->rows() - 1; if (aData->rows() >= aMaxVisibleRows) { aStartRow = aData->rows() - aMaxVisibleRows + 1; if (aStartRow < 0) aStartRow = 0; } set_data_size(); if (aEventHandler) aEventHandler->handle (FL_DATA_CHANGE); redraw(); } /** * Scrollbar has changed it position */ void Fl_Table::cb_hor () { aStartCol = aScrollbarHor->value (); quit_edit_mode (true); redraw (); } /** * Scrollbar has changed it position */ void Fl_Table::cb_ver () { aStartRow = aScrollbarVer->value (); quit_edit_mode (true); redraw (); } /** * Create a clip rectangle. * You must call fl_pop_clip after * @return int - CLIP_COL | CLIP_ROW if width or height has shrinked/changed */ int Fl_Table::clip (int xpos, int ypos, int width, int height, int row) { int retVal = 0; int win_width = x() + w() - ((row == FL_LABEL_ROW) ? 0 : (SCROLL_SIZE)); int win_height = y() + h() - ((row == FL_LABEL_ROW) ? 0 : (SCROLL_SIZE)); if ((xpos + width) >= win_width) { width = win_width - xpos; retVal |= CLIP_COL; } if ((ypos + height) > win_height) { height = win_height - ypos; retVal |= CLIP_ROW; } fl_clip (xpos, ypos, width, height); return retVal; } /** * Set new data source */ void Fl_Table::data (Fl_Table_Data* data) { delete aData; aData = data; set_data_size(); aCurrRow = aData->rows () - 1; aCurrCol = 0; aStartCol = 0; aStartRow = aCurrRow - (h() / aData->height(aCurrRow)) + 4; if (aStartRow < 0) aStartRow = 0; if (aStartCol < 0) aStartCol = 0; ((Fl_Valuator*)aScrollbarVer)->value (aStartRow); aScrollbarHor->slider_size (0.25); aScrollbarVer->slider_size (0.25); } /** * Draw lable, header and all cells. */ void Fl_Table::draw () { int xpos = x() + 1; int ypos = y() + 1; int foo = 1; Fl_Group::draw (); if (!aData) return; if (aData->show_label()) { draw_label (xpos + 1, ypos + foo); ypos += aData->height(FL_LABEL_ROW); foo = 0; } aVisibleCols = 0; if (aData->show_header()) { draw_header (xpos + 1, ypos + foo); ypos += aData->height (FL_HEADER_ROW); foo = 0; } aVisibleRows = aMaxVisibleRows = 0; aClipped = 1; aActiveX = aActiveY = aActiveW = aActiveH = aActiveR = aActiveC = -1; int clipped = 0; int lastHeight = 20; for (int f = aStartRow; f < aData->rows(); f++) { clipped = draw_row (f, xpos + 1, ypos + foo); if (clipped == CLIP_COL || clipped == CLIP_NONE) { aVisibleRows++; aMaxVisibleRows++; aClipped = 0; lastHeight = aData->height (f); ypos += lastHeight; } else break; } if (clipped != CLIP_ROW) aMaxVisibleRows += (y() + h() - ypos) / lastHeight; if (aEditWidget) { aEditWidget->redraw (); aEditWidget->draw (); Fl::focus (aEditWidget); } else if (aActiveH > -1) { clip (aActiveX, aActiveY, aActiveW, aActiveH); draw_cell (aActiveR, aActiveC, aActiveX, aActiveY, aActiveW, aActiveH); fl_pop_clip(); } } /** * Draw cell */ void Fl_Table::draw_cell (int row, int col, int xpos, int ypos, int width, int height) { int arow = row; if (row == aActiveR && col == aActiveC) arow = FL_ACTIVE_ROW; if (aData->editor_type(row, col, false) == FL_BOOL_EDITOR) { int addx = 2; int addy = (height / 2) - (aData->textsize (row, col) / 2) - 2; int size = aData->textsize (row, col) + 4; if (aData->align (row, col) == FL_ALIGN_RIGHT) addx = width - 4 - size; else if (aData->align (row, col) == FL_ALIGN_CENTER) addx = (width / 2) - (aData->textsize (row, col) / 2); draw_cell (xpos, ypos, width, height, aData->box_color (arow, col), aData->border_color (arow, col)); fl_draw_box (FL_DOWN_BOX, xpos + addx, ypos + addy, size, size, FL_WHITE); if (*aData->value (row, col) != '\0' && *aData->value (row, col) != '0') { fl_color (FL_BLACK); fl_line (xpos + addx + 3, ypos + addy + 3, xpos + addx + size - 4, ypos + addy + size - 4); fl_line (xpos + addx + size - 4, ypos + addy + 3, xpos + addx + 3, ypos + addy + size - 4); } } else if (aData->editor_type(row, col, false) == FL_SECRET_EDITOR) { draw_cell (xpos, ypos, width, height, aData->box_color (arow, col), aData->border_color (arow, col)); fl_font (aData->textfont (arow, col), aData->textsize (arow, col)); fl_color (aData->textcolor (arow, col)); fl_draw ("******", xpos + 2, ypos, width - 4, height, aData->align (arow, col)); } else { draw_cell (xpos, ypos, width, height, aData->box_color (arow, col), aData->border_color (arow, col)); fl_font (aData->textfont (arow, col), aData->textsize (arow, col)); fl_color (aData->textcolor (arow, col)); fl_draw (aData->value (row, col), xpos + 2, ypos, width - 4, height, aData->align (arow, col)); } } /** * Draw cell background area */ void Fl_Table::draw_cell (int x, int y, int w, int h, Fl_Color bg, Fl_Color fg) { fl_color (bg); fl_rectf (x, y, w, h); fl_color (fg); fl_rect (x, y, w, h); } /** * Draw table title */ void Fl_Table::draw_label (int xpos, int ypos) { int height = aData->height(FL_LABEL_ROW); int width = w() - 1; height--; clip (xpos, ypos, width, height, FL_LABEL_ROW); fl_draw_box (FL_UP_BOX, xpos, ypos, width - 1, height, aData->box_color (FL_LABEL_ROW, 0)); fl_font (aData->textfont (FL_LABEL_ROW, 0), aData->textsize (FL_LABEL_ROW, 0)); fl_color (aData->textcolor (FL_LABEL_ROW, 0)); fl_draw (aData->value(FL_LABEL_ROW, 0), xpos + 2, ypos, width - 4, height, FL_ALIGN_CENTER); fl_pop_clip (); } /** * Draw table header */ void Fl_Table::draw_header (int xpos, int ypos) { int height = aData->height(FL_HEADER_ROW); int width; int clipped; for (int f = aStartCol; f < aData->cols(); f++) { width = aWidth[f]; clipped = clip (xpos, ypos, width, height, FL_HEADER_ROW); fl_draw_box (FL_UP_BOX, xpos, ypos, width, height, aData->box_color (FL_HEADER_ROW, 0)); fl_font (aData->textfont (FL_HEADER_ROW, f), aData->textsize (FL_HEADER_ROW, f)); fl_color (aData->textcolor (FL_HEADER_ROW, f)); fl_draw (aData->value (FL_HEADER_ROW, f), xpos + 2, ypos, width - 4, height, aData->align (FL_HEADER_ROW, f)); fl_pop_clip (); if (clipped == CLIP_COL || clipped == CLIP_BOTH) return; else aVisibleCols++; xpos += aWidth[f]; } } /** * Draw table row, return true if row is clipped */ int Fl_Table::draw_row (int row, int xpos, int ypos) { int height; int width; int clipped = 0; for (int f = aStartCol; f < aData->cols(); f++) { height = aData->height(f); width = aWidth[f]; clipped = clip (xpos, ypos, width, height); height++; if (f < (aData->cols() - 1)) width++; if (row == (aData->rows() - 1)) height--; if (aEditWidget && row == aCurrRow && f == aCurrCol) aEditWidget->resize (xpos, ypos, width, height); else if (row == aCurrRow && f == aCurrCol) { // Save size and pos for drawing active box last, after all rows gave been drawn aActiveX = xpos; aActiveY = ypos; aActiveW = width; aActiveH = height; aActiveC = f; aActiveR = row; } else draw_cell (row, f, xpos, ypos, width, height); xpos += aWidth[f]; fl_pop_clip (); if (clipped == CLIP_COL) break; } return clipped; } /** * Start editing current row * @param bool - true to force use of the custom editor (FL_DLG_CUSTOM_EDITOR) flag */ void Fl_Table::edit (bool force_custom) { if (aEditWidget) { if (aData && aData->rows() > 0 && aCurrRow >= 0 && quit_edit_mode (true) == true) start_edit_mode (force_custom); } else start_edit_mode (force_custom); } /** * Erase current row */ void Fl_Table::erase () { aData->erase (aCurrRow); set_data_size(); set_cursor(aCurrRow, aCurrCol); if (aEventHandler) aEventHandler->handle (FL_DATA_CHANGE); redraw(); } /** * Mouse is dragged, change column size if right position */ void Fl_Table::ev_drag () { int xpos = Fl::event_x(); if (aDragState == DRAG_HOR) { int currx = x(); for (int f = aStartCol; f < aDragCol; f++) currx += aWidth[f]; if (xpos - currx > 10) aWidth[aDragCol] = xpos - currx; redraw (); } } /** * Keys are pressed down */ bool Fl_Table::ev_keyboard_down () { switch (Fl::event_key()) { case FL_Down: move_cursor (1, 0); break; case FL_Left: move_cursor (0, -1); break; case FL_Page_Down: if (Fl::event_state() == FL_CTRL) move_cursor (1999999999, 0); else move_cursor (SCROLL_JUMP, 0); break; case FL_Page_Up: if (Fl::event_state() == FL_CTRL) move_cursor (-1999999999, 0); else move_cursor (-SCROLL_JUMP, 0); break; case FL_Right: move_cursor (0, 1); break; case FL_Up: move_cursor (-1, 0); break; case FL_Escape: if (aEditWidget) quit_edit_mode (false); break; case FL_Enter: if (aEditWidget == 0) start_edit_mode (); else quit_edit_mode (true); break; default: if (Fl::event_state() == FL_ALT) return false; else if (Fl::event_state() == FL_CTRL) { //printf ("2 - %d\n", Fl::event_key()); switch (Fl::event_key()) { case 'a': case 'n': add (); break; case 'c': Fl::copy (aData->value (aCurrRow, aCurrCol), strlen (aData->value (aCurrRow, aCurrCol)), 1); break; case 'd': erase (); break; case 'f': find (false); break; case 'g': find (true); break; case 'i': insert (); break; case 's': if (dirty()) save (); break; case 'x': Fl::copy (aData->value (aCurrRow, aCurrCol), strlen (aData->value (aCurrRow, aCurrCol)), 1); aData->value ("", aCurrRow, aCurrCol); break; case 'v': aDummy->value (""); Fl::paste (*aDummy, 1); if (aData->value (aDummy->value(), aCurrRow, aCurrCol) == false && aEventHandler) aEventHandler->handle (FL_DATA_ERROR); break; case FL_Escape: break; } Fl::focus (this); redraw (); } break; } if (aCurrRow < 0) aCurrRow = 0; if (aCurrCol < 0) aCurrCol = 0; if (aCurrRow < aStartRow) aStartRow = aCurrRow; if (aCurrCol < aStartCol) aStartCol = aCurrCol; return true; } /** * Mouse is moved, check if user are above header. If so change mouse cursor if between cells. */ void Fl_Table::ev_move () { if (!aData) return; int xpos = Fl::event_x(); int ypos = Fl::event_y(); int currx = x(); int curry = y(); if (aData->show_label()) curry += (aData->textsize (FL_LABEL_ROW, 0) + ( aData->textsize (FL_LABEL_ROW, 0) / 2)); if (ypos > curry) { if (aData->show_header()) curry += aData->height (FL_HEADER_ROW); if (ypos < curry) { // Cursor is inside header for (int f = aStartCol; f < aData->cols(); f++) { currx += aWidth[f]; if (xpos > (currx - 3) && xpos < (currx + 4)) { aDragState = DRAG_HOR; aDragCol = f; fl_cursor (FL_CURSOR_WE); return; } } } } // Set cursor to standar one only if it was set to another cursor before if (aDragState != DRAG_NONE) { fl_cursor (FL_CURSOR_DEFAULT); aDragState = DRAG_NONE; } } /** * Mouse is pushed. * Select new current cell */ void Fl_Table::ev_push () { int xpos = Fl::event_x(); int ypos = Fl::event_y(); int row; int col; int c, d; get_cell_pos (row, col, xpos, ypos, c, d); if (aEditWidget) { if (row != aCurrRow || col != aCurrCol) { quit_edit_mode (true); Fl::focus (this); } else { aEditWidget->handle (FL_PUSH); aEditWidget->draw(); Fl::focus (aEditWidget); return; } } else Fl::focus (this); if (row <= FL_NO_ROW || col < 0) return; else if (row == FL_HEADER_ROW && col >= 0) { if (Fl::event_button() == FL_LEFT_MOUSE) aData->sort (col, true); else if (Fl::event_button() == FL_RIGHT_MOUSE) aData->sort (col, false); redraw (); } else if (row >= 0 && col >= 0 && (row != aCurrRow || col != aCurrCol)) { if (quit_edit_mode (true)) { aCurrRow = row; aCurrCol = col; redraw (); } } else { if (Fl::event_clicks() == 1) { if (aEditWidget == 0) start_edit_mode (); else quit_edit_mode (true); } } } /** * Search for text in cell. * Display a search dialog or continue to serach for next word */ void Fl_Table::find (bool nextword) { if (!aData) return; const char* searchWord = 0; const char* replaceWord = 0; bool found = false; char tmp[200]; int ret; int case_sense; int begin = 0; if (nextword == false || *aSearchWord == '\0') { ret = aFind->show_modal (aDlgParent); searchWord = aFind->text (); replaceWord = aFind->text (); case_sense = aFind->case_sensitive (); begin = aFind->beginning (); if (ret == 0) return; aCase = (case_sense == 1) ? true : false; if (searchWord && *searchWord) { strncpy (aSearchWord, searchWord, 199); if (aCase == false) { #ifdef WIN32 _strlwr (aSearchWord); #else char* f = aSearchWord; while (*f) { *f = tolower (*f); f++; } #endif } } else return; } for (int row = (begin == 0 ? aCurrRow : 0); row < aData->rows(); row++) { for (int col = (begin == 0 ? (row == aCurrRow ? aCurrCol + 1: 0) : 0); col < aData->cols(); col++) { if (aCase == false) { strncpy (tmp, aData->value (row, col), 199); #ifdef WIN32 _strlwr (tmp); #else char* f = tmp; while (*f) { *f = tolower (*f); f++; } #endif if (strstr (tmp, aSearchWord)) found = true; } else if (strstr (aData->value (row, col), aSearchWord)) found = true; if (found) { set_cursor (row, col); return; } } } fl_beep (FL_BEEP_ERROR); } /** * Get cell size and position */ void Fl_Table::get_cell_pos (int& row, int& col, int& xpos, int& ypos, int& width, int& height) { row = col = FL_NO_ROW; if (!aData) return; int currx = x(); int curry = y(); if (aData->show_label()) curry += (aData->height (FL_LABEL_ROW)); if (ypos < curry) { row = FL_LABEL_ROW; return; } if (aData->show_header()) curry += aData->height (FL_HEADER_ROW); if (ypos < curry) row = FL_HEADER_ROW; for (int c = aStartCol; c < aData->cols(); c++) { if (xpos > currx && xpos <= (currx + aWidth[c])) { col = c; xpos = currx; width = aWidth[c]; break; } else if (xpos > (x() + w() - aScrollbarVer->w())) break; currx += aWidth[c]; } if (row == FL_HEADER_ROW) return; for (int r = aStartRow; r < aData->rows(); r++) { if (ypos >= curry && ypos < (curry + aData->height(r))) { row = r; ypos = curry; height = aData->height(r); break; } else if (ypos > (y() + h() - aScrollbarHor->h())) break; curry += aData->height(r); } } /** * All events goes here * @param int - Event */ int Fl_Table::handle (int event) { if (!aData) return Fl_Group::handle (event); switch (event) { case FL_DRAG: ev_drag (); return 1; case FL_KEYDOWN: if (ev_keyboard_down ()) return 1; else break; case FL_KEYUP: if (aEditWidget) aEditWidget->redraw(); return 0; case FL_LEAVE: if (aDragState != DRAG_NONE) { fl_cursor (FL_CURSOR_DEFAULT); aDragState = DRAG_NONE; } return 0; case FL_MOVE: ev_move (); return 0; case FL_PUSH: ev_push (); Fl_Group::handle (event); return 1; default: break; } return Fl_Group::handle (event); } /** * Insert row at current position */ void Fl_Table::insert () { aData->insert (aCurrRow); set_data_size(); set_cursor(aCurrRow, aCurrCol); if (aEventHandler) aEventHandler->handle (FL_DATA_CHANGE); redraw(); } /** * Move cursor from current position * @param int - Number of rows to move cursor * @param int - Number of columns to move cursor */ void Fl_Table::move_cursor (int rows, int cols) { if (aEditWidget) return; if (!aData || aData->rows() == 0 || aData->cols() == 0) return; aCurrRow += rows; if (aVisibleRows > 1) { if (aCurrRow < aStartRow) aStartRow = aCurrRow; if (aCurrRow > (aStartRow + aVisibleRows - 1)) aStartRow = aCurrRow - aVisibleRows + 1; } else aStartRow = aCurrRow; if (aCurrRow >= aData->rows()) aCurrRow = aData->rows() - 1; if (aCurrRow < 0) aCurrRow = 0; if (aStartRow >= aData->rows() || aStartRow < 0) aStartRow = aCurrRow; aCurrCol += cols; if (aVisibleCols > 1) { if (aCurrCol < aStartCol) aStartCol = aCurrCol; if (aCurrCol > (aStartCol + aVisibleCols - 1)) aStartCol = aCurrCol - aVisibleCols + 1; } else aStartCol = aCurrCol; if (aCurrCol >= aData->cols()) aCurrCol = aData->cols() - 1; if (aCurrCol < 0) aCurrCol = 0; if (aStartCol >= aData->cols() || aStartCol < 0) aStartCol = aCurrCol; ((Fl_Valuator*)aScrollbarVer)->value ((double)aStartRow); ((Fl_Valuator*)aScrollbarHor)->value ((double)aStartCol); redraw (); } bool Fl_Table::quit_edit_mode (bool save) { if (aEditWidget) { const char** list; int row; int a, b; bool stop = true; char label[100]; if (save) { switch (aData->editor_type(aCurrRow, aCurrCol, false)) { case FL_BOOL_EDITOR: if (((Fl_Check_Button*)aEditWidget)->value() == 0) stop = aData->value ("\0", aCurrRow, aCurrCol); else stop = aData->value ("\1", aCurrRow, aCurrCol); break; case FL_LIST_EDITOR: row = ((Fl_Choice*)aEditWidget)->value (); list = aData->choice (aCurrRow, aCurrCol, a, b, label); stop = aData->value (list[row], aCurrRow, aCurrCol); break; default: stop = aData->value (((Fl_Input*)aEditWidget)->value(), aCurrRow, aCurrCol); break; } } if (stop == true) { remove (aEditWidget); delete aEditWidget; aEditWidget = 0; if (aEventHandler) aEventHandler->handle (FL_DATA_CHANGE); } else { fl_beep (FL_BEEP_ERROR); if (aEventHandler) aEventHandler->handle (FL_DATA_ERROR); aEditWidget->redraw (); Fl::focus (aEditWidget); return false; } } Fl::focus (this); redraw (); return true; } /** * Resize table and scrollbars. * @param int - X pos * @param int - Y pos * @param int - Width * @param int - Height */ void Fl_Table::resize (int x, int y, int w, int h) { Fl_Group::resize (x, y, w, h); int hfix = (aData && aData->show_label()) ? aData->height(FL_LABEL_ROW) : 0; int yfix = (aData && aData->show_label()) ? 0 : 2; aScrollbarVer->resize (x + w - SCROLL_SIZE, y + hfix + yfix, SCROLL_SIZE, h - hfix - yfix); aScrollbarHor->resize (x, y + h - SCROLL_SIZE, w - SCROLL_SIZE, SCROLL_SIZE); } /** * Let data save itself */ bool Fl_Table::save () { int row = aData->save (); if (row < 0) { if (aEventHandler) aEventHandler->handle (FL_DATA_SAVE); set_data_size(); redraw (); return true; } else { if (aEventHandler) aEventHandler->handle (FL_DATA_SAVE_ERROR); set_cursor (row, 0); redraw (); return false; } } /** * Start to edit a cell */ void Fl_Table::start_edit_mode (bool force_custom) { if (aData->editor_type (aCurrRow, aCurrCol, false) == FL_DLG_COLOR_EDITOR) { int col = atoi (aData->value(aCurrRow, aCurrCol)); if (col < 0 || col > 255) col = 0; int newcol = fl_show_colormap ((Fl_Color) col); char buff [31]; SNPRINTF (buff, 30, "%d", newcol); aData->value (buff, aCurrRow, aCurrCol); } else if (aData->editor_type (aCurrRow, aCurrCol, false) == FL_DLG_DIR_EDITOR) { char* dir = fl_dir_chooser("Select Directory", aData->value(aCurrRow, aCurrCol)); aData->value (dir, aCurrRow, aCurrCol); } else if (aData->editor_type (aCurrRow, aCurrCol, false) == FL_DLG_FILE_EDITOR) { char* file = fl_file_chooser("Select File", "*", aData->value(aCurrRow, aCurrCol)); aData->value (file, aCurrRow, aCurrCol); } else { aEditWidget = aData->editor (aCurrRow, aCurrCol, force_custom); if (!aEditWidget) return; switch (aData->editor_type(aCurrRow, aCurrCol, force_custom)) { case FL_DLG_LIST_EDITOR: { if (aEditWidget) { // This is a dialog popup mode and when dialog close the editing also stops Fl_Select* dlg = (Fl_Select*) aEditWidget; bool ok = false; Fl::event_clicks (0); if (dlg && dlg->show_modal (aDlgParent) == 1 && dlg->row () > 0) { int a, b; char label[100]; const char** list = aData->choice (aCurrRow, aCurrCol, a, b, label); ok = aData->value (list[dlg->row () - 1], aCurrRow, aCurrCol); } delete dlg; aEditWidget = 0; if (aEventHandler && ok) aEventHandler->handle (FL_DATA_CHANGE); } Fl::focus (this); break; } case FL_DLG_CUSTOM_EDITOR: { Fl_Dialog* dlg = (Fl_Dialog*) aEditWidget; bool ok = false; Fl::event_clicks (0); if (dlg) { if (dlg->show_modal (aDlgParent) == 1) { ok = true; // Dialog has changed data, make sure current data object nows that aData->dirty (true); } } delete dlg; aEditWidget = 0; if (aEventHandler && ok) aEventHandler->handle (FL_DATA_CHANGE); Fl::focus (this); break; } default: Fl_Group::add (aEditWidget); Fl::focus (aEditWidget); aEditWidget->draw (); break; } } redraw (); } /** * Set size of columns and scrollbar values */ void Fl_Table::set_data_size () { if (!aData) return; aScrollbarVer->range (0, aData->rows()); aScrollbarHor->range (0, aData->cols()); delete []aWidth; aWidth = new int[aData->cols() + 1]; for (int f = 0; f < aData->cols(); f++) aWidth[f] = aData->width (f); redraw(); }