X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/37fa90953440edfc8a4c1068258c29e7710be062..34dc8f910f88dc39a2f5fd9c3d894d797212a074:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index c19161b5c2..5e7ce897ad 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -37,15 +37,22 @@ #if wxUSE_LISTCTRL -#include "wx/dcscreen.h" -#include "wx/app.h" -#include "wx/listctrl.h" +#ifndef WX_PRECOMP + #include "wx/app.h" + + #include "wx/dynarray.h" + + #include "wx/dcscreen.h" + + #include "wx/textctrl.h" +#endif + #include "wx/imaglist.h" -#include "wx/dynarray.h" +#include "wx/listctrl.h" #ifdef __WXGTK__ -#include -#include "wx/gtk/win_gtk.h" + #include + #include "wx/gtk/win_gtk.h" #endif // ---------------------------------------------------------------------------- @@ -72,6 +79,7 @@ DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED) +DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED) DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT) // ---------------------------------------------------------------------------- @@ -494,6 +502,7 @@ private: wxString *m_res; wxListMainWindow *m_owner; wxString m_startValue; + bool m_finished; public: wxListTextCtrl() {} @@ -611,7 +620,13 @@ public: // bring the current item into view void MoveToFocus() { MoveToItem(m_current); } + // start editing the label of the given item void EditLabel( long item ); + + // suspend/resume redrawing the control + void Freeze(); + void Thaw(); + void OnRenameTimer(); void OnRenameAccept(); @@ -678,7 +693,9 @@ public: bool IsEmpty() const { return GetItemCount() == 0; } void SetItemCount(long count); - void ResetCurrent() { m_current = (size_t)-1; } + // change the current (== focused) item, send a notification event + void ChangeCurrent(size_t current); + void ResetCurrent() { ChangeCurrent((size_t)-1); } bool HasCurrent() const { return m_current != (size_t)-1; } // send out a wxListEvent @@ -821,12 +838,6 @@ private: // delete all items but don't refresh: called from dtor void DoDeleteAllItems(); - // called when an item is [un]focuded, i.e. becomes [not] current - // - // currently unused - void OnFocusLine( size_t line ); - void OnUnfocusLine( size_t line ); - // the height of one line using the current font wxCoord m_lineHeight; @@ -843,6 +854,9 @@ private: wxBrush *m_highlightBrush, *m_highlightUnfocusedBrush; + // if this is > 0, the control is frozen and doesn't redraw itself + size_t m_freezeCount; + DECLARE_DYNAMIC_CLASS(wxListMainWindow); DECLARE_EVENT_TABLE() }; @@ -965,8 +979,10 @@ bool wxSelectionStore::SelectRange(size_t itemFrom, size_t itemTo, // stop counting (see comment below) itemsChanged = NULL; } - - itemsChanged->Add(m_itemsSel[i]); + else + { + itemsChanged->Add(m_itemsSel[i]); + } } m_itemsSel.RemoveAt(i); @@ -1879,7 +1895,7 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) int numColumns = m_owner->GetColumnCount(); wxListItem item; - for (int i = 0; i < numColumns; i++) + for ( int i = 0; i < numColumns && x < w; i++ ) { m_owner->GetColumn( i, item ); int wCol = item.m_width; @@ -1923,11 +1939,9 @@ void wxListHeaderWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) dc.DrawText( item.GetText(), x + EXTRA_WIDTH, HEADER_OFFSET_Y + EXTRA_HEIGHT ); - if ( x > w - wCol + 5 ) - break; - x += wCol; } + dc.EndDrawing(); } @@ -2126,6 +2140,7 @@ wxListTextCtrl::wxListTextCtrl( wxWindow *parent, (*m_accept) = FALSE; (*m_res) = ""; m_startValue = value; + m_finished = FALSE; } void wxListTextCtrl::OnChar( wxKeyEvent &event ) @@ -2138,9 +2153,12 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); - if ((*m_accept) && ((*m_res) != m_startValue)) + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + return; } if (event.m_keyCode == WXK_ESCAPE) @@ -2151,6 +2169,9 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); + m_finished = TRUE; + m_owner->SetFocus(); // This doesn't work. TODO. + return; } @@ -2159,12 +2180,18 @@ void wxListTextCtrl::OnChar( wxKeyEvent &event ) void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) { + if (m_finished) + { + event.Skip(); + return; + } + // auto-grow the textctrl: wxSize parentSize = m_owner->GetSize(); wxPoint myPos = GetPosition(); wxSize mySize = GetSize(); int sx, sy; - GetTextExtent(GetValue() + _T("MM"), &sx, &sy); // FIXME: MM?? + GetTextExtent(GetValue() + _T("M"), &sx, &sy); // FIXME: MM?? if (myPos.x + sx > parentSize.x) sx = parentSize.x - myPos.x; if (mySize.x > sx) @@ -2174,12 +2201,21 @@ void wxListTextCtrl::OnKeyUp( wxKeyEvent &event ) event.Skip(); } -void wxListTextCtrl::OnKillFocus( wxFocusEvent &WXUNUSED(event) ) +void wxListTextCtrl::OnKillFocus( wxFocusEvent &event ) { + if (m_finished) + { + event.Skip(); + return; + } + if (!wxPendingDelete.Member(this)) wxPendingDelete.Append(this); - if ((*m_accept) && ((*m_res) != m_startValue)) + (*m_accept) = TRUE; + (*m_res) = GetValue(); + + if ((*m_res) != m_startValue) m_owner->OnRenameAccept(); } @@ -2229,6 +2265,8 @@ void wxListMainWindow::Init() m_currentEdit = m_lineLastClicked = m_lineBeforeLastClicked = (size_t)-1; + + m_freezeCount = 0; } void wxListMainWindow::InitScrolling() @@ -2664,15 +2702,30 @@ void wxListMainWindow::RefreshSelected() #endif // !__WXGTK__/__WXGTK__ } +void wxListMainWindow::Freeze() +{ + m_freezeCount++; +} + +void wxListMainWindow::Thaw() +{ + wxCHECK_RET( m_freezeCount > 0, _T("thawing unfrozen list control?") ); + + if ( !--m_freezeCount ) + { + Refresh(); + } +} + void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { // Note: a wxPaintDC must be constructed even if no drawing is // done (a Windows requirement). wxPaintDC dc( this ); - if ( IsEmpty() ) + if ( IsEmpty() || m_freezeCount ) { - // empty control. nothing to draw + // nothing to draw or not the moment to draw it return; } @@ -2841,21 +2894,22 @@ void wxListMainWindow::SendNotify( size_t line, // what we're trying to avoid if ( !IsVirtual() && (command != wxEVT_COMMAND_LIST_DELETE_ITEM) ) { - GetLine(line)->GetItem( 0, le.m_item ); + if ( line != (size_t)-1 ) + { + GetLine(line)->GetItem( 0, le.m_item ); + } + //else: this happens for wxEVT_COMMAND_LIST_ITEM_FOCUSED event } //else: there may be no more such item GetParent()->GetEventHandler()->ProcessEvent( le ); } -void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line) ) +void wxListMainWindow::ChangeCurrent(size_t current) { -// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED ); -} + m_current = current; -void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line) ) -{ -// SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED ); + SendNotify(current, wxEVT_COMMAND_LIST_ITEM_FOCUSED); } void wxListMainWindow::EditLabel( long item ) @@ -3062,7 +3116,8 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if ( IsSingleSel() || !(event.ControlDown() || event.ShiftDown()) ) { HighlightAll( FALSE ); - m_current = current; + + ChangeCurrent(current); ReverseHighlight(m_current); } @@ -3070,13 +3125,13 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) { if (event.ControlDown()) { - m_current = current; + ChangeCurrent(current); ReverseHighlight(m_current); } else if (event.ShiftDown()) { - m_current = current; + ChangeCurrent(current); size_t lineFrom = oldCurrent, lineTo = current; @@ -3099,8 +3154,6 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (m_current != oldCurrent) { RefreshLine( oldCurrent ); - OnUnfocusLine( oldCurrent ); - OnFocusLine( m_current ); } // forceClick is only set if the previous click was on another item @@ -3156,7 +3209,7 @@ void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event) // items anyhow if ( event.ShiftDown() && !IsSingleSel() ) { - m_current = newCurrent; + ChangeCurrent(newCurrent); // select all the items between the old and the new one if ( oldCurrent > newCurrent ) @@ -3173,7 +3226,7 @@ void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event) if ( !event.ControlDown() ) HighlightAll(FALSE); - m_current = newCurrent; + ChangeCurrent(newCurrent); HighlightLine( oldCurrent, FALSE ); RefreshLine( oldCurrent ); @@ -3184,8 +3237,6 @@ void wxListMainWindow::OnArrowChar(size_t newCurrent, const wxKeyEvent& event) } } - OnUnfocusLine( oldCurrent ); - OnFocusLine( m_current ); RefreshLine( m_current ); MoveToFocus(); @@ -3244,7 +3295,8 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) nevent.SetDirection( !event.ShiftDown() ); nevent.SetEventObject( GetParent()->GetParent() ); nevent.SetCurrentFocus( m_parent ); - if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) return; + if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent )) + return; } /* no item -> nothing to do */ @@ -3344,12 +3396,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_SPACE: if ( IsSingleSel() ) { - wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, - GetParent()->GetId() ); - le.SetEventObject( GetParent() ); - le.m_itemIndex = m_current; - GetLine(m_current)->GetItem( 0, le.m_item ); - GetParent()->GetEventHandler()->ProcessEvent( le ); + SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); if ( IsHighlighted(m_current) ) { @@ -3364,14 +3411,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_RETURN: case WXK_EXECUTE: - { - wxListEvent le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED, - GetParent()->GetId() ); - le.SetEventObject( GetParent() ); - le.m_itemIndex = m_current; - GetLine(m_current)->GetItem( 0, le.m_item ); - GetParent()->GetEventHandler()->ProcessEvent( le ); - } + SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); break; default: @@ -3698,9 +3738,7 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) // don't do anything if this item is already focused if ( item != m_current ) { - OnUnfocusLine( m_current ); - m_current = item; - OnFocusLine( m_current ); + ChangeCurrent(item); if ( oldCurrent != (size_t)-1 ) { @@ -3720,8 +3758,7 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) // don't do anything if this item is not focused if ( item == m_current ) { - OnUnfocusLine( m_current ); - m_current = (size_t)-1; + ResetCurrent(); RefreshLine( oldCurrent ); } @@ -3741,9 +3778,7 @@ void wxListMainWindow::SetItemState( long litem, long state, long stateMask ) // single sel mode if ( m_current != item ) { - OnUnfocusLine( m_current ); - m_current = item; - OnFocusLine( m_current ); + ChangeCurrent(item); if ( oldCurrent != (size_t)-1 ) { @@ -4000,12 +4035,7 @@ void wxListMainWindow::UpdateCurrent() { if ( !HasCurrent() && !IsEmpty() ) { - m_current = 0; - } - - if ( m_current != (size_t)-1 ) - { - OnFocusLine( m_current ); + ChangeCurrent(0); } } @@ -4445,53 +4475,6 @@ void wxListItem::ClearAttributes() } } -// ------------------------------------------------------------------------------------- -// wxListEvent -// ------------------------------------------------------------------------------------- - -IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent) - -wxListEvent::wxListEvent( wxEventType commandType, int id ) - : wxNotifyEvent( commandType, id ) -{ - m_code = 0; - m_itemIndex = 0; - m_oldItemIndex = 0; - m_col = 0; - m_cancelled = FALSE; - m_pointDrag.x = 0; - m_pointDrag.y = 0; -} - -void wxListEvent::CopyObject(wxObject& object_dest) const -{ - wxListEvent *obj = (wxListEvent *)&object_dest; - - wxNotifyEvent::CopyObject(object_dest); - - obj->m_code = m_code; - obj->m_itemIndex = m_itemIndex; - obj->m_oldItemIndex = m_oldItemIndex; - obj->m_col = m_col; - obj->m_cancelled = m_cancelled; - obj->m_pointDrag = m_pointDrag; - obj->m_item.m_mask = m_item.m_mask; - obj->m_item.m_itemId = m_item.m_itemId; - obj->m_item.m_col = m_item.m_col; - obj->m_item.m_state = m_item.m_state; - obj->m_item.m_stateMask = m_item.m_stateMask; - obj->m_item.m_text = m_item.m_text; - obj->m_item.m_image = m_item.m_image; - obj->m_item.m_data = m_item.m_data; - obj->m_item.m_format = m_item.m_format; - obj->m_item.m_width = m_item.m_width; - - if ( m_item.HasAttributes() ) - { - obj->m_item.SetTextColour(m_item.GetTextColour()); - } -} - // ------------------------------------------------------------------------------------- // wxListCtrl // ------------------------------------------------------------------------------------- @@ -4499,6 +4482,8 @@ void wxListEvent::CopyObject(wxObject& object_dest) const IMPLEMENT_DYNAMIC_CLASS(wxListCtrl, wxControl) IMPLEMENT_DYNAMIC_CLASS(wxListView, wxListCtrl) +IMPLEMENT_DYNAMIC_CLASS(wxListEvent, wxNotifyEvent) + BEGIN_EVENT_TABLE(wxListCtrl,wxControl) EVT_SIZE(wxListCtrl::OnSize) EVT_IDLE(wxListCtrl::OnIdle) @@ -4520,9 +4505,6 @@ wxListCtrl::wxListCtrl() wxListCtrl::~wxListCtrl() { - if ( m_mainWin ) - m_mainWin->ResetCurrent(); - if (m_ownsImageListNormal) delete m_imageListNormal; if (m_ownsImageListSmall) @@ -4904,7 +4886,7 @@ bool wxListCtrl::DeleteAllColumns() { size_t count = m_mainWin->m_columns.GetCount(); for ( size_t n = 0; n < count; n++ ) - DeleteColumn(n); + DeleteColumn(0); return TRUE; } @@ -5223,4 +5205,14 @@ void wxListCtrl::RefreshItems(long itemFrom, long itemTo) m_mainWin->RefreshLines(itemFrom, itemTo); } +void wxListCtrl::Freeze() +{ + m_mainWin->Freeze(); +} + +void wxListCtrl::Thaw() +{ + m_mainWin->Thaw(); +} + #endif // wxUSE_LISTCTRL