Implement best size calculation for report mode wxListCtrl.

Use the column labels to determine the minimal width required by the control
to show them all in full.

Also declare all image list and column-related wxListCtrl methods in
wxListCtrlBase now as we need some of them in DoGetBestClientSize()
implementation.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@70282 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Vadim Zeitlin 2012-01-07 15:09:43 +00:00
parent a9bd911fde
commit 94248d2ed1
10 changed files with 163 additions and 98 deletions

View File

@ -465,6 +465,7 @@ All (GUI):
- Allow using wxEVT_UPDATE_UI with wxRibbonButtonBar (Emilien Kia).
- Add wxRibbonButtonBar::InsertXXXButton() methods (Emilien Kia).
- Fix multiple item selection in generic wxTreeCtrl (Igor Korot).
- Implement best size calculation for report mode wxListCtrl.
GTK:

View File

@ -14,8 +14,6 @@
#include "wx/scrolwin.h"
#include "wx/textctrl.h"
class WXDLLIMPEXP_FWD_CORE wxImageList;
#if wxUSE_DRAG_AND_DROP
class WXDLLIMPEXP_FWD_CORE wxDropTarget;
#endif
@ -66,7 +64,7 @@ public:
const wxString &name = wxListCtrlNameStr);
bool GetColumn( int col, wxListItem& item ) const;
bool SetColumn( int col, wxListItem& item );
bool SetColumn( int col, const wxListItem& item );
int GetColumnWidth( int col ) const;
bool SetColumnWidth( int col, int width);
int GetCountPerPage() const; // not the same in wxGLC as in Windows, I think
@ -134,9 +132,6 @@ public:
long InsertItem( long index, const wxString& label );
long InsertItem( long index, int imageIndex );
long InsertItem( long index, const wxString& label, int imageIndex );
long InsertColumn( long col, wxListItem& info );
long InsertColumn( long col, const wxString& heading,
int format = wxLIST_FORMAT_LEFT, int width = -1 );
bool ScrollList( int dx, int dy );
bool SortItems( wxListCtrlCompare fn, wxIntPtr data );
@ -208,6 +203,10 @@ public:
wxListMainWindow *m_mainWin;
protected:
// Implement base class pure virtual methods.
long DoInsertColumn(long col, const wxListItem& info);
virtual bool DoPopupMenu( wxMenu *menu, int x, int y );
// take into account the coordinates difference between the container

View File

@ -581,7 +581,7 @@ public:
void SetItemSpacing( int spacing, bool isSmall = false );
int GetItemSpacing( bool isSmall = false );
void SetColumn( int col, wxListItem &item );
void SetColumn( int col, const wxListItem &item );
void SetColumnWidth( int col, int width );
void GetColumn( int col, wxListItem &item ) const;
int GetColumnWidth( int col ) const;
@ -645,7 +645,7 @@ public:
long FindItem( const wxPoint& pt );
long HitTest( int x, int y, int &flags ) const;
void InsertItem( wxListItem &item );
void InsertColumn( long col, wxListItem &item );
void InsertColumn( long col, const wxListItem &item );
int GetItemWidthWithImage(wxListItem * item);
void SortItems( wxListCtrlCompare fn, wxIntPtr data );

View File

@ -17,6 +17,8 @@
#include "wx/gdicmn.h"
#include "wx/event.h"
class WXDLLIMPEXP_FWD_CORE wxImageList;
// ----------------------------------------------------------------------------
// types
// ----------------------------------------------------------------------------
@ -384,9 +386,72 @@ class WXDLLIMPEXP_CORE wxListCtrlBase : public wxControl
public:
wxListCtrlBase() { }
// Image list methods.
// -------------------
// Associate the given (possibly NULL to indicate that no images will be
// used) image list with the control. The ownership of the image list
// passes to the control, i.e. it will be deleted when the control itself
// is destroyed.
//
// The value of "which" must be one of wxIMAGE_LIST_{NORMAL,SMALL,STATE}.
virtual void AssignImageList(wxImageList* imageList, int which) = 0;
// Same as AssignImageList() but the control does not delete the image list
// so it can be shared among several controls.
virtual void SetImageList(wxImageList* imageList, int which) = 0;
// Return the currently used image list, may be NULL.
virtual wxImageList* GetImageList(int which) const = 0;
// Column-related methods.
// -----------------------
// All these methods can only be used in report view mode.
// Add a new column to the control at the position "col".
//
// Returns the index of the newly inserted column or -1 on error.
long InsertColumn(long col, const wxListItem& info);
long InsertColumn(long col,
const wxString& heading,
int format = wxLIST_FORMAT_LEFT,
int width = -1);
// Delete the given or all columns.
virtual bool DeleteColumn(int col) = 0;
virtual bool DeleteAllColumns() = 0;
// Return the current number of columns.
virtual int GetColumnCount() const = 0;
// Get or update information about the given column. Set item mask to
// indicate the fields to retrieve or change.
//
// Returns false on error, e.g. if the column index is invalid.
virtual bool GetColumn(int col, wxListItem& item) const = 0;
virtual bool SetColumn(int col, const wxListItem& item) = 0;
// Convenient wrappers for the above methods which get or update just the
// column width.
virtual int GetColumnWidth(int col) const = 0;
virtual bool SetColumnWidth(int col, int width) = 0;
// Other miscellaneous accessors.
// ------------------------------
// Convenient functions for testing the list control mode:
bool InReportView() const { return HasFlag(wxLC_REPORT); }
bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL); }
protected:
// Real implementations methods to which our public forwards.
virtual long DoInsertColumn(long col, const wxListItem& info) = 0;
// Overridden methods of the base class.
virtual wxSize DoGetBestClientSize() const;
};
// ----------------------------------------------------------------------------

View File

@ -16,7 +16,6 @@
#include "wx/dynarray.h"
#include "wx/vector.h"
class WXDLLIMPEXP_FWD_CORE wxImageList;
class wxMSWListItemData;
// define this symbol to indicate the availability of SetColumnsOrder() and
@ -320,14 +319,6 @@ public:
// Insert an image/string item
long InsertItem(long index, const wxString& label, int imageIndex);
// For list view mode (only), inserts a column.
long InsertColumn(long col, const wxListItem& info);
long InsertColumn(long col,
const wxString& heading,
int format = wxLIST_FORMAT_LEFT,
int width = -1);
// set the number of items in a virtual list control
void SetItemCount(long count);
@ -393,6 +384,9 @@ protected:
// common part of all ctors
void Init();
// Implement base class pure virtual methods.
long DoInsertColumn(long col, const wxListItem& info);
// free memory taken by all internal data
void FreeAllInternalData();

View File

@ -252,12 +252,6 @@ class WXDLLIMPEXP_CORE wxListCtrl: public wxListCtrlBase
// Insert an image/string item
long InsertItem(long index, const wxString& label, int imageIndex);
// For list view mode (only), inserts a column.
long InsertColumn(long col, wxListItem& info);
long InsertColumn(long col, const wxString& heading, int format = wxLIST_FORMAT_LEFT,
int width = -1);
// Scrolls the list control. If in icon, small icon or report view mode,
// x specifies the number of pixels to scroll. If in list view mode, x
// specifies the number of columns to scroll.
@ -371,14 +365,14 @@ class WXDLLIMPEXP_CORE wxListCtrl: public wxListCtrlBase
GetClassDefaultAttributes(wxWindowVariant variant = wxWINDOW_VARIANT_NORMAL);
protected:
// Implement base class pure virtual methods.
long DoInsertColumn(long col, const wxListItem& info);
// protected overrides needed for pimpl approach
virtual void DoSetSize(int x, int y,
int width, int height,
int sizeFlags = wxSIZE_AUTO);
virtual wxSize DoGetBestSize() const;
long m_current;
wxListCtrlTextCtrlWrapper *m_textctrlWrapper;
wxListCtrlRenameTimer *m_renameTimer;

View File

@ -27,6 +27,10 @@
#include "wx/listctrl.h"
#ifndef WX_PRECOMP
#include "wx/dcclient.h"
#endif
const char wxListCtrlNameStr[] = "listCtrl";
// ListCtrl events
@ -128,4 +132,73 @@ IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl)
IMPLEMENT_DYNAMIC_CLASS(wxListItem, wxObject)
IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent)
// ----------------------------------------------------------------------------
// wxListCtrlBase implementation
// ----------------------------------------------------------------------------
long
wxListCtrlBase::InsertColumn(long col,
const wxString& heading,
int format,
int width)
{
wxListItem item;
item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
item.m_text = heading;
if ( width > -1 )
{
item.m_mask |= wxLIST_MASK_WIDTH;
item.m_width = width;
}
item.m_format = format;
return InsertColumn(col, item);
}
long wxListCtrlBase::InsertColumn(long col, const wxListItem& info)
{
long rc = DoInsertColumn(col, info);
if ( rc != -1 )
{
// As our best size calculation depends on the column headers,
// invalidate the previously cached best size when a column is added.
InvalidateBestSize();
}
return rc;
}
wxSize wxListCtrlBase::DoGetBestClientSize() const
{
// There is no obvious way to determine the best size in icon and list
// modes so just don't do it for now.
if ( !InReportView() )
return wxControl::DoGetBestClientSize();
// In report mode, we use only the column headers, not items, to determine
// the best width. The reason for this is that it's easier (we can't just
// iterate over all items, especially not in a virtual control, so we'd
// have to do something relatively complicated such as checking the size of
// some items in the beginning and the end only) and also because the
// columns are usually static while the list contents is dynamic so it
// usually doesn't make much sense to adjust the control size to it anyhow.
// And finally, scrollbars can always be used with the items while the
// headers are just truncated if there is not enough place for them.
const int columns = GetColumnCount();
if ( HasFlag(wxLC_NO_HEADER) || !columns )
return wxControl::DoGetBestClientSize();
wxClientDC dc(const_cast<wxListCtrlBase*>(this));
// Total width of all headers determines the best control width.
int totalWidth = 0;
for ( int col = 0; col < columns; col++ )
{
totalWidth += GetColumnWidth(col);
}
// Use some arbitrary height, there is no good way to determine it.
return wxSize(totalWidth, 10*dc.GetCharHeight());
}
#endif // wxUSE_LISTCTRL

View File

@ -3017,18 +3017,18 @@ int wxListMainWindow::GetItemSpacing( bool isSmall )
// columns
// ----------------------------------------------------------------------------
void wxListMainWindow::SetColumn( int col, wxListItem &item )
void wxListMainWindow::SetColumn( int col, const wxListItem &item )
{
wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
wxCHECK_RET( node, wxT("invalid column index in SetColumn") );
if ( item.m_width == wxLIST_AUTOSIZE_USEHEADER )
item.m_width = GetTextLength( item.m_text );
wxListHeaderData *column = node->GetData();
column->SetItem( item );
if ( item.m_width == wxLIST_AUTOSIZE_USEHEADER )
column->SetWidth(GetTextLength( item.m_text ));
wxListHeaderWindow *headerWin = GetListCtrl()->m_headerWin;
if ( headerWin )
headerWin->m_dirty = true;
@ -4122,15 +4122,15 @@ void wxListMainWindow::InsertItem( wxListItem &item )
RefreshLines(id, GetItemCount() - 1);
}
void wxListMainWindow::InsertColumn( long col, wxListItem &item )
void wxListMainWindow::InsertColumn( long col, const wxListItem &item )
{
m_dirty = true;
if ( InReportView() )
{
if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
item.m_width = GetTextLength( item.m_text );
wxListHeaderData *column = new wxListHeaderData( item );
if (item.m_width == wxLIST_AUTOSIZE_USEHEADER)
column->SetWidth(GetTextLength( item.m_text ));
wxColWidthInfo *colWidthInfo = new wxColWidthInfo();
bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount());
@ -4528,7 +4528,7 @@ bool wxGenericListCtrl::GetColumn(int col, wxListItem &item) const
return true;
}
bool wxGenericListCtrl::SetColumn( int col, wxListItem& item )
bool wxGenericListCtrl::SetColumn( int col, const wxListItem& item )
{
m_mainWin->SetColumn( col, item );
return true;
@ -4945,7 +4945,7 @@ long wxGenericListCtrl::InsertItem( long index, const wxString &label, int image
return InsertItem( info );
}
long wxGenericListCtrl::InsertColumn( long col, wxListItem &item )
long wxGenericListCtrl::DoInsertColumn( long col, const wxListItem &item )
{
wxCHECK_MSG( InReportView(), -1, wxT("can't add column in non report mode") );
@ -4959,23 +4959,6 @@ long wxGenericListCtrl::InsertColumn( long col, wxListItem &item )
return 0;
}
long wxGenericListCtrl::InsertColumn( long col, const wxString &heading,
int format, int width )
{
wxListItem item;
item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
item.m_text = heading;
if (width >= -2)
{
item.m_mask |= wxLIST_MASK_WIDTH;
item.m_width = width;
}
item.m_format = format;
return InsertColumn( col, item );
}
bool wxGenericListCtrl::ScrollList( int dx, int dy )
{
return m_mainWin->ScrollList(dx, dy);

View File

@ -1730,7 +1730,7 @@ long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
}
// For list view mode (only), inserts a column.
long wxListCtrl::InsertColumn(long col, const wxListItem& item)
long wxListCtrl::DoInsertColumn(long col, const wxListItem& item)
{
LV_COLUMN lvCol;
wxConvertToMSWListCol(GetHwnd(), col, item, lvCol);
@ -1757,24 +1757,6 @@ long wxListCtrl::InsertColumn(long col, const wxListItem& item)
return n;
}
long wxListCtrl::InsertColumn(long col,
const wxString& heading,
int format,
int width)
{
wxListItem item;
item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
item.m_text = heading;
if ( width > -1 )
{
item.m_mask |= wxLIST_MASK_WIDTH;
item.m_width = width;
}
item.m_format = format;
return InsertColumn(col, item);
}
// scroll the control by the given number of pixels (exception: in list view,
// dx is interpreted as number of columns)
bool wxListCtrl::ScrollList(int dx, int dy)

View File

@ -801,11 +801,6 @@ void wxListCtrl::DoSetSize( int x, int y, int width, int height, int sizeFlags )
}
}
wxSize wxListCtrl::DoGetBestSize() const
{
return wxWindow::DoGetBestSize();
}
bool wxListCtrl::SetFont(const wxFont& font)
{
bool rv = true;
@ -2161,7 +2156,7 @@ long wxListCtrl::InsertItem(long index, const wxString& label, int imageIndex)
}
// For list view mode (only), inserts a column.
long wxListCtrl::InsertColumn(long col, wxListItem& item)
long wxListCtrl::DoInsertColumn(long col, wxListItem& item)
{
if (m_genericImpl)
return m_genericImpl->InsertColumn(col, item);
@ -2214,27 +2209,6 @@ long wxListCtrl::InsertColumn(long col, wxListItem& item)
return col;
}
long wxListCtrl::InsertColumn(long col,
const wxString& heading,
int format,
int width)
{
if (m_genericImpl)
return m_genericImpl->InsertColumn(col, heading, format, width);
wxListItem item;
item.m_mask = wxLIST_MASK_TEXT | wxLIST_MASK_FORMAT;
item.m_text = heading;
if ( width > -1 )
{
item.m_mask |= wxLIST_MASK_WIDTH;
item.m_width = width;
}
item.m_format = format;
return InsertColumn(col, item);
}
// scroll the control by the given number of pixels (exception: in list view,
// dx is interpreted as number of columns)
bool wxListCtrl::ScrollList(int dx, int dy)