]>
git.saurik.com Git - wxWidgets.git/blob - src/common/bookctrl.cpp
6ab3784e11574d9f2ba4836ecf323b7b32259c66
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/bookctrl.cpp
3 // Purpose: wxBookCtrlBase implementation
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 // For compilers that support precompilation, includes "wx.h".
21 #include "wx/wxprec.h"
29 #include "wx/imaglist.h"
31 #include "wx/bookctrl.h"
33 // ============================================================================
35 // ============================================================================
37 // ----------------------------------------------------------------------------
39 // ----------------------------------------------------------------------------
41 IMPLEMENT_ABSTRACT_CLASS(wxBookCtrlBase
, wxControl
)
43 BEGIN_EVENT_TABLE(wxBookCtrlBase
, wxControl
)
44 EVT_SIZE(wxBookCtrlBase::OnSize
)
46 EVT_HELP(wxID_ANY
, wxBookCtrlBase::OnHelp
)
50 // ----------------------------------------------------------------------------
51 // constructors and destructors
52 // ----------------------------------------------------------------------------
54 void wxBookCtrlBase::Init()
56 m_selection
= wxNOT_FOUND
;
58 m_fitToCurrentPage
= false;
60 #if defined(__WXWINCE__)
67 m_controlSizer
= NULL
;
71 wxBookCtrlBase::Create(wxWindow
*parent
,
78 return wxControl::Create
90 // ----------------------------------------------------------------------------
92 // ----------------------------------------------------------------------------
94 void wxBookCtrlBase::DoInvalidateBestSize()
96 // notice that it is not necessary to invalidate our own best size
97 // explicitly if we have m_bookctrl as it will already invalidate the best
98 // size of its parent when its own size is invalidated and its parent is
101 m_bookctrl
->InvalidateBestSize();
103 wxControl::InvalidateBestSize();
106 wxSize
wxBookCtrlBase::CalcSizeFromPage(const wxSize
& sizePage
) const
108 // Add the size of the controller and the border between if it's shown.
109 if ( !m_bookctrl
|| !m_bookctrl
->IsShown() )
112 const wxSize sizeController
= GetControllerSize();
114 wxSize size
= sizePage
;
117 if ( sizeController
.x
> sizePage
.x
)
118 size
.x
= sizeController
.x
;
119 size
.y
+= sizeController
.y
+ GetInternalBorder();
121 else // left/right aligned
123 size
.x
+= sizeController
.x
+ GetInternalBorder();
124 if ( sizeController
.y
> sizePage
.y
)
125 size
.y
= sizeController
.y
;
131 void wxBookCtrlBase::SetPageSize(const wxSize
& size
)
133 SetClientSize(CalcSizeFromPage(size
));
136 wxSize
wxBookCtrlBase::DoGetBestSize() const
140 if (m_fitToCurrentPage
&& GetCurrentPage())
142 bestSize
= GetCurrentPage()->GetBestSize();
146 // iterate over all pages, get the largest width and height
147 const size_t nCount
= m_pages
.size();
148 for ( size_t nPage
= 0; nPage
< nCount
; nPage
++ )
150 const wxWindow
* const pPage
= m_pages
[nPage
];
152 bestSize
.IncTo(pPage
->GetBestSize());
156 // convert display area to window area, adding the size necessary for the
158 wxSize best
= CalcSizeFromPage(bestSize
);
163 wxRect
wxBookCtrlBase::GetPageRect() const
165 const wxSize size
= GetControllerSize();
168 wxRect
rectPage(pt
, GetClientSize());
170 switch ( GetWindowStyle() & wxBK_ALIGN_MASK
)
173 wxFAIL_MSG( wxT("unexpected alignment") );
177 rectPage
.y
= size
.y
+ GetInternalBorder();
181 rectPage
.height
-= size
.y
+ GetInternalBorder();
182 if (rectPage
.height
< 0)
187 rectPage
.x
= size
.x
+ GetInternalBorder();
191 rectPage
.width
-= size
.x
+ GetInternalBorder();
192 if (rectPage
.width
< 0)
201 void wxBookCtrlBase::DoSize()
205 // we're not fully created yet or OnSize() should be hidden by derived class
213 // resize controller and the page area to fit inside our new size
214 const wxSize
sizeClient( GetClientSize() ),
215 sizeBorder( m_bookctrl
->GetSize() - m_bookctrl
->GetClientSize() ),
216 sizeCtrl( GetControllerSize() );
218 m_bookctrl
->SetClientSize( sizeCtrl
.x
- sizeBorder
.x
, sizeCtrl
.y
- sizeBorder
.y
);
219 // if this changes the visibility of the scrollbars the best size changes, relayout in this case
220 wxSize sizeCtrl2
= GetControllerSize();
221 if ( sizeCtrl
!= sizeCtrl2
)
223 wxSize sizeBorder2
= m_bookctrl
->GetSize() - m_bookctrl
->GetClientSize();
224 m_bookctrl
->SetClientSize( sizeCtrl2
.x
- sizeBorder2
.x
, sizeCtrl2
.y
- sizeBorder2
.y
);
227 const wxSize sizeNew
= m_bookctrl
->GetSize();
229 switch ( GetWindowStyle() & wxBK_ALIGN_MASK
)
232 wxFAIL_MSG( wxT("unexpected alignment") );
237 // posCtrl is already ok
241 posCtrl
.y
= sizeClient
.y
- sizeNew
.y
;
245 posCtrl
.x
= sizeClient
.x
- sizeNew
.x
;
249 if ( m_bookctrl
->GetPosition() != posCtrl
)
250 m_bookctrl
->Move(posCtrl
);
253 // resize all pages to fit the new control size
254 const wxRect pageRect
= GetPageRect();
255 const unsigned pagesCount
= m_pages
.GetCount();
256 for ( unsigned int i
= 0; i
< pagesCount
; ++i
)
258 wxWindow
* const page
= m_pages
[i
];
261 wxASSERT_MSG( AllowNullPage(),
262 wxT("Null page in a control that does not allow null pages?") );
266 page
->SetSize(pageRect
);
270 void wxBookCtrlBase::OnSize(wxSizeEvent
& event
)
277 wxSize
wxBookCtrlBase::GetControllerSize() const
279 // For at least some book controls (e.g. wxChoicebook) it may make sense to
280 // (temporarily?) hide the controller and we shouldn't leave extra space
281 // for the hidden control in this case.
282 if ( !m_bookctrl
|| !m_bookctrl
->IsShown() )
285 const wxSize sizeClient
= GetClientSize();
289 // Ask for the best width/height considering the other direction.
292 size
.x
= sizeClient
.x
;
293 size
.y
= m_bookctrl
->GetBestHeight(sizeClient
.x
);
295 else // left/right aligned
297 size
.x
= m_bookctrl
->GetBestWidth(sizeClient
.y
);
298 size
.y
= sizeClient
.y
;
304 // ----------------------------------------------------------------------------
305 // miscellaneous stuff
306 // ----------------------------------------------------------------------------
310 void wxBookCtrlBase::OnHelp(wxHelpEvent
& event
)
312 // determine where does this even originate from to avoid redirecting it
313 // back to the page which generated it (resulting in an infinite loop)
315 // notice that we have to check in the hard(er) way instead of just testing
316 // if the event object == this because the book control can have other
317 // subcontrols inside it (e.g. wxSpinButton in case of a notebook in wxUniv)
318 wxWindow
*source
= wxStaticCast(event
.GetEventObject(), wxWindow
);
319 while ( source
&& source
!= this && source
->GetParent() != this )
321 source
= source
->GetParent();
324 if ( source
&& m_pages
.Index(source
) == wxNOT_FOUND
)
326 // this event is for the book control itself, redirect it to the
327 // corresponding page
328 wxWindow
*page
= NULL
;
330 if ( event
.GetOrigin() == wxHelpEvent::Origin_HelpButton
)
332 // show help for the page under the mouse
333 const int pagePos
= HitTest(ScreenToClient(event
.GetPosition()));
335 if ( pagePos
!= wxNOT_FOUND
)
337 page
= GetPage((size_t)pagePos
);
340 else // event from keyboard or unknown source
342 // otherwise show the current page help
343 page
= GetCurrentPage();
348 // change event object to the page to avoid infinite recursion if
349 // we get this event ourselves if the page doesn't handle it
350 event
.SetEventObject(page
);
352 if ( page
->GetEventHandler()->ProcessEvent(event
) )
354 // don't call event.Skip()
359 //else: event coming from one of our pages already
366 // ----------------------------------------------------------------------------
368 // ----------------------------------------------------------------------------
371 wxBookCtrlBase::InsertPage(size_t nPage
,
373 const wxString
& WXUNUSED(text
),
374 bool WXUNUSED(bSelect
),
375 int WXUNUSED(imageId
))
377 wxCHECK_MSG( page
|| AllowNullPage(), false,
378 wxT("NULL page in wxBookCtrlBase::InsertPage()") );
379 wxCHECK_MSG( nPage
<= m_pages
.size(), false,
380 wxT("invalid page index in wxBookCtrlBase::InsertPage()") );
382 m_pages
.Insert(page
, nPage
);
384 page
->SetSize(GetPageRect());
386 DoInvalidateBestSize();
391 bool wxBookCtrlBase::DeletePage(size_t nPage
)
393 wxWindow
*page
= DoRemovePage(nPage
);
394 if ( !(page
|| AllowNullPage()) )
397 // delete NULL is harmless
403 wxWindow
*wxBookCtrlBase::DoRemovePage(size_t nPage
)
405 wxCHECK_MSG( nPage
< m_pages
.size(), NULL
,
406 wxT("invalid page index in wxBookCtrlBase::DoRemovePage()") );
408 wxWindow
*pageRemoved
= m_pages
[nPage
];
409 m_pages
.RemoveAt(nPage
);
410 DoInvalidateBestSize();
415 int wxBookCtrlBase::GetNextPage(bool forward
) const
419 int nMax
= GetPageCount();
420 if ( nMax
-- ) // decrement it to get the last valid index
422 int nSel
= GetSelection();
424 // change selection wrapping if it becomes invalid
425 nPage
= forward
? nSel
== nMax
? 0
430 else // notebook is empty, no next page
438 bool wxBookCtrlBase::DoSetSelectionAfterInsertion(size_t n
, bool bSelect
)
442 else if ( m_selection
== wxNOT_FOUND
)
444 else // We're not going to select this page.
447 // Return true to indicate that we selected this page.
451 int wxBookCtrlBase::DoSetSelection(size_t n
, int flags
)
453 wxCHECK_MSG( n
< GetPageCount(), wxNOT_FOUND
,
454 wxT("invalid page index in wxBookCtrlBase::DoSetSelection()") );
456 const int oldSel
= GetSelection();
458 if ( n
!= (size_t)oldSel
)
460 wxBookCtrlEvent
*event
= CreatePageChangingEvent();
461 bool allowed
= false;
463 if ( flags
& SetSelection_SendEvent
)
465 event
->SetSelection(n
);
466 event
->SetOldSelection(oldSel
);
467 event
->SetEventObject(this);
469 allowed
= !GetEventHandler()->ProcessEvent(*event
) || event
->IsAllowed();
472 if ( !(flags
& SetSelection_SendEvent
) || allowed
)
474 if ( oldSel
!= wxNOT_FOUND
)
475 DoShowPage(m_pages
[oldSel
], false);
477 wxWindow
*page
= m_pages
[n
];
478 page
->SetSize(GetPageRect());
479 DoShowPage(page
, true);
481 // change selection now to ignore the selection change event
482 UpdateSelectedPage(n
);
484 if ( flags
& SetSelection_SendEvent
)
486 // program allows the page change
487 MakeChangedEvent(*event
);
488 (void)GetEventHandler()->ProcessEvent(*event
);
498 IMPLEMENT_DYNAMIC_CLASS(wxBookCtrlEvent
, wxNotifyEvent
)
500 #endif // wxUSE_BOOKCTRL