X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ef0120c1bbb3e9f8031e6aecebb497c58f2be432..bc14c8b21fe31a7bff1abf0fbb0eae2d5dd839df:/src/generic/listbkg.cpp diff --git a/src/generic/listbkg.cpp b/src/generic/listbkg.cpp index 676b202c93..dac6330df1 100644 --- a/src/generic/listbkg.cpp +++ b/src/generic/listbkg.cpp @@ -17,10 +17,6 @@ // headers // ---------------------------------------------------------------------------- -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) - #pragma implementation "listbook.h" -#endif - // For compilers that support precompilation, includes "wx.h". #include "wx/wxprec.h" @@ -45,7 +41,14 @@ const wxCoord MARGIN = 5; // ---------------------------------------------------------------------------- -// various wxWindows macros +// various wxWidgets macros +// ---------------------------------------------------------------------------- + +// check that the page index is valid +#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount()) + +// ---------------------------------------------------------------------------- +// event table // ---------------------------------------------------------------------------- IMPLEMENT_DYNAMIC_CLASS(wxListbook, wxControl) @@ -55,9 +58,8 @@ const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING = wxNewEventType(); const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED = wxNewEventType(); const int wxID_LISTBOOKLISTVIEW = wxNewId(); -BEGIN_EVENT_TABLE(wxListbook, wxBookCtrl) +BEGIN_EVENT_TABLE(wxListbook, wxBookCtrlBase) EVT_SIZE(wxListbook::OnSize) - EVT_LIST_ITEM_SELECTED(wxID_LISTBOOKLISTVIEW, wxListbook::OnListSelected) END_EVENT_TABLE() @@ -118,13 +120,23 @@ wxListbook::Create(wxWindow *parent, m_line = new wxStaticLine ( this, - -1, + wxID_ANY, wxDefaultPosition, wxDefaultSize, IsVertical() ? wxLI_HORIZONTAL : wxLI_VERTICAL ); #endif // wxUSE_LINE_IN_LISTBOOK +#ifdef __WXMSW__ + // On XP with themes enabled the GetViewRect used in GetListSize to + // determine the space needed for the list view will incorrectly return + // (0,0,0,0) the first time. So send a pending event so OnSize will be + // called again after the window is ready to go. Technically we don't + // need to do this on non-XP windows, but if things are already sized + // correctly then nothing changes and so there is no harm. + wxSizeEvent evt; + GetEventHandler()->AddPendingEvent(evt); +#endif return true; } @@ -135,7 +147,8 @@ wxListbook::Create(wxWindow *parent, wxSize wxListbook::GetListSize() const { const wxSize sizeClient = GetClientSize(), - sizeList = m_list->GetViewRect().GetSize(); + sizeBorder = m_list->GetSize() - m_list->GetClientSize(), + sizeList = m_list->GetViewRect().GetSize() + sizeBorder; wxSize size; if ( IsVertical() ) @@ -156,7 +169,8 @@ wxRect wxListbook::GetPageRect() const { const wxSize sizeList = m_list->GetSize(); - wxRect rectPage(wxPoint(0, 0), GetClientSize()); + wxPoint pt; + wxRect rectPage(pt, GetClientSize()); switch ( GetWindowStyle() & wxLB_ALIGN_MASK ) { default: @@ -193,10 +207,21 @@ void wxListbook::OnSize(wxSizeEvent& event) return; } + // arrange the icons before calling SetClientSize(), otherwise it wouldn't + // account for the scrollbars the list control might need and, at least + // under MSW, we'd finish with an ugly looking list control with both + // vertical and horizontal scrollbar (with one of them being added because + // the other one is not accounted for in client size computations) + m_list->Arrange(); + // resize the list control and the page area to fit inside our new size const wxSize sizeClient = GetClientSize(), + sizeBorder = m_list->GetSize() - m_list->GetClientSize(), sizeList = GetListSize(); + m_list->SetClientSize( sizeList.x - sizeBorder.x, sizeList.y - sizeBorder.y ); + + const wxSize sizeNew = m_list->GetSize(); wxPoint posList; switch ( GetWindowStyle() & wxLB_ALIGN_MASK ) { @@ -210,42 +235,42 @@ void wxListbook::OnSize(wxSizeEvent& event) break; case wxLB_BOTTOM: - posList.y = sizeClient.y - sizeList.y; + posList.y = sizeClient.y - sizeNew.y; break; case wxLB_RIGHT: - posList.x = sizeClient.x - sizeList.x; + posList.x = sizeClient.x - sizeNew.x; break; } - m_list->Move(posList.x, posList.y); - m_list->SetClientSize(sizeList.x, sizeList.y); + if ( m_list->GetPosition() != posList ) + m_list->Move(posList); #if wxUSE_LINE_IN_LISTBOOK if ( m_line ) { - wxRect rectLine(wxPoint(0, 0), sizeClient); + wxRect rectLine(sizeClient); switch ( GetWindowStyle() & wxLB_ALIGN_MASK ) { case wxLB_TOP: - rectLine.y = sizeList.y + 1; + rectLine.y = sizeNew.y + 1; rectLine.height = MARGIN - 2; break; case wxLB_BOTTOM: rectLine.height = MARGIN - 2; - rectLine.y = sizeClient.y - sizeList.y - rectLine.height; + rectLine.y = sizeClient.y - sizeNew.y - rectLine.height; break; case wxLB_LEFT: - rectLine.x = sizeList.x + 1; + rectLine.x = sizeNew.x + 1; rectLine.width = MARGIN - 2; break; case wxLB_RIGHT: rectLine.width = MARGIN - 2; - rectLine.x = sizeClient.x - sizeList.x - rectLine.width; + rectLine.x = sizeClient.x - sizeNew.x - rectLine.width; break; } @@ -253,22 +278,12 @@ void wxListbook::OnSize(wxSizeEvent& event) } #endif // wxUSE_LINE_IN_LISTBOOK - // we should always have some selection if possible - if ( m_selection == wxNOT_FOUND && GetPageCount() ) - { - SetSelection(0); - } - - if ( m_selection != wxNOT_FOUND ) + // resize the currently shown page + if (m_selection != wxNOT_FOUND ) { wxWindow *page = m_pages[m_selection]; wxCHECK_RET( page, _T("NULL page in wxListbook?") ); - page->SetSize(GetPageRect()); - if ( !page->IsShown() ) - { - page->Show(); - } } } @@ -311,12 +326,12 @@ int wxListbook::GetPageImage(size_t WXUNUSED(n)) const { wxFAIL_MSG( _T("wxListbook::GetPageImage() not implemented") ); - return -1; + return wxNOT_FOUND; } bool wxListbook::SetPageImage(size_t n, int imageId) { - return m_list->SetItemImage(n, imageId, imageId); + return m_list->SetItemImage(n, imageId); } // ---------------------------------------------------------------------------- @@ -327,7 +342,7 @@ void wxListbook::SetImageList(wxImageList *imageList) { m_list->SetImageList(imageList, wxIMAGE_LIST_NORMAL); - wxBookCtrl::SetImageList(imageList); + wxBookCtrlBase::SetImageList(imageList); } // ---------------------------------------------------------------------------- @@ -341,23 +356,40 @@ int wxListbook::GetSelection() const int wxListbook::SetSelection(size_t n) { - wxCHECK_MSG( n < GetPageCount(), wxNOT_FOUND, - _T("invalid page index in wxListbook::SetSelection()") ); + wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND, + wxT("invalid page index in wxListbook::SetSelection()") ); - int selOld = m_selection; + const int oldSel = m_selection; - if ( (int)n != m_selection ) + if ( int(n) != m_selection ) { - m_selection = n; + wxListbookEvent event(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, m_windowId); + event.SetSelection(n); + event.SetOldSelection(m_selection); + event.SetEventObject(this); + if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() ) + { + if ( m_selection != wxNOT_FOUND ) + m_pages[m_selection]->Hide(); - m_list->Select(m_selection); - m_list->Focus(m_selection); + wxWindow *page = m_pages[n]; + page->SetSize(GetPageRect()); + page->Show(); + + // change m_selection now to ignore the selection change event + m_selection = n; + m_list->Select(n); + m_list->Focus(n); + + // program allows the page change + event.SetEventType(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED); + (void)GetEventHandler()->ProcessEvent(event); + } } - return selOld; + return oldSel; } - // ---------------------------------------------------------------------------- // adding/removing the pages // ---------------------------------------------------------------------------- @@ -369,36 +401,78 @@ wxListbook::InsertPage(size_t n, bool bSelect, int imageId) { - if ( !wxBookCtrl::InsertPage(n, page, text, bSelect, imageId) ) + if ( !wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId) ) return false; m_list->InsertItem(n, text, imageId); - if ( bSelect ) + // if the inserted page is before the selected one, we must update the + // index of the selected page + if ( int(n) <= m_selection ) { - m_list->Select(n); - m_list->Focus(n); + // one extra page added + m_selection++; + m_list->Select(m_selection); + m_list->Focus(m_selection); } - else // don't select this page - { - // it will be shown only when selected + + // some page should be selected: either this one or the first one if there + // is still no selection + int selNew = -1; + if ( bSelect ) + selNew = n; + else if ( m_selection == -1 ) + selNew = 0; + + if ( selNew != m_selection ) page->Hide(); - } + if ( selNew != -1 ) + SetSelection(selNew); + + InvalidateBestSize(); + m_list->Arrange(); return true; } wxWindow *wxListbook::DoRemovePage(size_t page) { - wxWindow *win = wxBookCtrl::DoRemovePage(page); + const int page_count = GetPageCount(); + wxWindow *win = wxBookCtrlBase::DoRemovePage(page); + if ( win ) { m_list->DeleteItem(page); + + if (m_selection >= (int)page) + { + // force new sel valid if possible + int sel = m_selection - 1; + if (page_count == 1) + sel = wxNOT_FOUND; + else if ((page_count == 2) || (sel == -1)) + sel = 0; + + // force sel invalid if deleting current page - don't try to hide it + m_selection = (m_selection == (int)page) ? wxNOT_FOUND : m_selection - 1; + + if ((sel != wxNOT_FOUND) && (sel != m_selection)) + SetSelection(sel); + } + + m_list->Arrange(); } return win; } + +bool wxListbook::DeleteAllPages() +{ + m_list->DeleteAllItems(); + return wxBookCtrlBase::DeleteAllPages(); +} + // ---------------------------------------------------------------------------- // wxListbook events // ---------------------------------------------------------------------------- @@ -415,32 +489,14 @@ void wxListbook::OnListSelected(wxListEvent& eventList) return; } - // first send "change in progress" event which may be vetoed by user - wxListbookEvent eventIng(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, GetId()); + SetSelection(selNew); - eventIng.SetEventObject(this); - eventIng.SetSelection(selNew); - eventIng.SetOldSelection(m_selection); - if ( GetEventHandler()->ProcessEvent(eventIng) && !eventIng.IsAllowed() ) + // change wasn't allowed, return to previous state + if (m_selection != selNew) { m_list->Select(m_selection); - return; + m_list->Focus(m_selection); } - - // change allowed: do change the page and notify the user about it - if ( m_selection != wxNOT_FOUND ) - m_pages[m_selection]->Hide(); - wxWindow *page = m_pages[m_selection = selNew]; - page->SetSize(GetPageRect()); - page->Show(); - - wxListbookEvent eventEd(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED, GetId()); - - eventEd.SetEventObject(this); - eventEd.SetSelection(selNew); - eventEd.SetOldSelection(m_selection); - - (void)GetEventHandler()->ProcessEvent(eventEd); } #endif // wxUSE_LISTBOOK