#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;
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; }
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 );
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;
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
/////////////////////////////////////////////////////////////////////////////
/**
- 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.
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;
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;
// 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 );
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;
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)
bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem & parent, const wxDataViewItem & item)
{
+ GetOwner()->InvalidateColBestWidths();
+
if (IsVirtualList())
{
wxDataViewVirtualListModel *list_model =
bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem& parent,
const wxDataViewItem& item)
{
+ GetOwner()->InvalidateColBestWidths();
+
if (IsVirtualList())
{
wxDataViewVirtualListModel *list_model =
bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem & item)
{
+ GetOwner()->InvalidateColBestWidths();
+
SortPrepare();
g_model->Resort();
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
bool wxDataViewMainWindow::Cleared()
{
+ GetOwner()->InvalidateColBestWidths();
+
DestroyTree();
m_selection.Clear();
GetModel()->RemoveNotifier( m_notifier );
m_cols.Clear();
+ m_colsBestWidths.clear();
}
void wxDataViewCtrl::Init()
return false;
m_cols.Append( col );
+ m_colsBestWidths.push_back(0);
OnColumnsCountChanged();
return true;
}
return false;
m_cols.Insert( col );
+ m_colsBestWidths.insert(m_colsBestWidths.begin(), 0);
OnColumnsCountChanged();
return true;
}
return false;
m_cols.Insert( pos, col );
+ m_colsBestWidths.insert(m_colsBestWidths.begin() + pos, 0);
OnColumnsCountChanged();
return true;
}
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))
{
if (!ret)
return false;
+ m_colsBestWidths.erase(m_colsBestWidths.begin() + GetColumnIndex(column));
m_cols.Erase(ret);
OnColumnsCountChanged();
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
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 );
}
}