]> git.saurik.com Git - wxWidgets.git/blame - src/motif/notebook.cpp
fixes
[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
141 ChangePage(m_nSelection, nPage);
142
143 // TODO
144 return 0;
145}
146
147void 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
157bool wxNotebook::SetPageText(int nPage, const wxString& strText)
158{
159 wxASSERT( IS_VALID_PAGE(nPage) );
160
161 // TODO
162 return FALSE;
163}
164
165wxString wxNotebook::GetPageText(int nPage) const
166{
167 wxASSERT( IS_VALID_PAGE(nPage) );
168
169 // TODO
170 return wxString("");
171}
172
173int wxNotebook::GetPageImage(int nPage) const
174{
175 wxASSERT( IS_VALID_PAGE(nPage) );
176
177 // TODO
178 return 0;
179}
180
181bool wxNotebook::SetPageImage(int nPage, int nImage)
182{
183 wxASSERT( IS_VALID_PAGE(nPage) );
184
185 // TODO
186 return FALSE;
187}
188
189void 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
200bool wxNotebook::DeletePage(int nPage)
201{
4b5f3fe6
JS
202 wxFAIL_MSG("Sorry, DeletePage not implemented for Motif wxNotebook because wxTabView doesn't support it.");
203 return FALSE;
204
205/*
4bb6408c
JS
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;
4b5f3fe6 214*/
4bb6408c
JS
215}
216
217// remove all pages
218bool wxNotebook::DeleteAllPages()
219{
4b5f3fe6 220 m_tabView->ClearTabs(TRUE);
4bb6408c
JS
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
233bool 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
242bool 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
4b5f3fe6 251 m_tabView->AddTab(nPage, strText);
02800301 252 pPage->Show(FALSE);
4b5f3fe6
JS
253
254/*
255 if (bSelect)
256 m_tabView->SetTabSelection(nPage, TRUE);
257*/
4bb6408c
JS
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)
278void 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
4b5f3fe6
JS
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];
02800301
JS
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 }
4b5f3fe6
JS
333 }
334 Refresh();
4bb6408c
JS
335 }
336
337 // Processing continues to next OnSize
338 event.Skip();
339}
340
341void 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
351void 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
360void 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
381void 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
387bool wxNotebook::DoPhase(int /* nPhase */)
388{
389 return TRUE;
390}
391
392void 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
402void wxNotebook::ChangePage(int nOldSel, int nSel)
403{
404 wxASSERT( nOldSel != nSel ); // impossible
405
406 if ( nOldSel != -1 ) {
407 m_aPages[nOldSel]->Show(FALSE);
02800301 408 m_aPages[nOldSel]->Lower();
4bb6408c
JS
409 }
410
411 wxNotebookPage *pPage = m_aPages[nSel];
02800301
JS
412
413 wxRect clientRect = GetAvailableClientSize();
414 pPage->SetSize(clientRect.x, clientRect.y, clientRect.width, clientRect.height);
415
4bb6408c 416 pPage->Show(TRUE);
02800301 417 pPage->Raise();
4bb6408c
JS
418 pPage->SetFocus();
419
02800301
JS
420 Refresh();
421
4bb6408c
JS
422 m_nSelection = nSel;
423}
424
4b5f3fe6 425void wxNotebook::ChangeFont(bool keepOriginalSize)
0d57be45 426{
4b5f3fe6 427 wxWindow::ChangeFont(keepOriginalSize);
0d57be45
JS
428}
429
430void wxNotebook::ChangeBackgroundColour()
431{
4b5f3fe6 432 wxWindow::ChangeBackgroundColour();
0d57be45
JS
433}
434
435void wxNotebook::ChangeForegroundColour()
436{
4b5f3fe6
JS
437 wxWindow::ChangeForegroundColour();
438}
439
440void wxNotebook::OnMouseEvent(wxMouseEvent& event)
441{
442 if (m_tabView)
443 m_tabView->OnEvent(event);
444}
445
446void wxNotebook::OnPaint(wxPaintEvent& WXUNUSED(event) )
447{
448 wxPaintDC dc(this);
449 if (m_tabView)
450 m_tabView->Draw(dc);
451}
452
02800301
JS
453wxRect 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
4b5f3fe6
JS
470/*
471 * wxNotebookTabView
472 */
473
474IMPLEMENT_CLASS(wxNotebookTabView, wxTabView)
475
476wxNotebookTabView::wxNotebookTabView(wxNotebook *notebook, long style): wxTabView(style)
477{
478 m_notebook = notebook;
479
4b5f3fe6
JS
480 m_notebook->SetTabView(this);
481
482 SetWindow(m_notebook);
483}
484
485wxNotebookTabView::~wxNotebookTabView(void)
486{
4b5f3fe6
JS
487}
488
489// Called when a tab is activated
490void wxNotebookTabView::OnTabActivate(int activateId, int deactivateId)
491{
492 if (!m_notebook)
493 return;
02800301
JS
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 /*
4b5f3fe6
JS
502 wxWindow *oldWindow = ((deactivateId == -1) ? 0 : m_notebook->GetPage(deactivateId));
503 wxWindow *newWindow = m_notebook->GetPage(activateId);
504
505 if (oldWindow)
02800301 506 {
4b5f3fe6 507 oldWindow->Show(FALSE);
02800301
JS
508 oldWindow->Lower();
509 }
4b5f3fe6 510 if (newWindow)
02800301 511 {
4b5f3fe6 512 newWindow->Show(TRUE);
02800301
JS
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.
4b5f3fe6 530 m_notebook->Refresh();
02800301 531*/
0d57be45
JS
532}
533
4b5f3fe6
JS
534#if 0
535void wxNotebookTabView::AddTabWindow(int id, wxWindow *window)
536{
537 m_tabWindows.Append((long)id, window);
538 window->Show(FALSE);
539}
540
541wxWindow *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
549void wxNotebookTabView::ClearWindows(bool deleteWindows)
550{
551 if (deleteWindows)
552 m_tabWindows.DeleteContents(TRUE);
553 m_tabWindows.Clear();
554 m_tabWindows.DeleteContents(FALSE);
555}
556
557void 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