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