]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/mac/notebmac.cpp
fixed (yet another?) crash in wxStrtok
[wxWidgets.git] / src / mac / notebmac.cpp
... / ...
CommitLineData
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__
20 #pragma implementation "notebook.h"
21#endif
22
23#include "wx/app.h"
24#include "wx/string.h"
25#include "wx/log.h"
26#include "wx/imaglist.h"
27#include "wx/notebook.h"
28#include "wx/mac/uma.h"
29// ----------------------------------------------------------------------------
30// macros
31// ----------------------------------------------------------------------------
32
33// check that the page index is valid
34#define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
35
36static bool constantsSet = false ;
37
38 short kwxMacTabLeftMargin = 0 ;
39 short kwxMacTabTopMargin = 0 ;
40 short kwxMacTabRightMargin = 0 ;
41 short kwxMacTabBottomMargin = 0 ;
42
43// ----------------------------------------------------------------------------
44// event table
45// ----------------------------------------------------------------------------
46
47#if !USE_SHARED_LIBRARIES
48DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
49DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
50
51BEGIN_EVENT_TABLE(wxNotebook, wxControl)
52 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
53 EVT_MOUSE_EVENTS(wxNotebook::OnMouse)
54
55 EVT_SIZE(wxNotebook::OnSize)
56 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
57 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
58END_EVENT_TABLE()
59
60IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
61IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
62#endif
63
64// ============================================================================
65// implementation
66// ============================================================================
67
68// ----------------------------------------------------------------------------
69// wxNotebook construction
70// ----------------------------------------------------------------------------
71
72// common part of all ctors
73void wxNotebook::Init()
74{
75 if ( !constantsSet )
76 {
77 if ( UMAHasAquaLayout() )
78 {
79 // I got these values for Mac OS X from the Appearance mgr docs. (Mark Newsam)
80 kwxMacTabLeftMargin = 20 ;
81 kwxMacTabTopMargin = 38 ;
82 kwxMacTabRightMargin = 20 ;
83 kwxMacTabBottomMargin = 12 ;
84 }
85 else
86 {
87 kwxMacTabLeftMargin = 16 ;
88 kwxMacTabTopMargin = 30 ;
89 kwxMacTabRightMargin = 16 ;
90 kwxMacTabBottomMargin = 16 ;
91 }
92 constantsSet = true ;
93 }
94 if ( UMAHasAquaLayout() )
95 {
96 m_macHorizontalBorder = 7;
97 m_macVerticalBorder = 8;
98 }
99
100 m_nSelection = -1;
101}
102
103// default for dynamic class
104wxNotebook::wxNotebook()
105{
106 Init();
107}
108
109// the same arguments as for wxControl
110wxNotebook::wxNotebook(wxWindow *parent,
111 wxWindowID id,
112 const wxPoint& pos,
113 const wxSize& size,
114 long style,
115 const wxString& name)
116{
117 Init();
118
119 Create(parent, id, pos, size, style, name);
120}
121
122// Create() function
123bool wxNotebook::Create(wxWindow *parent,
124 wxWindowID id,
125 const wxPoint& pos,
126 const wxSize& size,
127 long style,
128 const wxString& name)
129{
130 Rect bounds ;
131 Str255 title ;
132
133 MacPreControlCreate( parent , id , "" , pos , size ,style, wxDefaultValidator , name , &bounds , title ) ;
134
135 m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , 1,
136 kControlTabSmallProc , (long) this ) ;
137
138 MacPostControlCreate() ;
139 return TRUE ;
140}
141
142// dtor
143wxNotebook::~wxNotebook()
144{
145 m_macControl = NULL ;
146}
147
148wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage)
149{
150 wxSize sizeTotal = sizePage;
151
152 int major,minor;
153 wxGetOsVersion( &major, &minor );
154
155 // Mac has large notebook borders. Aqua even more so.
156
157 if ( HasFlag(wxNB_LEFT) || HasFlag(wxNB_RIGHT) )
158 {
159 sizeTotal.x += 90;
160
161 if (major >= 10)
162 sizeTotal.y += 28;
163 else
164 sizeTotal.y += 20;
165 }
166 else
167 {
168 if (major >= 10)
169 {
170 sizeTotal.x += 34;
171 sizeTotal.y += 46;
172 }
173 else
174 {
175 sizeTotal.x += 22;
176 sizeTotal.y += 44;
177 }
178 }
179
180 return sizeTotal;
181}
182
183// ----------------------------------------------------------------------------
184// wxNotebook accessors
185// ----------------------------------------------------------------------------
186
187void wxNotebook::SetPadding(const wxSize& padding)
188{
189 wxFAIL_MSG( wxT("wxNotebook::SetPadding not implemented") );
190}
191
192void wxNotebook::SetTabSize(const wxSize& sz)
193{
194 wxFAIL_MSG( wxT("wxNotebook::SetTabSize not implemented") );
195}
196
197void wxNotebook::SetPageSize(const wxSize& size)
198{
199 wxFAIL_MSG( wxT("wxNotebook::SetPageSize not implemented") );
200}
201
202int wxNotebook::SetSelection(int nPage)
203{
204 if( !IS_VALID_PAGE(nPage) )
205 return m_nSelection ;
206
207 ChangePage(m_nSelection, nPage);
208 SetControl32BitValue( (ControlHandle) m_macControl , m_nSelection + 1 ) ;
209
210 return m_nSelection;
211}
212
213bool wxNotebook::SetPageText(int nPage, const wxString& strText)
214{
215 wxASSERT( IS_VALID_PAGE(nPage) );
216
217 wxNotebookPage *page = m_pages[nPage];
218 page->SetLabel(strText);
219 MacSetupTabs();
220
221 return true;
222}
223
224wxString wxNotebook::GetPageText(int nPage) const
225{
226 wxASSERT( IS_VALID_PAGE(nPage) );
227
228 wxNotebookPage *page = m_pages[nPage];
229 return page->GetLabel();
230}
231
232int wxNotebook::GetPageImage(int nPage) const
233{
234 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, _T("invalid notebook page") );
235
236 return 0 ;
237}
238
239bool wxNotebook::SetPageImage(int nPage, int nImage)
240{
241 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, _T("invalid notebook page") );
242
243 wxCHECK_MSG( m_imageList && nImage < m_imageList->GetImageCount(), FALSE,
244 _T("invalid image index in SetPageImage()") );
245
246 return FALSE;
247}
248
249// ----------------------------------------------------------------------------
250// wxNotebook operations
251// ----------------------------------------------------------------------------
252
253// remove one page from the notebook, without deleting the window
254wxNotebookPage* wxNotebook::DoRemovePage(int nPage)
255{
256 wxCHECK( IS_VALID_PAGE(nPage), NULL );
257 wxNotebookPage* page = m_pages[nPage] ;
258 m_pages.RemoveAt(nPage);
259
260 MacSetupTabs();
261
262 if(m_nSelection >= GetPageCount()) {
263 m_nSelection = GetPageCount() - 1;
264 }
265 if(m_nSelection >= 0) {
266 m_pages[m_nSelection]->Show(true);
267 }
268 return page;
269}
270
271// remove all pages
272bool wxNotebook::DeleteAllPages()
273{
274 // TODO: delete native widget pages
275
276 WX_CLEAR_ARRAY(m_pages) ;
277 MacSetupTabs();
278
279 return TRUE;
280}
281
282
283// same as AddPage() but does it at given position
284bool wxNotebook::InsertPage(int nPage,
285 wxNotebookPage *pPage,
286 const wxString& strText,
287 bool bSelect,
288 int imageId)
289{
290 wxASSERT( pPage != NULL );
291 wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE );
292
293 pPage->SetLabel(strText);
294
295 // save the pointer to the page
296 m_pages.Insert(pPage, nPage);
297
298 MacSetupTabs();
299
300 if ( bSelect ) {
301 m_nSelection = nPage;
302 }
303 else if ( m_nSelection == -1 ) {
304 m_nSelection = 0;
305 }
306 else if (m_nSelection >= nPage) {
307 m_nSelection++;
308 }
309 // don't show pages by default (we'll need to adjust their size first)
310 pPage->Show( false ) ;
311
312 int h, w;
313 GetSize(&w, &h);
314 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
315 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
316 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
317 if ( pPage->GetAutoLayout() ) {
318 pPage->Layout();
319 }
320
321 return true;
322}
323
324/* Added by Mark Newsam
325 * When a page is added or deleted to the notebook this function updates
326 * information held in the m_macControl so that it matches the order
327 * the user would expect.
328 */
329void wxNotebook::MacSetupTabs()
330{
331 SetControl32BitMaximum( (ControlHandle) m_macControl , GetPageCount() ) ;
332
333 wxNotebookPage *page;
334 ControlTabInfoRec info;
335 Boolean enabled = true;
336 for(int ii = 0; ii < GetPageCount(); ii++)
337 {
338 page = m_pages[ii];
339 info.version = 0;
340 info.iconSuiteID = 0;
341#if TARGET_CARBON
342 c2pstrcpy( (StringPtr) info.name , page->GetLabel() ) ;
343#else
344 strcpy( (char *) info.name , page->GetLabel() ) ;
345 c2pstr( (char *) info.name ) ;
346#endif
347 SetControlData( (ControlHandle) m_macControl, ii+1, kControlTabInfoTag,
348 sizeof( ControlTabInfoRec) , (char*) &info ) ;
349 SetControlData( (ControlHandle) m_macControl, ii+1, kControlTabEnabledFlagTag,
350 sizeof( Boolean ), (Ptr)&enabled );
351 }
352 Rect bounds;
353 GetControlBounds((ControlHandle)m_macControl, &bounds);
354 InvalWindowRect((WindowRef)MacGetRootWindow(), &bounds);
355}
356
357// ----------------------------------------------------------------------------
358// wxNotebook callbacks
359// ----------------------------------------------------------------------------
360
361// @@@ OnSize() is used for setting the font when it's called for the first
362// time because doing it in ::Create() doesn't work (for unknown reasons)
363void wxNotebook::OnSize(wxSizeEvent& event)
364{
365 // emulate page change (it's esp. important to do it first time because
366 // otherwise our page would stay invisible)
367 int nSel = m_nSelection;
368 m_nSelection = -1;
369 SetSelection(nSel);
370
371 // fit the notebook page to the tab control's display area
372 int w, h;
373 GetSize(&w, &h);
374
375 unsigned int nCount = m_pages.Count();
376 for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) {
377 wxNotebookPage *pPage = m_pages[nPage];
378 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
379 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
380 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
381 if ( pPage->GetAutoLayout() ) {
382 pPage->Layout();
383 }
384 }
385
386 // Processing continues to next OnSize
387 event.Skip();
388}
389
390void wxNotebook::OnSelChange(wxNotebookEvent& event)
391{
392 // is it our tab control?
393 if ( event.GetEventObject() == this )
394 ChangePage(event.GetOldSelection(), event.GetSelection());
395
396 // we want to give others a chance to process this message as well
397 event.Skip();
398}
399
400void wxNotebook::OnSetFocus(wxFocusEvent& event)
401{
402 // set focus to the currently selected page if any
403 if ( m_nSelection != -1 )
404 m_pages[m_nSelection]->SetFocus();
405
406 event.Skip();
407}
408
409void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
410{
411 if ( event.IsWindowChange() ) {
412 // change pages
413 AdvanceSelection(event.GetDirection());
414 }
415 else {
416 // pass to the parent
417 if ( GetParent() ) {
418 event.SetCurrentFocus(this);
419 GetParent()->ProcessEvent(event);
420 }
421 }
422}
423
424// ----------------------------------------------------------------------------
425// wxNotebook base class virtuals
426// ----------------------------------------------------------------------------
427
428// override these 2 functions to do nothing: everything is done in OnSize
429
430void wxNotebook::SetConstraintSizes(bool /* recurse */)
431{
432 // don't set the sizes of the pages - their correct size is not yet known
433 wxControl::SetConstraintSizes(FALSE);
434}
435
436bool wxNotebook::DoPhase(int /* nPhase */)
437{
438 return TRUE;
439}
440
441void wxNotebook::Command(wxCommandEvent& event)
442{
443 wxFAIL_MSG("wxNotebook::Command not implemented");
444}
445
446// ----------------------------------------------------------------------------
447// wxNotebook helper functions
448// ----------------------------------------------------------------------------
449
450// hide the currently active panel and show the new one
451void wxNotebook::ChangePage(int nOldSel, int nSel)
452{
453 // it's not an error (the message may be generated by the tab control itself)
454 // and it may happen - just do nothing
455 if ( nSel == nOldSel )
456 {
457 wxNotebookPage *pPage = m_pages[nSel];
458 pPage->Show(FALSE);
459 pPage->Show(TRUE);
460 pPage->SetFocus();
461 return;
462 }
463
464 // Hide previous page
465 if ( nOldSel != -1 ) {
466 m_pages[nOldSel]->Show(FALSE);
467 }
468
469 wxNotebookPage *pPage = m_pages[nSel];
470 pPage->Show(TRUE);
471 pPage->SetFocus();
472
473 m_nSelection = nSel;
474}
475
476
477void wxNotebook::OnMouse( wxMouseEvent &event )
478{
479 if ( (ControlHandle) m_macControl == NULL )
480 {
481 event.Skip() ;
482 return ;
483 }
484
485 if (event.GetEventType() == wxEVT_LEFT_DOWN || event.GetEventType() == wxEVT_LEFT_DCLICK )
486 {
487 int x = event.m_x ;
488 int y = event.m_y ;
489
490 MacClientToRootWindow( &x , &y ) ;
491
492 ControlHandle control ;
493 Point localwhere ;
494 SInt16 controlpart ;
495
496 localwhere.h = x ;
497 localwhere.v = y ;
498
499 short modifiers = 0;
500
501 if ( !event.m_leftDown && !event.m_rightDown )
502 modifiers |= btnState ;
503
504 if ( event.m_shiftDown )
505 modifiers |= shiftKey ;
506
507 if ( event.m_controlDown )
508 modifiers |= controlKey ;
509
510 if ( event.m_altDown )
511 modifiers |= optionKey ;
512
513 if ( event.m_metaDown )
514 modifiers |= cmdKey ;
515
516 control = (ControlHandle) m_macControl ;
517 if ( control && ::IsControlActive( control ) )
518 {
519 {
520 wxNotebookEvent changing(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING, m_windowId,
521 ::GetControl32BitValue(control) - 1, m_nSelection);
522 changing.SetEventObject(this);
523 ProcessEvent(changing);
524
525 if(changing.IsAllowed())
526 {
527 controlpart = ::HandleControlClick(control, localwhere, modifiers,
528 (ControlActionUPP) -1);
529 wxTheApp->s_lastMouseDown = 0 ;
530
531 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId,
532 ::GetControl32BitValue(control) - 1, m_nSelection);
533 event.SetEventObject(this);
534
535 ProcessEvent(event);
536 }
537 }
538 }
539 }
540}
541
542
543void wxNotebook::MacHandleControlClick( WXWidget control , wxInt16 controlpart )
544{
545#if 0
546 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId , ::GetControl32BitValue((ControlHandle)m_macControl) - 1, m_nSelection);
547 event.SetEventObject(this);
548
549 ProcessEvent(event);
550#endif
551}
552