]>
git.saurik.com Git - wxWidgets.git/blob - src/common/bookctrl.cpp
da06cdafeba1ce300f7bc3f26a1ccdde4ffda51b
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()
58 m_ownsImageList
= false;
59 m_fitToCurrentPage
= false;
61 #if defined(__WXWINCE__)
68 m_controlSizer
= NULL
;
72 wxBookCtrlBase::Create(wxWindow
*parent
,
79 return wxControl::Create
91 wxBookCtrlBase::~wxBookCtrlBase()
93 if ( m_ownsImageList
)
100 // ----------------------------------------------------------------------------
102 // ----------------------------------------------------------------------------
104 void wxBookCtrlBase::SetImageList(wxImageList
*imageList
)
106 if ( m_ownsImageList
)
111 m_ownsImageList
= false;
114 m_imageList
= imageList
;
117 void wxBookCtrlBase::AssignImageList(wxImageList
* imageList
)
119 SetImageList(imageList
);
121 m_ownsImageList
= true;
124 // ----------------------------------------------------------------------------
126 // ----------------------------------------------------------------------------
128 void wxBookCtrlBase::DoInvalidateBestSize()
130 // notice that it is not necessary to invalidate our own best size
131 // explicitly if we have m_bookctrl as it will already invalidate the best
132 // size of its parent when its own size is invalidated and its parent is
135 m_bookctrl
->InvalidateBestSize();
137 wxControl::InvalidateBestSize();
140 void wxBookCtrlBase::SetPageSize(const wxSize
& size
)
142 SetClientSize(CalcSizeFromPage(size
));
145 wxSize
wxBookCtrlBase::DoGetBestSize() const
149 // iterate over all pages, get the largest width and height
150 const size_t nCount
= m_pages
.size();
151 for ( size_t nPage
= 0; nPage
< nCount
; nPage
++ )
153 const wxWindow
* const pPage
= m_pages
[nPage
];
156 wxSize
childBestSize(pPage
->GetBestSize());
158 if ( childBestSize
.x
> bestSize
.x
)
159 bestSize
.x
= childBestSize
.x
;
161 if ( childBestSize
.y
> bestSize
.y
)
162 bestSize
.y
= childBestSize
.y
;
166 if (m_fitToCurrentPage
&& GetCurrentPage())
167 bestSize
= GetCurrentPage()->GetBestSize();
169 // convert display area to window area, adding the size necessary for the
171 wxSize best
= CalcSizeFromPage(bestSize
);
176 wxRect
wxBookCtrlBase::GetPageRect() const
178 const wxSize size
= GetControllerSize();
181 wxRect
rectPage(pt
, GetClientSize());
183 switch ( GetWindowStyle() & wxBK_ALIGN_MASK
)
186 wxFAIL_MSG( wxT("unexpected alignment") );
190 rectPage
.y
= size
.y
+ GetInternalBorder();
194 rectPage
.height
-= size
.y
+ GetInternalBorder();
195 if (rectPage
.height
< 0)
200 rectPage
.x
= size
.x
+ GetInternalBorder();
204 rectPage
.width
-= size
.x
+ GetInternalBorder();
205 if (rectPage
.width
< 0)
214 void wxBookCtrlBase::DoSize()
218 // we're not fully created yet or OnSize() should be hidden by derived class
226 // resize controller and the page area to fit inside our new size
227 const wxSize
sizeClient( GetClientSize() ),
228 sizeBorder( m_bookctrl
->GetSize() - m_bookctrl
->GetClientSize() ),
229 sizeCtrl( GetControllerSize() );
231 m_bookctrl
->SetClientSize( sizeCtrl
.x
- sizeBorder
.x
, sizeCtrl
.y
- sizeBorder
.y
);
232 // if this changes the visibility of the scrollbars the best size changes, relayout in this case
233 wxSize sizeCtrl2
= GetControllerSize();
234 if ( sizeCtrl
!= sizeCtrl2
)
236 wxSize sizeBorder2
= m_bookctrl
->GetSize() - m_bookctrl
->GetClientSize();
237 m_bookctrl
->SetClientSize( sizeCtrl2
.x
- sizeBorder2
.x
, sizeCtrl2
.y
- sizeBorder2
.y
);
240 const wxSize sizeNew
= m_bookctrl
->GetSize();
242 switch ( GetWindowStyle() & wxBK_ALIGN_MASK
)
245 wxFAIL_MSG( wxT("unexpected alignment") );
250 // posCtrl is already ok
254 posCtrl
.y
= sizeClient
.y
- sizeNew
.y
;
258 posCtrl
.x
= sizeClient
.x
- sizeNew
.x
;
262 if ( m_bookctrl
->GetPosition() != posCtrl
)
263 m_bookctrl
->Move(posCtrl
);
266 // resize all pages to fit the new control size
267 const wxRect pageRect
= GetPageRect();
268 const unsigned pagesCount
= m_pages
.GetCount();
269 for ( unsigned int i
= 0; i
< pagesCount
; ++i
)
271 wxWindow
* const page
= m_pages
[i
];
274 wxASSERT_MSG( AllowNullPage(),
275 wxT("Null page in a control that does not allow null pages?") );
279 page
->SetSize(pageRect
);
283 void wxBookCtrlBase::OnSize(wxSizeEvent
& event
)
290 wxSize
wxBookCtrlBase::GetControllerSize() const
295 const wxSize sizeClient
= GetClientSize(),
296 sizeCtrl
= m_bookctrl
->GetBestSize();
302 size
.x
= sizeClient
.x
;
305 else // left/right aligned
308 size
.y
= sizeClient
.y
;
314 // ----------------------------------------------------------------------------
315 // miscellaneous stuff
316 // ----------------------------------------------------------------------------
320 void wxBookCtrlBase::OnHelp(wxHelpEvent
& event
)
322 // determine where does this even originate from to avoid redirecting it
323 // back to the page which generated it (resulting in an infinite loop)
325 // notice that we have to check in the hard(er) way instead of just testing
326 // if the event object == this because the book control can have other
327 // subcontrols inside it (e.g. wxSpinButton in case of a notebook in wxUniv)
328 wxWindow
*source
= wxStaticCast(event
.GetEventObject(), wxWindow
);
329 while ( source
&& source
!= this && source
->GetParent() != this )
331 source
= source
->GetParent();
334 if ( source
&& m_pages
.Index(source
) == wxNOT_FOUND
)
336 // this event is for the book control itself, redirect it to the
337 // corresponding page
338 wxWindow
*page
= NULL
;
340 if ( event
.GetOrigin() == wxHelpEvent::Origin_HelpButton
)
342 // show help for the page under the mouse
343 const int pagePos
= HitTest(ScreenToClient(event
.GetPosition()));
345 if ( pagePos
!= wxNOT_FOUND
)
347 page
= GetPage((size_t)pagePos
);
350 else // event from keyboard or unknown source
352 // otherwise show the current page help
353 page
= GetCurrentPage();
358 // change event object to the page to avoid infinite recursion if
359 // we get this event ourselves if the page doesn't handle it
360 event
.SetEventObject(page
);
362 if ( page
->GetEventHandler()->ProcessEvent(event
) )
364 // don't call event.Skip()
369 //else: event coming from one of our pages already
376 // ----------------------------------------------------------------------------
378 // ----------------------------------------------------------------------------
381 wxBookCtrlBase::InsertPage(size_t nPage
,
383 const wxString
& WXUNUSED(text
),
384 bool WXUNUSED(bSelect
),
385 int WXUNUSED(imageId
))
387 wxCHECK_MSG( page
|| AllowNullPage(), false,
388 wxT("NULL page in wxBookCtrlBase::InsertPage()") );
389 wxCHECK_MSG( nPage
<= m_pages
.size(), false,
390 wxT("invalid page index in wxBookCtrlBase::InsertPage()") );
392 m_pages
.Insert(page
, nPage
);
394 page
->SetSize(GetPageRect());
396 DoInvalidateBestSize();
401 bool wxBookCtrlBase::DeletePage(size_t nPage
)
403 wxWindow
*page
= DoRemovePage(nPage
);
404 if ( !(page
|| AllowNullPage()) )
407 // delete NULL is harmless
413 wxWindow
*wxBookCtrlBase::DoRemovePage(size_t nPage
)
415 wxCHECK_MSG( nPage
< m_pages
.size(), NULL
,
416 wxT("invalid page index in wxBookCtrlBase::DoRemovePage()") );
418 wxWindow
*pageRemoved
= m_pages
[nPage
];
419 m_pages
.RemoveAt(nPage
);
420 DoInvalidateBestSize();
425 int wxBookCtrlBase::GetNextPage(bool forward
) const
429 int nMax
= GetPageCount();
430 if ( nMax
-- ) // decrement it to get the last valid index
432 int nSel
= GetSelection();
434 // change selection wrapping if it becomes invalid
435 nPage
= forward
? nSel
== nMax
? 0
440 else // notebook is empty, no next page
448 int wxBookCtrlBase::DoSetSelection(size_t n
, int flags
)
450 wxCHECK_MSG( n
< GetPageCount(), wxNOT_FOUND
,
451 wxT("invalid page index in wxBookCtrlBase::DoSetSelection()") );
453 const int oldSel
= GetSelection();
455 if ( n
!= (size_t)oldSel
)
457 wxBookCtrlEvent
*event
= CreatePageChangingEvent();
458 bool allowed
= false;
460 if ( flags
& SetSelection_SendEvent
)
462 event
->SetSelection(n
);
463 event
->SetOldSelection(oldSel
);
464 event
->SetEventObject(this);
466 allowed
= !GetEventHandler()->ProcessEvent(*event
) || event
->IsAllowed();
469 if ( !(flags
& SetSelection_SendEvent
) || allowed
)
471 if ( oldSel
!= wxNOT_FOUND
)
472 m_pages
[oldSel
]->Hide();
474 wxWindow
*page
= m_pages
[n
];
475 page
->SetSize(GetPageRect());
478 // change selection now to ignore the selection change event
479 UpdateSelectedPage(n
);
481 if ( flags
& SetSelection_SendEvent
)
483 // program allows the page change
484 MakeChangedEvent(*event
);
485 (void)GetEventHandler()->ProcessEvent(*event
);
495 IMPLEMENT_DYNAMIC_CLASS(wxBookCtrlEvent
, wxNotifyEvent
)
497 #endif // wxUSE_BOOKCTRL