]> git.saurik.com Git - wxWidgets.git/blob - src/mac/notebmac.cpp
wxDC::DoDrawRectangle hack is no longer needed
[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/string.h"
24 #include "wx/log.h"
25 #include "wx/imaglist.h"
26 #include "wx/notebook.h"
27 #include "wx/mac/uma.h"
28 // ----------------------------------------------------------------------------
29 // macros
30 // ----------------------------------------------------------------------------
31
32 // check that the page index is valid
33 #define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
34
35 static bool constantsSet = false ;
36
37 short kwxMacTabLeftMargin = 0 ;
38 short kwxMacTabTopMargin = 0 ;
39 short kwxMacTabRightMargin = 0 ;
40 short kwxMacTabBottomMargin = 0 ;
41
42 // ----------------------------------------------------------------------------
43 // event table
44 // ----------------------------------------------------------------------------
45
46 #if !USE_SHARED_LIBRARIES
47 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED)
48 DEFINE_EVENT_TYPE(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGING)
49
50 BEGIN_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)
56 END_EVENT_TABLE()
57
58 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
59 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
60 #endif
61
62 // ============================================================================
63 // implementation
64 // ============================================================================
65
66 // ----------------------------------------------------------------------------
67 // wxNotebook construction
68 // ----------------------------------------------------------------------------
69
70 // common part of all ctors
71 void wxNotebook::Init()
72 {
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
98 m_nSelection = -1;
99 }
100
101 // default for dynamic class
102 wxNotebook::wxNotebook()
103 {
104 Init();
105 }
106
107 // the same arguments as for wxControl
108 wxNotebook::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
121 bool 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
133 m_macControl = ::NewControl( MAC_WXHWND(parent->MacGetRootWindow()) , &bounds , title , false , 0 , 0 , 1,
134 kControlTabSmallProc , (long) this ) ;
135
136 MacPostControlCreate() ;
137 return TRUE ;
138 }
139
140 // dtor
141 wxNotebook::~wxNotebook()
142 {
143 m_macControl = NULL ;
144 }
145
146 wxSize wxNotebook::CalcSizeFromPage(const wxSize& sizePage)
147 {
148 wxSize sizeTotal = sizePage;
149
150 int major,minor;
151 wxGetOsVersion( &major, &minor );
152
153 // Mac has large notebook borders. Aqua even more so.
154
155 if ( HasFlag(wxNB_LEFT) || HasFlag(wxNB_RIGHT) )
156 {
157 sizeTotal.x += 90;
158
159 if (major >= 10)
160 sizeTotal.y += 28;
161 else
162 sizeTotal.y += 20;
163 }
164 else
165 {
166 if (major >= 10)
167 {
168 sizeTotal.x += 34;
169 sizeTotal.y += 46;
170 }
171 else
172 {
173 sizeTotal.x += 22;
174 sizeTotal.y += 44;
175 }
176 }
177
178 return sizeTotal;
179 }
180
181 // ----------------------------------------------------------------------------
182 // wxNotebook accessors
183 // ----------------------------------------------------------------------------
184
185 void wxNotebook::SetPadding(const wxSize& padding)
186 {
187 wxFAIL_MSG( wxT("wxNotebook::SetPadding not implemented") );
188 }
189
190 void wxNotebook::SetTabSize(const wxSize& sz)
191 {
192 wxFAIL_MSG( wxT("wxNotebook::SetTabSize not implemented") );
193 }
194
195 void wxNotebook::SetPageSize(const wxSize& size)
196 {
197 wxFAIL_MSG( wxT("wxNotebook::SetPageSize not implemented") );
198 }
199
200 int wxNotebook::SetSelection(int nPage)
201 {
202 if( !IS_VALID_PAGE(nPage) )
203 return m_nSelection ;
204
205 ChangePage(m_nSelection, nPage);
206 SetControlValue( (ControlHandle) m_macControl , m_nSelection + 1 ) ;
207
208 return m_nSelection;
209 }
210
211 bool wxNotebook::SetPageText(int nPage, const wxString& strText)
212 {
213 wxASSERT( IS_VALID_PAGE(nPage) );
214
215 wxNotebookPage *page = m_pages[nPage];
216 page->SetLabel(strText);
217 MacSetupTabs();
218
219 return true;
220 }
221
222 wxString wxNotebook::GetPageText(int nPage) const
223 {
224 wxASSERT( IS_VALID_PAGE(nPage) );
225
226 wxNotebookPage *page = m_pages[nPage];
227 return page->GetLabel();
228 }
229
230 int wxNotebook::GetPageImage(int nPage) const
231 {
232 wxCHECK_MSG( IS_VALID_PAGE(nPage), -1, _T("invalid notebook page") );
233
234 return 0 ;
235 }
236
237 bool wxNotebook::SetPageImage(int nPage, int nImage)
238 {
239 wxCHECK_MSG( IS_VALID_PAGE(nPage), FALSE, _T("invalid notebook page") );
240
241 wxCHECK_MSG( m_imageList && nImage < m_imageList->GetImageCount(), FALSE,
242 _T("invalid image index in SetPageImage()") );
243
244 return FALSE;
245 }
246
247 // ----------------------------------------------------------------------------
248 // wxNotebook operations
249 // ----------------------------------------------------------------------------
250
251 // remove one page from the notebook, without deleting the window
252 wxNotebookPage* wxNotebook::DoRemovePage(int nPage)
253 {
254 wxCHECK( IS_VALID_PAGE(nPage), NULL );
255 wxNotebookPage* page = m_pages[nPage] ;
256 m_pages.RemoveAt(nPage);
257
258 MacSetupTabs();
259
260 if(m_nSelection >= GetPageCount()) {
261 m_nSelection = GetPageCount() - 1;
262 }
263 if(m_nSelection >= 0) {
264 m_pages[m_nSelection]->Show(true);
265 }
266 return page;
267 }
268
269 // remove all pages
270 bool wxNotebook::DeleteAllPages()
271 {
272 // TODO: delete native widget pages
273
274 WX_CLEAR_ARRAY(m_pages) ;
275 MacSetupTabs();
276
277 return TRUE;
278 }
279
280
281 // same as AddPage() but does it at given position
282 bool wxNotebook::InsertPage(int nPage,
283 wxNotebookPage *pPage,
284 const wxString& strText,
285 bool bSelect,
286 int imageId)
287 {
288 wxASSERT( pPage != NULL );
289 wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE );
290
291 pPage->SetLabel(strText);
292
293 // save the pointer to the page
294 m_pages.Insert(pPage, nPage);
295
296 MacSetupTabs();
297
298 if ( bSelect ) {
299 m_nSelection = nPage;
300 }
301 else if ( m_nSelection == -1 ) {
302 m_nSelection = 0;
303 }
304 else if (m_nSelection >= nPage) {
305 m_nSelection++;
306 }
307 // don't show pages by default (we'll need to adjust their size first)
308 pPage->Show( false ) ;
309
310 int h, w;
311 GetSize(&w, &h);
312 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
313 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
314 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
315 if ( pPage->GetAutoLayout() ) {
316 pPage->Layout();
317 }
318
319 return true;
320 }
321
322 /* Added by Mark Newsam
323 * When a page is added or deleted to the notebook this function updates
324 * information held in the m_macControl so that it matches the order
325 * the user would expect.
326 */
327 void wxNotebook::MacSetupTabs()
328 {
329 SetControlMaximum( (ControlHandle) m_macControl , GetPageCount() ) ;
330
331 wxNotebookPage *page;
332 ControlTabInfoRec info;
333 Boolean enabled = true;
334 for(int ii = 0; ii < GetPageCount(); ii++)
335 {
336 page = m_pages[ii];
337 info.version = 0;
338 info.iconSuiteID = 0;
339 #if TARGET_CARBON
340 c2pstrcpy( (StringPtr) info.name , page->GetLabel() ) ;
341 #else
342 strcpy( (char *) info.name , page->GetLabel() ) ;
343 c2pstr( (char *) info.name ) ;
344 #endif
345 SetControlData( (ControlHandle) m_macControl, ii+1, kControlTabInfoTag,
346 sizeof( ControlTabInfoRec) , (char*) &info ) ;
347 SetControlData( (ControlHandle) m_macControl, ii+1, kControlTabEnabledFlagTag,
348 sizeof( Boolean ), (Ptr)&enabled );
349 }
350 Rect bounds;
351 GetControlBounds((ControlHandle)m_macControl, &bounds);
352 InvalWindowRect((WindowRef)MacGetRootWindow(), &bounds);
353 }
354
355 // ----------------------------------------------------------------------------
356 // wxNotebook callbacks
357 // ----------------------------------------------------------------------------
358
359 // @@@ OnSize() is used for setting the font when it's called for the first
360 // time because doing it in ::Create() doesn't work (for unknown reasons)
361 void wxNotebook::OnSize(wxSizeEvent& event)
362 {
363 // emulate page change (it's esp. important to do it first time because
364 // otherwise our page would stay invisible)
365 int nSel = m_nSelection;
366 m_nSelection = -1;
367 SetSelection(nSel);
368
369 // fit the notebook page to the tab control's display area
370 int w, h;
371 GetSize(&w, &h);
372
373 unsigned int nCount = m_pages.Count();
374 for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) {
375 wxNotebookPage *pPage = m_pages[nPage];
376 pPage->SetSize(kwxMacTabLeftMargin, kwxMacTabTopMargin,
377 w - kwxMacTabLeftMargin - kwxMacTabRightMargin,
378 h - kwxMacTabTopMargin - kwxMacTabBottomMargin );
379 if ( pPage->GetAutoLayout() ) {
380 pPage->Layout();
381 }
382 }
383
384 // Processing continues to next OnSize
385 event.Skip();
386 }
387
388 void wxNotebook::OnSelChange(wxNotebookEvent& event)
389 {
390 // is it our tab control?
391 if ( event.GetEventObject() == this )
392 ChangePage(event.GetOldSelection(), event.GetSelection());
393
394 // we want to give others a chance to process this message as well
395 event.Skip();
396 }
397
398 void wxNotebook::OnSetFocus(wxFocusEvent& event)
399 {
400 // set focus to the currently selected page if any
401 if ( m_nSelection != -1 )
402 m_pages[m_nSelection]->SetFocus();
403
404 event.Skip();
405 }
406
407 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
408 {
409 if ( event.IsWindowChange() ) {
410 // change pages
411 AdvanceSelection(event.GetDirection());
412 }
413 else {
414 // pass to the parent
415 if ( GetParent() ) {
416 event.SetCurrentFocus(this);
417 GetParent()->ProcessEvent(event);
418 }
419 }
420 }
421
422 // ----------------------------------------------------------------------------
423 // wxNotebook base class virtuals
424 // ----------------------------------------------------------------------------
425
426 // override these 2 functions to do nothing: everything is done in OnSize
427
428 void wxNotebook::SetConstraintSizes(bool /* recurse */)
429 {
430 // don't set the sizes of the pages - their correct size is not yet known
431 wxControl::SetConstraintSizes(FALSE);
432 }
433
434 bool wxNotebook::DoPhase(int /* nPhase */)
435 {
436 return TRUE;
437 }
438
439 void wxNotebook::Command(wxCommandEvent& event)
440 {
441 wxFAIL_MSG("wxNotebook::Command not implemented");
442 }
443
444 // ----------------------------------------------------------------------------
445 // wxNotebook helper functions
446 // ----------------------------------------------------------------------------
447
448 // hide the currently active panel and show the new one
449 void wxNotebook::ChangePage(int nOldSel, int nSel)
450 {
451 // it's not an error (the message may be generated by the tab control itself)
452 // and it may happen - just do nothing
453 if ( nSel == nOldSel )
454 {
455 wxNotebookPage *pPage = m_pages[nSel];
456 pPage->Show(FALSE);
457 pPage->Show(TRUE);
458 pPage->SetFocus();
459 return;
460 }
461
462 // Hide previous page
463 if ( nOldSel != -1 ) {
464 m_pages[nOldSel]->Show(FALSE);
465 }
466
467 wxNotebookPage *pPage = m_pages[nSel];
468 pPage->Show(TRUE);
469 pPage->SetFocus();
470
471 m_nSelection = nSel;
472 }
473
474 void wxNotebook::MacHandleControlClick( WXWidget control , wxInt16 controlpart )
475 {
476 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_windowId , ::GetControlValue((ControlHandle)m_macControl) - 1, m_nSelection);
477 event.SetEventObject(this);
478
479 ProcessEvent(event);
480 }
481