]> git.saurik.com Git - wxWidgets.git/blob - src/motif/notebook.cpp
Changes to WXDLLEXPORT keyword position for VC++ 6.0; changed
[wxWidgets.git] / src / motif / notebook.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: notebook.cpp
3 // Purpose: implementation of wxNotebook
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 17/09/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart
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/dcclient.h>
28
29 #include <Xm/Xm.h>
30 #include <wx/motif/private.h>
31
32 // ----------------------------------------------------------------------------
33 // macros
34 // ----------------------------------------------------------------------------
35
36 // check that the page index is valid
37 #define IS_VALID_PAGE(nPage) (((nPage) >= 0) && ((nPage) < GetPageCount()))
38
39 // ----------------------------------------------------------------------------
40 // event table
41 // ----------------------------------------------------------------------------
42
43 #if !USE_SHARED_LIBRARIES
44 BEGIN_EVENT_TABLE(wxNotebook, wxControl)
45 EVT_NOTEBOOK_PAGE_CHANGED(-1, wxNotebook::OnSelChange)
46 EVT_SIZE(wxNotebook::OnSize)
47 EVT_PAINT(wxNotebook::OnPaint)
48 EVT_MOUSE_EVENTS(wxNotebook::OnMouseEvent)
49 EVT_SET_FOCUS(wxNotebook::OnSetFocus)
50 EVT_NAVIGATION_KEY(wxNotebook::OnNavigationKey)
51 END_EVENT_TABLE()
52
53 IMPLEMENT_DYNAMIC_CLASS(wxNotebook, wxControl)
54 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
55 #endif
56
57 // ============================================================================
58 // implementation
59 // ============================================================================
60
61 // ----------------------------------------------------------------------------
62 // wxNotebook construction
63 // ----------------------------------------------------------------------------
64
65 // common part of all ctors
66 void wxNotebook::Init()
67 {
68 m_tabView = (wxNotebookTabView*) NULL;
69 m_pImageList = NULL;
70 m_nSelection = -1;
71 }
72
73 // default for dynamic class
74 wxNotebook::wxNotebook()
75 {
76 Init();
77 }
78
79 // the same arguments as for wxControl
80 wxNotebook::wxNotebook(wxWindow *parent,
81 wxWindowID id,
82 const wxPoint& pos,
83 const wxSize& size,
84 long style,
85 const wxString& name)
86 {
87 Init();
88
89 Create(parent, id, pos, size, style, name);
90 }
91
92 // Create() function
93 bool wxNotebook::Create(wxWindow *parent,
94 wxWindowID id,
95 const wxPoint& pos,
96 const wxSize& size,
97 long style,
98 const wxString& name)
99 {
100 // base init
101 SetName(name);
102
103 m_windowId = id == -1 ? NewControlId() : id;
104
105 // It's like a normal window...
106 if (!wxWindow::Create(parent, id, pos, size, style, name))
107 return FALSE;
108
109 SetTabView(new wxNotebookTabView(this));
110
111 return TRUE;
112 }
113
114 // dtor
115 wxNotebook::~wxNotebook()
116 {
117 delete m_tabView;
118 }
119
120 // ----------------------------------------------------------------------------
121 // wxNotebook accessors
122 // ----------------------------------------------------------------------------
123 int wxNotebook::GetPageCount() const
124 {
125 return m_aPages.Count();
126 }
127
128 int wxNotebook::GetRowCount() const
129 {
130 // TODO
131 return 0;
132 }
133
134 int wxNotebook::SetSelection(int nPage)
135 {
136 if (nPage == -1)
137 return 0;
138
139 wxASSERT( IS_VALID_PAGE(nPage) );
140
141 ChangePage(m_nSelection, nPage);
142
143 // TODO
144 return 0;
145 }
146
147 void wxNotebook::AdvanceSelection(bool bForward)
148 {
149 int nSel = GetSelection();
150 int nMax = GetPageCount() - 1;
151 if ( bForward )
152 SetSelection(nSel == nMax ? 0 : nSel + 1);
153 else
154 SetSelection(nSel == 0 ? nMax : nSel - 1);
155 }
156
157 bool wxNotebook::SetPageText(int nPage, const wxString& strText)
158 {
159 wxASSERT( IS_VALID_PAGE(nPage) );
160
161 // TODO
162 return FALSE;
163 }
164
165 wxString wxNotebook::GetPageText(int nPage) const
166 {
167 wxASSERT( IS_VALID_PAGE(nPage) );
168
169 // TODO
170 return wxString("");
171 }
172
173 int wxNotebook::GetPageImage(int nPage) const
174 {
175 wxASSERT( IS_VALID_PAGE(nPage) );
176
177 // TODO
178 return 0;
179 }
180
181 bool wxNotebook::SetPageImage(int nPage, int nImage)
182 {
183 wxASSERT( IS_VALID_PAGE(nPage) );
184
185 // TODO
186 return FALSE;
187 }
188
189 void wxNotebook::SetImageList(wxImageList* imageList)
190 {
191 m_pImageList = imageList;
192 // TODO
193 }
194
195 // ----------------------------------------------------------------------------
196 // wxNotebook operations
197 // ----------------------------------------------------------------------------
198
199 // remove one page from the notebook
200 bool wxNotebook::DeletePage(int nPage)
201 {
202 wxFAIL_MSG("Sorry, DeletePage not implemented for Motif wxNotebook because wxTabView doesn't support it.");
203 return FALSE;
204
205 /*
206 wxCHECK( IS_VALID_PAGE(nPage), FALSE );
207
208 // TODO: delete native widget page
209
210 delete m_aPages[nPage];
211 m_aPages.Remove(nPage);
212
213 return TRUE;
214 */
215 }
216
217 // remove all pages
218 bool wxNotebook::DeleteAllPages()
219 {
220 m_tabView->ClearTabs(TRUE);
221
222 int nPageCount = GetPageCount();
223 int nPage;
224 for ( nPage = 0; nPage < nPageCount; nPage++ )
225 delete m_aPages[nPage];
226
227 m_aPages.Clear();
228
229 return TRUE;
230 }
231
232 // add a page to the notebook
233 bool wxNotebook::AddPage(wxNotebookPage *pPage,
234 const wxString& strText,
235 bool bSelect,
236 int imageId)
237 {
238 return InsertPage(GetPageCount(), pPage, strText, bSelect, imageId);
239 }
240
241 // same as AddPage() but does it at given position
242 bool wxNotebook::InsertPage(int nPage,
243 wxNotebookPage *pPage,
244 const wxString& strText,
245 bool bSelect,
246 int imageId)
247 {
248 wxASSERT( pPage != NULL );
249 wxCHECK( IS_VALID_PAGE(nPage) || nPage == GetPageCount(), FALSE );
250
251 m_tabView->AddTab(nPage, strText);
252 pPage->Show(FALSE);
253
254 /*
255 if (bSelect)
256 m_tabView->SetTabSelection(nPage, TRUE);
257 */
258
259 // save the pointer to the page
260 m_aPages.Insert(pPage, nPage);
261
262 // some page must be selected: either this one or the first one if there is
263 // still no selection
264 if ( bSelect )
265 m_nSelection = nPage;
266 else if ( m_nSelection == -1 )
267 m_nSelection = 0;
268
269 return TRUE;
270 }
271
272 // ----------------------------------------------------------------------------
273 // wxNotebook callbacks
274 // ----------------------------------------------------------------------------
275
276 // @@@ OnSize() is used for setting the font when it's called for the first
277 // time because doing it in ::Create() doesn't work (for unknown reasons)
278 void wxNotebook::OnSize(wxSizeEvent& event)
279 {
280 static bool s_bFirstTime = TRUE;
281 if ( s_bFirstTime ) {
282 // TODO: any first-time-size processing.
283 s_bFirstTime = FALSE;
284 }
285
286 if (m_tabView)
287 {
288 int cw, ch;
289 GetClientSize(& cw, & ch);
290
291 int tabHeight = m_tabView->GetTotalTabHeight();
292 wxRect rect;
293 rect.x = 4;
294 rect.y = tabHeight + 4;
295 rect.width = cw - 8;
296 rect.height = ch - 4 - rect.y ;
297
298 m_tabView->SetViewRect(rect);
299
300 m_tabView->Layout();
301
302 // Need to do it a 2nd time to get the tab height with
303 // the new view width, since changing the view width changes the
304 // tab layout.
305 tabHeight = m_tabView->GetTotalTabHeight();
306 rect.x = 4;
307 rect.y = tabHeight + 4;
308 rect.width = cw - 8;
309 rect.height = ch - 4 - rect.y ;
310
311 m_tabView->SetViewRect(rect);
312
313 m_tabView->Layout();
314
315 // emulate page change (it's esp. important to do it first time because
316 // otherwise our page would stay invisible)
317 int nSel = m_nSelection;
318 m_nSelection = -1;
319 SetSelection(nSel);
320
321 // fit the notebook page to the tab control's display area
322
323 unsigned int nCount = m_aPages.Count();
324 for ( unsigned int nPage = 0; nPage < nCount; nPage++ ) {
325 wxNotebookPage *pPage = m_aPages[nPage];
326 if (pPage->IsShown())
327 {
328 wxRect clientRect = GetAvailableClientSize();
329 pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height);
330 if ( pPage->GetAutoLayout() )
331 pPage->Layout();
332 }
333 }
334 Refresh();
335 }
336
337 // Processing continues to next OnSize
338 event.Skip();
339 }
340
341 void wxNotebook::OnSelChange(wxNotebookEvent& event)
342 {
343 // is it our tab control?
344 if ( event.GetEventObject() == this )
345 ChangePage(event.GetOldSelection(), event.GetSelection());
346
347 // we want to give others a chance to process this message as well
348 event.Skip();
349 }
350
351 void wxNotebook::OnSetFocus(wxFocusEvent& event)
352 {
353 // set focus to the currently selected page if any
354 if ( m_nSelection != -1 )
355 m_aPages[m_nSelection]->SetFocus();
356
357 event.Skip();
358 }
359
360 void wxNotebook::OnNavigationKey(wxNavigationKeyEvent& event)
361 {
362 if ( event.IsWindowChange() ) {
363 // change pages
364 AdvanceSelection(event.GetDirection());
365 }
366 else {
367 // pass to the parent
368 if ( GetParent() ) {
369 event.SetCurrentFocus(this);
370 GetParent()->ProcessEvent(event);
371 }
372 }
373 }
374
375 // ----------------------------------------------------------------------------
376 // wxNotebook base class virtuals
377 // ----------------------------------------------------------------------------
378
379 // override these 2 functions to do nothing: everything is done in OnSize
380
381 void wxNotebook::SetConstraintSizes(bool /* recurse */)
382 {
383 // don't set the sizes of the pages - their correct size is not yet known
384 wxControl::SetConstraintSizes(FALSE);
385 }
386
387 bool wxNotebook::DoPhase(int /* nPhase */)
388 {
389 return TRUE;
390 }
391
392 void wxNotebook::Command(wxCommandEvent& event)
393 {
394 wxFAIL_MSG("wxNotebook::Command not implemented");
395 }
396
397 // ----------------------------------------------------------------------------
398 // wxNotebook helper functions
399 // ----------------------------------------------------------------------------
400
401 // hide the currently active panel and show the new one
402 void wxNotebook::ChangePage(int nOldSel, int nSel)
403 {
404 wxASSERT( nOldSel != nSel ); // impossible
405
406 if ( nOldSel != -1 ) {
407 m_aPages[nOldSel]->Show(FALSE);
408 m_aPages[nOldSel]->Lower();
409 }
410
411 wxNotebookPage *pPage = m_aPages[nSel];
412
413 wxRect clientRect = GetAvailableClientSize();
414 pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height);
415
416 pPage->Show(TRUE);
417 pPage->Raise();
418 pPage->SetFocus();
419
420 Refresh();
421
422 m_nSelection = nSel;
423 }
424
425 void wxNotebook::ChangeFont(bool keepOriginalSize)
426 {
427 wxWindow::ChangeFont(keepOriginalSize);
428 }
429
430 void wxNotebook::ChangeBackgroundColour()
431 {
432 wxWindow::ChangeBackgroundColour();
433 }
434
435 void wxNotebook::ChangeForegroundColour()
436 {
437 wxWindow::ChangeForegroundColour();
438 }
439
440 void wxNotebook::OnMouseEvent(wxMouseEvent& event)
441 {
442 if (m_tabView)
443 m_tabView->OnEvent(event);
444 }
445
446 void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event) )
447 {
448 wxPaintDC dc(this);
449 if (m_tabView)
450 m_tabView->Draw(dc);
451 }
452
453 wxRect wxNotebook::GetAvailableClientSize()
454 {
455 int cw, ch;
456 GetClientSize(& cw, & ch);
457
458 int tabHeight = m_tabView->GetTotalTabHeight();
459
460 // TODO: these margins should be configurable.
461 wxRect rect;
462 rect.x = 6;
463 rect.y = tabHeight + 6;
464 rect.width = cw - 12;
465 rect.height = ch - 4 - rect.y ;
466
467 return rect;
468 }
469
470 /*
471 * wxNotebookTabView
472 */
473
474 IMPLEMENT_CLASS(wxNotebookTabView, wxTabView)
475
476 wxNotebookTabView::wxNotebookTabView(wxNotebook *notebook, long style): wxTabView(style)
477 {
478 m_notebook = notebook;
479
480 m_notebook->SetTabView(this);
481
482 SetWindow(m_notebook);
483 }
484
485 wxNotebookTabView::~wxNotebookTabView(void)
486 {
487 }
488
489 // Called when a tab is activated
490 void wxNotebookTabView::OnTabActivate(int activateId, int deactivateId)
491 {
492 if (!m_notebook)
493 return;
494
495 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED, m_notebook->GetId());
496 event.SetEventObject(m_notebook);
497 event.SetSelection(activateId);
498 event.SetOldSelection(deactivateId);
499 m_notebook->GetEventHandler()->ProcessEvent(event);
500
501 /*
502 wxWindow *oldWindow = ((deactivateId == -1) ? 0 : m_notebook->GetPage(deactivateId));
503 wxWindow *newWindow = m_notebook->GetPage(activateId);
504
505 if (oldWindow)
506 {
507 oldWindow->Show(FALSE);
508 oldWindow->Lower();
509 }
510 if (newWindow)
511 {
512 newWindow->Show(TRUE);
513 newWindow->Raise();
514
515 int cw, ch;
516 m_notebook->GetClientSize(& cw, & ch);
517
518 int tabHeight = GetTotalTabHeight();
519 wxRect rect;
520 rect.x = 4;
521 rect.y = tabHeight + 4;
522 rect.width = cw - 8;
523 rect.height = ch - 4 - rect.y ;
524
525 newWindow->SetSize(rect.x + 2, rect.y + 2, rect.width - 2, rect.height - 2);
526 newWindow->Refresh();
527 }
528
529 // TODO: only refresh the tab area.
530 m_notebook->Refresh();
531 */
532 }
533
534 #if 0
535 void wxNotebookTabView::AddTabWindow(int id, wxWindow *window)
536 {
537 m_tabWindows.Append((long)id, window);
538 window->Show(FALSE);
539 }
540
541 wxWindow *wxNotebookTabView::GetTabWindow(int id) const
542 {
543 wxNode *node = m_tabWindows.Find((long)id);
544 if (!node)
545 return (wxWindow *) NULL;
546 return (wxWindow *)node->Data();
547 }
548
549 void wxNotebookTabView::ClearWindows(bool deleteWindows)
550 {
551 if (deleteWindows)
552 m_tabWindows.DeleteContents(TRUE);
553 m_tabWindows.Clear();
554 m_tabWindows.DeleteContents(FALSE);
555 }
556
557 void wxNotebookTabView::ShowWindowForTab(int id)
558 {
559 wxWindow *newWindow = GetTabWindow(id);
560 if (newWindow == m_currentWindow)
561 return;
562 if (m_currentWindow)
563 m_currentWindow->Show(FALSE);
564 newWindow->Show(TRUE);
565 newWindow->Refresh();
566 }
567 #endif
568