X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/29686ebc000a1d95ae56a58b9ff2a5a6f23eed84..683df83d51c0f080e2e5210dc8115be0cb30d1ad:/src/generic/listctrl.cpp diff --git a/src/generic/listctrl.cpp b/src/generic/listctrl.cpp index ddd950997a..6575083534 100644 --- a/src/generic/listctrl.cpp +++ b/src/generic/listctrl.cpp @@ -342,12 +342,23 @@ bool wxListHeaderData::IsHit( int x, int y ) const void wxListHeaderData::GetItem( wxListItem& item ) { - item.m_mask = m_mask; - item.m_text = m_text; - item.m_image = m_image; - item.m_format = m_format; - item.m_width = m_width; - item.m_state = m_state; + long mask = item.m_mask; + if ( !mask ) + { + // by default, get everything for backwards compatibility + mask = -1; + } + + if ( mask & wxLIST_MASK_STATE ) + item.m_state = m_state; + if ( mask & wxLIST_MASK_TEXT ) + item.m_text = m_text; + if ( mask & wxLIST_MASK_IMAGE ) + item.m_image = m_image; + if ( mask & wxLIST_MASK_WIDTH ) + item.m_width = m_width; + if ( mask & wxLIST_MASK_FORMAT ) + item.m_format = m_format; } int wxListHeaderData::GetImage() const @@ -923,7 +934,6 @@ void wxListLineData::ReverseHighlight( void ) BEGIN_EVENT_TABLE(wxListHeaderWindow,wxWindow) EVT_PAINT (wxListHeaderWindow::OnPaint) EVT_MOUSE_EVENTS (wxListHeaderWindow::OnMouse) - EVT_SET_FOCUS (wxListHeaderWindow::OnSetFocus) END_EVENT_TABLE() void wxListHeaderWindow::Init() @@ -942,15 +952,17 @@ wxListHeaderWindow::wxListHeaderWindow() m_resizeCursor = NULL; } -wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, - wxWindowID id, - wxListMainWindow *owner, - const wxPoint& pos, - const wxSize& size, - long style, - const wxString &name ) - : wxWindow( win, id, pos, size, style, name ) +bool wxListHeaderWindow::Create( wxWindow *win, + wxWindowID id, + wxListMainWindow *owner, + const wxPoint& pos, + const wxSize& size, + long style, + const wxString &name ) { + if ( !wxWindow::Create(win, id, pos, size, style, name) ) + return false; + Init(); m_owner = owner; @@ -968,6 +980,8 @@ wxListHeaderWindow::wxListHeaderWindow( wxWindow *win, if (!m_hasFont) SetOwnFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT )); #endif + + return true; } wxListHeaderWindow::~wxListHeaderWindow() @@ -1204,7 +1218,7 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) if (m_isDragging) { - SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING, event.GetPosition()); + SendListEvent(wxEVT_LIST_COL_DRAGGING, event.GetPosition()); // we don't draw the line beyond our window, but we allow dragging it // there @@ -1223,7 +1237,7 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) m_isDragging = false; m_dirty = true; m_owner->SetColumnWidth( m_column, m_currentX - m_minX ); - SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG, event.GetPosition()); + SendListEvent(wxEVT_LIST_COL_END_DRAG, event.GetPosition()); } else { @@ -1276,7 +1290,7 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) { if (hit_border && event.LeftDown()) { - if ( SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG, + if ( SendListEvent(wxEVT_LIST_COL_BEGIN_DRAG, event.GetPosition()) ) { m_isDragging = true; @@ -1305,8 +1319,8 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) } SendListEvent( event.LeftDown() - ? wxEVT_COMMAND_LIST_COL_CLICK - : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK, + ? wxEVT_LIST_COL_CLICK + : wxEVT_LIST_COL_RIGHT_CLICK, event.GetPosition()); } } @@ -1330,12 +1344,6 @@ void wxListHeaderWindow::OnMouse( wxMouseEvent &event ) } } -void wxListHeaderWindow::OnSetFocus( wxFocusEvent &WXUNUSED(event) ) -{ - m_owner->SetFocus(); - m_owner->Update(); -} - bool wxListHeaderWindow::SendListEvent(wxEventType type, const wxPoint& pos) { wxWindow *parent = GetParent(); @@ -1367,6 +1375,15 @@ void wxListRenameTimer::Notify() m_owner->OnRenameTimer(); } +//----------------------------------------------------------------------------- +// wxListFindTimer (internal) +//----------------------------------------------------------------------------- + +void wxListFindTimer::Notify() +{ + m_owner->OnFindTimer(); +} + //----------------------------------------------------------------------------- // wxListTextCtrlWrapper (internal) //----------------------------------------------------------------------------- @@ -1559,6 +1576,8 @@ void wxListMainWindow::Init() m_lastOnSame = false; m_renameTimer = new wxListRenameTimer( this ); + m_findTimer = NULL; + m_findBell = 0; // default is to not ring bell at all m_textctrlWrapper = NULL; m_current = @@ -1578,10 +1597,9 @@ wxListMainWindow::wxListMainWindow() wxListMainWindow::wxListMainWindow( wxWindow *parent, wxWindowID id, const wxPoint& pos, - const wxSize& size, - long style, - const wxString &name ) - : wxWindow( parent, id, pos, size, style, name ) + const wxSize& size ) + : wxWindow( parent, id, pos, size, + wxWANTS_CHARS | wxBORDER_NONE ) { Init(); @@ -1622,6 +1640,7 @@ wxListMainWindow::~wxListMainWindow() delete m_highlightBrush; delete m_highlightUnfocusedBrush; delete m_renameTimer; + delete m_findTimer; } void wxListMainWindow::SetReportView(bool inReportView) @@ -1873,8 +1892,8 @@ bool wxListMainWindow::HighlightLine( size_t line, bool highlight ) if ( changed ) { - SendNotify( line, highlight ? wxEVT_COMMAND_LIST_ITEM_SELECTED - : wxEVT_COMMAND_LIST_ITEM_DESELECTED ); + SendNotify( line, highlight ? wxEVT_LIST_ITEM_SELECTED + : wxEVT_LIST_ITEM_DESELECTED ); } return changed; @@ -2028,7 +2047,7 @@ void wxListMainWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) // tell the caller cache to cache the data if ( IsVirtual() ) { - wxListEvent evCache(wxEVT_COMMAND_LIST_CACHE_HINT, + wxListEvent evCache(wxEVT_LIST_CACHE_HINT, GetParent()->GetId()); evCache.SetEventObject( GetParent() ); evCache.m_oldItemIndex = visibleFrom; @@ -2180,7 +2199,7 @@ void wxListMainWindow::SendNotify( size_t line, { GetLine(line)->GetItem( 0, le.m_item ); } - //else: this happens for wxEVT_COMMAND_LIST_ITEM_FOCUSED event + //else: this happens for wxEVT_LIST_ITEM_FOCUSED event } //else: there may be no more such item @@ -2196,7 +2215,7 @@ void wxListMainWindow::ChangeCurrent(size_t current) if ( m_renameTimer->IsRunning() ) m_renameTimer->Stop(); - SendNotify(current, wxEVT_COMMAND_LIST_ITEM_FOCUSED); + SendNotify(current, wxEVT_LIST_ITEM_FOCUSED); } wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass) @@ -2204,12 +2223,12 @@ wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass wxCHECK_MSG( (item >= 0) && ((size_t)item < GetItemCount()), NULL, wxT("wrong index in wxGenericListCtrl::EditLabel()") ); - wxASSERT_MSG( textControlClass->IsKindOf(CLASSINFO(wxTextCtrl)), + wxASSERT_MSG( textControlClass->IsKindOf(wxCLASSINFO(wxTextCtrl)), wxT("EditLabel() needs a text control") ); size_t itemEdit = (size_t)item; - wxListEvent le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() ); + wxListEvent le( wxEVT_LIST_BEGIN_LABEL_EDIT, GetParent()->GetId() ); le.SetEventObject( GetParent() ); le.m_item.m_itemId = le.m_itemIndex = item; @@ -2223,19 +2242,10 @@ wxTextCtrl *wxListMainWindow::EditLabel(long item, wxClassInfo* textControlClass return NULL; } - // We have to call this here because the label in question might just have - // been added and no screen update taken place. if ( m_dirty ) { - // TODO: use wxTheApp->SafeYieldFor(NULL, wxEVT_CATEGORY_UI) instead - // so that no pending events may change the item count (see below) - // IMPORTANT: needs to be tested! - wxSafeYield(); - - // Pending events dispatched by wxSafeYield might have changed the item - // count - if ( (size_t)item >= GetItemCount() ) - return NULL; + // Ensure the display is updated before we start editing. + Update(); } wxTextCtrl * const text = (wxTextCtrl *)textControlClass->CreateObject(); @@ -2252,7 +2262,7 @@ void wxListMainWindow::OnRenameTimer() bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value) { - wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() ); + wxListEvent le( wxEVT_LIST_END_LABEL_EDIT, GetParent()->GetId() ); le.SetEventObject( GetParent() ); le.m_item.m_itemId = le.m_itemIndex = itemEdit; @@ -2270,7 +2280,7 @@ bool wxListMainWindow::OnRenameAccept(size_t itemEdit, const wxString& value) void wxListMainWindow::OnRenameCancelled(size_t itemEdit) { // let owner know that the edit was cancelled - wxListEvent le( wxEVT_COMMAND_LIST_END_LABEL_EDIT, GetParent()->GetId() ); + wxListEvent le( wxEVT_LIST_END_LABEL_EDIT, GetParent()->GetId() ); le.SetEditCanceled(true); @@ -2285,6 +2295,18 @@ void wxListMainWindow::OnRenameCancelled(size_t itemEdit) GetEventHandler()->ProcessEvent( le ); } +void wxListMainWindow::OnFindTimer() +{ + m_findPrefix.clear(); + if ( m_findBell ) + m_findBell = 1; +} + +void wxListMainWindow::EnableBellOnNoMatch( bool on ) +{ + m_findBell = on; +} + void wxListMainWindow::OnMouse( wxMouseEvent &event ) { #ifdef __WXMAC__ @@ -2297,10 +2319,16 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) #endif // __WXMAC__ if ( event.LeftDown() ) - SetFocus(); + { + // Ensure we skip the event to let the system set focus to this window. + event.Skip(); + } - event.SetEventObject( GetParent() ); - if ( GetParent()->GetEventHandler()->ProcessEvent( event) ) + // Pretend that the event happened in wxListCtrl itself. + wxMouseEvent me(event); + me.SetEventObject( GetParent() ); + me.SetId(GetParent()->GetId()); + if ( GetParent()->GetEventHandler()->ProcessEvent( me )) return; if (event.GetEventType() == wxEVT_MOUSEWHEEL) @@ -2314,7 +2342,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) { if (event.RightDown()) { - SendNotify( (size_t)-1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); + SendNotify( (size_t)-1, wxEVT_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); wxContextMenuEvent evtCtx(wxEVT_CONTEXT_MENU, GetParent()->GetId(), @@ -2370,7 +2398,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) m_dragCount = 0; // The only mouse event that can be generated without any valid item is - // wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK as it can be useful to have a global + // wxEVT_LIST_ITEM_RIGHT_CLICK as it can be useful to have a global // popup menu for the list control itself which should be shown even when // the user clicks outside of any item. if ( !hitResult ) @@ -2378,7 +2406,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) // outside of any item if (event.RightDown()) { - SendNotify( (size_t) -1, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); + SendNotify( (size_t) -1, wxEVT_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); wxContextMenuEvent evtCtx( wxEVT_CONTEXT_MENU, @@ -2409,15 +2437,10 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (m_dragCount != 3) return; - int command = event.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG - : wxEVT_COMMAND_LIST_BEGIN_DRAG; + int command = event.RightIsDown() ? wxEVT_LIST_BEGIN_RDRAG + : wxEVT_LIST_BEGIN_DRAG; - wxListEvent le( command, GetParent()->GetId() ); - le.SetEventObject( GetParent() ); - le.m_item.m_itemId = - le.m_itemIndex = m_lineLastClicked; - le.m_pointDrag = m_dragStart; - GetParent()->GetEventHandler()->ProcessEvent( le ); + SendNotify( m_lineLastClicked, command, m_dragStart ); return; } @@ -2432,7 +2455,7 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if ( current == m_lineLastClicked ) { - SendNotify( current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); + SendNotify( current, wxEVT_LIST_ITEM_ACTIVATED ); return; } @@ -2466,9 +2489,10 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) m_renameTimer->Start(dclick > 0 ? dclick : 250, true); } } + + m_lastOnSame = false; } - m_lastOnSame = false; m_lineSelectSingleOnUp = (size_t)-1; } else @@ -2493,14 +2517,14 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) ReverseHighlight(m_current); } - SendNotify( current, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); + SendNotify( current, wxEVT_LIST_ITEM_RIGHT_CLICK, event.GetPosition() ); // Allow generation of context menu event event.Skip(); } else if (event.MiddleDown()) { - SendNotify( current, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK ); + SendNotify( current, wxEVT_LIST_ITEM_MIDDLE_CLICK ); } else if ( event.LeftDown() || forceClick ) { @@ -2560,8 +2584,16 @@ void wxListMainWindow::OnMouse( wxMouseEvent &event ) if (m_current != oldCurrent) RefreshLine( oldCurrent ); - // forceClick is only set if the previous click was on another item - m_lastOnSame = !forceClick && (m_current == oldCurrent) && oldWasSelected; + // Set the flag telling us whether the next click on this item should + // start editing its label. This should happen if we clicked on the + // current item and it was already selected, i.e. if this click was not + // done to select it. + // + // It should not happen if this was a double click (forceClick is true) + // nor if we hadn't had the focus before as then this click was used to + // give focus to the control. + m_lastOnSame = (m_current == oldCurrent) && oldWasSelected && + !forceClick && HasFocus(); } } @@ -2707,11 +2739,12 @@ void wxListMainWindow::OnKeyDown( wxKeyEvent &event ) // propagate the key event upwards wxKeyEvent ke(event); ke.SetEventObject( parent ); + ke.SetId(GetParent()->GetId()); if (parent->GetEventHandler()->ProcessEvent( ke )) return; // send a list event - wxListEvent le( wxEVT_COMMAND_LIST_KEY_DOWN, parent->GetId() ); + wxListEvent le( wxEVT_LIST_KEY_DOWN, parent->GetId() ); le.m_item.m_itemId = le.m_itemIndex = m_current; if (HasCurrent()) @@ -2730,6 +2763,8 @@ void wxListMainWindow::OnKeyUp( wxKeyEvent &event ) // propagate the key event upwards wxKeyEvent ke(event); + ke.SetEventObject( parent ); + ke.SetId(GetParent()->GetId()); if (parent->GetEventHandler()->ProcessEvent( ke )) return; @@ -2754,23 +2789,12 @@ void wxListMainWindow::OnCharHook( wxKeyEvent &event ) void wxListMainWindow::OnChar( wxKeyEvent &event ) { -#ifdef __WXGTK__ - // Under GTK we get some keys (notably cursor arrows) even while the in - // place editing control is shown. Processing them here results in UI - // problems, e.g. we could change the current item on WXK_DOWN press but - // the edit control would remain on the item above. So we need to either - // cancel in-place editing or ignore any such keys while it's active. To - // avoid aggravating the user by losing his changes just because a cursor - // arrow key was mistakenly pressed, do nothing in this case. - if ( m_textctrlWrapper ) - return; -#endif // __WXGTK__ - wxWindow *parent = GetParent(); // propagate the char event upwards wxKeyEvent ke(event); ke.SetEventObject( parent ); + ke.SetId(GetParent()->GetId()); if (parent->GetEventHandler()->ProcessEvent( ke )) return; @@ -2796,7 +2820,8 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) event.m_keyCode = WXK_RIGHT; } - switch ( event.GetKeyCode() ) + int keyCode = event.GetKeyCode(); + switch ( keyCode ) { case WXK_UP: if ( m_current > 0 ) @@ -2879,7 +2904,7 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) } else // normal space press { - SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); + SendNotify( m_current, wxEVT_LIST_ITEM_ACTIVATED ); } } else // multiple selection @@ -2890,11 +2915,83 @@ void wxListMainWindow::OnChar( wxKeyEvent &event ) case WXK_RETURN: case WXK_EXECUTE: - SendNotify( m_current, wxEVT_COMMAND_LIST_ITEM_ACTIVATED ); + SendNotify( m_current, wxEVT_LIST_ITEM_ACTIVATED ); break; default: - event.Skip(); + if ( !event.HasModifiers() && + ((keyCode >= '0' && keyCode <= '9') || + (keyCode >= 'a' && keyCode <= 'z') || + (keyCode >= 'A' && keyCode <= 'Z') || + (keyCode == '_') || + (keyCode == '+') || + (keyCode == '*') || + (keyCode == '-'))) + { + // find the next item starting with the given prefix + wxChar ch = (wxChar)keyCode; + size_t item; + + // if the same character is typed multiple times then go to the + // next entry starting with that character instead of searching + // for an item starting with multiple copies of this character, + // this is more useful and is how it works under Windows. + if ( m_findPrefix.length() == 1 && m_findPrefix[0] == ch ) + { + item = PrefixFindItem(m_current, ch); + } + else + { + const wxString newPrefix(m_findPrefix + ch); + item = PrefixFindItem(m_current, newPrefix); + if ( item != (size_t)-1 ) + m_findPrefix = newPrefix; + } + + // also start the timer to reset the current prefix if the user + // doesn't press any more alnum keys soon -- we wouldn't want + // to use this prefix for a new item search + if ( !m_findTimer ) + { + m_findTimer = new wxListFindTimer( this ); + } + + // Notice that we should start the timer even if we didn't find + // anything to make sure we reset the search state later. + m_findTimer->Start(wxListFindTimer::DELAY, wxTIMER_ONE_SHOT); + + // restart timer even when there's no match so bell get's reset + if ( item != (size_t)-1 ) + { + // Select the found item and go to it. + HighlightAll(false); + SetItemState(item, + wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED, + wxLIST_STATE_FOCUSED | wxLIST_STATE_SELECTED); + + // Reset the bell flag if it had been temporarily disabled + // before. + if ( m_findBell ) + m_findBell = 1; + } + else // No such item + { + // Signal it with a bell if enabled. + if ( m_findBell == 1 ) + { + ::wxBell(); + + // Disable it for the next unsuccessful match, we only + // beep once, this is usually enough and continuing to + // do it would be annoying. + m_findBell = -1; + } + } + } + else + { + event.Skip(); + } } } @@ -3845,7 +3942,7 @@ void wxListMainWindow::DeleteItem( long lindex ) ResetVisibleLinesRange(); } - SendNotify( index, wxEVT_COMMAND_LIST_DELETE_ITEM, wxDefaultPosition ); + SendNotify( index, wxEVT_LIST_DELETE_ITEM, wxDefaultPosition ); if ( IsVirtual() ) { @@ -3923,7 +4020,7 @@ void wxListMainWindow::DoDeleteAllItems() // for all of them: this is compatible with wxMSW and documented in // DeleteAllItems() description - wxListEvent event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS, GetParent()->GetId() ); + wxListEvent event( wxEVT_LIST_DELETE_ALL_ITEMS, GetParent()->GetId() ); event.SetEventObject( GetParent() ); GetParent()->GetEventHandler()->ProcessEvent( event ); @@ -4134,13 +4231,15 @@ void wxListMainWindow::InsertItem( wxListItem &item ) if ( HasCurrent() && m_current >= id ) m_current++; - SendNotify(id, wxEVT_COMMAND_LIST_INSERT_ITEM); + SendNotify(id, wxEVT_LIST_INSERT_ITEM); RefreshLines(id, GetItemCount() - 1); } -void wxListMainWindow::InsertColumn( long col, const wxListItem &item ) +long wxListMainWindow::InsertColumn( long col, const wxListItem &item ) { + long idx = -1; + m_dirty = true; if ( InReportView() ) { @@ -4157,9 +4256,11 @@ void wxListMainWindow::InsertColumn( long col, const wxListItem &item ) node = m_columns.Item( col ); m_columns.Insert( node, column ); m_aColWidths.Insert( colWidthInfo, col ); + idx = col; } else { + idx = m_aColWidths.GetCount(); m_columns.Append( column ); m_aColWidths.Add( colWidthInfo ); } @@ -4181,6 +4282,7 @@ void wxListMainWindow::InsertColumn( long col, const wxListItem &item ) // invalidate it as it has to be recalculated m_headerWidth = 0; } + return idx; } int wxListMainWindow::GetItemWidthWithImage(wxListItem * item) @@ -4311,6 +4413,61 @@ void wxListMainWindow::GetVisibleLinesRange(size_t *from, size_t *to) *to = m_lineTo; } +size_t +wxListMainWindow::PrefixFindItem(size_t idParent, + const wxString& prefixOrig) const +{ + // if no items then just return + if ( idParent == (size_t)-1 ) + return idParent; + + // match is case insensitive as this is more convenient to the user: having + // to press Shift-letter to go to the item starting with a capital letter + // would be too bothersome + wxString prefix = prefixOrig.Lower(); + + // determine the starting point: we shouldn't take the current item (this + // allows to switch between two items starting with the same letter just by + // pressing it) but we shouldn't jump to the next one if the user is + // continuing to type as otherwise he might easily skip the item he wanted + size_t itemid = idParent; + if ( prefix.length() == 1 ) + { + itemid += 1; + } + + // look for the item starting with the given prefix after it + while ( ( itemid < (size_t)GetItemCount() ) && + !GetLine(itemid)->GetText(0).Lower().StartsWith(prefix) ) + { + itemid += 1; + } + + // if we haven't found anything... + if ( !( itemid < (size_t)GetItemCount() ) ) + { + // ... wrap to the beginning + itemid = 0; + + // and try all the items (stop when we get to the one we started from) + while ( ( itemid < (size_t)GetItemCount() ) && itemid != idParent && + !GetLine(itemid)->GetText(0).Lower().StartsWith(prefix) ) + { + itemid += 1; + } + // If we haven't found the item, id will be (size_t)-1, as per + // documentation + if ( !( itemid < (size_t)GetItemCount() ) || + ( ( itemid == idParent ) && + !GetLine(itemid)->GetText(0).Lower().StartsWith(prefix) ) ) + { + itemid = (size_t)-1; + } + } + + return itemid; +} + // ------------------------------------------------------------------------------------- // wxGenericListCtrl // ------------------------------------------------------------------------------------- @@ -4356,7 +4513,13 @@ void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded() if (needs_header) { - m_headerWin = new wxListHeaderWindow + // Notice that we must initialize m_headerWin first, and create the + // real window only later, so that the test in the beginning of the + // function blocks repeated creation of the header as it could happen + // before via wxNavigationEnabled::AddChild() -> ToggleWindowStyle() -> + // SetWindowStyleFlag(). + m_headerWin = new wxListHeaderWindow(); + m_headerWin->Create ( this, wxID_ANY, m_mainWin, wxPoint(0,0), @@ -4367,7 +4530,7 @@ void wxGenericListCtrl::CreateOrDestroyHeaderWindowAsNeeded() ), wxTAB_TRAVERSAL ); - + #if defined( __WXMAC__ ) static wxFont font( wxOSX_SYSTEM_FONT_SMALL ); m_headerWin->SetFont( font ); @@ -4402,12 +4565,7 @@ bool wxGenericListCtrl::Create(wxWindow *parent, validator, name ) ) return false; -#ifdef __WXGTK__ - style &= ~wxBORDER_MASK; - style |= wxBORDER_THEME; -#endif - - m_mainWin = new wxListMainWindow( this, wxID_ANY, wxPoint(0, 0), size, style ); + m_mainWin = new wxListMainWindow(this, wxID_ANY, wxPoint(0, 0), size); SetTargetWindow( m_mainWin ); @@ -4464,13 +4622,14 @@ void wxGenericListCtrl::OnScroll(wxScrollWinEvent& event) // the window the next time m_mainWin->ResetVisibleLinesRange(); - HandleOnScroll( event ); - if ( event.GetOrientation() == wxHORIZONTAL && HasHeader() ) { m_headerWin->Refresh(); m_headerWin->Update(); } + + // Let the window be scrolled as usual by the default handler. + event.Skip(); } void wxGenericListCtrl::SetSingleStyle( long style, bool add ) @@ -4966,14 +5125,14 @@ long wxGenericListCtrl::DoInsertColumn( long col, const wxListItem &item ) { wxCHECK_MSG( InReportView(), -1, wxT("can't add column in non report mode") ); - m_mainWin->InsertColumn( col, item ); + long idx = m_mainWin->InsertColumn( col, item ); // NOTE: if wxLC_NO_HEADER was given, then we are in report view mode but // still have m_headerWin==NULL if (m_headerWin) m_headerWin->Refresh(); - return 0; + return idx; } bool wxGenericListCtrl::ScrollList( int dx, int dy ) @@ -5140,38 +5299,10 @@ bool wxGenericListCtrl::DoPopupMenu( wxMenu *menu, int x, int y ) #endif } -void wxGenericListCtrl::DoClientToScreen( int *x, int *y ) const -{ - // It's not clear whether this can be called before m_mainWin is created - // but it seems better to be on the safe side and check. - if ( m_mainWin ) - m_mainWin->DoClientToScreen(x, y); - else - wxListCtrlBase::DoClientToScreen(x, y); -} - -void wxGenericListCtrl::DoScreenToClient( int *x, int *y ) const -{ - // At least in wxGTK/Univ build this method can be called before m_mainWin - // is created so avoid crashes in this case. - if ( m_mainWin ) - m_mainWin->DoScreenToClient(x, y); - else - wxListCtrlBase::DoScreenToClient(x, y); -} - -void wxGenericListCtrl::SetFocus() -{ - // The test in window.cpp fails as we are a composite - // window, so it checks against "this", but not m_mainWin. - if ( DoFindFocus() != this ) - m_mainWin->SetFocus(); -} - wxSize wxGenericListCtrl::DoGetBestClientSize() const { - // Something is better than nothing even if this is completely arbitrary. - wxSize sizeBest(100, 80); + // The base class version can compute the best size in report view only. + wxSize sizeBest = wxListCtrlBase::DoGetBestClientSize(); if ( !InReportView() ) { @@ -5256,16 +5387,6 @@ int wxGenericListCtrl::OnGetItemColumnImage(long item, long column) const return -1; } -wxListItemAttr * -wxGenericListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item)) const -{ - wxASSERT_MSG( item >= 0 && item < GetItemCount(), - wxT("invalid item index in OnGetItemAttr()") ); - - // no attributes by default - return NULL; -} - void wxGenericListCtrl::SetItemCount(long count) { wxASSERT_MSG( IsVirtual(), wxT("this is for virtual controls only") ); @@ -5283,6 +5404,11 @@ void wxGenericListCtrl::RefreshItems(long itemFrom, long itemTo) m_mainWin->RefreshLines(itemFrom, itemTo); } +void wxGenericListCtrl::EnableBellOnNoMatch( bool on ) +{ + m_mainWin->EnableBellOnNoMatch(on); +} + // Generic wxListCtrl is more or less a container for two other // windows which drawings are done upon. These are namely // 'm_headerWin' and 'm_mainWin'.