table_panel.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:49k
- /*
- * ===========================================================================
- * PRODUCTION $Log: table_panel.hpp,v $
- * PRODUCTION Revision 1000.4 2004/06/01 19:52:33 gouriano
- * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
- * PRODUCTION
- * ===========================================================================
- */
- #ifndef GUI_WIDGETS_TABLE___TABLE_PANEL__HPP
- #define GUI_WIDGETS_TABLE___TABLE_PANEL__HPP
- /* $Id: table_panel.hpp,v 1000.4 2004/06/01 19:52:33 gouriano Exp $
- * ===========================================================================
- *
- * PUBLIC DOMAIN NOTICE
- * National Center for Biotechnology Information
- *
- * This software/database is a "United States Government Work" under the
- * terms of the United States Copyright Act. It was written as part of
- * the author's official duties as a United States Government employee and
- * thus cannot be copyrighted. This software/database is freely available
- * to the public for use. The National Library of Medicine and the U.S.
- * Government have not placed any restriction on its use or reproduction.
- *
- * Although all reasonable efforts have been taken to ensure the accuracy
- * and reliability of the software and data, the NLM and the U.S.
- * Government do not and cannot warrant the performance or results that
- * may be obtained by using this software or data. The NLM and the U.S.
- * Government disclaim all warranties, express or implied, including
- * warranties of performance, merchantability or fitness for any particular
- * purpose.
- *
- * Please cite the author in any work or product based on this material.
- *
- * ===========================================================================
- *
- * Authors: Mike DiCuccio
- *
- * File Description:
- * CTablePanel -- Extends Flv_Table to provide notions of hidden and visible
- * columns
- * CListPanel -- Extends CTablePanel to provide a row-selectable
- * multicolumn list widget that stores arbitrary data with
- * each row.
- */
- #include <corelib/ncbiobj.hpp>
- #include <gui/gui.hpp>
- #include <FL/Enumerations.H>
- #include <FL/Fl.H>
- #include <FL/fl_draw.H>
- #include <gui/widgets/Fl_Table/Fl_Table_Row.H>
- #include <gui/utils/fltk_utils.hpp>
- #include <algorithm>
- #include <memory>
- #include <string>
- #include <vector>
- /** @addtogroup GUI_FltkWidgets
- *
- * @{
- */
- BEGIN_NCBI_SCOPE
- class NCBI_GUIWIDGETS_TABLE_EXPORT CTablePanelBase : public Fl_Table_Row
- {
- public:
- CTablePanelBase(int x, int y, int w, int h, const char* label = NULL);
- // safe (virtual) accessors
- virtual size_t GetRows() const;
- virtual void SetRows(size_t r);
- virtual size_t GetCols() const;
- virtual void SetCols(size_t c);
- // overrides from Fl_Table_Row (these may be dangerous - they're not
- // virtual)
- void rows(int r);
- int rows() const;
- void cols(int c);
- int cols() const;
- // draw() - enforces clipping
- void draw();
- // handle() - traps double-clicks on headers
- int handle(int event);
- // check if a given row is selected. The base class row_selected() is
- // non-const, for reasons that baffle me.
- bool IsRowSelected(size_t row) const;
- // access the FLTK box type used for drawing a cell
- Fl_Boxtype GetCellBox(void) const;
- void SetCellBox(CFltkUtils::EBoxType);
- void SetCellBox(Fl_Boxtype);
- // access the FLTK box type used for drawing row header cells
- Fl_Boxtype GetRowHeaderBox(void) const;
- void SetRowHeaderBox(CFltkUtils::EBoxType);
- void SetRowHeaderBox(Fl_Boxtype);
- Fl_Boxtype GetColHeaderBox(void) const;
- void SetColHeaderBox(CFltkUtils::EBoxType);
- void SetColHeaderBox(Fl_Boxtype);
- // set the box type for both rows and cols simultaneously
- void SetHeaderBox(Fl_Boxtype);
- void SetHeaderBox(CFltkUtils::EBoxType);
- protected:
- // GUI event processor
- CGUIEvent m_Handler;
- // box styles for cells and headers
- Fl_Boxtype m_CellBox;
- Fl_Boxtype m_RowHeaderBox;
- Fl_Boxtype m_ColHeaderBox;
- // internal handlers for cut/copy/paste operations
- virtual int x_OnCut();
- virtual int x_OnCopy();
- virtual int x_OnPaste();
- // internal handlers for header cell clicks
- virtual int x_HandleRowHeaderClick(size_t row);
- virtual int x_HandleColHeaderClick(size_t col);
- virtual int x_HandleCellClick(size_t row, size_t col);
- };
- class CColumnSelectDlg;
- //
- // clas ITableData defines the data interface used by all table classes
- //
- template <class RowData>
- class ITableData : public CObject
- {
- public:
- virtual ~ITableData() {}
- virtual void Reserve (size_t rows, size_t cols) = 0;
- virtual void SetSize (size_t rows, size_t cols) = 0;
- virtual void SetRows (size_t rows) = 0;
- virtual void SetCols (size_t cols) = 0;
- virtual void AddRow (void) = 0;
- virtual void RemoveRow(size_t row) = 0;
- virtual size_t GetRows (void) const = 0;
- virtual size_t GetCols (void) const = 0;
- virtual const vector<string>& GetRow(size_t row) const = 0;
- virtual vector<string>& SetRow(size_t row) = 0;
- virtual const string& GetCell(size_t row, size_t col) const = 0;
- virtual string& SetCell(size_t row, size_t col) = 0;
- virtual const string& GetRowHeader(size_t row) const = 0;
- virtual string& SetRowHeader(size_t row) = 0;
- // access a given row's data
- virtual const RowData& GetData(size_t row) const = 0;
- virtual RowData& SetData(size_t row) = 0;
- // sort the data
- virtual void SortByCol(size_t col, bool ascending, bool numeric) = 0;
- };
- //
- // class CTableData defines a specialization of the table data
- // structure with a concrete type stored in each row
- //
- template <class RowData>
- class CTableData : public ITableData<RowData>
- {
- public:
- CTableData();
- // interface requirements
- virtual void Reserve (size_t rows, size_t cols);
- virtual void SetSize (size_t rows, size_t cols);
- virtual void SetRows (size_t rows);
- virtual void SetCols (size_t cols);
- virtual void AddRow (void);
- virtual void RemoveRow(size_t row);
- virtual size_t GetRows (void) const;
- virtual size_t GetCols (void) const;
- virtual const vector<string>& GetRow(size_t row) const;
- virtual vector<string>& SetRow(size_t row);
- virtual const string& GetCell(size_t row, size_t col) const;
- virtual string& SetCell(size_t row, size_t col);
- virtual const string& GetRowHeader(size_t row) const;
- virtual string& SetRowHeader(size_t row);
- // access a given row's data
- const RowData& GetData(size_t row) const;
- RowData& SetData(size_t row);
- // sort the data
- void SortByCol(size_t col, bool ascending, bool numeric);
- private:
- // typedefs and nested classes for our columns and data
- // NB: these are public to avoid compiler errors regarding use of a
- // protected typedef in a protected nested class
- class CRow
- {
- public:
- RowData m_Data;
- string m_RowHeader;
- vector<string> m_Columns;
- };
- typedef CRow TRow;
- typedef vector<TRow> TTable;
- size_t m_Cols;
- TTable m_Data;
- //
- // internal functors for sorting columns
- //
- struct SColSorter {
- size_t col_idx;
- bool sort_ascending;
- bool sort_numeric;
- SColSorter(size_t col, bool asc, bool numeric)
- : col_idx(col),
- sort_ascending(asc),
- sort_numeric(numeric) { }
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- _ASSERT(col_idx < row0.m_Columns.size());
- _ASSERT(col_idx < row1.m_Columns.size());
- _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
- if (sort_ascending) {
- if (sort_numeric) {
- return (NStr::StringToDouble(row0.m_Columns[col_idx]) <
- NStr::StringToDouble(row1.m_Columns[col_idx]));
- } else {
- return (row0.m_Columns[col_idx] < row1.m_Columns[col_idx]);
- }
- } else {
- if (sort_numeric) {
- return (NStr::StringToDouble(row0.m_Columns[col_idx]) >
- NStr::StringToDouble(row1.m_Columns[col_idx]));
- } else {
- return (row0.m_Columns[col_idx] > row1.m_Columns[col_idx]);
- }
- }
- }
- };
- struct SColSorter_Asc_Numeric {
- size_t col_idx;
- SColSorter_Asc_Numeric(size_t col)
- : col_idx(col) { }
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- _ASSERT(col_idx < row0.m_Columns.size());
- _ASSERT(col_idx < row1.m_Columns.size());
- _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
- return (NStr::StringToDouble(row0.m_Columns[col_idx]) <
- NStr::StringToDouble(row1.m_Columns[col_idx]));
- }
- };
- struct SColSorter_Desc_Numeric {
- size_t col_idx;
- SColSorter_Desc_Numeric(size_t col)
- : col_idx(col) { }
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- _ASSERT(col_idx < row0.m_Columns.size());
- _ASSERT(col_idx < row1.m_Columns.size());
- _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
- return (NStr::StringToDouble(row0.m_Columns[col_idx]) >
- NStr::StringToDouble(row1.m_Columns[col_idx]));
- }
- };
- struct SColSorter_Asc_Text {
- size_t col_idx;
- SColSorter_Asc_Text(size_t col)
- : col_idx(col) { }
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- _ASSERT(col_idx < row0.m_Columns.size());
- _ASSERT(col_idx < row1.m_Columns.size());
- _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
- return (row0.m_Columns[col_idx] < row1.m_Columns[col_idx]);
- }
- };
- struct SColSorter_Desc_Text {
- size_t col_idx;
- SColSorter_Desc_Text(size_t col)
- : col_idx(col) { }
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- _ASSERT(col_idx < row0.m_Columns.size());
- _ASSERT(col_idx < row1.m_Columns.size());
- _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
- return (row0.m_Columns[col_idx] > row1.m_Columns[col_idx]);
- }
- };
- };
- //
- // class CTablePanel extends Fl_Table with a few convenience functions.
- //
- // The main provision is for things such as uniform handling of column headers,
- // widths, alignments, and visibility.
- //
- template <class RowData>
- class CTablePanel : public CTablePanelBase
- {
- public:
- typedef ITableData<RowData> TTableData;
- // enumerated list of sort states for our columns
- enum ESortState {
- eNotSorted,
- eAscending,
- eDescending
- };
- // enumerated list of column representations
- enum EColumnType {
- eString,
- eNumeric
- };
- CTablePanel(int x, int y, int w, int h, const char* label = NULL);
- virtual ~CTablePanel() { }
- // clear the contents of the table
- virtual void Clear();
- // reserve space in the table for a certain number of rows
- void Reserve(size_t rows, size_t cols);
- void Reserve(size_t rows);
- // set the size of the table in rows and cols
- void SetSize(size_t rows, size_t cols);
- // set the number of rows in the table
- void SetRows(size_t rows);
- // set the number of columns in the table
- void SetCols(size_t cols);
- // get the number of rows in the table
- size_t GetRows(void) const;
- // get the number of columns in the table
- size_t GetCols(void) const;
- // add a row to the table, returning its index
- size_t AddRow (void);
- // remove a row to the table, returning its index
- void RemoveRow(size_t row);
- // return a single row from the table
- const vector<string>& GetRow(size_t row) const;
- vector<string>& SetRow(size_t row);
- // access a single cell in the table
- const string& GetCell(size_t row, size_t col) const;
- string& SetCell(size_t row, size_t col);
- void SetCell(size_t row, size_t col, const string& val);
- // access the row headers
- const string& GetRowHeader(size_t row) const;
- string& SetRowHeader(size_t row);
- void SetRowHeader(size_t row, const string& val);
- // access the col headers
- const string& GetColHeader(size_t col) const;
- string& SetColHeader(size_t col);
- void SetColHeader(size_t col, const string& val);
- // access a given row's data
- const RowData& GetData(size_t row) const;
- RowData& SetData(size_t row);
- void SetData(size_t row, const RowData& data);
- // FLTK overload: resize the widget
- virtual void resize(int x, int y, int w, int h);
- // get/set the column data type. This determines behavior on sorting.
- void SetColType(size_t col, EColumnType type);
- EColumnType GetColType(size_t col) const;
- // get/set the column relative widths
- // These are a vector of floats that will be normalized ( = sum to 1.0) to
- // compute actual widths
- void SetRelWidth(size_t col, float width_frac);
- float GetRelWidth(size_t col) const;
- // get/set the absolute column widths, in pixels
- void SetWidth(size_t col, float width);
- float GetWidth(size_t col) const;
- // set the default alignment for a given column
- void SetColAlign(size_t col, Fl_Align align);
- Fl_Align GetColAlign(size_t col) const;
- // set all column parameters at once
- void SetColumn(size_t col, const string& header, EColumnType type,
- Fl_Align align, float rel_width);
- // function to set up the width and alignments for the current
- // visible columns.
- void SetupColumns();
- // sort by an indicated column in a given sort order
- void SortByCol(size_t col_idx, ESortState sort_order = eAscending);
- // set the virtual column for a given index
- void SetVirtualCol(int visible_col, int actual_col);
- // clear all virtual columns. NOTE: this will leave the table with no
- // columns!
- void ClearVirtualCols();
- // show the column selector dialog and process its results. This allows
- // users to select from the list of virtual columns.
- //void ShowColSelectDlg();
- protected:
- CRef<TTableData> m_Data;
- // safe accessors for m_Data
- TTableData& x_SetData(void);
- const TTableData& x_GetData(void) const;
- // general information we store concerning columns
- // this allows us to be smart about such things as sorting, visibility,
- // etc.
- struct SColInfo {
- SColInfo()
- : align(FL_ALIGN_LEFT),
- width_frac(1.0f),
- width(100.0f),
- sort_state(eNotSorted) {}
- string header;
- Fl_Align align;
- float width_frac;
- float width;
- ESortState sort_state;
- EColumnType type;
- };
- typedef vector<SColInfo> TColInfo;
- TColInfo m_ColInfo;
- // FLTK overloads
- virtual void draw_cell(TableContext ctx, int row, int col,
- int x, int y, int w, int h);
- // get the foreground color associated with a given row. This is virtual
- // to permit derived classes to easily change what the color will be, based
- // on criteria not known to this class
- virtual Fl_Color x_GetRowForegroundColor(size_t row);
- virtual Fl_Color x_GetRowBackgroundColor(size_t row);
- // handle column header clicks for sorting
- int x_HandleColHeaderClick(size_t col);
- // our virtual columns.
- // We store or represent internally a number of columns potentially larger
- // than that whic we display. This allows for a high degree of
- // customization - the user could theoretically select which columns to
- // display and the order of display as well.
- vector<size_t> m_VirtCols;
- // a dialog that allows us to select columns for viewing
- //auto_ptr<CColumnSelectDlg> m_SelectDlg;
- // virtual function to adjust internal structures to fit a certain number
- // of columns. These are real, not virtual, columns!
- //virtual void x_SetNumColumns(int cols);
- };
- //////////////////////////////////////////////////////////////
- //
- // CTableData implementation
- //
- template <class RowData>
- inline CTableData<RowData>::CTableData()
- : m_Cols(0)
- {
- }
- template <class RowData>
- inline void CTableData<RowData>::Reserve(size_t rows, size_t cols)
- {
- if (cols > GetCols()) {
- SetCols(cols);
- }
- m_Data.reserve(rows);
- }
- template <class RowData>
- inline void CTableData<RowData>::SetSize(size_t rows, size_t cols)
- {
- SetCols(cols);
- SetRows(rows);
- }
- template <class RowData>
- inline void CTableData<RowData>::SetCols(size_t cols)
- {
- NON_CONST_ITERATE (typename TTable, iter, m_Data) {
- iter->m_Columns.resize(cols);
- }
- m_Cols = cols;
- }
- template <class RowData>
- inline void CTableData<RowData>::SetRows(size_t rows)
- {
- m_Data.resize(rows);
- NON_CONST_ITERATE (typename TTable, iter, m_Data) {
- iter->m_Columns.resize(m_Cols);
- }
- }
- template <class RowData>
- inline void CTableData<RowData>::AddRow(void)
- {
- TRow row;
- row.m_Columns.resize(GetCols());
- m_Data.push_back(row);
- }
- template <class RowData>
- inline void CTableData<RowData>::RemoveRow(size_t idx)
- {
- _ASSERT(idx < GetRows());
- m_Data.erase(m_Data.begin() + idx);
- }
- template <class RowData>
- inline size_t CTableData<RowData>::GetRows(void) const
- {
- return m_Data.size();
- }
- template <class RowData>
- inline size_t CTableData<RowData>::GetCols(void) const
- {
- return m_Cols;
- }
- template <class RowData>
- inline const RowData&
- CTableData<RowData>::GetData(size_t row) const
- {
- _ASSERT(row < GetRows());
- return m_Data[row].m_Data;
- }
- template <class RowData>
- inline RowData&
- CTableData<RowData>::SetData(size_t row)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- return m_Data[row].m_Data;
- }
- template <class RowData>
- inline const vector<string>&
- CTableData<RowData>::GetRow(size_t row) const
- {
- _ASSERT(row < GetRows());
- return m_Data[row].m_Columns;
- }
- template <class RowData>
- inline vector<string>&
- CTableData<RowData>::SetRow(size_t row)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- return m_Data[row].m_Columns;
- }
- template <class RowData>
- inline const string&
- CTableData<RowData>::GetCell(size_t row, size_t col) const
- {
- _ASSERT(row < GetRows());
- _ASSERT(col < GetCols());
- return m_Data[row].m_Columns[col];
- }
- template <class RowData>
- inline string&
- CTableData<RowData>::SetCell(size_t row, size_t col)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- _ASSERT(row < GetRows());
- _ASSERT(col < GetCols());
- return m_Data[row].m_Columns[col];
- }
- template <class RowData>
- inline const string&
- CTableData<RowData>::GetRowHeader(size_t row) const
- {
- _ASSERT(row < GetRows());
- return m_Data[row].m_RowHeader;
- }
- template <class RowData>
- inline string&
- CTableData<RowData>::SetRowHeader(size_t row)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- return m_Data[row].m_RowHeader;
- }
- template <class RowData>
- inline void
- CTableData<RowData>::SortByCol(size_t col_idx, bool ascending, bool numeric)
- {
- _ASSERT(col_idx < GetCols());
- if (ascending) {
- if (numeric) {
- SColSorter_Asc_Numeric sorter(col_idx);
- std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
- } else {
- SColSorter_Asc_Text sorter(col_idx);
- std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
- }
- } else {
- if (numeric) {
- SColSorter_Desc_Numeric sorter(col_idx);
- std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
- } else {
- SColSorter_Desc_Text sorter(col_idx);
- std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
- }
- }
- }
- //////////////////////////////////////////////////////////////
- //
- // CTablePanel implementation
- //
- template <class RowData>
- inline
- CTablePanel<RowData>::CTablePanel(int x, int y, int w, int h,
- const char* label)
- : CTablePanelBase(x, y, w, h, label)
- {
- // this creates a dummy data class for us
- x_SetData();
- row_header(false);
- col_header(true);
- col_resize(RESIZE_ROW_BELOW);
- }
- //
- // get the data object associated with a single row
- //
- template <class RowData>
- inline
- const RowData& CTablePanel<RowData>::GetData(size_t row) const
- {
- _ASSERT(row < GetRows());
- return x_GetData().GetData(row);
- }
- template <class RowData>
- inline
- RowData& CTablePanel<RowData>::SetData(size_t row)
- {
- return x_SetData().SetData(row);
- }
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetData(size_t row, const RowData& data)
- {
- x_SetData().SetData(row) = data;
- }
- //
- // get the data class associated with the table
- // this makes no assumptions about whether the data class is valid
- //
- template <class RowData>
- inline
- const typename CTablePanel<RowData>::TTableData&
- CTablePanel<RowData>::x_GetData(void) const
- {
- _ASSERT(m_Data);
- return *m_Data;
- }
- //
- // get the data class in non-const form. If the data class isn't present,
- // a default one is created.
- //
- template <class RowData>
- inline
- typename CTablePanel<RowData>::TTableData&
- CTablePanel<RowData>::x_SetData(void)
- {
- if ( !m_Data ) {
- m_Data.Reset(new CTableData<RowData>());
- m_Data->SetCols(GetCols());
- m_Data->SetRows(GetRows());
- }
- _ASSERT(m_Data);
- return *m_Data;
- }
- // reserve space in the table for a certain number of rows
- template <class RowData>
- inline
- void CTablePanel<RowData>::Reserve(size_t rows, size_t cols)
- {
- if (cols >= GetCols()) {
- SetCols(cols + 1);
- }
- x_SetData().Reserve(rows, cols);
- }
- template <class RowData>
- inline
- void CTablePanel<RowData>::Reserve(size_t rows)
- {
- x_SetData().Reserve(rows, GetCols());
- }
- // set the size of the table in rows and cols
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetSize(size_t rows, size_t cols)
- {
- SetCols(cols);
- SetRows(rows);
- }
- // set the number of rows in the table
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetRows(size_t rows)
- {
- x_SetData().SetRows(rows);
- CTablePanelBase::SetRows(rows);
- }
- // set the number of columns in the table
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetCols(size_t cols)
- {
- x_SetData().SetCols(cols);
- m_ColInfo.resize(cols);
- // adjust for our virtual columns
- vector<size_t>::iterator iter = m_VirtCols.begin();
- for ( ; iter != m_VirtCols.end(); ) {
- if (*iter >= cols) {
- iter = m_VirtCols.erase(iter);
- } else {
- ++iter;
- }
- }
- // pass the virtual columns to the base class
- CTablePanelBase::SetCols(m_VirtCols.size());
- }
- // clear the table
- template <class RowData>
- inline
- void CTablePanel<RowData>::Clear()
- {
- SetRows(0);
- select_all_rows(0);
- }
- // add a row to the table, returning its index
- template <class RowData>
- inline
- size_t CTablePanel<RowData>::AddRow(void)
- {
- x_SetData().AddRow();
- SetRows(x_GetData().GetRows());
- return x_GetData().GetRows() - 1;
- }
- template <class RowData>
- inline
- void CTablePanel<RowData>::RemoveRow(size_t idx)
- {
- x_SetData().RemoveRow(idx);
- SetRows(x_GetData().GetRows());
- }
- // get the number of rows in the table
- template <class RowData>
- inline
- size_t CTablePanel<RowData>::GetRows(void) const
- {
- return x_GetData().GetRows();
- }
- // get the number of columns in the table
- template <class RowData>
- inline
- size_t CTablePanel<RowData>::GetCols(void) const
- {
- return x_GetData().GetCols();
- }
- // retrieve a single row from the table
- template <class RowData>
- inline
- const vector<string>& CTablePanel<RowData>::GetRow(size_t row) const
- {
- return x_GetData().GetRow(row);
- }
- template <class RowData>
- inline
- vector<string>& CTablePanel<RowData>::SetRow(size_t row)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- return x_SetData().SetRow(row);
- }
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetCell(size_t row, size_t col, const string& val)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- x_SetData().SetCell(row, col) = val;
- }
- template <class RowData>
- inline
- string& CTablePanel<RowData>::SetCell(size_t row, size_t col)
- {
- if (row >= GetRows()) {
- SetRows(row + 1);
- }
- return x_SetData().SetCell(row, col);
- }
- template <class RowData>
- inline
- const string& CTablePanel<RowData>::GetCell(size_t row, size_t col) const
- {
- return x_GetData().GetCell(row, col);
- }
- template <class RowData>
- inline
- string& CTablePanel<RowData>::SetRowHeader(size_t row)
- {
- return x_SetData().SetRowHeader(row);
- }
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetRowHeader(size_t row, const string& str)
- {
- x_SetData().SetRowHeader(row) = str;
- }
- template <class RowData>
- inline
- const string& CTablePanel<RowData>::GetRowHeader(size_t row) const
- {
- return x_GetData().GetRowHeader(row);
- }
- //
- // overloaded resize(). Here, we force the columns to size correctly.
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::resize(int x, int y, int w, int h)
- {
- float total_width = 0;
- ITERATE (vector<size_t>, iter, m_VirtCols) {
- const SColInfo& info = m_ColInfo[*iter];
- total_width += info.width;
- }
- Fl_Table_Row::resize(x, y, w, h);
- if (w > total_width) {
- int idx = 0;
- NON_CONST_ITERATE (vector<size_t>, iter, m_VirtCols) {
- SColInfo& info = m_ColInfo[*iter];
- info.width *= w / total_width;
- col_width(idx++, (int)info.width);
- }
- }
- }
- template <class RowData>
- inline
- int CTablePanel<RowData>::x_HandleColHeaderClick(size_t col)
- {
- if (Fl::event_clicks() != 0) {
- NON_CONST_ITERATE (typename TColInfo, iter, m_ColInfo) {
- string::size_type pos = iter->header.find_last_of("@");
- if (pos != string::npos && pos > 0) {
- iter->header.erase(pos - 1);
- }
- }
- SColInfo& col_info = m_ColInfo[col];
- // double click - sort by column
- switch (col_info.sort_state) {
- case eNotSorted:
- case eDescending:
- {{
- col_info.sort_state = eAscending;
- col_info.header += " @-28UpArrow";
- }}
- break;
- case eAscending:
- {{
- col_info.sort_state = eDescending;
- col_info.header += " @-22UpArrow";
- }}
- break;
- }
- SortByCol(col, col_info.sort_state);
- redraw();
- return 1;
- }
- return CTablePanelBase::x_HandleColHeaderClick(col);
- }
- template <class RowData>
- inline Fl_Color
- CTablePanel<RowData>::x_GetRowForegroundColor(size_t row)
- {
- return labelcolor();
- }
- template <class RowData>
- inline Fl_Color
- CTablePanel<RowData>::x_GetRowBackgroundColor(size_t row)
- {
- return FL_BACKGROUND2_COLOR;
- }
- //
- // sort by a given column
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SortByCol(size_t col, ESortState sort_order)
- {
- _ASSERT(col < GetCols());
- x_SetData().SortByCol(col,
- (sort_order == eAscending),
- (m_ColInfo[col].type == eNumeric));
- }
- //
- // SetColType()
- // set the type of data represented in the column. This determines how the
- // column is sorted.
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetColType(size_t col, EColumnType type)
- {
- if (col >= GetCols()) {
- SetCols(col + 1);
- }
- m_ColInfo[col].type = type;
- }
- //
- // GetColType()
- // Return the type of data used in a given column
- //
- template <class RowData>
- inline typename CTablePanel<RowData>::EColumnType
- CTablePanel<RowData>::GetColType(size_t col) const
- {
- _ASSERT(col < GetCols());
- return m_ColInfo[col].type;
- }
- //
- // SetRelWidth()
- // Set the relative width of a given column. The relative width only
- // makes sense in the context of the sum of the relative widths of all the
- // other visible columns.
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetRelWidth(size_t col, float width_frac)
- {
- if (col >= GetCols()) {
- SetCols(col + 1);
- }
- m_ColInfo[col].width_frac = width_frac;
- }
- //
- // GetRelWidth()
- // Returns the relative width of a given column. The number returned only
- // makes sense in the context of the sum of the relative widths of all the
- // other visible columns.
- //
- template <class RowData>
- inline
- float CTablePanel<RowData>::GetRelWidth(size_t col) const
- {
- _ASSERT(col < GetCols());
- return m_ColInfo[col].width_frac;
- }
- //
- // SetWidth()
- // Set the actual width in pixels for a given column
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetWidth(size_t col, float width)
- {
- if (col >= GetCols()) {
- SetCols(col + 1);
- }
- m_ColInfo[col].width = width;
- ITERATE (vector<size_t>, iter, m_VirtCols) {
- if (*iter == col) {
- col_width(iter - m_VirtCols.begin(), (int)width);
- }
- }
- }
- //
- // GetWidth()
- // Returns the relative width of a given column. The number returned only
- // makes sense in the context of the sum of the relative widths of all the
- // other visible columns.
- //
- template <class RowData>
- inline
- float CTablePanel<RowData>::GetWidth(size_t col) const
- {
- _ASSERT(col < GetCols());
- return m_ColInfo[col].width;
- }
- //
- // SetColAlign()
- // set the default alignment for a given column
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetColAlign(size_t col, Fl_Align align)
- {
- if (col >= GetCols()) {
- SetCols(col + 1);
- }
- m_ColInfo[col].align = align;
- }
- //
- // GetColAlign()
- // Return the current slignment setting for a given column
- //
- template <class RowData>
- inline
- Fl_Align CTablePanel<RowData>::GetColAlign(size_t col) const
- {
- _ASSERT(col < GetCols());
- return m_ColInfo[col].align;
- }
- //
- // SetColumn()
- // This function sets all column properties; internally, it just calls other
- // functions to set individual properties on the selected column.
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetColumn(size_t col, const string& header,
- EColumnType type,
- Fl_Align align,
- float rel_width)
- {
- SetColHeader(col, header);
- SetColType (col, type);
- SetColAlign (col, align);
- SetRelWidth (col, rel_width);
- // always add a new column
- SetVirtualCol(m_VirtCols.size(), col);
- SetupColumns();
- }
- //
- // SetVirtualCol()
- //
- template <class RowData>
- inline void
- CTablePanel<RowData>::ClearVirtualCols()
- {
- m_VirtCols.clear();
- CTablePanelBase::SetCols(0);
- }
- //
- // SetVirtualCol()
- //
- template <class RowData>
- inline void
- CTablePanel<RowData>::SetVirtualCol(int virt_col, int actual_col)
- {
- m_VirtCols.push_back(actual_col);
- // call our base class's resize
- CTablePanelBase::SetCols(m_VirtCols.size());
- }
- //
- // SetupColumns()
- // Internal function to correctly set column widths and alignments. This is
- // intended to be called any time the column setup changes - i.e., any time the
- // user selects a different set of visible columns.
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetupColumns()
- {
- float sum = 0;
- ITERATE (vector<size_t>, iter, m_VirtCols) {
- const SColInfo& info = m_ColInfo[ *iter];
- sum += info.width_frac;
- }
- float widget_width = (float)(w() - 1);
- int idx = 0;
- float total_rel_width = 0.0f;
- NON_CONST_ITERATE (vector<size_t>, iter, m_VirtCols) {
- SColInfo& info = m_ColInfo[ *iter];
- float prev_rel_width = total_rel_width;
- total_rel_width += info.width_frac;
- float prev_width = (widget_width * prev_rel_width / sum);
- float total_width = (widget_width * total_rel_width / sum);
- info.width = total_width - prev_width;
- // actually set our width
- // we take this opportunity to set the column style as well
- col_width(idx++, (int)info.width);
- }
- }
- //
- // access a column header
- //
- template <class RowData>
- inline
- void CTablePanel<RowData>::SetColHeader(size_t col, const string& str)
- {
- if (col >= GetCols()) {
- SetCols(col + 1);
- }
- m_ColInfo[col].header = str;
- }
- template <class RowData>
- inline
- const string& CTablePanel<RowData>::GetColHeader(size_t col) const
- {
- _ASSERT(col < GetCols());
- return m_ColInfo[col].header;
- }
- //
- // Fl_Table_Row overload: draw_cell()
- // This actually does the work of drawing our data
- //
- template <class Data>
- inline
- void CTablePanel<Data>::draw_cell(TableContext ctx,
- int row, int col,
- int x, int y, int w, int h)
- {
- // flip for our virtual columns
- if (m_VirtCols.size()) {
- col = m_VirtCols[col];
- }
- switch (ctx) {
- case CONTEXT_STARTPAGE:
- fl_font(labelfont(), labelsize());
- break;
- case CONTEXT_ROW_HEADER:
- fl_push_clip(x, y, w, h);
- {{
- fl_draw_box(m_RowHeaderBox, x, y, w, h, row_header_color());
- if ((size_t)row < GetRows()) {
- fl_color(labelcolor());
- fl_draw(GetRowHeader(row).c_str(),
- x, y, w, h, FL_ALIGN_CENTER);
- }
- }}
- fl_pop_clip();
- break;
- case CONTEXT_COL_HEADER:
- fl_push_clip(x, y, w, h);
- {{
- fl_draw_box(m_ColHeaderBox, x, y, w, h, col_header_color());
- if ((size_t)col < GetCols()) {
- fl_color(labelcolor());
- fl_draw(GetColHeader(col).c_str(),
- x, y, w, h, FL_ALIGN_CENTER);
- }
- }}
- fl_pop_clip();
- break;
- case CONTEXT_CELL:
- fl_push_clip(x, y, w, h);
- {{
- // BG COLOR
- if (row_selected(row)) {
- fl_color(selection_color());
- } else {
- fl_color(x_GetRowBackgroundColor(row));
- }
- fl_rectf(x, y, w, h);
- // TEXT
- if ((size_t)row < GetRows() && (size_t)col < GetCols()) {
- if (row_selected(row)) {
- fl_color(FL_YELLOW);
- } else {
- fl_color(x_GetRowForegroundColor(row));
- }
- const char *p = GetCell(row, col).c_str();
- fl_draw(p,
- x + Fl::box_dx(m_CellBox),
- y + Fl::box_dy(m_CellBox),
- w - Fl::box_dw(m_CellBox),
- h - Fl::box_dh(m_CellBox),
- GetColAlign(col));
- }
- // BORDER
- fl_draw_box(m_CellBox, x, y, w, h, FL_LIGHT2);
- }}
- fl_pop_clip();
- break;
- case CONTEXT_ENDPAGE:
- fl_push_clip(this->x(), this->y(), this->w(), this->h());
- {{
- fl_draw_box(box(),
- this->x(), this->y(), this->w(), this->h(),
- color());
- }}
- fl_pop_clip();
- break;
- default:
- break;
- }
- }
- #if 0
- //
- // stock data comparators - one to dereference, and one to compare by value
- //
- template <class Data>
- struct SCompareByPtr {
- bool operator() (const Data& d0, const Data& d1) const {
- return (*d0 < *d1);
- }
- };
- template <class Data>
- struct SCompareByValue {
- bool operator() (const Data& d0, const Data& d1) const {
- return (d0 < d1);
- }
- };
- //
- // class CListPanel extends CTablePanel by creating a multi-column list panel.
- //
- // This panel has a few features not found in CTablePanel:
- // - It stores all data in the widget itself, rather than relying on a virtual
- // accessor mechanism.
- // - It provides a means of sorting by columns. -1 = sort by original data.
- //
- template <class Data, class Comparator = SCompareByPtr<Data> >
- class CListPanel : public CTablePanel
- {
- public:
- // typedefs and nested classes for our columns and data
- // NB: these are public to avoid compiler errors regarding use of a
- // protected typedef in a protected nested class
- typedef vector<string> TColumns;
- class CRow
- {
- public:
- Data m_Data;
- string m_RowHeader;
- TColumns m_Columns;
- };
- typedef CRow TRow;
- typedef vector<TRow> TTable;
- CListPanel(int x, int y, int w, int h, const char* label = NULL);
- virtual ~CListPanel() {}
- // sort by a given column
- void SortByCol(int col);
- // get/set the row headers
- void SetRowHeader(int row, const string& header);
- const string& GetRowHeader(int row) const;
- // access the data for a given row
- Data GetData(int row) { return m_Data[row].m_Data; }
- protected:
- // our data
- TTable m_Data;
- // predicate for sorting our table data by a given column
- struct SColSorter
- {
- int m_Col;
- bool m_Ascending;
- EColumnType type;
- Comparator m_Comparator;
- SColSorter(int col, bool ascending, EColumnType type)
- : m_Col(col)
- , m_Ascending(ascending)
- , type(type) {}
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- bool comp = false;
- switch (type) {
- case eString:
- if (row0.m_Columns[m_Col] != row1.m_Columns[m_Col]) {
- comp = (row0.m_Columns[m_Col] < row1.m_Columns[m_Col]);
- } else {
- comp = m_Comparator(row0.m_Data, row1.m_Data);
- }
- break;
- case eNumeric:
- {
- int r0 = 0;
- int r1 = 0;
- if ( !row0.m_Columns[m_Col].empty() ) {
- r0 = NStr::StringToInt(row0.m_Columns[m_Col],
- 10, NStr::eCheck_Skip);
- }
- if ( !row1.m_Columns[m_Col].empty() ) {
- r1 = NStr::StringToInt(row1.m_Columns[m_Col],
- 10, NStr::eCheck_Skip);
- }
- if (r0 != r1) {
- comp = (r0 < r1);
- } else {
- comp = m_Comparator(row0.m_Data, row1.m_Data);
- }
- }
- break;
- }
- return (m_Ascending ? comp : !comp);
- }
- };
- // predicate for sorting our table data by the underlying data object
- struct SDataSorter
- {
- bool m_Ascending;
- Comparator m_Comp;
- SDataSorter(bool ascending)
- : m_Ascending(ascending) {}
- bool operator() (const TRow& row0, const TRow& row1) const
- {
- return (m_Ascending ?
- ( m_Comp(row0.m_Data, row1.m_Data) ):
- ( m_Comp(row1.m_Data, row0.m_Data) ) );
- }
- };
- // FLTK overloads
- virtual int handle(int event);
- virtual void draw_cell(TableContext ctx, int row, int col,
- int x, int y, int w, int h);
- };
- //
- // default ctor
- //
- template <class Data, class Comparator>
- inline CListPanel<Data, Comparator>::CListPanel(int x, int y, int w, int h,
- const char* label)
- : CTablePanel(x, y, w, h, label)
- {
- }
- //
- // Utility function: sort by a given column
- // NOTE: the 'column' here is the *actual* column. The one exception is the
- // special column '-1', which indicates 'sort by underlying data'
- //
- template <class Data, class Comparator>
- inline void CListPanel<Data, Comparator>::SortByCol(int col)
- {
- if (col >= 0) {
- if (col >= int (m_ColInfo.size())) {
- return;
- }
- bool ascending = false;
- if (m_ColInfo[col].sort_state != eAscending) {
- ascending = true;
- }
- NON_CONST_ITERATE (TColInfo, iter, m_ColInfo) {
- iter->sort_state = eNotSorted;
- }
- m_ColInfo[col].sort_state = (ascending ? eAscending : eDescending);
- // string sort by column
- // we need to map our visible column to our underlying data column
- std::sort(m_Data.begin(), m_Data.end(),
- SColSorter(col, ascending, m_ColInfo[col].type));
- } else {
- // sort by data
- std::sort(m_Data.begin(), m_Data.end(), SDataSorter(true));
- }
- }
- //
- // SetRowHeader()
- // Set the header for a given row
- //
- template <class Data, class Comparator>
- inline void
- CListPanel<Data, Comparator>::SetRowHeader(int row, const string& header)
- {
- if (int (m_Data.size()) <= row) {
- m_Data.resize(row + 1);
- }
- m_Data[row].m_RowHeader = header;
- }
- //
- // GetRowHeader()
- // Return the header for a given row
- //
- template <class Data, class Comparator>
- inline const string&
- CListPanel<Data, Comparator>::GetRowHeader(int row) const
- {
- return m_Data[row].m_RowHeader;
- }
- //
- // Flek overload: draw_cell()
- // This actually does the work of drawing our data
- //
- template <class Data, class Comparator>
- inline void CListPanel<Data, Comparator>::draw_cell(TableContext ctx,
- int row, int col,
- int x, int y,
- int w, int h)
- {
- // transform col (virtual col) to actual table column
- int actual_col = 0;
- if (col < m_VirtCols.size() ) {
- actual_col = m_VirtCols[col];
- }
- switch (ctx) {
- case CONTEXT_STARTPAGE:
- fl_font(labelfont(), labelsize());
- break;
- case CONTEXT_ROW_HEADER:
- fl_push_clip(x, y, w, h);
- {{
- fl_draw_box(m_HeaderBox, x, y, w, h, row_header_color());
- fl_color(labelcolor());
- if (row < m_Data.size()) {
- fl_draw(m_Data[row].m_RowHeader.c_str(),
- x, y, w, h, FL_ALIGN_CENTER);
- }
- }}
- fl_pop_clip();
- break;
- case CONTEXT_COL_HEADER:
- fl_push_clip(x, y, w, h);
- {{
- fl_draw_box(m_HeaderBox, x, y, w, h, col_header_color());
- if (actual_col < m_ColInfo.size()) {
- fl_color(labelcolor());
- fl_draw(m_ColInfo[actual_col].header.c_str(),
- x, y, w, h, FL_ALIGN_CENTER);
- }
- }}
- fl_pop_clip();
- break;
- case CONTEXT_CELL:
- fl_push_clip(x, y, w, h);
- {{
- // BG COLOR
- fl_color(row_selected(row) ?
- selection_color() : FL_BACKGROUND2_COLOR);
- fl_rectf(x, y, w, h);
- // TEXT
- if (row < m_Data.size() &&
- actual_col < m_Data[row].m_Columns.size()) {
- fl_color(labelcolor());
- const char *p = m_Data[row].m_Columns[actual_col].c_str();
- fl_draw(p,
- x + Fl::box_dx(m_CellBox),
- y + Fl::box_dy(m_CellBox),
- w - Fl::box_dw(m_CellBox),
- h - Fl::box_dh(m_CellBox),
- GetColAlign(actual_col));
- }
- // BORDER
- fl_draw_box(m_CellBox, x, y, w, h, FL_LIGHT2);
- }}
- fl_pop_clip();
- break;
- default:
- break;
- }
- }
- //
- // overloaded event handler
- // here we trigger column sorting
- //
- template <class Data, class Comparator>
- inline int CListPanel<Data, Comparator>::handle(int event)
- {
- int row = -1;
- int col = -1;
- switch (event)
- {
- case FL_PUSH:
- /** FIXME
- row = get_row(Fl::event_x(), Fl::event_y());
- if (row != -1 || Fl::event_clicks() != 1) {
- break;
- }
- col = get_col(Fl::event_x(), Fl::event_y());
- SortByCol(m_VirtCols[col]);
- redraw();
- **/
- break;
- default:
- break;
- };
- return Fl_Table_Row::handle(event);
- }
- #endif
- END_NCBI_SCOPE
- /* @} */
- /*
- * ===========================================================================
- * $Log: table_panel.hpp,v $
- * Revision 1000.4 2004/06/01 19:52:33 gouriano
- * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
- *
- * Revision 1.15 2004/05/28 14:54:54 dicuccio
- * Added functions to take CFltkUtils::EBoxType directly
- *
- * Revision 1.14 2004/05/25 17:06:39 dicuccio
- * MOved border drawing code outside of row check. Changed ascending/descending
- * sort arrows to meet user expectations
- *
- * Revision 1.13 2004/05/11 18:55:14 dicuccio
- * Added doxygen modules info
- *
- * Revision 1.12 2004/05/07 15:44:47 dicuccio
- * Fixed compiler warning about type conversion
- *
- * Revision 1.11 2004/05/03 12:47:08 dicuccio
- * Added #include for gui/gui.hpp. gui/utils ->gui/objutils where needed.
- *
- * Revision 1.10 2004/04/22 15:08:08 gorelenk
- * Fixed compilation error in implementation of 'CTablePanel<RowData>::SetRow'
- *
- * Revision 1.9 2004/04/22 14:21:41 gorelenk
- * Fixed compilation errors on MSVC7.
- *
- * Revision 1.8 2004/04/16 14:32:54 dicuccio
- * Added IsRowSelected() - const wrapper around non-const function
- *
- * Revision 1.7 2004/04/07 12:42:08 dicuccio
- * Call SetRows() in RemoveRow(). Make sure that draw_cell() will be entered even
- * if no items are present (insures that column headers will be drawn)
- *
- * Revision 1.6 2004/03/19 18:02:17 dicuccio
- * Added SetWidth()/GetWidth() - width of a column in pixels. Added better
- * (smooth) handling of resize() - resize columns to fit only if they are less
- * than the current width.
- *
- * Revision 1.5 2004/03/19 17:00:12 dicuccio
- * Fix for resize() - preserve virtual width of the table
- *
- * Revision 1.4 2004/03/11 17:22:41 dicuccio
- * Reinstaed virtual columns
- *
- * Revision 1.3 2004/03/05 17:28:26 dicuccio
- * Added standard handlers for cut/copy/paste events. Added abiluty to remove
- * rows
- *
- * Revision 1.2 2004/01/20 18:11:11 dicuccio
- * Changed SetColumns() to SetCols(). Introduced GetRows()/SetRows()/SetCols()
- * as virtual replacements for rows()/cols(). Added sorting of columns on
- * double-click of header. Added standard virtual hooks for trapping click
- * events inside of cells / headers. Added more natural API to SetCells().
- *
- * Revision 1.1 2003/12/09 15:54:10 dicuccio
- * Deprecated Fl_Tree_Browser - use Flu_Tree_Browser instead
- *
- * Revision 1.22 2003/12/05 02:03:14 ucko
- * Add missing definitions of CTablePanel::{Get,Set}RowHeader(size_t),
- * and fix the other definition of GetRowHeader to avoid looping forever.
- *
- * Revision 1.21 2003/12/04 18:07:48 dicuccio
- * Removed direct access to underlying data component in CTablePanel<> - makes
- * the class more tightly encapsulated
- *
- * Revision 1.20 2003/09/29 15:16:02 dicuccio
- * Added typename where required
- *
- * Revision 1.19 2003/09/24 18:21:56 dicuccio
- * Introduce new base class interposed between CTablePanel<> and Fl_Table_Row;
- * this class incorporates most of the generic features of CTablePanel<> and
- * allows for easier extension of list views
- *
- * Revision 1.18 2003/09/17 16:19:58 dicuccio
- * Make sure to set the row height appropriately for the font when setting rows
- *
- * Revision 1.17 2003/08/18 14:53:04 dicuccio
- * Code clean-up. Made interface class for table data cleaner, more
- * comprehensive
- *
- * Revision 1.16 2003/07/28 11:53:29 dicuccio
- * Rewrote CTablePanel<> to be more flexible and better contained
- *
- * Revision 1.15 2003/07/25 13:40:46 dicuccio
- * Replaced Flv_Table with Fl_Table
- *
- * Revision 1.14 2003/06/25 16:59:42 dicuccio
- * Changed CPluginHandle into a pointer-to-implementation (the previous
- * implementation is now the pointer held). Lots of #include file clean-ups.
- *
- * Revision 1.13 2003/03/17 14:58:33 dicuccio
- * Eliminated annoying compiler warning about unsigned-signed compare
- *
- * Revision 1.12 2003/03/10 17:49:04 kuznets
- * iterate->ITERATE
- *
- * Revision 1.11 2003/02/25 14:43:20 dicuccio
- * Added smart resizing of multicolumn list widget
- *
- * Revision 1.10 2003/02/20 19:43:13 dicuccio
- * Changed column sort to be triggered on double-click, not single-click
- *
- * Revision 1.9 2003/01/17 21:09:49 dicuccio
- * Altered sorting - fall back to feature sort order if sort returns
- * equivalence
- *
- * Revision 1.8 2003/01/15 17:48:32 dicuccio
- * Fixed thinko: don't try to numerically convert an empty column string
- *
- * Revision 1.7 2003/01/13 13:11:44 dicuccio
- * Namespace clean-up. Retired namespace gui -> converted to namespace ncbi.
- * Moved all FLUID-generated code into namespace ncbi.
- *
- * Revision 1.6 2003/01/08 20:19:19 dicuccio
- * Fix for solaris builds: cannot use protected typedefs in protected nested
- * classes.
- *
- * Revision 1.5 2003/01/08 14:47:45 dicuccio
- * Moved column selection dialog into internal directory. Made column
- * selection dialog part of the base class; it is expressible via
- * CTablePanel::ShowColSelectDlg(). Added ability to specify type of data
- * stored in column (currently string or numeric); added ability to sort based
- * on underlying type.
- *
- * Revision 1.4 2003/01/03 18:38:08 dicuccio
- * Fixed compilation error in WIndows - can't reference protected enum from
- * nested protected class.
- *
- * Revision 1.3 2003/01/03 13:28:14 dicuccio
- * Lots of clean-up. Added stored sort state. Added new class to hold all
- * info for one virtual column. Added dialog box for selecting visible
- * columns.
- *
- * Revision 1.2 2002/12/30 20:18:14 dicuccio
- * Added Win32 export specifier. Rearranged #include directives
- *
- * Revision 1.1 2002/12/30 18:42:39 dicuccio
- * Initial revision
- *
- * ===========================================================================
- */
- #endif // GUI_WIDGETS_TABLE___TABLE_PANEL__HPP