table_panel.hpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:49k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: table_panel.hpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:52:33  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. #ifndef GUI_WIDGETS_TABLE___TABLE_PANEL__HPP
  10. #define GUI_WIDGETS_TABLE___TABLE_PANEL__HPP
  11. /*  $Id: table_panel.hpp,v 1000.4 2004/06/01 19:52:33 gouriano Exp $
  12.  * ===========================================================================
  13.  *
  14.  *                            PUBLIC DOMAIN NOTICE
  15.  *               National Center for Biotechnology Information
  16.  *
  17.  *  This software/database is a "United States Government Work" under the
  18.  *  terms of the United States Copyright Act.  It was written as part of
  19.  *  the author's official duties as a United States Government employee and
  20.  *  thus cannot be copyrighted.  This software/database is freely available
  21.  *  to the public for use. The National Library of Medicine and the U.S.
  22.  *  Government have not placed any restriction on its use or reproduction.
  23.  *
  24.  *  Although all reasonable efforts have been taken to ensure the accuracy
  25.  *  and reliability of the software and data, the NLM and the U.S.
  26.  *  Government do not and cannot warrant the performance or results that
  27.  *  may be obtained by using this software or data. The NLM and the U.S.
  28.  *  Government disclaim all warranties, express or implied, including
  29.  *  warranties of performance, merchantability or fitness for any particular
  30.  *  purpose.
  31.  *
  32.  *  Please cite the author in any work or product based on this material.
  33.  *
  34.  * ===========================================================================
  35.  *
  36.  * Authors:  Mike DiCuccio
  37.  *
  38.  * File Description:
  39.  *    CTablePanel -- Extends Flv_Table to provide notions of hidden and visible
  40.  *                   columns
  41.  *    CListPanel  -- Extends CTablePanel to provide a row-selectable
  42.  *                   multicolumn list widget that stores arbitrary data with
  43.  *                   each row.
  44.  */
  45. #include <corelib/ncbiobj.hpp>
  46. #include <gui/gui.hpp>
  47. #include <FL/Enumerations.H>
  48. #include <FL/Fl.H>
  49. #include <FL/fl_draw.H>
  50. #include <gui/widgets/Fl_Table/Fl_Table_Row.H>
  51. #include <gui/utils/fltk_utils.hpp>
  52. #include <algorithm>
  53. #include <memory>
  54. #include <string>
  55. #include <vector>
  56. /** @addtogroup GUI_FltkWidgets
  57.  *
  58.  * @{
  59.  */
  60. BEGIN_NCBI_SCOPE
  61. class NCBI_GUIWIDGETS_TABLE_EXPORT CTablePanelBase : public Fl_Table_Row
  62. {
  63. public:
  64.     CTablePanelBase(int x, int y, int w, int h, const char* label = NULL);
  65.     // safe (virtual) accessors
  66.     virtual size_t GetRows() const;
  67.     virtual void   SetRows(size_t r);
  68.     virtual size_t GetCols() const;
  69.     virtual void   SetCols(size_t c);
  70.     // overrides from Fl_Table_Row (these may be dangerous - they're not
  71.     // virtual)
  72.     void rows(int r);
  73.     int  rows() const;
  74.     void cols(int c);
  75.     int  cols() const;
  76.     // draw() - enforces clipping
  77.     void draw();
  78.     // handle() - traps double-clicks on headers
  79.     int handle(int event);
  80.     // check if a given row is selected.  The base class row_selected() is
  81.     // non-const, for reasons that baffle me.
  82.     bool IsRowSelected(size_t row) const;
  83.     // access the FLTK box type used for drawing a cell
  84.     Fl_Boxtype  GetCellBox(void) const;
  85.     void        SetCellBox(CFltkUtils::EBoxType);
  86.     void        SetCellBox(Fl_Boxtype);
  87.     // access the FLTK box type used for drawing row header cells
  88.     Fl_Boxtype  GetRowHeaderBox(void) const;
  89.     void        SetRowHeaderBox(CFltkUtils::EBoxType);
  90.     void        SetRowHeaderBox(Fl_Boxtype);
  91.     Fl_Boxtype  GetColHeaderBox(void) const;
  92.     void        SetColHeaderBox(CFltkUtils::EBoxType);
  93.     void        SetColHeaderBox(Fl_Boxtype);
  94.     // set the box type for both rows and cols simultaneously
  95.     void        SetHeaderBox(Fl_Boxtype);
  96.     void        SetHeaderBox(CFltkUtils::EBoxType);
  97. protected:
  98.     // GUI event processor
  99.     CGUIEvent m_Handler;
  100.     // box styles for cells and headers
  101.     Fl_Boxtype  m_CellBox;
  102.     Fl_Boxtype  m_RowHeaderBox;
  103.     Fl_Boxtype  m_ColHeaderBox;
  104.     // internal handlers for cut/copy/paste operations
  105.     virtual int x_OnCut();
  106.     virtual int x_OnCopy();
  107.     virtual int x_OnPaste();
  108.     // internal handlers for header cell clicks
  109.     virtual int x_HandleRowHeaderClick(size_t row);
  110.     virtual int x_HandleColHeaderClick(size_t col);
  111.     virtual int x_HandleCellClick(size_t row, size_t col);
  112. };
  113. class CColumnSelectDlg;
  114. //
  115. // clas ITableData defines the data interface used by all table classes
  116. //
  117. template <class RowData>
  118. class ITableData : public CObject
  119. {
  120. public:
  121.     virtual ~ITableData() {}
  122.     virtual void   Reserve  (size_t rows, size_t cols) = 0;
  123.     virtual void   SetSize  (size_t rows, size_t cols) = 0;
  124.     virtual void   SetRows  (size_t rows) = 0;
  125.     virtual void   SetCols  (size_t cols) = 0;
  126.     virtual void   AddRow   (void) = 0;
  127.     virtual void   RemoveRow(size_t row) = 0;
  128.     virtual size_t GetRows  (void) const = 0;
  129.     virtual size_t GetCols  (void) const = 0;
  130.     virtual const vector<string>& GetRow(size_t row) const = 0;
  131.     virtual vector<string>&       SetRow(size_t row) = 0;
  132.     virtual const string& GetCell(size_t row, size_t col) const = 0;
  133.     virtual string&       SetCell(size_t row, size_t col) = 0;
  134.     virtual const string& GetRowHeader(size_t row) const = 0;
  135.     virtual string&       SetRowHeader(size_t row) = 0;
  136.     // access a given row's data
  137.     virtual const RowData& GetData(size_t row) const = 0;
  138.     virtual RowData&       SetData(size_t row) = 0;
  139.     // sort the data
  140.     virtual void SortByCol(size_t col, bool ascending, bool numeric) = 0;
  141. };
  142. //
  143. // class CTableData defines a specialization of the table data
  144. // structure with a concrete type stored in each row
  145. //
  146. template <class RowData>
  147. class CTableData : public ITableData<RowData>
  148. {
  149. public:
  150.     CTableData();
  151.     // interface requirements
  152.     virtual void   Reserve  (size_t rows, size_t cols);
  153.     virtual void   SetSize  (size_t rows, size_t cols);
  154.     virtual void   SetRows  (size_t rows);
  155.     virtual void   SetCols  (size_t cols);
  156.     virtual void   AddRow   (void);
  157.     virtual void   RemoveRow(size_t row);
  158.     virtual size_t GetRows  (void) const;
  159.     virtual size_t GetCols  (void) const;
  160.     virtual const vector<string>& GetRow(size_t row) const;
  161.     virtual vector<string>&       SetRow(size_t row);
  162.     virtual const string& GetCell(size_t row, size_t col) const;
  163.     virtual string&       SetCell(size_t row, size_t col);
  164.     virtual const string& GetRowHeader(size_t row) const;
  165.     virtual string&       SetRowHeader(size_t row);
  166.     // access a given row's data
  167.     const RowData& GetData(size_t row) const;
  168.     RowData&       SetData(size_t row);
  169.     // sort the data
  170.     void SortByCol(size_t col, bool ascending, bool numeric);
  171. private:
  172.     // typedefs and nested classes for our columns and data
  173.     // NB: these are public to avoid compiler errors regarding use of a
  174.     // protected typedef in a protected nested class
  175.     class CRow
  176.     {
  177.     public:
  178.         RowData         m_Data;
  179.         string          m_RowHeader;
  180.         vector<string>  m_Columns;
  181.     };
  182.     typedef CRow TRow;
  183.     typedef vector<TRow>    TTable;
  184.     size_t m_Cols;
  185.     TTable m_Data;
  186.     //
  187.     // internal functors for sorting columns
  188.     //
  189.     struct SColSorter {
  190.         size_t col_idx;
  191.         bool   sort_ascending;
  192.         bool   sort_numeric;
  193.         SColSorter(size_t col, bool asc, bool numeric)
  194.             : col_idx(col),
  195.               sort_ascending(asc),
  196.               sort_numeric(numeric) { }
  197.         bool operator() (const TRow& row0, const TRow& row1) const
  198.         {
  199.             _ASSERT(col_idx < row0.m_Columns.size());
  200.             _ASSERT(col_idx < row1.m_Columns.size());
  201.             _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
  202.             if (sort_ascending) {
  203.                 if (sort_numeric) {
  204.                     return (NStr::StringToDouble(row0.m_Columns[col_idx]) <
  205.                             NStr::StringToDouble(row1.m_Columns[col_idx]));
  206.                 } else {
  207.                     return (row0.m_Columns[col_idx] < row1.m_Columns[col_idx]);
  208.                 }
  209.             } else {
  210.                 if (sort_numeric) {
  211.                     return (NStr::StringToDouble(row0.m_Columns[col_idx]) >
  212.                             NStr::StringToDouble(row1.m_Columns[col_idx]));
  213.                 } else {
  214.                     return (row0.m_Columns[col_idx] > row1.m_Columns[col_idx]);
  215.                 }
  216.             }
  217.         }
  218.     };
  219.     struct SColSorter_Asc_Numeric {
  220.         size_t col_idx;
  221.         SColSorter_Asc_Numeric(size_t col)
  222.             : col_idx(col) { }
  223.         bool operator() (const TRow& row0, const TRow& row1) const
  224.         {
  225.             _ASSERT(col_idx < row0.m_Columns.size());
  226.             _ASSERT(col_idx < row1.m_Columns.size());
  227.             _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
  228.             return (NStr::StringToDouble(row0.m_Columns[col_idx]) <
  229.                     NStr::StringToDouble(row1.m_Columns[col_idx]));
  230.         }
  231.     };
  232.     struct SColSorter_Desc_Numeric {
  233.         size_t col_idx;
  234.         SColSorter_Desc_Numeric(size_t col)
  235.             : col_idx(col) { }
  236.         bool operator() (const TRow& row0, const TRow& row1) const
  237.         {
  238.             _ASSERT(col_idx < row0.m_Columns.size());
  239.             _ASSERT(col_idx < row1.m_Columns.size());
  240.             _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
  241.             return (NStr::StringToDouble(row0.m_Columns[col_idx]) >
  242.                     NStr::StringToDouble(row1.m_Columns[col_idx]));
  243.         }
  244.     };
  245.     struct SColSorter_Asc_Text {
  246.         size_t col_idx;
  247.         SColSorter_Asc_Text(size_t col)
  248.             : col_idx(col) { }
  249.         bool operator() (const TRow& row0, const TRow& row1) const
  250.         {
  251.             _ASSERT(col_idx < row0.m_Columns.size());
  252.             _ASSERT(col_idx < row1.m_Columns.size());
  253.             _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
  254.             return (row0.m_Columns[col_idx] < row1.m_Columns[col_idx]);
  255.         }
  256.     };
  257.     struct SColSorter_Desc_Text {
  258.         size_t col_idx;
  259.         SColSorter_Desc_Text(size_t col)
  260.             : col_idx(col) { }
  261.         bool operator() (const TRow& row0, const TRow& row1) const
  262.         {
  263.             _ASSERT(col_idx < row0.m_Columns.size());
  264.             _ASSERT(col_idx < row1.m_Columns.size());
  265.             _ASSERT(row0.m_Columns.size() == row1.m_Columns.size());
  266.             return (row0.m_Columns[col_idx] > row1.m_Columns[col_idx]);
  267.         }
  268.     };
  269. };
  270. //
  271. // class CTablePanel extends Fl_Table with a few convenience functions.
  272. //
  273. // The main provision is for things such as uniform handling of column headers,
  274. // widths, alignments, and visibility.
  275. //
  276. template <class RowData>
  277. class CTablePanel : public CTablePanelBase
  278. {
  279. public:
  280.     typedef ITableData<RowData> TTableData;
  281.     // enumerated list of sort states for our columns
  282.     enum ESortState {
  283.         eNotSorted,
  284.         eAscending,
  285.         eDescending
  286.     };
  287.     // enumerated list of column representations
  288.     enum EColumnType {
  289.         eString,
  290.         eNumeric
  291.     };
  292.     CTablePanel(int x, int y, int w, int h, const char* label = NULL);
  293.     virtual ~CTablePanel() { }
  294.     // clear the contents of the table
  295.     virtual void Clear();
  296.     // reserve space in the table for a certain number of rows
  297.     void   Reserve(size_t rows, size_t cols);
  298.     void   Reserve(size_t rows);
  299.     // set the size of the table in rows and cols
  300.     void   SetSize(size_t rows, size_t cols);
  301.     // set the number of rows in the table
  302.     void   SetRows(size_t rows);
  303.     // set the number of columns in the table
  304.     void   SetCols(size_t cols);
  305.     // get the number of rows in the table
  306.     size_t GetRows(void) const;
  307.     // get the number of columns in the table
  308.     size_t GetCols(void) const;
  309.     // add a row to the table, returning its index
  310.     size_t AddRow (void);
  311.     // remove a row to the table, returning its index
  312.     void RemoveRow(size_t row);
  313.     // return a single row from the table
  314.     const vector<string>& GetRow(size_t row) const;
  315.     vector<string>& SetRow(size_t row);
  316.     // access a single cell in the table
  317.     const string& GetCell(size_t row, size_t col) const;
  318.     string&       SetCell(size_t row, size_t col);
  319.     void          SetCell(size_t row, size_t col, const string& val);
  320.     // access the row headers
  321.     const string& GetRowHeader(size_t row) const;
  322.     string&       SetRowHeader(size_t row);
  323.     void          SetRowHeader(size_t row, const string& val);
  324.     // access the col headers
  325.     const string& GetColHeader(size_t col) const;
  326.     string&       SetColHeader(size_t col);
  327.     void          SetColHeader(size_t col, const string& val);
  328.     // access a given row's data
  329.     const RowData& GetData(size_t row) const;
  330.     RowData&       SetData(size_t row);
  331.     void           SetData(size_t row, const RowData& data);
  332.     // FLTK overload: resize the widget
  333.     virtual void resize(int x, int y, int w, int h);
  334.     // get/set the column data type.  This determines behavior on sorting.
  335.     void            SetColType(size_t col, EColumnType type);
  336.     EColumnType     GetColType(size_t col) const;
  337.     // get/set the column relative widths
  338.     // These are a vector of floats that will be normalized ( = sum to 1.0) to
  339.     // compute actual widths
  340.     void        SetRelWidth(size_t col, float width_frac);
  341.     float       GetRelWidth(size_t col) const;
  342.     // get/set the absolute column widths, in pixels
  343.     void        SetWidth(size_t col, float width);
  344.     float       GetWidth(size_t col) const;
  345.     // set the default alignment for a given column
  346.     void        SetColAlign(size_t col, Fl_Align align);
  347.     Fl_Align    GetColAlign(size_t col) const;
  348.     // set all column parameters at once
  349.     void        SetColumn(size_t col, const string& header, EColumnType type,
  350.                           Fl_Align align, float rel_width);
  351.     // function to set up the width and alignments for the current
  352.     // visible columns.
  353.     void SetupColumns();
  354.     // sort by an indicated column in a given sort order
  355.     void SortByCol(size_t col_idx, ESortState sort_order = eAscending);
  356.     // set the virtual column for a given index
  357.     void        SetVirtualCol(int visible_col, int actual_col);
  358.     // clear all virtual columns.  NOTE: this will leave the table with no
  359.     // columns!
  360.     void        ClearVirtualCols();
  361.     // show the column selector dialog and process its results.  This allows
  362.     // users to select from the list of virtual columns.
  363.     //void        ShowColSelectDlg();
  364. protected:
  365.     CRef<TTableData> m_Data;
  366.     // safe accessors for m_Data
  367.     TTableData&       x_SetData(void);
  368.     const TTableData& x_GetData(void) const;
  369.     // general information we store concerning columns
  370.     // this allows us to be smart about such things as sorting, visibility,
  371.     // etc.
  372.     struct SColInfo {
  373.         SColInfo()
  374.             : align(FL_ALIGN_LEFT),
  375.               width_frac(1.0f),
  376.               width(100.0f),
  377.               sort_state(eNotSorted) {}
  378.         string      header;
  379.         Fl_Align    align;
  380.         float       width_frac;
  381.         float       width;
  382.         ESortState  sort_state;
  383.         EColumnType type;
  384.     };
  385.     typedef vector<SColInfo>    TColInfo;
  386.     TColInfo m_ColInfo;
  387.     // FLTK overloads
  388.     virtual void draw_cell(TableContext ctx, int row, int col,
  389.                            int x, int y, int w, int h);
  390.     // get the foreground color associated with a given row.  This is virtual
  391.     // to permit derived classes to easily change what the color will be, based
  392.     // on criteria not known to this class
  393.     virtual Fl_Color x_GetRowForegroundColor(size_t row);
  394.     virtual Fl_Color x_GetRowBackgroundColor(size_t row);
  395.     // handle column header clicks for sorting
  396.     int x_HandleColHeaderClick(size_t col);
  397.     // our virtual columns.
  398.     // We store or represent internally a number of columns potentially larger
  399.     // than that whic we display.  This allows for a high degree of
  400.     // customization - the user could theoretically select which columns to
  401.     // display and the order of display as well.
  402.     vector<size_t> m_VirtCols;
  403.     // a dialog that allows us to select columns for viewing
  404.     //auto_ptr<CColumnSelectDlg>  m_SelectDlg;
  405.     // virtual function to adjust internal structures to fit a certain number
  406.     // of columns.  These are real, not virtual, columns!
  407.     //virtual void x_SetNumColumns(int cols);
  408. };
  409. //////////////////////////////////////////////////////////////
  410. //
  411. // CTableData implementation
  412. //
  413. template <class RowData>
  414. inline CTableData<RowData>::CTableData()
  415.     : m_Cols(0)
  416. {
  417. }
  418. template <class RowData>
  419. inline void CTableData<RowData>::Reserve(size_t rows, size_t cols)
  420. {
  421.     if (cols > GetCols()) {
  422.         SetCols(cols);
  423.     }
  424.     m_Data.reserve(rows);
  425. }
  426. template <class RowData>
  427. inline void CTableData<RowData>::SetSize(size_t rows, size_t cols)
  428. {
  429.     SetCols(cols);
  430.     SetRows(rows);
  431. }
  432. template <class RowData>
  433. inline void CTableData<RowData>::SetCols(size_t cols)
  434. {
  435.     NON_CONST_ITERATE (typename TTable, iter, m_Data) {
  436.         iter->m_Columns.resize(cols);
  437.     }
  438.     m_Cols = cols;
  439. }
  440. template <class RowData>
  441. inline void CTableData<RowData>::SetRows(size_t rows)
  442. {
  443.     m_Data.resize(rows);
  444.     NON_CONST_ITERATE (typename TTable, iter, m_Data) {
  445.         iter->m_Columns.resize(m_Cols);
  446.     }
  447. }
  448. template <class RowData>
  449. inline void CTableData<RowData>::AddRow(void)
  450. {
  451.     TRow row;
  452.     row.m_Columns.resize(GetCols());
  453.     m_Data.push_back(row);
  454. }
  455. template <class RowData>
  456. inline void CTableData<RowData>::RemoveRow(size_t idx)
  457. {
  458.     _ASSERT(idx < GetRows());
  459.     m_Data.erase(m_Data.begin() + idx);
  460. }
  461. template <class RowData>
  462. inline size_t CTableData<RowData>::GetRows(void) const
  463. {
  464.     return m_Data.size();
  465. }
  466. template <class RowData>
  467. inline size_t CTableData<RowData>::GetCols(void) const
  468. {
  469.     return m_Cols;
  470. }
  471. template <class RowData>
  472. inline const RowData&
  473. CTableData<RowData>::GetData(size_t row) const
  474. {
  475.     _ASSERT(row < GetRows());
  476.     return m_Data[row].m_Data;
  477. }
  478. template <class RowData>
  479. inline RowData&
  480. CTableData<RowData>::SetData(size_t row)
  481. {
  482.     if (row >= GetRows()) {
  483.         SetRows(row + 1);
  484.     }
  485.     return m_Data[row].m_Data;
  486. }
  487. template <class RowData>
  488. inline const vector<string>&
  489. CTableData<RowData>::GetRow(size_t row) const
  490. {
  491.     _ASSERT(row < GetRows());
  492.     return m_Data[row].m_Columns;
  493. }
  494. template <class RowData>
  495. inline vector<string>&
  496. CTableData<RowData>::SetRow(size_t row)
  497. {
  498.     if (row >= GetRows()) {
  499.         SetRows(row + 1);
  500.     }
  501.     return m_Data[row].m_Columns;
  502. }
  503. template <class RowData>
  504. inline const string&
  505. CTableData<RowData>::GetCell(size_t row, size_t col) const
  506. {
  507.     _ASSERT(row < GetRows());
  508.     _ASSERT(col < GetCols());
  509.     return m_Data[row].m_Columns[col];
  510. }
  511. template <class RowData>
  512. inline string&
  513. CTableData<RowData>::SetCell(size_t row, size_t col)
  514. {
  515.     if (row >= GetRows()) {
  516.         SetRows(row + 1);
  517.     }
  518.     _ASSERT(row < GetRows());
  519.     _ASSERT(col < GetCols());
  520.     return m_Data[row].m_Columns[col];
  521. }
  522. template <class RowData>
  523. inline const string&
  524. CTableData<RowData>::GetRowHeader(size_t row) const
  525. {
  526.     _ASSERT(row < GetRows());
  527.     return m_Data[row].m_RowHeader;
  528. }
  529. template <class RowData>
  530. inline string&
  531. CTableData<RowData>::SetRowHeader(size_t row)
  532. {
  533.     if (row >= GetRows()) {
  534.         SetRows(row + 1);
  535.     }
  536.     return m_Data[row].m_RowHeader;
  537. }
  538. template <class RowData>
  539. inline void
  540. CTableData<RowData>::SortByCol(size_t col_idx, bool ascending, bool numeric)
  541. {
  542.     _ASSERT(col_idx < GetCols());
  543.     if (ascending) {
  544.         if (numeric) {
  545.             SColSorter_Asc_Numeric sorter(col_idx);
  546.             std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
  547.         } else {
  548.             SColSorter_Asc_Text sorter(col_idx);
  549.             std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
  550.         }
  551.     } else {
  552.         if (numeric) {
  553.             SColSorter_Desc_Numeric sorter(col_idx);
  554.             std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
  555.         } else {
  556.             SColSorter_Desc_Text sorter(col_idx);
  557.             std::stable_sort(m_Data.begin(), m_Data.end(), sorter);
  558.         }
  559.     }
  560. }
  561. //////////////////////////////////////////////////////////////
  562. //
  563. // CTablePanel implementation
  564. //
  565. template <class RowData>
  566. inline
  567. CTablePanel<RowData>::CTablePanel(int x, int y, int w, int h,
  568.                                   const char* label)
  569.     : CTablePanelBase(x, y, w, h, label)
  570. {
  571.     // this creates a dummy data class for us
  572.     x_SetData();
  573.     row_header(false);
  574.     col_header(true);
  575.     col_resize(RESIZE_ROW_BELOW);
  576. }
  577. //
  578. // get the data object associated with a single row
  579. //
  580. template <class RowData>
  581. inline
  582. const RowData& CTablePanel<RowData>::GetData(size_t row) const
  583. {
  584.     _ASSERT(row < GetRows());
  585.     return x_GetData().GetData(row);
  586. }
  587. template <class RowData>
  588. inline
  589. RowData& CTablePanel<RowData>::SetData(size_t row)
  590. {
  591.     return x_SetData().SetData(row);
  592. }
  593. template <class RowData>
  594. inline
  595. void CTablePanel<RowData>::SetData(size_t row, const RowData& data)
  596. {
  597.     x_SetData().SetData(row) = data;
  598. }
  599. //
  600. // get the data class associated with the table
  601. // this makes no assumptions about whether the data class is valid
  602. //
  603. template <class RowData>
  604. inline
  605. const typename CTablePanel<RowData>::TTableData&
  606. CTablePanel<RowData>::x_GetData(void) const
  607. {
  608.     _ASSERT(m_Data);
  609.     return *m_Data;
  610. }
  611. //
  612. // get the data class in non-const form.  If the data class isn't present,
  613. // a default one is created.
  614. //
  615. template <class RowData>
  616. inline
  617. typename CTablePanel<RowData>::TTableData&
  618. CTablePanel<RowData>::x_SetData(void)
  619. {
  620.     if ( !m_Data ) {
  621.         m_Data.Reset(new CTableData<RowData>());
  622.         m_Data->SetCols(GetCols());
  623.         m_Data->SetRows(GetRows());
  624.     }
  625.     _ASSERT(m_Data);
  626.     return *m_Data;
  627. }
  628. // reserve space in the table for a certain number of rows
  629. template <class RowData>
  630. inline
  631. void CTablePanel<RowData>::Reserve(size_t rows, size_t cols)
  632. {
  633.     if (cols >= GetCols()) {
  634.         SetCols(cols + 1);
  635.     }
  636.     x_SetData().Reserve(rows, cols);
  637. }
  638. template <class RowData>
  639. inline
  640. void CTablePanel<RowData>::Reserve(size_t rows)
  641. {
  642.     x_SetData().Reserve(rows, GetCols());
  643. }
  644. // set the size of the table in rows and cols
  645. template <class RowData>
  646. inline
  647. void CTablePanel<RowData>::SetSize(size_t rows, size_t cols)
  648. {
  649.     SetCols(cols);
  650.     SetRows(rows);
  651. }
  652. // set the number of rows in the table
  653. template <class RowData>
  654. inline
  655. void CTablePanel<RowData>::SetRows(size_t rows)
  656. {
  657.     x_SetData().SetRows(rows);
  658.     CTablePanelBase::SetRows(rows);
  659. }
  660. // set the number of columns in the table
  661. template <class RowData>
  662. inline
  663. void CTablePanel<RowData>::SetCols(size_t cols)
  664. {
  665.     x_SetData().SetCols(cols);
  666.     m_ColInfo.resize(cols);
  667.     // adjust for our virtual columns
  668.     vector<size_t>::iterator iter = m_VirtCols.begin();
  669.     for ( ;  iter != m_VirtCols.end();  ) {
  670.         if (*iter >= cols) {
  671.             iter = m_VirtCols.erase(iter);
  672.         } else {
  673.             ++iter;
  674.         }
  675.     }
  676.     // pass the virtual columns to the base class
  677.     CTablePanelBase::SetCols(m_VirtCols.size());
  678. }
  679. // clear the table
  680. template <class RowData>
  681. inline
  682. void CTablePanel<RowData>::Clear()
  683. {
  684.     SetRows(0);
  685.     select_all_rows(0);
  686. }
  687. // add a row to the table, returning its index
  688. template <class RowData>
  689. inline
  690. size_t CTablePanel<RowData>::AddRow(void)
  691. {
  692.     x_SetData().AddRow();
  693.     SetRows(x_GetData().GetRows());
  694.     return x_GetData().GetRows() - 1;
  695. }
  696. template <class RowData>
  697. inline
  698. void CTablePanel<RowData>::RemoveRow(size_t idx)
  699. {
  700.     x_SetData().RemoveRow(idx);
  701.     SetRows(x_GetData().GetRows());
  702. }
  703. // get the number of rows in the table
  704. template <class RowData>
  705. inline
  706. size_t CTablePanel<RowData>::GetRows(void) const
  707. {
  708.     return x_GetData().GetRows();
  709. }
  710. // get the number of columns in the table
  711. template <class RowData>
  712. inline
  713. size_t CTablePanel<RowData>::GetCols(void) const
  714. {
  715.     return x_GetData().GetCols();
  716. }
  717. // retrieve a single row from the table
  718. template <class RowData>
  719. inline
  720. const vector<string>& CTablePanel<RowData>::GetRow(size_t row) const
  721. {
  722.     return x_GetData().GetRow(row);
  723. }
  724. template <class RowData>
  725. inline
  726. vector<string>& CTablePanel<RowData>::SetRow(size_t row)
  727. {
  728.     if (row >= GetRows()) {
  729.         SetRows(row + 1);
  730.     }
  731.     return x_SetData().SetRow(row);
  732. }
  733. template <class RowData>
  734. inline
  735. void CTablePanel<RowData>::SetCell(size_t row, size_t col, const string& val)
  736. {
  737.     if (row >= GetRows()) {
  738.         SetRows(row + 1);
  739.     }
  740.     x_SetData().SetCell(row, col) = val;
  741. }
  742. template <class RowData>
  743. inline
  744. string& CTablePanel<RowData>::SetCell(size_t row, size_t col)
  745. {
  746.     if (row >= GetRows()) {
  747.         SetRows(row + 1);
  748.     }
  749.     return x_SetData().SetCell(row, col);
  750. }
  751. template <class RowData>
  752. inline
  753. const string& CTablePanel<RowData>::GetCell(size_t row, size_t col) const
  754. {
  755.     return x_GetData().GetCell(row, col);
  756. }
  757. template <class RowData>
  758. inline
  759. string& CTablePanel<RowData>::SetRowHeader(size_t row)
  760. {
  761.     return x_SetData().SetRowHeader(row);
  762. }
  763. template <class RowData>
  764. inline
  765. void CTablePanel<RowData>::SetRowHeader(size_t row, const string& str)
  766. {
  767.     x_SetData().SetRowHeader(row) = str;
  768. }
  769. template <class RowData>
  770. inline
  771. const string& CTablePanel<RowData>::GetRowHeader(size_t row) const
  772. {
  773.     return x_GetData().GetRowHeader(row);
  774. }
  775. //
  776. // overloaded resize().  Here, we force the columns to size correctly.
  777. //
  778. template <class RowData>
  779. inline
  780. void CTablePanel<RowData>::resize(int x, int y, int w, int h)
  781. {
  782.     float total_width = 0;
  783.     ITERATE (vector<size_t>, iter, m_VirtCols) {
  784.         const SColInfo& info = m_ColInfo[*iter];
  785.         total_width += info.width;
  786.     }
  787.     Fl_Table_Row::resize(x, y, w, h);
  788.     if (w > total_width) {
  789.         int idx = 0;
  790.         NON_CONST_ITERATE (vector<size_t>, iter, m_VirtCols) {
  791.             SColInfo& info = m_ColInfo[*iter];
  792.             info.width *= w / total_width;
  793.             col_width(idx++, (int)info.width);
  794.         }
  795.     }
  796. }
  797. template <class RowData>
  798. inline
  799. int CTablePanel<RowData>::x_HandleColHeaderClick(size_t col)
  800. {
  801.     if (Fl::event_clicks() != 0) {
  802.         NON_CONST_ITERATE (typename TColInfo, iter, m_ColInfo) {
  803.             string::size_type pos = iter->header.find_last_of("@");
  804.             if (pos != string::npos  &&  pos > 0) {
  805.                 iter->header.erase(pos - 1);
  806.             }
  807.         }
  808.         SColInfo& col_info = m_ColInfo[col];
  809.         // double click - sort by column
  810.         switch (col_info.sort_state) {
  811.         case eNotSorted:
  812.         case eDescending:
  813.             {{
  814.                  col_info.sort_state = eAscending;
  815.                  col_info.header += " @-28UpArrow";
  816.              }}
  817.             break;
  818.         case eAscending:
  819.             {{
  820.                  col_info.sort_state = eDescending;
  821.                  col_info.header += " @-22UpArrow";
  822.              }}
  823.             break;
  824.         }
  825.         SortByCol(col, col_info.sort_state);
  826.         redraw();
  827.         return 1;
  828.     }
  829.     return CTablePanelBase::x_HandleColHeaderClick(col);
  830. }
  831. template <class RowData>
  832. inline Fl_Color
  833. CTablePanel<RowData>::x_GetRowForegroundColor(size_t row)
  834. {
  835.     return labelcolor();
  836. }
  837. template <class RowData>
  838. inline Fl_Color
  839. CTablePanel<RowData>::x_GetRowBackgroundColor(size_t row)
  840. {
  841.     return FL_BACKGROUND2_COLOR;
  842. }
  843. //
  844. // sort by a given column
  845. //
  846. template <class RowData>
  847. inline
  848. void CTablePanel<RowData>::SortByCol(size_t col, ESortState sort_order)
  849. {
  850.     _ASSERT(col < GetCols());
  851.     x_SetData().SortByCol(col,
  852.                           (sort_order == eAscending),
  853.                           (m_ColInfo[col].type == eNumeric));
  854. }
  855. //
  856. // SetColType()
  857. // set the type of data represented in the column.  This determines how the
  858. // column is sorted.
  859. //
  860. template <class RowData>
  861. inline
  862. void CTablePanel<RowData>::SetColType(size_t col, EColumnType type)
  863. {
  864.     if (col >= GetCols()) {
  865.         SetCols(col + 1);
  866.     }
  867.     m_ColInfo[col].type = type;
  868. }
  869. //
  870. // GetColType()
  871. // Return the type of data used in a given column
  872. // 
  873. template <class RowData>
  874. inline typename CTablePanel<RowData>::EColumnType
  875. CTablePanel<RowData>::GetColType(size_t col) const
  876. {
  877.     _ASSERT(col < GetCols());
  878.     return m_ColInfo[col].type;
  879. }
  880. //
  881. // SetRelWidth()
  882. // Set the relative width of a given column.  The relative width only
  883. // makes sense in the context of the sum of the relative widths of all the
  884. // other visible columns.
  885. //
  886. template <class RowData>
  887. inline
  888. void CTablePanel<RowData>::SetRelWidth(size_t col, float width_frac)
  889. {
  890.     if (col >= GetCols()) {
  891.         SetCols(col + 1);
  892.     }
  893.     m_ColInfo[col].width_frac = width_frac;
  894. }
  895. //
  896. // GetRelWidth()
  897. // Returns the relative width of a given column.  The number returned only
  898. // makes sense in the context of the sum of the relative widths of all the
  899. // other visible columns.
  900. //
  901. template <class RowData>
  902. inline
  903. float CTablePanel<RowData>::GetRelWidth(size_t col) const
  904. {
  905.     _ASSERT(col < GetCols());
  906.     return m_ColInfo[col].width_frac;
  907. }
  908. //
  909. // SetWidth()
  910. // Set the actual width in pixels for a given column
  911. template <class RowData>
  912. inline
  913. void CTablePanel<RowData>::SetWidth(size_t col, float width)
  914. {
  915.     if (col >= GetCols()) {
  916.         SetCols(col + 1);
  917.     }
  918.     m_ColInfo[col].width = width;
  919.     ITERATE (vector<size_t>, iter, m_VirtCols) {
  920.         if (*iter == col) {
  921.             col_width(iter - m_VirtCols.begin(), (int)width);
  922.         }
  923.     }
  924. }
  925. //
  926. // GetWidth()
  927. // Returns the relative width of a given column.  The number returned only
  928. // makes sense in the context of the sum of the relative widths of all the
  929. // other visible columns.
  930. //
  931. template <class RowData>
  932. inline
  933. float CTablePanel<RowData>::GetWidth(size_t col) const
  934. {
  935.     _ASSERT(col < GetCols());
  936.     return m_ColInfo[col].width;
  937. }
  938. //
  939. // SetColAlign()
  940. // set the default alignment for a given column
  941. //
  942. template <class RowData>
  943. inline
  944. void CTablePanel<RowData>::SetColAlign(size_t col, Fl_Align align)
  945. {
  946.     if (col >= GetCols()) {
  947.         SetCols(col + 1);
  948.     }
  949.     m_ColInfo[col].align = align;
  950. }
  951. //
  952. // GetColAlign()
  953. // Return the current slignment setting for a given column
  954. //
  955. template <class RowData>
  956. inline
  957. Fl_Align CTablePanel<RowData>::GetColAlign(size_t col) const
  958. {
  959.     _ASSERT(col < GetCols());
  960.     return m_ColInfo[col].align;
  961. }
  962. //
  963. // SetColumn()
  964. // This function sets all column properties; internally, it just calls other
  965. // functions to set individual properties on the selected column.
  966. //
  967. template <class RowData>
  968. inline
  969. void CTablePanel<RowData>::SetColumn(size_t col, const string& header,
  970.                                      EColumnType type,
  971.                                      Fl_Align align,
  972.                                      float rel_width)
  973. {
  974.     SetColHeader(col, header);
  975.     SetColType  (col, type);
  976.     SetColAlign (col, align);
  977.     SetRelWidth (col, rel_width);
  978.     // always add a new column
  979.     SetVirtualCol(m_VirtCols.size(), col);
  980.     SetupColumns();
  981. }
  982. //
  983. // SetVirtualCol()
  984. //
  985. template <class RowData>
  986. inline void
  987. CTablePanel<RowData>::ClearVirtualCols()
  988. {
  989.     m_VirtCols.clear();
  990.     CTablePanelBase::SetCols(0);
  991. }
  992. //
  993. // SetVirtualCol()
  994. //
  995. template <class RowData>
  996. inline void
  997. CTablePanel<RowData>::SetVirtualCol(int virt_col, int actual_col)
  998. {
  999.     m_VirtCols.push_back(actual_col);
  1000.     // call our base class's resize
  1001.     CTablePanelBase::SetCols(m_VirtCols.size());
  1002. }
  1003. //
  1004. // SetupColumns()
  1005. // Internal function to correctly set column widths and alignments.  This is
  1006. // intended to be called any time the column setup changes - i.e., any time the
  1007. // user selects a different set of visible columns.
  1008. //
  1009. template <class RowData>
  1010. inline
  1011. void CTablePanel<RowData>::SetupColumns()
  1012. {
  1013.     float sum = 0;
  1014.     ITERATE (vector<size_t>, iter, m_VirtCols) {
  1015.         const SColInfo& info = m_ColInfo[ *iter];
  1016.         sum += info.width_frac;
  1017.     }
  1018.     float widget_width = (float)(w() - 1);
  1019.     int idx = 0;
  1020.     float total_rel_width = 0.0f;
  1021.     NON_CONST_ITERATE (vector<size_t>, iter, m_VirtCols) {
  1022.         SColInfo& info = m_ColInfo[ *iter];
  1023.         float prev_rel_width = total_rel_width;
  1024.         total_rel_width += info.width_frac;
  1025.         float prev_width  = (widget_width * prev_rel_width / sum);
  1026.         float total_width = (widget_width * total_rel_width / sum);
  1027.         info.width = total_width - prev_width;
  1028.         // actually set our width
  1029.         // we take this opportunity to set the column style as well
  1030.         col_width(idx++, (int)info.width);
  1031.     }
  1032. }
  1033. //
  1034. // access a column header
  1035. //
  1036. template <class RowData>
  1037. inline
  1038. void CTablePanel<RowData>::SetColHeader(size_t col, const string& str)
  1039. {
  1040.     if (col >= GetCols()) {
  1041.         SetCols(col + 1);
  1042.     }
  1043.     m_ColInfo[col].header = str;
  1044. }
  1045. template <class RowData>
  1046. inline
  1047. const string& CTablePanel<RowData>::GetColHeader(size_t col) const
  1048. {
  1049.     _ASSERT(col < GetCols());
  1050.     return m_ColInfo[col].header;
  1051. }
  1052. //
  1053. // Fl_Table_Row overload: draw_cell()
  1054. // This actually does the work of drawing our data
  1055. //
  1056. template <class Data>
  1057. inline
  1058. void CTablePanel<Data>::draw_cell(TableContext ctx,
  1059.                                   int row, int col,
  1060.                                   int x, int y, int w, int h)
  1061. {
  1062.     // flip for our virtual columns
  1063.     if (m_VirtCols.size()) {
  1064.         col = m_VirtCols[col];
  1065.     }
  1066.     switch (ctx) {
  1067.     case CONTEXT_STARTPAGE:
  1068. fl_font(labelfont(), labelsize());
  1069.         break;
  1070.     case CONTEXT_ROW_HEADER:
  1071.         fl_push_clip(x, y, w, h);
  1072.         {{
  1073.             fl_draw_box(m_RowHeaderBox, x, y, w, h, row_header_color());
  1074.             if ((size_t)row < GetRows()) {
  1075.                 fl_color(labelcolor());
  1076.                 fl_draw(GetRowHeader(row).c_str(),
  1077.                         x, y, w, h, FL_ALIGN_CENTER);
  1078.             }
  1079.          }}
  1080.         fl_pop_clip();
  1081.         break;
  1082.     case CONTEXT_COL_HEADER:
  1083.         fl_push_clip(x, y, w, h);
  1084.         {{
  1085.             fl_draw_box(m_ColHeaderBox, x, y, w, h, col_header_color());
  1086.             if ((size_t)col < GetCols()) {
  1087.                 fl_color(labelcolor());
  1088.                 fl_draw(GetColHeader(col).c_str(),
  1089.                         x, y, w, h, FL_ALIGN_CENTER);
  1090.             }
  1091.          }}
  1092.         fl_pop_clip();
  1093.         break;
  1094.     case CONTEXT_CELL:
  1095.         fl_push_clip(x, y, w, h);
  1096.         {{
  1097.     // BG COLOR
  1098.             if (row_selected(row)) {
  1099.         fl_color(selection_color());
  1100.             } else {
  1101.                 fl_color(x_GetRowBackgroundColor(row));
  1102.             }
  1103.     fl_rectf(x, y, w, h);
  1104.     // TEXT
  1105.             if ((size_t)row < GetRows()  && (size_t)col < GetCols()) {
  1106.                 if (row_selected(row)) {
  1107.                     fl_color(FL_YELLOW);
  1108.                 } else {
  1109.                     fl_color(x_GetRowForegroundColor(row));
  1110.                 }
  1111.                 const char *p = GetCell(row, col).c_str();
  1112.                 fl_draw(p,
  1113.                         x + Fl::box_dx(m_CellBox),
  1114.                         y + Fl::box_dy(m_CellBox),
  1115.                         w - Fl::box_dw(m_CellBox),
  1116.                         h - Fl::box_dh(m_CellBox),
  1117.                         GetColAlign(col));
  1118.             }
  1119.             // BORDER
  1120.             fl_draw_box(m_CellBox, x, y, w, h, FL_LIGHT2);
  1121.         }}
  1122.         fl_pop_clip();
  1123.         break;
  1124.     case CONTEXT_ENDPAGE:
  1125.         fl_push_clip(this->x(), this->y(), this->w(), this->h());
  1126.         {{
  1127.             fl_draw_box(box(),
  1128.                         this->x(), this->y(), this->w(), this->h(),
  1129.                         color());
  1130.         }}
  1131.         fl_pop_clip();
  1132.         break;
  1133.     default:
  1134.         break;
  1135.     }
  1136. }
  1137. #if 0
  1138. //
  1139. // stock data comparators - one to dereference, and one to compare by value
  1140. //
  1141. template <class Data>
  1142. struct SCompareByPtr {
  1143.     bool operator() (const Data& d0, const Data& d1) const {
  1144.         return (*d0 < *d1);
  1145.     }
  1146. };
  1147. template <class Data>
  1148. struct SCompareByValue {
  1149.     bool operator() (const Data& d0, const Data& d1) const {
  1150.         return (d0 < d1);
  1151.     }
  1152. };
  1153. //
  1154. // class CListPanel extends CTablePanel by creating a multi-column list panel.
  1155. //
  1156. // This panel has a few features not found in CTablePanel:
  1157. //  - It stores all data in the widget itself, rather than relying on a virtual
  1158. //    accessor mechanism.
  1159. //  - It provides a means of sorting by columns.  -1 = sort by original data.
  1160. //
  1161. template <class Data, class Comparator = SCompareByPtr<Data> >
  1162. class CListPanel : public CTablePanel
  1163. {
  1164. public:
  1165.     // typedefs and nested classes for our columns and data
  1166.     // NB: these are public to avoid compiler errors regarding use of a
  1167.     // protected typedef in a protected nested class
  1168.     typedef vector<string>  TColumns;
  1169.     class CRow
  1170.     {
  1171.     public:
  1172.         Data        m_Data;
  1173.         string      m_RowHeader;
  1174.         TColumns    m_Columns;
  1175.     };
  1176.     typedef CRow TRow;
  1177.     typedef vector<TRow>    TTable;
  1178.     CListPanel(int x, int y, int w, int h, const char* label = NULL);
  1179.     virtual ~CListPanel() {}
  1180.     // sort by a given column
  1181.     void        SortByCol(int col);
  1182.     // get/set the row headers
  1183.     void            SetRowHeader(int row, const string& header);
  1184.     const string&   GetRowHeader(int row) const;
  1185.     // access the data for a given row
  1186.     Data        GetData(int row)    { return m_Data[row].m_Data; }
  1187. protected:
  1188.     // our data
  1189.     TTable                  m_Data;
  1190.     // predicate for sorting our table data by a given column
  1191.     struct SColSorter
  1192.     {
  1193.         int m_Col;
  1194.         bool m_Ascending;
  1195.         EColumnType type;
  1196.         Comparator m_Comparator;
  1197.         SColSorter(int col, bool ascending, EColumnType type)
  1198.             : m_Col(col)
  1199.             , m_Ascending(ascending)
  1200.             , type(type) {}
  1201.         bool operator() (const TRow& row0, const TRow& row1) const
  1202.         {
  1203.             bool comp = false;
  1204.             switch (type) {
  1205.             case eString:
  1206.                 if (row0.m_Columns[m_Col] != row1.m_Columns[m_Col]) {
  1207.                     comp = (row0.m_Columns[m_Col] < row1.m_Columns[m_Col]);
  1208.                 } else {
  1209.                     comp = m_Comparator(row0.m_Data, row1.m_Data);
  1210.                 }
  1211.                 break;
  1212.             case eNumeric:
  1213.                 {
  1214.                     int r0 = 0;
  1215.                     int r1 = 0;
  1216.                     if ( !row0.m_Columns[m_Col].empty() ) {
  1217.                         r0 = NStr::StringToInt(row0.m_Columns[m_Col],
  1218.                                                10, NStr::eCheck_Skip);
  1219.                     }
  1220.                     if ( !row1.m_Columns[m_Col].empty() ) {
  1221.                         r1 = NStr::StringToInt(row1.m_Columns[m_Col],
  1222.                                                10, NStr::eCheck_Skip);
  1223.                     }
  1224.                     if (r0 != r1) {
  1225.                         comp = (r0 < r1);
  1226.                     } else {
  1227.                         comp = m_Comparator(row0.m_Data, row1.m_Data);
  1228.                     }
  1229.                 }
  1230.                 break;
  1231.             }
  1232.             return (m_Ascending ? comp : !comp);
  1233.         }
  1234.     };
  1235.     // predicate for sorting our table data by the underlying data object
  1236.     struct SDataSorter
  1237.     {
  1238.         bool m_Ascending;
  1239.         Comparator m_Comp;
  1240.         SDataSorter(bool ascending)
  1241.             : m_Ascending(ascending) {}
  1242.         bool operator() (const TRow& row0, const TRow& row1) const
  1243.         {
  1244.             return (m_Ascending ?
  1245.                     ( m_Comp(row0.m_Data, row1.m_Data) ):
  1246.                     ( m_Comp(row1.m_Data, row0.m_Data) ) );
  1247.         }
  1248.     };
  1249.     // FLTK overloads
  1250.     virtual int handle(int event);
  1251.     virtual void draw_cell(TableContext ctx, int row, int col,
  1252.                            int x, int y, int w, int h);
  1253. };
  1254. //
  1255. // default ctor
  1256. //
  1257. template <class Data, class Comparator>
  1258. inline CListPanel<Data, Comparator>::CListPanel(int x, int y, int w, int h,
  1259.                                     const char* label)
  1260.     : CTablePanel(x, y, w, h, label)
  1261. {
  1262. }
  1263. //
  1264. // Utility function: sort by a given column
  1265. // NOTE: the 'column' here is the *actual* column.  The one exception is the
  1266. // special column '-1', which indicates 'sort by underlying data'
  1267. //
  1268. template <class Data, class Comparator>
  1269. inline void CListPanel<Data, Comparator>::SortByCol(int col)
  1270. {
  1271.     if (col >= 0) {
  1272.         if (col >= int (m_ColInfo.size())) {
  1273.             return;
  1274.         }
  1275.         bool ascending = false;
  1276.         if (m_ColInfo[col].sort_state != eAscending) {
  1277.             ascending = true;
  1278.         }
  1279.         NON_CONST_ITERATE (TColInfo, iter, m_ColInfo) {
  1280.             iter->sort_state = eNotSorted;
  1281.         }
  1282.         m_ColInfo[col].sort_state = (ascending ? eAscending : eDescending);
  1283.         // string sort by column
  1284.         // we need to map our visible column to our underlying data column
  1285.         std::sort(m_Data.begin(), m_Data.end(),
  1286.                   SColSorter(col, ascending, m_ColInfo[col].type));
  1287.     } else {
  1288.         // sort by data
  1289.         std::sort(m_Data.begin(), m_Data.end(), SDataSorter(true));
  1290.     }
  1291. }
  1292. //
  1293. // SetRowHeader()
  1294. // Set the header for a given row
  1295. //
  1296. template <class Data, class Comparator>
  1297. inline void
  1298. CListPanel<Data, Comparator>::SetRowHeader(int row, const string& header)
  1299. {
  1300.     if (int (m_Data.size()) <= row) {
  1301.         m_Data.resize(row + 1);
  1302.     }
  1303.     m_Data[row].m_RowHeader = header;
  1304. }
  1305. //
  1306. // GetRowHeader()
  1307. // Return the header for a given row
  1308. //
  1309. template <class Data, class Comparator>
  1310. inline const string&
  1311. CListPanel<Data, Comparator>::GetRowHeader(int row) const
  1312. {
  1313.     return m_Data[row].m_RowHeader;
  1314. }
  1315. //
  1316. // Flek overload: draw_cell()
  1317. // This actually does the work of drawing our data
  1318. //
  1319. template <class Data, class Comparator>
  1320. inline void CListPanel<Data, Comparator>::draw_cell(TableContext ctx,
  1321.                                                     int row, int col,
  1322.                                                     int x, int y,
  1323.                                                     int w, int h)
  1324. {
  1325.     // transform col (virtual col) to actual table column
  1326.     int actual_col = 0;
  1327.     if (col < m_VirtCols.size() ) {
  1328.         actual_col = m_VirtCols[col];
  1329.     }
  1330.     switch (ctx) {
  1331.     case CONTEXT_STARTPAGE:
  1332. fl_font(labelfont(), labelsize());
  1333.         break;
  1334.     case CONTEXT_ROW_HEADER:
  1335.         fl_push_clip(x, y, w, h);
  1336.         {{
  1337.             fl_draw_box(m_HeaderBox, x, y, w, h, row_header_color());
  1338.             fl_color(labelcolor());
  1339.             if (row < m_Data.size()) {
  1340.                 fl_draw(m_Data[row].m_RowHeader.c_str(),
  1341.                         x, y, w, h, FL_ALIGN_CENTER);
  1342.             }
  1343.          }}
  1344.         fl_pop_clip();
  1345.         break;
  1346.     case CONTEXT_COL_HEADER:
  1347.         fl_push_clip(x, y, w, h);
  1348.         {{
  1349.             fl_draw_box(m_HeaderBox, x, y, w, h, col_header_color());
  1350.             if (actual_col < m_ColInfo.size()) {
  1351.                 fl_color(labelcolor());
  1352.                 fl_draw(m_ColInfo[actual_col].header.c_str(),
  1353.                         x, y, w, h, FL_ALIGN_CENTER);
  1354.             }
  1355.          }}
  1356.         fl_pop_clip();
  1357.         break;
  1358.     case CONTEXT_CELL:
  1359.         fl_push_clip(x, y, w, h);
  1360.         {{
  1361.     // BG COLOR
  1362.     fl_color(row_selected(row) ?
  1363.                      selection_color() : FL_BACKGROUND2_COLOR);
  1364.     fl_rectf(x, y, w, h);
  1365.     // TEXT
  1366.             if (row < m_Data.size()  &&
  1367.                 actual_col < m_Data[row].m_Columns.size()) {
  1368.         fl_color(labelcolor());
  1369.                 const char *p = m_Data[row].m_Columns[actual_col].c_str();
  1370.                 fl_draw(p,
  1371.                         x + Fl::box_dx(m_CellBox),
  1372.                         y + Fl::box_dy(m_CellBox),
  1373.                         w - Fl::box_dw(m_CellBox),
  1374.                         h - Fl::box_dh(m_CellBox),
  1375.                         GetColAlign(actual_col));
  1376.             }
  1377.     // BORDER
  1378.     fl_draw_box(m_CellBox, x, y, w, h, FL_LIGHT2);
  1379.          }}
  1380.         fl_pop_clip();
  1381.         break;
  1382.     default:
  1383.         break;
  1384.     }
  1385. }
  1386. //
  1387. // overloaded event handler
  1388. // here we trigger column sorting
  1389. //
  1390. template <class Data, class Comparator>
  1391. inline int CListPanel<Data, Comparator>::handle(int event)
  1392. {
  1393.     int row = -1;
  1394.     int col = -1;
  1395.     switch (event)
  1396.     {
  1397.     case FL_PUSH:
  1398.         /** FIXME
  1399.         row = get_row(Fl::event_x(), Fl::event_y());
  1400.         if (row != -1  ||  Fl::event_clicks() != 1) {
  1401.             break;
  1402.         }
  1403.         col = get_col(Fl::event_x(), Fl::event_y());
  1404.         SortByCol(m_VirtCols[col]);
  1405.         redraw();
  1406.         **/
  1407.         break;
  1408.     default:
  1409.         break;
  1410.     };
  1411.     return Fl_Table_Row::handle(event);
  1412. }
  1413. #endif
  1414. END_NCBI_SCOPE
  1415. /* @} */
  1416. /*
  1417.  * ===========================================================================
  1418.  * $Log: table_panel.hpp,v $
  1419.  * Revision 1000.4  2004/06/01 19:52:33  gouriano
  1420.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.15
  1421.  *
  1422.  * Revision 1.15  2004/05/28 14:54:54  dicuccio
  1423.  * Added functions to take CFltkUtils::EBoxType directly
  1424.  *
  1425.  * Revision 1.14  2004/05/25 17:06:39  dicuccio
  1426.  * MOved border drawing code outside of row check.  Changed ascending/descending
  1427.  * sort arrows to meet user expectations
  1428.  *
  1429.  * Revision 1.13  2004/05/11 18:55:14  dicuccio
  1430.  * Added doxygen modules info
  1431.  *
  1432.  * Revision 1.12  2004/05/07 15:44:47  dicuccio
  1433.  * Fixed compiler warning about type conversion
  1434.  *
  1435.  * Revision 1.11  2004/05/03 12:47:08  dicuccio
  1436.  * Added #include for gui/gui.hpp.  gui/utils ->gui/objutils where needed.
  1437.  *
  1438.  * Revision 1.10  2004/04/22 15:08:08  gorelenk
  1439.  * Fixed compilation error in implementation of 'CTablePanel<RowData>::SetRow'
  1440.  *
  1441.  * Revision 1.9  2004/04/22 14:21:41  gorelenk
  1442.  * Fixed compilation errors on MSVC7.
  1443.  *
  1444.  * Revision 1.8  2004/04/16 14:32:54  dicuccio
  1445.  * Added IsRowSelected() - const wrapper around non-const function
  1446.  *
  1447.  * Revision 1.7  2004/04/07 12:42:08  dicuccio
  1448.  * Call SetRows() in RemoveRow().  Make sure that draw_cell() will be entered even
  1449.  * if no items are present (insures that column headers will be drawn)
  1450.  *
  1451.  * Revision 1.6  2004/03/19 18:02:17  dicuccio
  1452.  * Added SetWidth()/GetWidth() - width of a column in pixels.  Added better
  1453.  * (smooth) handling of resize() - resize columns to fit only if they are less
  1454.  * than the current width.
  1455.  *
  1456.  * Revision 1.5  2004/03/19 17:00:12  dicuccio
  1457.  * Fix for resize() - preserve virtual width of the table
  1458.  *
  1459.  * Revision 1.4  2004/03/11 17:22:41  dicuccio
  1460.  * Reinstaed virtual columns
  1461.  *
  1462.  * Revision 1.3  2004/03/05 17:28:26  dicuccio
  1463.  * Added standard handlers for cut/copy/paste events.  Added abiluty to remove
  1464.  * rows
  1465.  *
  1466.  * Revision 1.2  2004/01/20 18:11:11  dicuccio
  1467.  * Changed SetColumns() to SetCols().  Introduced GetRows()/SetRows()/SetCols()
  1468.  * as virtual replacements for rows()/cols().  Added sorting of columns on
  1469.  * double-click of header.  Added standard virtual hooks for trapping click
  1470.  * events inside of cells / headers.  Added more natural API to SetCells().
  1471.  *
  1472.  * Revision 1.1  2003/12/09 15:54:10  dicuccio
  1473.  * Deprecated Fl_Tree_Browser - use Flu_Tree_Browser instead
  1474.  *
  1475.  * Revision 1.22  2003/12/05 02:03:14  ucko
  1476.  * Add missing definitions of CTablePanel::{Get,Set}RowHeader(size_t),
  1477.  * and fix the other definition of GetRowHeader to avoid looping forever.
  1478.  *
  1479.  * Revision 1.21  2003/12/04 18:07:48  dicuccio
  1480.  * Removed direct access to underlying data component in CTablePanel<> - makes
  1481.  * the class more tightly encapsulated
  1482.  *
  1483.  * Revision 1.20  2003/09/29 15:16:02  dicuccio
  1484.  * Added typename where required
  1485.  *
  1486.  * Revision 1.19  2003/09/24 18:21:56  dicuccio
  1487.  * Introduce new base class interposed between CTablePanel<> and Fl_Table_Row;
  1488.  * this class incorporates most of the generic features of CTablePanel<> and
  1489.  * allows for easier extension of list views
  1490.  *
  1491.  * Revision 1.18  2003/09/17 16:19:58  dicuccio
  1492.  * Make sure to set the row height appropriately for the font when setting rows
  1493.  *
  1494.  * Revision 1.17  2003/08/18 14:53:04  dicuccio
  1495.  * Code clean-up.  Made interface class for table data cleaner, more
  1496.  * comprehensive
  1497.  *
  1498.  * Revision 1.16  2003/07/28 11:53:29  dicuccio
  1499.  * Rewrote CTablePanel<> to be more flexible and better contained
  1500.  *
  1501.  * Revision 1.15  2003/07/25 13:40:46  dicuccio
  1502.  * Replaced Flv_Table with Fl_Table
  1503.  *
  1504.  * Revision 1.14  2003/06/25 16:59:42  dicuccio
  1505.  * Changed CPluginHandle into a pointer-to-implementation (the previous
  1506.  * implementation is now the pointer held).  Lots of #include file clean-ups.
  1507.  *
  1508.  * Revision 1.13  2003/03/17 14:58:33  dicuccio
  1509.  * Eliminated annoying compiler warning about unsigned-signed compare
  1510.  *
  1511.  * Revision 1.12  2003/03/10 17:49:04  kuznets
  1512.  * iterate->ITERATE
  1513.  *
  1514.  * Revision 1.11  2003/02/25 14:43:20  dicuccio
  1515.  * Added smart resizing of multicolumn list widget
  1516.  *
  1517.  * Revision 1.10  2003/02/20 19:43:13  dicuccio
  1518.  * Changed column sort to be triggered on double-click, not single-click
  1519.  *
  1520.  * Revision 1.9  2003/01/17 21:09:49  dicuccio
  1521.  * Altered sorting - fall back to feature sort order if sort returns
  1522.  * equivalence
  1523.  *
  1524.  * Revision 1.8  2003/01/15 17:48:32  dicuccio
  1525.  * Fixed thinko: don't try to numerically convert an empty column string
  1526.  *
  1527.  * Revision 1.7  2003/01/13 13:11:44  dicuccio
  1528.  * Namespace clean-up.  Retired namespace gui -> converted to namespace ncbi.
  1529.  * Moved all FLUID-generated code into namespace ncbi.
  1530.  *
  1531.  * Revision 1.6  2003/01/08 20:19:19  dicuccio
  1532.  * Fix for solaris builds: cannot use protected typedefs in protected nested
  1533.  * classes.
  1534.  *
  1535.  * Revision 1.5  2003/01/08 14:47:45  dicuccio
  1536.  * Moved column selection dialog into internal directory.  Made column
  1537.  * selection dialog part of the base class; it is expressible via
  1538.  * CTablePanel::ShowColSelectDlg().  Added ability to specify type of data
  1539.  * stored in column (currently string or numeric); added ability to sort based
  1540.  * on underlying type.
  1541.  *
  1542.  * Revision 1.4  2003/01/03 18:38:08  dicuccio
  1543.  * Fixed compilation error in WIndows - can't reference protected enum from
  1544.  * nested protected class.
  1545.  *
  1546.  * Revision 1.3  2003/01/03 13:28:14  dicuccio
  1547.  * Lots of clean-up.  Added stored sort state.  Added new class to hold all
  1548.  * info for one virtual column.  Added dialog box for selecting visible
  1549.  * columns.
  1550.  *
  1551.  * Revision 1.2  2002/12/30 20:18:14  dicuccio
  1552.  * Added Win32 export specifier.  Rearranged #include directives
  1553.  *
  1554.  * Revision 1.1  2002/12/30 18:42:39  dicuccio
  1555.  * Initial revision
  1556.  *
  1557.  * ===========================================================================
  1558.  */
  1559. #endif  // GUI_WIDGETS_TABLE___TABLE_PANEL__HPP