// private classes
// ============================================================================
+//-----------------------------------------------------------------------------
+// wxColWidthInfo (internal)
+//-----------------------------------------------------------------------------
+
+struct wxColWidthInfo
+{
+ int nMaxWidth;
+ bool bNeedsUpdate; // only set to true when an item whose
+ // width == nMaxWidth is removed
+
+ wxColWidthInfo(int w = 0, bool needsUpdate = false)
+ {
+ nMaxWidth = w;
+ bNeedsUpdate = needsUpdate;
+ }
+};
+
+WX_DEFINE_ARRAY_PTR(wxColWidthInfo *, ColWidthArray);
+
//-----------------------------------------------------------------------------
// wxListItemData (internal)
//-----------------------------------------------------------------------------
// the part to be highlighted
wxRect m_rectHighlight;
- // extend all our rects to be centered inside theo ne of given width
+ // extend all our rects to be centered inside the one of given width
void ExtendWidth(wxCoord w)
{
wxASSERT_MSG( m_rectAll.width <= w,
long HitTest( int x, int y, int &flags );
void InsertItem( wxListItem &item );
void InsertColumn( long col, wxListItem &item );
+ int GetItemWidthWithImage(wxListItem * item);
void SortItems( wxListCtrlCompare fn, long data );
size_t GetItemCount() const;
bool m_isCreated;
int m_dragCount;
wxPoint m_dragStart;
+ ColWidthArray m_aColWidths;
// for double click logic
size_t m_lineLastClicked,
// get the colour to be used for drawing the rules
wxColour GetRuleColour() const
{
-#ifdef __WXMAC__
- return *wxWHITE;
-#else
return wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT);
-#endif
}
private:
// end of the current column
int xpos = 0;
- // find the column where this event occured
+ // find the column where this event occurred
int col,
countCol = m_owner->GetColumnCount();
for (col = 0; col < countCol; col++)
void wxListTextCtrl::OnKillFocus( wxFocusEvent &event )
{
- if ( !m_finished )
+ if ( !m_finished && !m_aboutToFinish )
{
// We must finish regardless of success, otherwise we'll get
// focus problems:
wxSOLID
);
- wxSize sz = size;
- sz.y = 25;
-
SetScrollbars( 0, 0, 0, 0, 0, 0 );
wxVisualAttributes attr = wxGenericListCtrl::GetClassDefaultAttributes();
{
DoDeleteAllItems();
WX_CLEAR_LIST(wxListHeaderDataList, m_columns);
+ WX_CLEAR_ARRAY(m_aColWidths);
delete m_highlightBrush;
delete m_highlightUnfocusedBrush;
HighlightAll( false );
ReverseHighlight(m_lineSelectSingleOnUp);
}
- else if (m_lastOnSame)
+ if (m_lastOnSame)
{
if ((current == m_current) &&
(hitResult == wxLIST_HITTEST_ONITEMLABEL) &&
- HasFlag(wxLC_EDIT_LABELS) )
+ HasFlag(wxLC_EDIT_LABELS) )
{
m_renameTimer->Start( 100, true );
}
}
else
{
- // This is neccessary , because after a DnD operation in
+ // This is necessary, because after a DnD operation in
// from and to ourself, the up event is swallowed by the
// DnD code. So on next non-up event (which means here and
// now) m_lineSelectSingleOnUp should be reset.
m_lineLastClicked = current;
size_t oldCurrent = m_current;
+ bool oldWasSelected = IsHighlighted(m_current);
+
bool cmdModifierDown = event.CmdDown();
- if ( !(cmdModifierDown || event.ShiftDown()) )
+ if ( IsSingleSel() || !(cmdModifierDown || event.ShiftDown()) )
{
if( IsSingleSel() || !IsHighlighted(current) )
{
}
// forceClick is only set if the previous click was on another item
- m_lastOnSame = !forceClick && (m_current == oldCurrent);
+ m_lastOnSame = !forceClick && (m_current == oldCurrent) && oldWasSelected;
}
}
int max = AUTOSIZE_COL_MARGIN;
- for ( size_t i = 0; i < count; i++ )
+ // if the cached column width isn't valid then recalculate it
+ if (m_aColWidths.Item(col)->bNeedsUpdate)
{
- wxListLineData *line = GetLine(i);
- wxListItemDataList::compatibility_iterator n = line->m_items.Item( col );
-
- wxCHECK_RET( n, _T("no subitem?") );
+ for (size_t i = 0; i < count; i++)
+ {
+ wxListLineData *line = GetLine(i);
+ wxListItemDataList::compatibility_iterator n = line->m_items.Item( col );
- wxListItemData *item = n->GetData();
- int current = 0;
+ wxCHECK_RET( n, _T("no subitem?") );
- if (item->HasImage())
- {
- int ix, iy;
- GetImageSize( item->GetImage(), ix, iy );
- current += ix + 5;
- }
+ wxListItemData *itemData = n->GetData();
+ wxListItem item;
- if (item->HasText())
- {
- wxCoord w;
- dc.GetTextExtent( item->GetText(), &w, NULL );
- current += w;
+ itemData->GetItem(item);
+ int itemWidth = GetItemWidthWithImage(&item);
+ if (itemWidth > max)
+ max = itemWidth;
}
- if (current > max)
- max = current;
+ m_aColWidths.Item(col)->bNeedsUpdate = false;
+ m_aColWidths.Item(col)->nMaxWidth = max;
}
+ max = m_aColWidths.Item(col)->nMaxWidth;
width = max + AUTOSIZE_COL_MARGIN;
}
}
{
wxListLineData *line = GetLine((size_t)id);
line->SetItem( item.m_col, item );
+
+ if (InReportView())
+ {
+ // update the Max Width Cache if needed
+ int width = GetItemWidthWithImage(&item);
+
+ if (width > m_aColWidths.Item(item.m_col)->nMaxWidth)
+ m_aColWidths.Item(item.m_col)->nMaxWidth = width;
+ }
}
// update the item on screen
return;
}
- wxCHECK_RET( litem >= 0 && (size_t)litem < GetItemCount(),
- _T("invalid list ctrl item index in SetItem") );
+ wxCHECK_RET( litem >= 0 && (size_t)litem < GetItemCount(),
+ _T("invalid list ctrl item index in SetItem") );
size_t oldCurrent = m_current;
size_t item = (size_t)litem; // safe because of the check above
if ( InReportView() )
{
+ // mark the Column Max Width cache as dirty if the items in the line
+ // we're deleting contain the Max Column Width
+ wxListLineData * const line = GetLine(index);
+ wxListItemDataList::compatibility_iterator n;
+ wxListItemData *itemData;
+ wxListItem item;
+ int itemWidth;
+
+ for (size_t i = 0; i < m_columns.GetCount(); i++)
+ {
+ n = line->m_items.Item( i );
+ itemData = n->GetData();
+ itemData->GetItem(item);
+
+ itemWidth = GetItemWidthWithImage(&item);
+
+ if (itemWidth >= m_aColWidths.Item(i)->nMaxWidth)
+ m_aColWidths.Item(i)->bNeedsUpdate = true;
+ }
+
ResetVisibleLinesRange();
}
}
}
+ if ( InReportView() ) // we only cache max widths when in Report View
+ {
+ delete m_aColWidths.Item(col);
+ m_aColWidths.RemoveAt(col);
+ }
+
// invalidate it as it has to be recalculated
m_headerWidth = 0;
}
if ( InReportView() )
{
ResetVisibleLinesRange();
+ for (size_t i = 0; i < m_aColWidths.GetCount(); i++)
+ {
+ m_aColWidths.Item(i)->bNeedsUpdate = true;
+ }
}
m_lines.Clear();
void wxListMainWindow::DeleteEverything()
{
WX_CLEAR_LIST(wxListHeaderDataList, m_columns);
+ WX_CLEAR_ARRAY(m_aColWidths);
DeleteAllItems();
}
m_dirty = true;
- #if 0
- // this is unused variable
- int mode = 0;
- #endif
if ( InReportView() )
{
- #if 0
- // this is unused variable
- mode = wxLC_REPORT;
- #endif
ResetVisibleLinesRange();
- }
- else if ( HasFlag(wxLC_LIST) )
- #if 0
- // this is unused variable
- mode = wxLC_LIST;
- #else
- {}
- #endif
- else if ( HasFlag(wxLC_ICON) )
- #if 0
- // this is unused variable
- mode = wxLC_ICON;
- #else
- {}
- #endif
- else if ( HasFlag(wxLC_SMALL_ICON) )
- #if 0
- // this is unused variable
- mode = wxLC_ICON; // no typo
- #else
- {}
- #endif
- else
- {
- wxFAIL_MSG( _T("unknown mode") );
+
+ // calculate the width of the item and adjust the max column width
+ wxColWidthInfo *pWidthInfo = m_aColWidths.Item(item.GetColumn());
+ int width = GetItemWidthWithImage(&item);
+ item.SetWidth(width);
+ if (width > pWidthInfo->nMaxWidth)
+ pWidthInfo->nMaxWidth = width;
}
wxListLineData *line = new wxListLineData(this);
item.m_width = GetTextLength( item.m_text );
wxListHeaderData *column = new wxListHeaderData( item );
+ wxColWidthInfo *colWidthInfo = new wxColWidthInfo();
+
bool insert = (col >= 0) && ((size_t)col < m_columns.GetCount());
if ( insert )
{
- wxListHeaderDataList::compatibility_iterator node = m_columns.Item( col );
+ wxListHeaderDataList::compatibility_iterator
+ node = m_columns.Item( col );
m_columns.Insert( node, column );
+ m_aColWidths.Insert( colWidthInfo, col );
}
else
{
m_columns.Append( column );
+ m_aColWidths.Add( colWidthInfo );
}
if ( !IsVirtual() )
}
}
+int wxListMainWindow::GetItemWidthWithImage(wxListItem * item)
+{
+ int width = 0;
+ wxClientDC dc(this);
+
+ dc.SetFont( GetFont() );
+
+ if (item->GetImage() != -1)
+ {
+ int ix, iy;
+ GetImageSize( item->GetImage(), ix, iy );
+ width += ix + 5;
+ }
+
+ if (!item->GetText().empty())
+ {
+ wxCoord w;
+ dc.GetTextExtent( item->GetText(), &w, NULL );
+ width += w;
+ }
+
+ return width;
+}
+
// ----------------------------------------------------------------------------
// sorting
// ----------------------------------------------------------------------------
ResetVisibleLinesRange();
// FIXME
-#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
+#if ( defined(__WXGTK__) || defined(__WXMAC__) ) && !defined(__WXUNIVERSAL__)
wxScrolledWindow::OnScroll(event);
#else
HandleOnScroll( event );
return info.GetBackgroundColour();
}
+void wxGenericListCtrl::SetItemFont( long item, const wxFont &f )
+{
+ wxListItem info;
+ info.m_itemId = item;
+ info.SetFont( f );
+ m_mainWin->SetItem( info );
+}
+
+wxFont wxGenericListCtrl::GetItemFont( long item ) const
+{
+ wxListItem info;
+ info.m_itemId = item;
+ m_mainWin->GetItem( info );
+ return info.GetFont();
+}
+
int wxGenericListCtrl::GetSelectedItemCount() const
{
return m_mainWin->GetSelectedItemCount();