]> git.saurik.com Git - wxWidgets.git/blame - src/mac/notebmac.cpp
don't crash in UnselectAll() if the tree has no root
[wxWidgets.git] / src / mac / notebmac.cpp
CommitLineData
ee6b1d97
SC
1///////////////////////////////////////////////////////////////////////////////
2// Name: notebook.cpp
3// Purpose: implementation of wxNotebook
4// Author: AUTHOR
5// Modified by:
6// Created: ??/??/98
7// RCS-ID: $Id$
8// Copyright: (c) AUTHOR
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19#ifdef __GNUG__
3ef585df 20 #pragma implementation "notebook.h"
ee6b1d97
SC
21#endif
22
d497dca4
GD
23#include "wx/string.h"
24#include "wx/log.h"
25#include "wx/imaglist.h"
26#include "wx/notebook.h"
27#include "wx/mac/uma.h"
ee6b1d97
SC
28// ----------------------------------------------------------------------------
29// macros
30// ----------------------------------------------------------------------------
31
32// check that the page index is valid
33#define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
34
dd47b3d3
SC
35static bool constantsSet = false ;
36
37 short kwxMacTabLeftMargin = 0 ;
38 short kwxMacTabTopMargin = 0 ;
39 short kwxMacTabRightMargin = 0 ;
40 short kwxMacTabBottomMargin = 0 ;
ee6b1d97
SC
41
42// ----------------------------------------------------------------------------
43// event table
44// ----------------------------------------------------------------------------
45
46#if !USE_SHARED_LIBRARIES
5b781a67
SC
47DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
48DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
49
ee6b1d97
SC
50BEGIN_EVENT_TABLE(wxNotebook, wxControl)
51 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
52
53 EVT_SIZE(wxNotebook::OnSize)
54 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
55 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
56END_EVENT_TABLE()
57
58IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
59IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
60#endif
61
62// ============================================================================
63// implementation
64// ============================================================================
65
66// ----------------------------------------------------------------------------
67// wxNotebook construction
68// ----------------------------------------------------------------------------
69
70// common part of all ctors
71void wxNotebook::Init()
72{
dd47b3d3
SC
73 if ( !constantsSet )
74 {
75 if ( UMAHasAquaLayout() )
76 {
77 // I got these values for Mac OS X from the Appearance mgr docs. (Mark Newsam)
78 kwxMacTabLeftMargin = 20 ;
79 kwxMacTabTopMargin = 38 ;
80 kwxMacTabRightMargin = 20 ;
81 kwxMacTabBottomMargin = 12 ;
82 }
83 else
84 {
85 kwxMacTabLeftMargin = 16 ;
86 kwxMacTabTopMargin = 30 ;
87 kwxMacTabRightMargin = 16 ;
88 kwxMacTabBottomMargin = 16 ;
89 }
90 constantsSet = true ;
91 }
92 if ( UMAHasAquaLayout() )
93 {
94 m_macHorizontalBorder = 7;
95 m_macVerticalBorder = 8;
96 }
97
ee6b1d97
SC
98 m_nSelection = -1;
99}
100
101// default for dynamic class
102wxNotebook::wxNotebook()
103{
104 Init();
105}
106
107// the same arguments as for wxControl
108wxNotebook::wxNotebook(wxWindow *parent,
109 wxWindowID id,
110 const wxPoint& pos,
111 const wxSize& size,
112 long style,
113 const wxString& name)
114{
115 Init();
116
117 Create(parent, id, pos, size, style, name);
118}
119
120// Create() function
121bool wxNotebook::Create(wxWindow *parent,
122 wxWindowID id,
123 const wxPoint& pos,
124 const wxSize& size,
125 long style,
126 const wxString& name)
127{
128 Rect bounds ;
129 Str255 title ;
130
131 MacPreControlCreate( parent , id , "" , pos , size ,style, wxDefaultValidator , name , &bounds , title ) ;
132
41c9a21f 133 m_macControl = ::NewControl( parent->MacGetRootWindow() , &bounds , title , false , 0 , 0 , 1,
ee6b1d97
SC
134 kControlTabSmallProc , (long) this ) ;
135
136 MacPostControlCreate() ;
137 return TRUE ;
138}
139
140// dtor
141wxNotebook::~wxNotebook()
142{
143 m_macControl = NULL ;
144}
145
146// ----------------------------------------------------------------------------
147// wxNotebook accessors
148// ----------------------------------------------------------------------------
90b959ae
SC
149
150void wxNotebook::SetPadding(const wxSize& padding)
151{
fc0daf84 152 wxFAIL_MSG( wxT("wxNotebook::SetPadding not implemented") );
90b959ae
SC
153}
154
155void wxNotebook::SetTabSize(const wxSize& sz)
ee6b1d97 156{
fc0daf84 157 wxFAIL_MSG( wxT("wxNotebook::SetTabSize not implemented") );
ee6b1d97
SC
158}
159
90b959ae 160void wxNotebook::SetPageSize(const wxSize& size)
ee6b1d97 161{
fc0daf84 162 wxFAIL_MSG( wxT("wxNotebook::SetPageSize not implemented") );
ee6b1d97
SC
163}
164
165int wxNotebook::SetSelection(int nPage)
166{
9453cf2b
SC
167 if( !IS_VALID_PAGE(nPage) )
168 return m_nSelection ;
ee6b1d97
SC
169
170 ChangePage(m_nSelection, nPage);
c854c7d9
GD
171 SetControlValue( m_macControl , m_nSelection + 1 ) ;
172
ee6b1d97
SC
173 return m_nSelection;
174}
175
ee6b1d97
SC
176bool wxNotebook::SetPageText(int nPage, const wxString& strText)
177{
178 wxASSERT( IS_VALID_PAGE(nPage) );
179
90b959ae 180 wxNotebookPage *page = m_pages[nPage];
c854c7d9
GD
181 page->SetLabel(strText);
182 MacSetupTabs();
183
184 return true;
ee6b1d97
SC
185}
186
187wxString wxNotebook::GetPageText(int nPage) const
188{
189 wxASSERT( IS_VALID_PAGE(nPage) );
190
90b959ae 191 wxNotebookPage *page = m_pages[nPage];
c854c7d9 192 return page->GetLabel();
ee6b1d97
SC
193}
194
195int wxNotebook::GetPageImage(int nPage) const
196{
fc0daf84 197 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, _T("invalid notebook page") );
ee6b1d97 198
fc0daf84 199 return 0 ;
ee6b1d97
SC
200}
201
202bool wxNotebook::SetPageImage(int nPage, int nImage)
203{
fc0daf84
SC
204 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, _T("invalid notebook page") );
205
206 wxCHECK_MSG( m_imageList && nImage < m_imageList->GetImageCount(), FALSE,
207 _T("invalid image index in SetPageImage()") );
ee6b1d97 208
ee6b1d97
SC
209 return FALSE;
210}
211
ee6b1d97
SC
212// ----------------------------------------------------------------------------
213// wxNotebook operations
214// ----------------------------------------------------------------------------
215
90b959ae
SC
216// remove one page from the notebook, without deleting the window
217wxNotebookPage* wxNotebook::DoRemovePage(int nPage)
ee6b1d97 218{
90b959ae
SC
219 wxCHECK( IS_VALID_PAGE(nPage), NULL );
220 wxNotebookPage* page = m_pages[nPage] ;
3ef585df 221 m_pages.RemoveAt(nPage);
ee6b1d97 222
c854c7d9
GD
223 MacSetupTabs();
224
225 if(m_nSelection >= GetPageCount()) {
226 m_nSelection = GetPageCount() - 1;
227 }
228 if(m_nSelection >= 0) {
90b959ae 229 m_pages[m_nSelection]->Show(true);
c854c7d9 230 }
90b959ae 231 return page;
ee6b1d97
SC
232}
233
234// remove all pages
235bool wxNotebook::DeleteAllPages()
236{
237 // TODO: delete native widget pages
238
90b959ae 239 WX_CLEAR_ARRAY(m_pages) ;
c854c7d9
GD
240 MacSetupTabs();
241
ee6b1d97
SC
242 return TRUE;
243}
244
ee6b1d97
SC
245
246// same as AddPage() but does it at given position
247bool wxNotebook::InsertPage(int nPage,
248 wxNotebookPage *pPage,
249 const wxString& strText,
250 bool bSelect,
251 int imageId)
252{
253 wxASSERT( pPage != NULL );
254 wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE );
255
c854c7d9 256 pPage->SetLabel(strText);
ee6b1d97
SC
257
258 // save the pointer to the page
90b959ae 259 m_pages.Insert(pPage, nPage);
ee6b1d97 260
c854c7d9
GD
261 MacSetupTabs();
262
263 if ( bSelect ) {
ee6b1d97 264 m_nSelection = nPage;
c854c7d9
GD
265 }
266 else if ( m_nSelection == -1 ) {
ee6b1d97 267 m_nSelection = 0;
c854c7d9
GD
268 }
269 else if (m_nSelection >= nPage) {
270 m_nSelection++;
271 }
272 // don't show pages by default (we'll need to adjust their size first)
273 pPage->Show( false ) ;
ee6b1d97 274
c854c7d9
GD
275 int h, w;
276 GetSize(&w, &h);
277 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
278 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
279 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
280 if ( pPage->GetAutoLayout() ) {
281 pPage->Layout();
282 }
ee6b1d97 283
c854c7d9
GD
284 return true;
285}
286
287/* Added by Mark Newsam
288 * When a page is added or deleted to the notebook this function updates
289 * information held in the m_macControl so that it matches the order
290 * the user would expect.
291 */
292void wxNotebook::MacSetupTabs()
293{
294 SetControlMaximum( m_macControl , GetPageCount() ) ;
295
296 wxNotebookPage *page;
297 ControlTabInfoRec info;
298 Boolean enabled = true;
299 for(int ii = 0; ii < GetPageCount(); ii++)
300 {
90b959ae 301 page = m_pages[ii];
c854c7d9
GD
302 info.version = 0;
303 info.iconSuiteID = 0;
304#if TARGET_CARBON
305 c2pstrcpy( (StringPtr) info.name , page->GetLabel() ) ;
306#else
307 strcpy( (char *) info.name , page->GetLabel() ) ;
308 c2pstr( (char *) info.name ) ;
309#endif
310 SetControlData( m_macControl, ii+1, kControlTabInfoTag,
311 sizeof( ControlTabInfoRec) , (char*) &info ) ;
312 SetControlData( m_macControl, ii+1, kControlTabEnabledFlagTag,
313 sizeof( Boolean ), (Ptr)&enabled );
314 }
315 Rect bounds;
316 GetControlBounds(m_macControl, &bounds);
41c9a21f 317 InvalWindowRect(MacGetRootWindow(), &bounds);
ee6b1d97
SC
318}
319
320// ----------------------------------------------------------------------------
321// wxNotebook callbacks
322// ----------------------------------------------------------------------------
323
324// @@@ OnSize() is used for setting the font when it's called for the first
325// time because doing it in ::Create() doesn't work (for unknown reasons)
326void wxNotebook::OnSize(wxSizeEvent& event)
327{
ee6b1d97
SC
328 // emulate page change (it's esp. important to do it first time because
329 // otherwise our page would stay invisible)
330 int nSel = m_nSelection;
331 m_nSelection = -1;
332 SetSelection(nSel);
333
334 // fit the notebook page to the tab control's display area
335 int w, h;
336 GetSize(&w, &h);
337
90b959ae 338 unsigned int nCount = m_pages.Count();
ee6b1d97 339 for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) {
90b959ae 340 wxNotebookPage *pPage = m_pages[nPage];
c854c7d9
GD
341 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
342 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
343 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
344 if ( pPage->GetAutoLayout() ) {
ee6b1d97 345 pPage->Layout();
c854c7d9 346 }
ee6b1d97
SC
347 }
348
349 // Processing continues to next OnSize
350 event.Skip();
351}
352
353void wxNotebook::OnSelChange(wxNotebookEvent& event)
354{
355 // is it our tab control?
356 if ( event.GetEventObject() == this )
357 ChangePage(event.GetOldSelection(), event.GetSelection());
358
359 // we want to give others a chance to process this message as well
360 event.Skip();
361}
362
363void wxNotebook::OnSetFocus(wxFocusEvent& event)
364{
365 // set focus to the currently selected page if any
366 if ( m_nSelection != -1 )
90b959ae 367 m_pages[m_nSelection]->SetFocus();
ee6b1d97
SC
368
369 event.Skip();
370}
371
372void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
373{
374 if ( event.IsWindowChange() ) {
375 // change pages
376 AdvanceSelection(event.GetDirection());
377 }
378 else {
379 // pass to the parent
380 if ( GetParent() ) {
381 event.SetCurrentFocus(this);
382 GetParent()->ProcessEvent(event);
383 }
384 }
385}
386
387// ----------------------------------------------------------------------------
388// wxNotebook base class virtuals
389// ----------------------------------------------------------------------------
390
391// override these 2 functions to do nothing: everything is done in OnSize
392
393void wxNotebook::SetConstraintSizes(bool /* recurse */)
394{
395 // don't set the sizes of the pages - their correct size is not yet known
396 wxControl::SetConstraintSizes(FALSE);
397}
398
399bool wxNotebook::DoPhase(int /* nPhase */)
400{
401 return TRUE;
402}
403
404void wxNotebook::Command(wxCommandEvent& event)
405{
406 wxFAIL_MSG("wxNotebook::Command not implemented");
407}
408
409// ----------------------------------------------------------------------------
410// wxNotebook helper functions
411// ----------------------------------------------------------------------------
412
413// hide the currently active panel and show the new one
414void wxNotebook::ChangePage(int nOldSel, int nSel)
415{
c854c7d9
GD
416 // it's not an error (the message may be generated by the tab control itself)
417 // and it may happen - just do nothing
418 if ( nSel == nOldSel )
419 {
90b959ae 420 wxNotebookPage *pPage = m_pages[nSel];
c854c7d9
GD
421 pPage->Show(FALSE);
422 pPage->Show(TRUE);
423 pPage->SetFocus();
424 return;
425 }
ee6b1d97 426
c854c7d9 427 // Hide previous page
ee6b1d97 428 if ( nOldSel != -1 ) {
90b959ae 429 m_pages[nOldSel]->Show(FALSE);
ee6b1d97
SC
430 }
431
90b959ae 432 wxNotebookPage *pPage = m_pages[nSel];
ee6b1d97
SC
433 pPage->Show(TRUE);
434 pPage->SetFocus();
435
436 m_nSelection = nSel;
437}
438
439void wxNotebook::MacHandleControlClick( ControlHandle control , SInt16 controlpart )
440{
441 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId , ::GetControlValue(m_macControl) - 1, m_nSelection);
442 event.SetEventObject(this);
443
444 ProcessEvent(event);
445}
446