constraints for notebook pages work (again)
[wxWidgets.git] / src / gtk / notebook.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: notebook.cpp
3 // Purpose:
4 // Author: Robert Roebling
5 // Created: 01/02/97
6 // Id:
7 // Copyright: (c) 1998 Robert Roebling, Julian Smart and Markus Holzem
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 #ifdef __GNUG__
12 #pragma implementation "notebook.h"
13 #endif
14
15 #include "wx/notebook.h"
16 #include "wx/panel.h"
17 #include "wx/utils.h"
18 #include "wx/imaglist.h"
19 #include "wx/intl.h"
20 #include "wx/log.h"
21
22 //-----------------------------------------------------------------------------
23 // wxNotebookPage
24 //-----------------------------------------------------------------------------
25
26 class wxNotebookPage: public wxObject
27 {
28 public:
29 wxNotebookPage()
30 {
31 m_id = -1;
32 m_text = "";
33 m_image = -1;
34 m_page = NULL;
35 m_client = NULL;
36 m_parent = NULL;
37 };
38
39 //private:
40 int m_id;
41 wxString m_text;
42 int m_image;
43 GtkNotebookPage *m_page;
44 GtkLabel *m_label;
45 wxWindow *m_client;
46 GtkNotebook *m_parent;
47 };
48
49 //-----------------------------------------------------------------------------
50 // GTK callbacks
51 //-----------------------------------------------------------------------------
52
53 // page change callback
54 static void gtk_notebook_page_change_callback(GtkNotebook *WXUNUSED(widget),
55 GtkNotebookPage *WXUNUSED(page),
56 gint nPage,
57 gpointer data)
58 {
59 wxNotebook *notebook = (wxNotebook *)data;
60
61 int nOld = notebook->GetSelection();
62
63 // TODO: emulate PAGE_CHANGING event
64 wxNotebookEvent event(wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
65 notebook->GetId(),
66 nPage,
67 nOld);
68 event.SetEventObject(notebook);
69 notebook->ProcessEvent(event);
70 }
71
72 //-----------------------------------------------------------------------------
73 // wxNotebook
74 //-----------------------------------------------------------------------------
75
76 BEGIN_EVENT_TABLE(wxNotebook, wxControl)
77 EVT_SIZE(wxNotebook::OnSize)
78 END_EVENT_TABLE()
79
80 IMPLEMENT_DYNAMIC_CLASS(wxNotebook,wxControl)
81
82 void wxNotebook::Init()
83 {
84 m_imageList = NULL;
85 m_pages.DeleteContents( TRUE );
86 m_idHandler = 0;
87 }
88
89 wxNotebook::wxNotebook()
90 {
91 Init();
92 };
93
94 wxNotebook::wxNotebook( wxWindow *parent, wxWindowID id,
95 const wxPoint& pos, const wxSize& size,
96 long style, const wxString& name )
97 {
98 Init();
99 Create( parent, id, pos, size, style, name );
100 };
101
102 wxNotebook::~wxNotebook()
103 {
104 // don't generate change page events any more
105 if ( m_idHandler != 0 )
106 gtk_signal_disconnect(GTK_OBJECT(m_widget), m_idHandler);
107
108 if (m_imageList)
109 delete m_imageList;
110 DeleteAllPages();
111 };
112
113 bool wxNotebook::Create(wxWindow *parent, wxWindowID id,
114 const wxPoint& pos, const wxSize& size,
115 long style, const wxString& name )
116 {
117 m_needParent = TRUE;
118
119 PreCreation( parent, id, pos, size, style, name );
120
121 m_widget = gtk_notebook_new();
122 m_idHandler = gtk_signal_connect
123 (
124 GTK_OBJECT(m_widget), "switch_page",
125 GTK_SIGNAL_FUNC(gtk_notebook_page_change_callback),
126 (gpointer)this
127 );
128
129 PostCreation();
130
131 Show( TRUE );
132
133 return TRUE;
134 };
135
136 int wxNotebook::GetSelection() const
137 {
138 if (m_pages.Number() == 0)
139 return -1;
140
141 GtkNotebookPage *g_page = GTK_NOTEBOOK(m_widget)->cur_page;
142
143 wxNotebookPage *page = NULL;
144
145 wxNode *node = m_pages.First();
146 while (node)
147 {
148 page = (wxNotebookPage*)node->Data();
149 if (page->m_page == g_page)
150 break;
151 node = node->Next();
152 };
153
154 wxCHECK_MSG( node != NULL, -1, "wxNotebook: no selection?");
155
156 return page->m_id;
157 };
158
159 int wxNotebook::GetPageCount() const
160 {
161 return m_pages.Number();
162 };
163
164 int wxNotebook::GetRowCount() const
165 {
166 return 1;
167 };
168
169 wxString wxNotebook::GetPageText( int page ) const
170 {
171 wxNotebookPage* nb_page = GetNotebookPage(page);
172 if (nb_page)
173 return nb_page->m_text;
174 else
175 return "";
176 };
177
178 int wxNotebook::GetPageImage( int page ) const
179 {
180 wxNotebookPage* nb_page = GetNotebookPage(page);
181 if (nb_page)
182 return nb_page->m_image;
183 else
184 return 0;
185 };
186
187 wxNotebookPage* wxNotebook::GetNotebookPage(int page) const
188 {
189 wxNotebookPage *nb_page = NULL;
190
191 wxNode *node = m_pages.First();
192 while (node)
193 {
194 nb_page = (wxNotebookPage*)node->Data();
195 if (nb_page->m_id == page)
196 return nb_page;
197 node = node->Next();
198 };
199
200 wxLogDebug( "Notebook page %d not found!", page );
201
202 return NULL;
203 };
204
205 int wxNotebook::SetSelection( int page )
206 {
207 int selOld = GetSelection();
208 wxNotebookPage* nb_page = GetNotebookPage(page);
209 if (!nb_page)
210 return -1;
211
212 int page_num = 0;
213 GList *child = GTK_NOTEBOOK(m_widget)->children;
214 while (child)
215 {
216 if (nb_page->m_page == (GtkNotebookPage*)child->data)
217 break;
218 page_num++;
219 child = child->next;
220 };
221
222 if (!child) return -1;
223
224 gtk_notebook_set_page( GTK_NOTEBOOK(m_widget), page_num );
225
226 return selOld;
227 };
228
229 void wxNotebook::AdvanceSelection(bool bForward)
230 {
231 int nSel = GetSelection(),
232 nMax = GetPageCount();
233
234 if ( bForward ) {
235 SetSelection(nSel == nMax ? 0 : nSel + 1);
236 }
237 else {
238 SetSelection(nSel == 0 ? nMax : nSel - 1);
239 }
240 }
241
242 void wxNotebook::SetImageList( wxImageList* imageList )
243 {
244 m_imageList = imageList;
245 };
246
247 bool wxNotebook::SetPageText( int page, const wxString &text )
248 {
249 wxNotebookPage* nb_page = GetNotebookPage(page);
250 if (!nb_page)
251 return FALSE;
252
253 nb_page->m_text = text;
254
255 return TRUE;
256 };
257
258 bool wxNotebook::SetPageImage( int page, int image )
259 {
260 wxNotebookPage* nb_page = GetNotebookPage(page);
261 if (!nb_page)
262 return FALSE;
263
264 nb_page->m_image = image;
265
266 return TRUE;
267 };
268
269 void wxNotebook::SetPageSize( const wxSize &WXUNUSED(size) )
270 {
271 wxFAIL_MSG("wxNotebook::SetPageSize not implemented");
272 };
273
274 void wxNotebook::SetPadding( const wxSize &WXUNUSED(padding) )
275 {
276 wxFAIL_MSG("wxNotebook::SetPadding not implemented");
277 };
278
279 bool wxNotebook::DeleteAllPages()
280 {
281 wxNode *page_node = m_pages.First();
282 while (page_node)
283 {
284 wxNotebookPage *page = (wxNotebookPage*)page_node->Data();
285
286 DeletePage( page->m_id );
287
288 page_node = m_pages.First();
289 };
290
291 return TRUE;
292 };
293
294 bool wxNotebook::DeletePage( int page )
295 {
296 wxNotebookPage* nb_page = GetNotebookPage(page);
297 if (!nb_page) return FALSE;
298
299 int page_num = 0;
300 GList *child = GTK_NOTEBOOK(m_widget)->children;
301 while (child)
302 {
303 if (nb_page->m_page == (GtkNotebookPage*)child->data) break;
304 page_num++;
305 child = child->next;
306 };
307
308 wxASSERT( child );
309
310 delete nb_page->m_client;
311
312 // Amazingly, this is not necessary
313 // gtk_notebook_remove_page( GTK_NOTEBOOK(m_widget), page_num );
314
315 m_pages.DeleteObject( nb_page );
316
317 return TRUE;
318 };
319
320 bool wxNotebook::AddPage(wxWindow* win, const wxString& text,
321 bool bSelect, int imageId)
322 {
323 // we've created the notebook page in AddChild(). Now we just have to set
324 // the caption for the page and set the others parameters.
325
326 // first, find the page
327 wxNotebookPage *page = NULL;
328
329 wxNode *node = m_pages.First();
330 while (node)
331 {
332 page = (wxNotebookPage*)node->Data();
333 if ( page->m_client == win )
334 break; // found
335 node = node->Next();
336 };
337
338 wxCHECK_MSG(page != NULL, FALSE,
339 "Can't add a page whose parent is not the notebook!");
340
341 // then set the attributes
342 page->m_text = text;
343 if ( page->m_text.IsEmpty() )
344 page->m_text = "";
345 page->m_image = imageId;
346 gtk_label_set(page->m_label, page->m_text);
347
348 if ( bSelect ) {
349 SetSelection(GetPageCount());
350 }
351
352 return TRUE;
353 };
354
355 wxWindow *wxNotebook::GetPage( int page ) const
356 {
357 wxNotebookPage* nb_page = GetNotebookPage(page);
358 if (!nb_page)
359 return NULL;
360 else
361 return nb_page->m_client;
362 };
363
364 void wxNotebook::AddChild( wxWindow *win )
365 {
366 // @@@ normally done in wxWindow::AddChild but for some reason wxNotebook
367 // case is special there (Robert?)
368 // Robert: Don't you think the code below looks different from the one
369 // in wxWindow::AddChild :-)
370
371 m_children.Append(win);
372
373
374 wxNotebookPage *page = new wxNotebookPage();
375
376 page->m_id = GetPageCount();
377 page->m_label = (GtkLabel *)gtk_label_new("Handle");
378 page->m_client = win;
379 gtk_notebook_append_page( GTK_NOTEBOOK(m_widget), win->m_widget,
380 (GtkWidget *)page->m_label);
381 gtk_misc_set_alignment(GTK_MISC(page->m_label), 0.0, 0.5);
382
383 page->m_page =
384 (GtkNotebookPage*) (g_list_last(GTK_NOTEBOOK(m_widget)->children)->data);
385
386 page->m_parent = GTK_NOTEBOOK(m_widget);
387
388 if (!page->m_page)
389 {
390 wxLogFatalError( "Notebook page creation error" );
391 return;
392 }
393
394 m_pages.Append( page );
395 };
396
397 void wxNotebook::OnSize(wxSizeEvent& event)
398 {
399 // forward this event to all pages
400 wxNode *node = m_pages.First();
401 while (node)
402 {
403 wxWindow *page = ((wxNotebookPage*)node->Data())->m_client;
404 // @@@@ the numbers I substract here are completely arbitrary, instead we
405 // should somehow calculate the size of the page from the size of the
406 // notebook
407 page->SetSize(event.GetSize().GetX() - 5,
408 event.GetSize().GetY() - 30);
409
410 if ( page->GetAutoLayout() )
411 page->Layout();
412
413 node = node->Next();
414 };
415 }
416
417 // override these 2 functions to do nothing: everything is done in OnSize
418 void wxNotebook::SetConstraintSizes(bool /* recurse */)
419 {
420 // don't set the sizes of the pages - their correct size is not yet known
421 wxControl::SetConstraintSizes(FALSE);
422 }
423
424 bool wxNotebook::DoPhase(int /* nPhase */)
425 {
426 return TRUE;
427 }
428
429 //-----------------------------------------------------------------------------
430 // wxNotebookEvent
431 //-----------------------------------------------------------------------------
432
433 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)