Add optional columns autosizing to wxDataViewCtrl.
Only implemented in the generic and GTK+ versions at the moment, OS X support will be added later. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@65948 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
9aebcb5e44
commit
d0154e3a5a
@ -17,6 +17,7 @@
|
||||
#include "wx/control.h"
|
||||
#include "wx/scrolwin.h"
|
||||
#include "wx/icon.h"
|
||||
#include "wx/vector.h"
|
||||
|
||||
class WXDLLIMPEXP_FWD_ADV wxDataViewMainWindow;
|
||||
class WXDLLIMPEXP_FWD_ADV wxDataViewHeaderWindow;
|
||||
@ -56,7 +57,7 @@ public:
|
||||
virtual wxString GetTitle() const { return m_title; }
|
||||
|
||||
virtual void SetWidth(int width) { m_width = width; UpdateDisplay(); }
|
||||
virtual int GetWidth() const { return m_width; }
|
||||
virtual int GetWidth() const;
|
||||
|
||||
virtual void SetMinWidth(int minWidth) { m_minWidth = minWidth; UpdateDisplay(); }
|
||||
virtual int GetMinWidth() const { return m_minWidth; }
|
||||
@ -206,10 +207,7 @@ protected:
|
||||
public: // utility functions not part of the API
|
||||
|
||||
// returns the "best" width for the idx-th column
|
||||
unsigned int GetBestColumnWidth(int WXUNUSED(idx)) const
|
||||
{
|
||||
return GetClientSize().GetWidth() / GetColumnCount();
|
||||
}
|
||||
unsigned int GetBestColumnWidth(int idx) const;
|
||||
|
||||
// called by header window after reorder
|
||||
void ColumnMoved( wxDataViewColumn* col, unsigned int new_pos );
|
||||
@ -232,7 +230,13 @@ private:
|
||||
virtual wxDataViewItem DoGetCurrentItem() const;
|
||||
virtual void DoSetCurrentItem(const wxDataViewItem& item);
|
||||
|
||||
void InvalidateColBestWidths();
|
||||
void InvalidateColBestWidth(int idx);
|
||||
|
||||
wxDataViewColumnList m_cols;
|
||||
// cached column best widths or 0 if not computed, values are for
|
||||
// respective columns from m_cols and the arrays have same size
|
||||
wxVector<int> m_colsBestWidths;
|
||||
wxDataViewModelNotifier *m_notifier;
|
||||
wxDataViewMainWindow *m_clientArea;
|
||||
wxDataViewHeaderWindow *m_headerArea;
|
||||
|
@ -22,7 +22,10 @@
|
||||
enum
|
||||
{
|
||||
// special value for column width meaning unspecified/default
|
||||
wxCOL_WIDTH_DEFAULT = -1
|
||||
wxCOL_WIDTH_DEFAULT = -1,
|
||||
|
||||
// size the column automatically to fit all values
|
||||
wxCOL_WIDTH_AUTOSIZE = -2
|
||||
};
|
||||
|
||||
// bit masks for the various column attributes
|
||||
|
@ -9,9 +9,16 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
Special value used for column width meaning unspecified or default.
|
||||
Column width special values.
|
||||
*/
|
||||
enum { wxCOL_WIDTH_DEFAULT = -1 };
|
||||
enum
|
||||
{
|
||||
/// Special value used for column width meaning unspecified or default.
|
||||
wxCOL_WIDTH_DEFAULT = -1,
|
||||
|
||||
/// Size the column automatically to fit all values.
|
||||
wxCOL_WIDTH_AUTOSIZE = -2
|
||||
};
|
||||
|
||||
/**
|
||||
Bit flags used as wxHeaderColumn flags.
|
||||
@ -77,7 +84,8 @@ public:
|
||||
Returns the current width of the column.
|
||||
|
||||
@return
|
||||
Width of the column in pixels, never wxCOL_WIDTH_DEFAULT.
|
||||
Width of the column in pixels, never wxCOL_WIDTH_DEFAULT or
|
||||
wxCOL_WIDTH_AUTOSIZE.
|
||||
*/
|
||||
virtual int GetWidth() const = 0;
|
||||
|
||||
@ -199,8 +207,9 @@ public:
|
||||
Set the column width.
|
||||
|
||||
@param width
|
||||
The column width in pixels or the special wxCOL_WIDTH_DEFAULT value
|
||||
meaning to use default width.
|
||||
The column width in pixels or the special wxCOL_WIDTH_DEFAULT
|
||||
(meaning to use default width) or wxCOL_WIDTH_AUTOSIZE (size to
|
||||
fit the content) value.
|
||||
*/
|
||||
virtual void SetWidth(int width) = 0;
|
||||
|
||||
|
@ -622,16 +622,18 @@ void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned l
|
||||
// the various columns
|
||||
m_ctrl[1]->AppendTextColumn("editable string",
|
||||
MyListModel::Col_EditableText,
|
||||
wxDATAVIEW_CELL_EDITABLE);
|
||||
wxDATAVIEW_CELL_EDITABLE,
|
||||
wxCOL_WIDTH_AUTOSIZE);
|
||||
m_ctrl[1]->AppendIconTextColumn("icon",
|
||||
MyListModel::Col_IconText,
|
||||
wxDATAVIEW_CELL_EDITABLE);
|
||||
wxDATAVIEW_CELL_EDITABLE,
|
||||
wxCOL_WIDTH_AUTOSIZE);
|
||||
|
||||
m_attributes =
|
||||
new wxDataViewColumn("attributes",
|
||||
new wxDataViewTextRenderer,
|
||||
MyListModel::Col_TextWithAttr,
|
||||
80,
|
||||
wxCOL_WIDTH_AUTOSIZE,
|
||||
wxALIGN_RIGHT,
|
||||
wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE );
|
||||
m_ctrl[1]->AppendColumn( m_attributes );
|
||||
|
@ -88,7 +88,7 @@ static bool g_asending = true;
|
||||
|
||||
void wxDataViewColumn::Init(int width, wxAlignment align, int flags)
|
||||
{
|
||||
m_width = width == wxCOL_WIDTH_DEFAULT ? wxDVC_DEFAULT_WIDTH : width;
|
||||
m_width = width;
|
||||
m_minWidth = 0;
|
||||
m_align = align;
|
||||
m_flags = flags;
|
||||
@ -96,6 +96,22 @@ void wxDataViewColumn::Init(int width, wxAlignment align, int flags)
|
||||
m_sortAscending = true;
|
||||
}
|
||||
|
||||
int wxDataViewColumn::GetWidth() const
|
||||
{
|
||||
switch ( m_width )
|
||||
{
|
||||
case wxCOL_WIDTH_DEFAULT:
|
||||
return wxDVC_DEFAULT_WIDTH;
|
||||
|
||||
case wxCOL_WIDTH_AUTOSIZE:
|
||||
wxCHECK_MSG( m_owner, wxDVC_DEFAULT_WIDTH, "no owner control" );
|
||||
return m_owner->GetBestColumnWidth(m_owner->GetColumnIndex(this));
|
||||
|
||||
default:
|
||||
return m_width;
|
||||
}
|
||||
}
|
||||
|
||||
void wxDataViewColumn::UpdateDisplay()
|
||||
{
|
||||
if (m_owner)
|
||||
@ -1930,6 +1946,8 @@ bool Walker( wxDataViewTreeNode * node, DoJob & func )
|
||||
|
||||
bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxDataViewItem & item)
|
||||
{
|
||||
GetOwner()->InvalidateColBestWidths();
|
||||
|
||||
if (IsVirtualList())
|
||||
{
|
||||
wxDataViewVirtualListModel *list_model =
|
||||
@ -1972,6 +1990,8 @@ static void DestroyTreeHelper( wxDataViewTreeNode * node);
|
||||
bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
|
||||
const wxDataViewItem& item)
|
||||
{
|
||||
GetOwner()->InvalidateColBestWidths();
|
||||
|
||||
if (IsVirtualList())
|
||||
{
|
||||
wxDataViewVirtualListModel *list_model =
|
||||
@ -2050,6 +2070,8 @@ bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
|
||||
|
||||
bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item)
|
||||
{
|
||||
GetOwner()->InvalidateColBestWidths();
|
||||
|
||||
SortPrepare();
|
||||
g_model->Resort();
|
||||
|
||||
@ -2066,6 +2088,8 @@ bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item)
|
||||
|
||||
bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned int col )
|
||||
{
|
||||
GetOwner()->InvalidateColBestWidth(col);
|
||||
|
||||
// NOTE: to be valid, we cannot use e.g. INT_MAX - 1
|
||||
/*#define MAX_VIRTUAL_WIDTH 100000
|
||||
|
||||
@ -2093,6 +2117,8 @@ bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem & item, unsigned i
|
||||
|
||||
bool wxDataViewMainWindow::Cleared()
|
||||
{
|
||||
GetOwner()->InvalidateColBestWidths();
|
||||
|
||||
DestroyTree();
|
||||
m_selection.Clear();
|
||||
|
||||
@ -3879,6 +3905,7 @@ wxDataViewCtrl::~wxDataViewCtrl()
|
||||
GetModel()->RemoveNotifier( m_notifier );
|
||||
|
||||
m_cols.Clear();
|
||||
m_colsBestWidths.clear();
|
||||
}
|
||||
|
||||
void wxDataViewCtrl::Init()
|
||||
@ -4029,6 +4056,7 @@ bool wxDataViewCtrl::AppendColumn( wxDataViewColumn *col )
|
||||
return false;
|
||||
|
||||
m_cols.Append( col );
|
||||
m_colsBestWidths.push_back(0);
|
||||
OnColumnsCountChanged();
|
||||
return true;
|
||||
}
|
||||
@ -4039,6 +4067,7 @@ bool wxDataViewCtrl::PrependColumn( wxDataViewColumn *col )
|
||||
return false;
|
||||
|
||||
m_cols.Insert( col );
|
||||
m_colsBestWidths.insert(m_colsBestWidths.begin(), 0);
|
||||
OnColumnsCountChanged();
|
||||
return true;
|
||||
}
|
||||
@ -4049,6 +4078,7 @@ bool wxDataViewCtrl::InsertColumn( unsigned int pos, wxDataViewColumn *col )
|
||||
return false;
|
||||
|
||||
m_cols.Insert( pos, col );
|
||||
m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, 0);
|
||||
OnColumnsCountChanged();
|
||||
return true;
|
||||
}
|
||||
@ -4111,6 +4141,44 @@ int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn *column) const
|
||||
return wxNOT_FOUND;
|
||||
}
|
||||
|
||||
unsigned int wxDataViewCtrl::GetBestColumnWidth(int idx) const
|
||||
{
|
||||
if ( m_colsBestWidths[idx] != 0 )
|
||||
return m_colsBestWidths[idx];
|
||||
|
||||
const unsigned count = m_clientArea->GetRowCount();
|
||||
wxDataViewColumn *column = GetColumn(idx);
|
||||
wxDataViewRenderer *renderer =
|
||||
const_cast<wxDataViewRenderer*>(column->GetRenderer());
|
||||
|
||||
int max_width = 0;
|
||||
|
||||
if ( m_headerArea )
|
||||
{
|
||||
max_width = m_headerArea->GetTextExtent(column->GetTitle()).x;
|
||||
|
||||
// Labels on native MSW header are indented on both sides
|
||||
max_width += wxRendererNative::Get().GetHeaderButtonMargin(m_headerArea);
|
||||
}
|
||||
|
||||
for ( unsigned row = 0; row < count; row++ )
|
||||
{
|
||||
wxDataViewItem item = m_clientArea->GetItemByRow(row);
|
||||
|
||||
wxVariant value;
|
||||
GetModel()->GetValue(value, item, column->GetModelColumn());
|
||||
renderer->SetValue(value);
|
||||
|
||||
max_width = (unsigned)wxMax((int)max_width, renderer->GetSize().x);
|
||||
}
|
||||
|
||||
if ( max_width > 0 )
|
||||
max_width += 2 * PADDING_RIGHTLEFT;
|
||||
|
||||
const_cast<wxDataViewCtrl*>(this)->m_colsBestWidths[idx] = max_width;
|
||||
return max_width;
|
||||
}
|
||||
|
||||
void wxDataViewCtrl::ColumnMoved(wxDataViewColumn * WXUNUSED(col),
|
||||
unsigned int WXUNUSED(new_pos))
|
||||
{
|
||||
@ -4126,6 +4194,7 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
m_colsBestWidths.erase(m_colsBestWidths.begin() + GetColumnIndex(column));
|
||||
m_cols.Erase(ret);
|
||||
OnColumnsCountChanged();
|
||||
|
||||
@ -4135,10 +4204,31 @@ bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn *column )
|
||||
bool wxDataViewCtrl::ClearColumns()
|
||||
{
|
||||
m_cols.Clear();
|
||||
m_colsBestWidths.clear();
|
||||
OnColumnsCountChanged();
|
||||
return true;
|
||||
}
|
||||
|
||||
void wxDataViewCtrl::InvalidateColBestWidth(int idx)
|
||||
{
|
||||
m_colsBestWidths[idx] = 0;
|
||||
|
||||
if ( m_headerArea )
|
||||
m_headerArea->UpdateColumn(idx);
|
||||
}
|
||||
|
||||
void wxDataViewCtrl::InvalidateColBestWidths()
|
||||
{
|
||||
m_colsBestWidths.clear();
|
||||
m_colsBestWidths.resize(m_cols.size());
|
||||
|
||||
if ( m_headerArea )
|
||||
{
|
||||
// this updates visual appearance of columns 0 and up, not just 0
|
||||
m_headerArea->UpdateColumn(0);
|
||||
}
|
||||
}
|
||||
|
||||
int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn *column ) const
|
||||
{
|
||||
#if 1
|
||||
|
@ -3205,23 +3205,20 @@ int wxDataViewColumn::GetWidth() const
|
||||
|
||||
void wxDataViewColumn::SetWidth( int width )
|
||||
{
|
||||
if (width < 0)
|
||||
if ( width == wxCOL_WIDTH_AUTOSIZE )
|
||||
{
|
||||
#if 1
|
||||
gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED );
|
||||
|
||||
// TODO find a better calculation
|
||||
gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), wxDVC_DEFAULT_WIDTH );
|
||||
#else
|
||||
// this is unpractical for large numbers of items and disables
|
||||
// user resizing, which is totally unexpected
|
||||
// NB: this disables user resizing
|
||||
gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_AUTOSIZE );
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED );
|
||||
if ( width == wxCOL_WIDTH_DEFAULT )
|
||||
{
|
||||
// TODO find a better calculation
|
||||
width = wxDVC_DEFAULT_WIDTH;
|
||||
}
|
||||
|
||||
gtk_tree_view_column_set_sizing( GTK_TREE_VIEW_COLUMN(m_column), GTK_TREE_VIEW_COLUMN_FIXED );
|
||||
gtk_tree_view_column_set_fixed_width( GTK_TREE_VIEW_COLUMN(m_column), width );
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user