]> git.saurik.com Git - wxWidgets.git/blame - src/osx/notebook_osx.cpp
defer calling SetCanFocus() on wxGTK until after creation
[wxWidgets.git] / src / osx / notebook_osx.cpp
CommitLineData
e53b3d16
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: src/osx/notebook_osx.cpp
3// Purpose: implementation of wxNotebook
4// Author: Stefan Csomor
5// Modified by:
6// Created: 1998-01-01
e53b3d16
SC
7// Copyright: (c) Stefan Csomor
8// Licence: wxWindows licence
9///////////////////////////////////////////////////////////////////////////////
10
11#include "wx/wxprec.h"
12
13#if wxUSE_NOTEBOOK
14
15#include "wx/notebook.h"
16
17#ifndef WX_PRECOMP
18 #include "wx/string.h"
19 #include "wx/log.h"
20 #include "wx/app.h"
21 #include "wx/image.h"
22#endif
23
24#include "wx/string.h"
25#include "wx/imaglist.h"
26#include "wx/osx/private.h"
27
28
29// check that the page index is valid
30#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
31
32BEGIN_EVENT_TABLE(wxNotebook, wxBookCtrlBase)
33 EVT_NOTEBOOK_PAGE_CHANGED(wxID_ANY, wxNotebook::OnSelChange)
34
35 EVT_SIZE(wxNotebook::OnSize)
36 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
37 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
38END_EVENT_TABLE()
39
e53b3d16
SC
40bool wxNotebook::Create( wxWindow *parent,
41 wxWindowID id,
42 const wxPoint& pos,
43 const wxSize& size,
44 long style,
45 const wxString& name )
d15694e8
SC
46{
47 DontCreatePeer();
48
e53b3d16
SC
49 if (! (style & wxBK_ALIGN_MASK))
50 style |= wxBK_TOP;
51
52 if ( !wxNotebookBase::Create( parent, id, pos, size, style, name ) )
53 return false;
54
22756322 55 SetPeer(wxWidgetImpl::CreateTabView(this,parent, id, pos, size, style, GetExtraStyle() ));
03647350 56
e53b3d16
SC
57 MacPostControlCreate( pos, size );
58
59 return true ;
60}
61
62// dtor
63wxNotebook::~wxNotebook()
64{
65}
66
67// ----------------------------------------------------------------------------
68// wxNotebook accessors
69// ----------------------------------------------------------------------------
70
71void wxNotebook::SetPadding(const wxSize& WXUNUSED(padding))
72{
73 // unsupported by OS
74}
75
76void wxNotebook::SetTabSize(const wxSize& WXUNUSED(sz))
77{
78 // unsupported by OS
79}
80
81void wxNotebook::SetPageSize(const wxSize& size)
82{
83 SetSize( CalcSizeFromPage( size ) );
84}
85
86wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage) const
87{
88 return DoGetSizeFromClientSize( sizePage );
89}
90
91int wxNotebook::DoSetSelection(size_t nPage, int flags)
92{
93 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("DoSetSelection: invalid notebook page") );
94
681be2ef 95 if ( m_selection == wxNOT_FOUND || nPage != (size_t)m_selection )
e53b3d16
SC
96 {
97 if ( flags & SetSelection_SendEvent )
98 {
99 if ( !SendPageChangingEvent(nPage) )
100 {
101 // vetoed by program
681be2ef 102 return m_selection;
e53b3d16
SC
103 }
104 //else: program allows the page change
105
681be2ef 106 SendPageChangedEvent(m_selection, nPage);
e53b3d16
SC
107 }
108
681be2ef 109 ChangePage(m_selection, nPage);
e53b3d16
SC
110 }
111 //else: no change
112
681be2ef 113 return m_selection;
e53b3d16
SC
114}
115
116bool wxNotebook::SetPageText(size_t nPage, const wxString& strText)
117{
118 wxCHECK_MSG( IS_VALID_PAGE(nPage), false, wxT("SetPageText: invalid notebook page") );
119
120 wxNotebookPage *page = m_pages[nPage];
121 page->SetLabel(wxStripMenuCodes(strText));
122 MacSetupTabs();
123
124 return true;
125}
126
127wxString wxNotebook::GetPageText(size_t nPage) const
128{
129 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxEmptyString, wxT("GetPageText: invalid notebook page") );
130
131 wxNotebookPage *page = m_pages[nPage];
132
133 return page->GetLabel();
134}
135
136int wxNotebook::GetPageImage(size_t nPage) const
137{
138 wxCHECK_MSG( IS_VALID_PAGE(nPage), wxNOT_FOUND, wxT("GetPageImage: invalid notebook page") );
139
140 return m_images[nPage];
141}
142
143bool wxNotebook::SetPageImage(size_t nPage, int nImage)
144{
145 wxCHECK_MSG( IS_VALID_PAGE(nPage), false,
146 wxT("SetPageImage: invalid notebook page") );
abfdefed 147 wxCHECK_MSG( HasImageList() && nImage < GetImageList()->GetImageCount(), false,
e53b3d16
SC
148 wxT("SetPageImage: invalid image index") );
149
150 if ( nImage != m_images[nPage] )
151 {
152 // if the item didn't have an icon before or, on the contrary, did have
153 // it but has lost it now, its size will change - but if the icon just
154 // changes, it won't
155 m_images[nPage] = nImage;
156
157 MacSetupTabs() ;
158 }
159
160 return true;
161}
162
163// ----------------------------------------------------------------------------
164// wxNotebook operations
165// ----------------------------------------------------------------------------
166
167// remove one page from the notebook, without deleting the window
168wxNotebookPage* wxNotebook::DoRemovePage(size_t nPage)
169{
170 wxCHECK_MSG( IS_VALID_PAGE(nPage), NULL,
171 wxT("DoRemovePage: invalid notebook page") );
172
173 wxNotebookPage* page = m_pages[nPage] ;
174 m_pages.RemoveAt(nPage);
f2d8a276 175 m_images.RemoveAt(nPage);
e53b3d16
SC
176
177 MacSetupTabs();
178
f197e652
SC
179 if ( m_selection >= (int)nPage )
180 {
181 if ( GetPageCount() == 0 )
182 m_selection = wxNOT_FOUND;
183 else
184 m_selection = m_selection ? m_selection - 1 : 0;
185
186 GetPeer()->SetValue( m_selection + 1 ) ;
187 }
e53b3d16 188
681be2ef
VZ
189 if (m_selection >= 0)
190 m_pages[m_selection]->Show(true);
e53b3d16
SC
191
192 InvalidateBestSize();
193
194 return page;
195}
196
197// remove all pages
198bool wxNotebook::DeleteAllPages()
199{
f2d8a276
SC
200 WX_CLEAR_ARRAY(m_pages);
201 m_images.clear();
e53b3d16 202 MacSetupTabs();
681be2ef 203 m_selection = wxNOT_FOUND ;
e53b3d16
SC
204 InvalidateBestSize();
205
206 return true;
207}
208
209// same as AddPage() but does it at given position
210bool wxNotebook::InsertPage(size_t nPage,
211 wxNotebookPage *pPage,
212 const wxString& strText,
213 bool bSelect,
214 int imageId )
215{
216 if ( !wxNotebookBase::InsertPage( nPage, pPage, strText, bSelect, imageId ) )
217 return false;
218
219 wxASSERT_MSG( pPage->GetParent() == this, wxT("notebook pages must have notebook as parent") );
220
221 // don't show pages by default (we'll need to adjust their size first)
222 pPage->Show( false ) ;
223
224 pPage->SetLabel( wxStripMenuCodes(strText) );
225
226 m_images.Insert( imageId, nPage );
227
228 MacSetupTabs();
229
230 wxRect rect = GetPageRect() ;
231 pPage->SetSize( rect );
232 if ( pPage->GetAutoLayout() )
233 pPage->Layout();
234
235 // now deal with the selection
236 // ---------------------------
237
238 // if the inserted page is before the selected one, we must update the
239 // index of the selected page
240
681be2ef 241 if ( int(nPage) <= m_selection )
e53b3d16 242 {
681be2ef 243 m_selection++;
e53b3d16
SC
244
245 // while this still is the same page showing, we need to update the tabs
22756322 246 GetPeer()->SetValue( m_selection + 1 ) ;
e53b3d16
SC
247 }
248
60d5c563 249 DoSetSelectionAfterInsertion(nPage, bSelect);
e53b3d16
SC
250
251 InvalidateBestSize();
252
253 return true;
254}
255
ddd7e430 256int wxNotebook::HitTest(const wxPoint& pt, long *flags) const
e53b3d16 257{
dfd0756f 258 return GetPeer()->TabHitTest(pt,flags);
e53b3d16
SC
259}
260
261// Added by Mark Newsam
262// When a page is added or deleted to the notebook this function updates
263// information held in the control so that it matches the order
264// the user would expect.
265//
266void wxNotebook::MacSetupTabs()
267{
22756322 268 GetPeer()->SetupTabs(*this);
e53b3d16
SC
269 Refresh();
270}
271
272wxRect wxNotebook::GetPageRect() const
273{
274 wxSize size = GetClientSize() ;
275
276 return wxRect( 0 , 0 , size.x , size.y ) ;
277}
278
279// ----------------------------------------------------------------------------
280// wxNotebook callbacks
281// ----------------------------------------------------------------------------
282
283// @@@ OnSize() is used for setting the font when it's called for the first
284// time because doing it in ::Create() doesn't work (for unknown reasons)
285void wxNotebook::OnSize(wxSizeEvent& event)
286{
287 unsigned int nCount = m_pages.Count();
288 wxRect rect = GetPageRect() ;
289
290 for ( unsigned int nPage = 0; nPage < nCount; nPage++ )
291 {
292 wxNotebookPage *pPage = m_pages[nPage];
ff94c563 293 pPage->SetSize(rect, wxSIZE_FORCE_EVENT);
e53b3d16
SC
294 }
295
43321b80 296#if 0 // deactivate r65078 for the moment
5bdeabaf
VZ
297 // If the selected page is hidden at this point, the notebook
298 // has become visible for the first time after creation, and
299 // we postponed showing the page in ChangePage().
300 // So show the selected page now.
681be2ef 301 if ( m_selection != wxNOT_FOUND )
5bdeabaf 302 {
681be2ef 303 wxNotebookPage *pPage = m_pages[m_selection];
5bdeabaf
VZ
304 if ( !pPage->IsShown() )
305 {
306 pPage->Show( true );
307 pPage->SetFocus();
308 }
309 }
43321b80 310#endif
5bdeabaf 311
e53b3d16
SC
312 // Processing continues to next OnSize
313 event.Skip();
314}
315
316void wxNotebook::OnSelChange(wxBookCtrlEvent& event)
317{
318 // is it our tab control?
319 if ( event.GetEventObject() == this )
320 ChangePage(event.GetOldSelection(), event.GetSelection());
321
322 // we want to give others a chance to process this message as well
323 event.Skip();
324}
325
326void wxNotebook::OnSetFocus(wxFocusEvent& event)
327{
328 // set focus to the currently selected page if any
681be2ef
VZ
329 if ( m_selection != wxNOT_FOUND )
330 m_pages[m_selection]->SetFocus();
e53b3d16
SC
331
332 event.Skip();
333}
334
335void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
336{
337 if ( event.IsWindowChange() )
338 {
339 // change pages
340 AdvanceSelection( event.GetDirection() );
341 }
342 else
343 {
344 // we get this event in 2 cases
345 //
346 // a) one of our pages might have generated it because the user TABbed
347 // out from it in which case we should propagate the event upwards and
348 // our parent will take care of setting the focus to prev/next sibling
349 //
350 // or
351 //
352 // b) the parent panel wants to give the focus to us so that we
353 // forward it to our selected page. We can't deal with this in
354 // OnSetFocus() because we don't know which direction the focus came
355 // from in this case and so can't choose between setting the focus to
356 // first or last panel child
357 wxWindow *parent = GetParent();
358
359 // the cast is here to fix a GCC ICE
360 if ( ((wxWindow*)event.GetEventObject()) == parent )
361 {
362 // no, it doesn't come from child, case (b): forward to a page
681be2ef 363 if ( m_selection != wxNOT_FOUND )
e53b3d16
SC
364 {
365 // so that the page knows that the event comes from it's parent
366 // and is being propagated downwards
367 event.SetEventObject( this );
368
681be2ef 369 wxWindow *page = m_pages[m_selection];
e53b3d16
SC
370 if ( !page->HandleWindowEvent( event ) )
371 {
372 page->SetFocus();
373 }
374 //else: page manages focus inside it itself
375 }
376 else
377 {
378 // we have no pages - still have to give focus to _something_
379 SetFocus();
380 }
381 }
382 else
383 {
384 // it comes from our child, case (a), pass to the parent
385 if ( parent )
386 {
387 event.SetCurrentFocus( this );
388 parent->HandleWindowEvent( event );
389 }
390 }
391 }
392}
393
394// ----------------------------------------------------------------------------
395// wxNotebook base class virtuals
396// ----------------------------------------------------------------------------
397
398#if wxUSE_CONSTRAINTS
399
400// override these 2 functions to do nothing: everything is done in OnSize
401
402void wxNotebook::SetConstraintSizes(bool WXUNUSED(recurse))
403{
404 // don't set the sizes of the pages - their correct size is not yet known
405 wxControl::SetConstraintSizes( false );
406}
407
408bool wxNotebook::DoPhase(int WXUNUSED(nPhase))
409{
410 return true;
411}
412
413#endif // wxUSE_CONSTRAINTS
414
415void wxNotebook::Command(wxCommandEvent& WXUNUSED(event))
416{
417 wxFAIL_MSG(wxT("wxNotebook::Command not implemented"));
418}
419
420// ----------------------------------------------------------------------------
421// wxNotebook helper functions
422// ----------------------------------------------------------------------------
423
424// hide the currently active panel and show the new one
425void wxNotebook::ChangePage(int nOldSel, int nSel)
426{
427 if (nOldSel == nSel)
428 return;
429
7e837615 430 if ( nOldSel != wxNOT_FOUND )
e53b3d16
SC
431 m_pages[nOldSel]->Show( false );
432
7e837615 433 if ( nSel != wxNOT_FOUND )
e53b3d16
SC
434 {
435 wxNotebookPage *pPage = m_pages[nSel];
43321b80 436#if 0 // deactivate r65078 for the moment
5bdeabaf
VZ
437 if ( IsShownOnScreen() )
438 {
439 pPage->Show( true );
440 pPage->SetFocus();
441 }
442 else
443 {
444 // Postpone Show() until the control is actually shown.
445 // Otherwise this forces the containing toplevel window
446 // to show, even if it's just being created and called
447 // AddPage() without intent to show the window yet.
448 // We Show() the selected page in our OnSize handler,
449 // unless it already is shown.
450 }
43321b80
SC
451#else
452 pPage->Show( true );
453 pPage->SetFocus();
454#endif
e53b3d16
SC
455 }
456
681be2ef 457 m_selection = nSel;
22756322 458 GetPeer()->SetValue( m_selection + 1 ) ;
e53b3d16
SC
459}
460
0faf03bf 461bool wxNotebook::OSXHandleClicked( double WXUNUSED(timestampsec) )
e53b3d16
SC
462{
463 bool status = false ;
464
22756322 465 SInt32 newSel = GetPeer()->GetValue() - 1 ;
681be2ef 466 if ( newSel != m_selection )
e53b3d16
SC
467 {
468 wxBookCtrlEvent changing(
ce7fe42e 469 wxEVT_NOTEBOOK_PAGE_CHANGING, m_windowId,
681be2ef 470 newSel , m_selection );
e53b3d16
SC
471 changing.SetEventObject( this );
472 HandleWindowEvent( changing );
473
474 if ( changing.IsAllowed() )
475 {
476 wxBookCtrlEvent event(
ce7fe42e 477 wxEVT_NOTEBOOK_PAGE_CHANGED, m_windowId,
681be2ef 478 newSel, m_selection );
e53b3d16
SC
479 event.SetEventObject( this );
480 HandleWindowEvent( event );
821073e3
VZ
481
482 m_selection = newSel;
e53b3d16
SC
483 }
484 else
485 {
22756322 486 GetPeer()->SetValue( m_selection + 1 ) ;
e53b3d16
SC
487 }
488
489 status = true ;
490 }
491
492 return status ;
493}
494
495#endif