]> git.saurik.com Git - wxWidgets.git/blob - src/mac/notebmac.cpp
removed WXK_SPACE as duplicating the selection event, added theme text drawing patch
[wxWidgets.git] / src / mac / notebmac.cpp
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
36 static 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
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
49 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
50
51 BEGIN_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)
58 END_EVENT_TABLE()
59
60 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
61 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
62 #endif
63
64 // ============================================================================
65 // implementation
66 // ============================================================================
67
68 // ----------------------------------------------------------------------------
69 // wxNotebook construction
70 // ----------------------------------------------------------------------------
71
72 // common part of all ctors
73 void 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
104 wxNotebook::wxNotebook()
105 {
106 Init();
107 }
108
109 // the same arguments as for wxControl
110 wxNotebook::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
123 bool 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
143 wxNotebook::~wxNotebook()
144 {
145 m_macControl = NULL ;
146 }
147
148 wxSize 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
187 void wxNotebook::SetPadding(const wxSize& padding)
188 {
189 wxFAIL_MSG( wxT("wxNotebook::SetPadding not implemented") );
190 }
191
192 void wxNotebook::SetTabSize(const wxSize& sz)
193 {
194 wxFAIL_MSG( wxT("wxNotebook::SetTabSize not implemented") );
195 }
196
197 void wxNotebook::SetPageSize(const wxSize& size)
198 {
199 wxFAIL_MSG( wxT("wxNotebook::SetPageSize not implemented") );
200 }
201
202 int 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
213 bool 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
224 wxString 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
232 int wxNotebook::GetPageImage(int nPage) const
233 {
234 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, _T("invalid notebook page") );
235
236 return 0 ;
237 }
238
239 bool 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
254 wxNotebookPage* 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
272 bool 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
284 bool 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 */
329 void 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)
363 void 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
390 void 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
400 void 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
409 void 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
430 void 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
436 bool wxNotebook::DoPhase(int /* nPhase */)
437 {
438 return TRUE;
439 }
440
441 void 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
451 void 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
477 void 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
543 void 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