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