Implement wxCOL_WIDTH_AUTOSIZE on OS X.
Only Cocoa build on 10.5+ is supported. Before that, NSOutlineView didn't have reasonable support for determining cell sizes. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@66634 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -376,6 +376,7 @@ public:
|
|||||||
virtual wxDataViewColumn* GetColumn (unsigned int pos) const;
|
virtual wxDataViewColumn* GetColumn (unsigned int pos) const;
|
||||||
virtual int GetColumnPosition (wxDataViewColumn const* columnPtr) const;
|
virtual int GetColumnPosition (wxDataViewColumn const* columnPtr) const;
|
||||||
virtual bool InsertColumn (unsigned int pos, wxDataViewColumn* columnPtr);
|
virtual bool InsertColumn (unsigned int pos, wxDataViewColumn* columnPtr);
|
||||||
|
virtual void FitColumnWidthToContent(unsigned int WXUNUSED(pos)) { /*not implemented*/ }
|
||||||
|
|
||||||
//
|
//
|
||||||
// item related methods (inherited from wxDataViewWidgetImpl)
|
// item related methods (inherited from wxDataViewWidgetImpl)
|
||||||
|
|||||||
@@ -441,6 +441,7 @@ public:
|
|||||||
virtual wxDataViewColumn* GetColumn(unsigned int pos) const;
|
virtual wxDataViewColumn* GetColumn(unsigned int pos) const;
|
||||||
virtual int GetColumnPosition(wxDataViewColumn const* columnPtr) const;
|
virtual int GetColumnPosition(wxDataViewColumn const* columnPtr) const;
|
||||||
virtual bool InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr);
|
virtual bool InsertColumn(unsigned int pos, wxDataViewColumn* columnPtr);
|
||||||
|
virtual void FitColumnWidthToContent(unsigned int pos);
|
||||||
|
|
||||||
// item related methods (inherited from wxDataViewWidgetImpl)
|
// item related methods (inherited from wxDataViewWidgetImpl)
|
||||||
virtual bool Add(const wxDataViewItem& parent, const wxDataViewItem& item);
|
virtual bool Add(const wxDataViewItem& parent, const wxDataViewItem& item);
|
||||||
|
|||||||
@@ -58,6 +58,7 @@ public:
|
|||||||
virtual int GetColumnPosition (wxDataViewColumn const* columnPtr) const = 0; // returns the position of the passed column in the native control
|
virtual int GetColumnPosition (wxDataViewColumn const* columnPtr) const = 0; // returns the position of the passed column in the native control
|
||||||
virtual bool InsertColumn (unsigned int pos, wxDataViewColumn* columnPtr) = 0; // inserts a column at pos in the native control;
|
virtual bool InsertColumn (unsigned int pos, wxDataViewColumn* columnPtr) = 0; // inserts a column at pos in the native control;
|
||||||
// the method can assume that the column's owner is already set
|
// the method can assume that the column's owner is already set
|
||||||
|
virtual void FitColumnWidthToContent(unsigned int pos) = 0; // resizes column to fit its content
|
||||||
|
|
||||||
//
|
//
|
||||||
// item related methods
|
// item related methods
|
||||||
|
|||||||
@@ -95,8 +95,8 @@ private:
|
|||||||
m_flags = flags & ~wxDATAVIEW_COL_HIDDEN; // TODO
|
m_flags = flags & ~wxDATAVIEW_COL_HIDDEN; // TODO
|
||||||
m_maxWidth = 30000;
|
m_maxWidth = 30000;
|
||||||
m_minWidth = 0;
|
m_minWidth = 0;
|
||||||
m_width = width >= 0 ? width : wxDVC_DEFAULT_WIDTH;
|
|
||||||
m_alignment = align;
|
m_alignment = align;
|
||||||
|
SetWidth(width);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool m_ascending; // sorting order
|
bool m_ascending; // sorting order
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ enum
|
|||||||
/// Special value used for column width meaning unspecified or default.
|
/// Special value used for column width meaning unspecified or default.
|
||||||
wxCOL_WIDTH_DEFAULT = -1,
|
wxCOL_WIDTH_DEFAULT = -1,
|
||||||
|
|
||||||
/// Size the column automatically to fit all values.
|
/**
|
||||||
|
Size the column automatically to fit all values.
|
||||||
|
|
||||||
|
@note On OS X, this style is only implemented in the Cocoa build on
|
||||||
|
OS X >= 10.5; it behaves identically to wxCOL_WIDTH_DEFAULT otherwise.
|
||||||
|
*/
|
||||||
wxCOL_WIDTH_AUTOSIZE = -2
|
wxCOL_WIDTH_AUTOSIZE = -2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2746,6 +2746,16 @@ void wxDataViewColumn::SetWidth(int width)
|
|||||||
{
|
{
|
||||||
wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
|
wxDataViewCtrl* dataViewCtrlPtr(GetOwner());
|
||||||
|
|
||||||
|
switch ( width )
|
||||||
|
{
|
||||||
|
case wxCOL_WIDTH_AUTOSIZE:
|
||||||
|
// not implemented, fall through
|
||||||
|
case wxCOL_WIDTH_DEFAULT:
|
||||||
|
width = wxDVC_DEFAULT_WIDTH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((width >= m_minWidth) && (width <= m_maxWidth))
|
if ((width >= m_minWidth) && (width <= m_maxWidth))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include "wx/osx/private.h"
|
#include "wx/osx/private.h"
|
||||||
#include "wx/osx/cocoa/dataview.h"
|
#include "wx/osx/cocoa/dataview.h"
|
||||||
#include "wx/renderer.h"
|
#include "wx/renderer.h"
|
||||||
|
#include "wx/stopwatch.h"
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// Constants used locally
|
// Constants used locally
|
||||||
@@ -321,7 +322,6 @@ NSTableColumn* CreateNativeColumn(const wxDataViewColumn *column)
|
|||||||
);
|
);
|
||||||
|
|
||||||
// setting the size related parameters:
|
// setting the size related parameters:
|
||||||
const int width = column->GetWidthVariable();
|
|
||||||
int resizingMask;
|
int resizingMask;
|
||||||
if (column->IsResizeable())
|
if (column->IsResizeable())
|
||||||
{
|
{
|
||||||
@@ -340,7 +340,6 @@ NSTableColumn* CreateNativeColumn(const wxDataViewColumn *column)
|
|||||||
: NSTableColumnNoResizing;
|
: NSTableColumnNoResizing;
|
||||||
}
|
}
|
||||||
[nativeColumn setResizingMask:resizingMask];
|
[nativeColumn setResizingMask:resizingMask];
|
||||||
[nativeColumn setWidth:width];
|
|
||||||
|
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
|
||||||
// setting the visibility:
|
// setting the visibility:
|
||||||
@@ -1945,10 +1944,132 @@ bool wxCocoaDataViewControl::InsertColumn(unsigned int pos, wxDataViewColumn* co
|
|||||||
[m_OutlineView addTableColumn:nativeColumn];
|
[m_OutlineView addTableColumn:nativeColumn];
|
||||||
if (pos != static_cast<unsigned int>([m_OutlineView numberOfColumns]-1))
|
if (pos != static_cast<unsigned int>([m_OutlineView numberOfColumns]-1))
|
||||||
[m_OutlineView moveColumn:[m_OutlineView numberOfColumns]-1 toColumn:pos];
|
[m_OutlineView moveColumn:[m_OutlineView numberOfColumns]-1 toColumn:pos];
|
||||||
|
|
||||||
|
// set columns width now that it can be computed even for autosized columns:
|
||||||
|
columnPtr->SetWidth(columnPtr->GetWidthVariable());
|
||||||
|
|
||||||
// done:
|
// done:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxCocoaDataViewControl::FitColumnWidthToContent(unsigned int pos)
|
||||||
|
{
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||||
|
const int count = GetCount();
|
||||||
|
NSTableColumn *column = GetColumn(pos)->GetNativeData()->GetNativeColumnPtr();
|
||||||
|
|
||||||
|
class MaxWidthCalculator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
MaxWidthCalculator(wxCocoaOutlineView *view,
|
||||||
|
NSTableColumn *column, unsigned columnIndex)
|
||||||
|
: m_width(0),
|
||||||
|
m_view(view),
|
||||||
|
m_column(columnIndex),
|
||||||
|
m_indent(0)
|
||||||
|
{
|
||||||
|
// account for indentation in the column with expander
|
||||||
|
if ( column == [m_view outlineTableColumn] )
|
||||||
|
m_indent = [m_view indentationPerLevel];
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWithWidth(int width)
|
||||||
|
{
|
||||||
|
m_width = wxMax(m_width, width);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UpdateWithRow(int row)
|
||||||
|
{
|
||||||
|
NSCell *cell = [m_view preparedCellAtColumn:m_column row:row];
|
||||||
|
unsigned cellWidth = [cell cellSize].width + 1/*round the float up*/;
|
||||||
|
|
||||||
|
if ( m_indent )
|
||||||
|
cellWidth += m_indent * ([m_view levelForRow:row] + 1);
|
||||||
|
|
||||||
|
m_width = wxMax(m_width, cellWidth);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetMaxWidth() const { return m_width; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
int m_width;
|
||||||
|
wxCocoaOutlineView *m_view;
|
||||||
|
unsigned m_column;
|
||||||
|
int m_indent;
|
||||||
|
};
|
||||||
|
|
||||||
|
MaxWidthCalculator calculator(m_OutlineView, column, pos);
|
||||||
|
|
||||||
|
if ( [column headerCell] )
|
||||||
|
{
|
||||||
|
calculator.UpdateWithWidth([[column headerCell] cellSize].width + 1/*round the float up*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The code below deserves some explanation. For very large controls, we
|
||||||
|
// simply can't afford to calculate sizes for all items, it takes too
|
||||||
|
// long. So the best we can do is to check the first and the last N/2
|
||||||
|
// items in the control for some sufficiently large N and calculate best
|
||||||
|
// sizes from that. That can result in the calculated best width being too
|
||||||
|
// small for some outliers, but it's better to get slightly imperfect
|
||||||
|
// result than to wait several seconds after every update. To avoid highly
|
||||||
|
// visible miscalculations, we also include all currently visible items
|
||||||
|
// no matter what. Finally, the value of N is determined dynamically by
|
||||||
|
// measuring how much time we spent on the determining item widths so far.
|
||||||
|
|
||||||
|
#if wxUSE_STOPWATCH
|
||||||
|
int top_part_end = count;
|
||||||
|
static const long CALC_TIMEOUT = 20/*ms*/;
|
||||||
|
// don't call wxStopWatch::Time() too often
|
||||||
|
static const unsigned CALC_CHECK_FREQ = 100;
|
||||||
|
wxStopWatch timer;
|
||||||
|
#else
|
||||||
|
// use some hard-coded limit, that's the best we can do without timer
|
||||||
|
int top_part_end = wxMin(500, count);
|
||||||
|
#endif // wxUSE_STOPWATCH/!wxUSE_STOPWATCH
|
||||||
|
|
||||||
|
int row = 0;
|
||||||
|
|
||||||
|
for ( row = 0; row < top_part_end; row++ )
|
||||||
|
{
|
||||||
|
#if wxUSE_STOPWATCH
|
||||||
|
if ( row % CALC_CHECK_FREQ == CALC_CHECK_FREQ-1 &&
|
||||||
|
timer.Time() > CALC_TIMEOUT )
|
||||||
|
break;
|
||||||
|
#endif // wxUSE_STOPWATCH
|
||||||
|
calculator.UpdateWithRow(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
// row is the first unmeasured item now; that's our value of N/2
|
||||||
|
|
||||||
|
if ( row < count )
|
||||||
|
{
|
||||||
|
top_part_end = row;
|
||||||
|
|
||||||
|
// add bottom N/2 items now:
|
||||||
|
const int bottom_part_start = wxMax(row, count - row);
|
||||||
|
for ( row = bottom_part_start; row < count; row++ )
|
||||||
|
calculator.UpdateWithRow(row);
|
||||||
|
|
||||||
|
// finally, include currently visible items in the calculation:
|
||||||
|
const NSRange visible = [m_OutlineView rowsInRect:[m_OutlineView visibleRect]];
|
||||||
|
const int first_visible = wxMax(visible.location, top_part_end);
|
||||||
|
const int last_visible = wxMin(first_visible + visible.length, bottom_part_start);
|
||||||
|
|
||||||
|
for ( row = first_visible; row < last_visible; row++ )
|
||||||
|
calculator.UpdateWithRow(row);
|
||||||
|
|
||||||
|
wxLogTrace("dataview",
|
||||||
|
"determined best size from %d top, %d bottom plus %d more visible items out of %d total",
|
||||||
|
top_part_end,
|
||||||
|
count - bottom_part_start,
|
||||||
|
wxMax(0, last_visible - first_visible),
|
||||||
|
count);
|
||||||
|
}
|
||||||
|
|
||||||
|
[column setWidth:calculator.GetMaxWidth()];
|
||||||
|
#endif // MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// item related methods (inherited from wxDataViewWidgetImpl)
|
// item related methods (inherited from wxDataViewWidgetImpl)
|
||||||
//
|
//
|
||||||
@@ -3025,8 +3146,29 @@ void wxDataViewColumn::SetTitle(const wxString& title)
|
|||||||
|
|
||||||
void wxDataViewColumn::SetWidth(int width)
|
void wxDataViewColumn::SetWidth(int width)
|
||||||
{
|
{
|
||||||
[m_NativeDataPtr->GetNativeColumnPtr() setWidth:width];
|
|
||||||
m_width = width;
|
m_width = width;
|
||||||
|
|
||||||
|
switch ( width )
|
||||||
|
{
|
||||||
|
case wxCOL_WIDTH_AUTOSIZE:
|
||||||
|
#if MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_5
|
||||||
|
if ( GetOwner() )
|
||||||
|
{
|
||||||
|
wxCocoaDataViewControl *peer = static_cast<wxCocoaDataViewControl*>(GetOwner()->GetPeer());
|
||||||
|
peer->FitColumnWidthToContent(GetOwner()->GetColumnPosition(this));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
// fall through if unsupported (OSX < 10.5) or not yet settable
|
||||||
|
|
||||||
|
case wxCOL_WIDTH_DEFAULT:
|
||||||
|
width = wxDVC_DEFAULT_WIDTH;
|
||||||
|
// fall through
|
||||||
|
|
||||||
|
default:
|
||||||
|
[m_NativeDataPtr->GetNativeColumnPtr() setWidth:width];
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
|
void wxDataViewColumn::SetAsSortKey(bool WXUNUSED(sort))
|
||||||
|
|||||||
@@ -76,6 +76,8 @@ protected:
|
|||||||
void AdjustRowHeight(wxDataViewItem const& item);
|
void AdjustRowHeight(wxDataViewItem const& item);
|
||||||
// ... and the same method for a couple of items:
|
// ... and the same method for a couple of items:
|
||||||
void AdjustRowHeights(wxDataViewItemArray const& items);
|
void AdjustRowHeights(wxDataViewItemArray const& items);
|
||||||
|
// adjust wxCOL_WIDTH_AUTOSIZE columns to fit the data
|
||||||
|
void AdjustAutosizedColumns();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxDataViewCtrl* m_DataViewCtrlPtr;
|
wxDataViewCtrl* m_DataViewCtrlPtr;
|
||||||
@@ -130,6 +132,7 @@ bool wxOSXDataViewModelNotifier::ItemChanged(wxDataViewItem const& item)
|
|||||||
m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
|
m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
|
||||||
// row height may have to be adjusted:
|
// row height may have to be adjusted:
|
||||||
AdjustRowHeight(item);
|
AdjustRowHeight(item);
|
||||||
|
AdjustAutosizedColumns();
|
||||||
// done
|
// done
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -156,6 +159,7 @@ bool wxOSXDataViewModelNotifier::ItemsChanged(wxDataViewItemArray const& items)
|
|||||||
return false;
|
return false;
|
||||||
// if this location is reached all items have been updated:
|
// if this location is reached all items have been updated:
|
||||||
AdjustRowHeights(items);
|
AdjustRowHeights(items);
|
||||||
|
AdjustAutosizedColumns();
|
||||||
// done:
|
// done:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -174,6 +178,8 @@ bool wxOSXDataViewModelNotifier::ItemDeleted(wxDataViewItem const& parent, wxDat
|
|||||||
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,item);
|
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,item);
|
||||||
// enable automatic updating again:
|
// enable automatic updating again:
|
||||||
m_DataViewCtrlPtr->SetDeleting(false);
|
m_DataViewCtrlPtr->SetDeleting(false);
|
||||||
|
|
||||||
|
AdjustAutosizedColumns();
|
||||||
// done:
|
// done:
|
||||||
return noFailureFlag;
|
return noFailureFlag;
|
||||||
}
|
}
|
||||||
@@ -192,6 +198,8 @@ bool wxOSXDataViewModelNotifier::ItemsDeleted(wxDataViewItem const& parent, wxDa
|
|||||||
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,items);
|
noFailureFlag = m_DataViewCtrlPtr->GetDataViewPeer()->Remove(parent,items);
|
||||||
// enable automatic updating again:
|
// enable automatic updating again:
|
||||||
m_DataViewCtrlPtr->SetDeleting(false);
|
m_DataViewCtrlPtr->SetDeleting(false);
|
||||||
|
|
||||||
|
AdjustAutosizedColumns();
|
||||||
// done:
|
// done:
|
||||||
return noFailureFlag;
|
return noFailureFlag;
|
||||||
}
|
}
|
||||||
@@ -209,6 +217,8 @@ bool wxOSXDataViewModelNotifier::ValueChanged(wxDataViewItem const& item, unsign
|
|||||||
dataViewEvent.SetItem(item);
|
dataViewEvent.SetItem(item);
|
||||||
// send the equivalent wxWidget event:
|
// send the equivalent wxWidget event:
|
||||||
m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
|
m_DataViewCtrlPtr->HandleWindowEvent(dataViewEvent);
|
||||||
|
|
||||||
|
AdjustAutosizedColumns();
|
||||||
// done
|
// done
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -292,6 +302,18 @@ void wxOSXDataViewModelNotifier::AdjustRowHeights(wxDataViewItemArray const& ite
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxOSXDataViewModelNotifier::AdjustAutosizedColumns()
|
||||||
|
{
|
||||||
|
unsigned count = m_DataViewCtrlPtr->GetColumnCount();
|
||||||
|
for ( unsigned col = 0; col < count; col++ )
|
||||||
|
{
|
||||||
|
wxDataViewColumn *column = m_DataViewCtrlPtr->GetColumnPtr(col);
|
||||||
|
|
||||||
|
if ( column->GetWidthVariable() == wxCOL_WIDTH_AUTOSIZE )
|
||||||
|
m_DataViewCtrlPtr->GetDataViewPeer()->FitColumnWidthToContent(col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------
|
// ---------------------------------------------------------
|
||||||
// wxDataViewCustomRenderer
|
// wxDataViewCustomRenderer
|
||||||
// The constructor, the implementation macro and environment
|
// The constructor, the implementation macro and environment
|
||||||
|
|||||||
Reference in New Issue
Block a user