]> git.saurik.com Git - wxWidgets.git/blob - src/gtk/notebook.cpp
Prealpha, prebeta of new wxTreeCtrl for GTK. It is possible to AddRoot,
[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 = (GtkNotebookPage *) NULL;
35 m_client = (wxWindow *) NULL;
36 m_parent = (GtkNotebook *) NULL;
37 m_box = (GtkWidget *) NULL;
38 }
39
40 //private:
41 int m_id;
42 wxString m_text;
43 int m_image;
44 GtkNotebookPage *m_page;
45 GtkLabel *m_label;
46 wxWindow *m_client;
47 GtkNotebook *m_parent;
48 GtkWidget *m_box; // in which the label and image are packed
49 };
50
51 //-----------------------------------------------------------------------------
52 // "switch_page"
53 //-----------------------------------------------------------------------------
54
55 static void gtk_notebook_page_change_callback(GtkNotebook *WXUNUSED(widget),
56 GtkNotebookPage *WXUNUSED(page),
57 gint nPage,
58 gpointer data)
59 {
60 wxNotebook *notebook = (wxNotebook *)data;
61
62 int old = notebook->GetSelection();
63
64 // TODO: emulate PAGE_CHANGING event
65
66 wxNotebookEvent event( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED,
67 notebook->GetId(), nPage, old );
68 event.SetEventObject( notebook );
69 notebook->GetEventHandler()->ProcessEvent( event );
70 }
71
72 //-----------------------------------------------------------------------------
73 // "size_allocate"
74 //-----------------------------------------------------------------------------
75
76 static void gtk_page_size_callback( GtkWidget *WXUNUSED(widget), GtkAllocation* alloc, wxWindow *win )
77 {
78 if (win->GetAutoLayout()) win->Layout();
79
80 if ((win->m_x == alloc->x) &&
81 (win->m_y == alloc->y) &&
82 (win->m_width == alloc->width) &&
83 (win->m_height == alloc->height))
84 {
85 return;
86 }
87
88 win->SetSize( alloc->x, alloc->y, alloc->width, alloc->height );
89 }
90
91 //-----------------------------------------------------------------------------
92 // wxNotebook
93 //-----------------------------------------------------------------------------
94
95 IMPLEMENT_DYNAMIC_CLASS(wxNotebook,wxControl)
96
97 void wxNotebook::Init()
98 {
99 m_imageList = (wxImageList *) NULL;
100 m_pages.DeleteContents( TRUE );
101 m_idHandler = 0;
102 }
103
104 wxNotebook::wxNotebook()
105 {
106 Init();
107 }
108
109 wxNotebook::wxNotebook( wxWindow *parent, wxWindowID id,
110 const wxPoint& pos, const wxSize& size,
111 long style, const wxString& name )
112 {
113 Init();
114 Create( parent, id, pos, size, style, name );
115 }
116
117 wxNotebook::~wxNotebook()
118 {
119 // don't generate change page events any more
120 if (m_idHandler != 0)
121 gtk_signal_disconnect(GTK_OBJECT(m_widget), m_idHandler);
122
123 DeleteAllPages();
124 }
125
126 bool wxNotebook::Create(wxWindow *parent, wxWindowID id,
127 const wxPoint& pos, const wxSize& size,
128 long style, const wxString& name )
129 {
130 m_needParent = TRUE;
131
132 PreCreation( parent, id, pos, size, style, name );
133
134 m_widget = gtk_notebook_new();
135
136 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget), 1 );
137
138 m_idHandler = gtk_signal_connect
139 (
140 GTK_OBJECT(m_widget), "switch_page",
141 GTK_SIGNAL_FUNC(gtk_notebook_page_change_callback),
142 (gpointer)this
143 );
144
145 PostCreation();
146
147 Show( TRUE );
148
149 return TRUE;
150 }
151
152 int wxNotebook::GetSelection() const
153 {
154 if (m_pages.Number() == 0) return -1;
155
156 GtkNotebookPage *g_page = GTK_NOTEBOOK(m_widget)->cur_page;
157
158 wxNotebookPage *page = (wxNotebookPage *) NULL;
159
160 wxNode *node = m_pages.First();
161 while (node)
162 {
163 page = (wxNotebookPage*)node->Data();
164 if (page->m_page == g_page)
165 break;
166 node = node->Next();
167 }
168
169 wxCHECK_MSG( node != NULL, -1, "wxNotebook: no selection?" );
170
171 return page->m_id;
172 }
173
174 int wxNotebook::GetPageCount() const
175 {
176 return m_pages.Number();
177 }
178
179 int wxNotebook::GetRowCount() const
180 {
181 return 1;
182 }
183
184 wxString wxNotebook::GetPageText( int page ) const
185 {
186 wxNotebookPage* nb_page = GetNotebookPage(page);
187 if (nb_page)
188 return nb_page->m_text;
189 else
190 return "";
191 }
192
193 int wxNotebook::GetPageImage( int page ) const
194 {
195 wxNotebookPage* nb_page = GetNotebookPage(page);
196 if (nb_page)
197 return nb_page->m_image;
198 else
199 return 0;
200 }
201
202 wxNotebookPage* wxNotebook::GetNotebookPage(int page) const
203 {
204 wxNotebookPage *nb_page = (wxNotebookPage *) NULL;
205
206 wxNode *node = m_pages.First();
207 while (node)
208 {
209 nb_page = (wxNotebookPage*)node->Data();
210 if (nb_page->m_id == page)
211 return nb_page;
212 node = node->Next();
213 }
214
215 wxLogDebug( "Notebook page %d not found!", page );
216
217 return (wxNotebookPage *) NULL;
218 }
219
220 int wxNotebook::SetSelection( int page )
221 {
222 int selOld = GetSelection();
223 wxNotebookPage* nb_page = GetNotebookPage(page);
224
225 if (!nb_page) return -1;
226
227 int page_num = 0;
228 GList *child = GTK_NOTEBOOK(m_widget)->children;
229 while (child)
230 {
231 if (nb_page->m_page == (GtkNotebookPage*)child->data) break;
232 page_num++;
233 child = child->next;
234 }
235
236 if (!child) return -1;
237
238 gtk_notebook_set_page( GTK_NOTEBOOK(m_widget), page_num );
239
240 return selOld;
241 }
242
243 void wxNotebook::AdvanceSelection( bool bForward )
244 {
245 int sel = GetSelection();
246 int max = GetPageCount();
247
248 if (bForward)
249 SetSelection( sel == max ? 0 : sel + 1 );
250 else
251 SetSelection( sel == 0 ? max : sel - 1 );
252 }
253
254 void wxNotebook::SetImageList( wxImageList* imageList )
255 {
256 m_imageList = imageList;
257 }
258
259 bool wxNotebook::SetPageText( int page, const wxString &text )
260 {
261 wxNotebookPage* nb_page = GetNotebookPage(page);
262
263 if (!nb_page) return FALSE;
264
265 nb_page->m_text = text;
266
267 return TRUE;
268 }
269
270 bool wxNotebook::SetPageImage( int page, int image )
271 {
272 wxNotebookPage* nb_page = GetNotebookPage(page);
273
274 if (!nb_page) return FALSE;
275
276 nb_page->m_image = image;
277
278 return TRUE;
279 }
280
281 void wxNotebook::SetPageSize( const wxSize &WXUNUSED(size) )
282 {
283 wxFAIL_MSG( "wxNotebook::SetPageSize not implemented" );
284 }
285
286 void wxNotebook::SetPadding( const wxSize &WXUNUSED(padding) )
287 {
288 wxFAIL_MSG( "wxNotebook::SetPadding not implemented" );
289 }
290
291 bool wxNotebook::DeleteAllPages()
292 {
293 wxNode *page_node = m_pages.First();
294 while (page_node)
295 {
296 wxNotebookPage *page = (wxNotebookPage*)page_node->Data();
297
298 DeletePage( page->m_id );
299
300 page_node = m_pages.First();
301 }
302
303 return TRUE;
304 }
305
306 bool wxNotebook::DeletePage( int page )
307 {
308 wxNotebookPage* nb_page = GetNotebookPage(page);
309 if (!nb_page) return FALSE;
310
311 int page_num = 0;
312 GList *child = GTK_NOTEBOOK(m_widget)->children;
313 while (child)
314 {
315 if (nb_page->m_page == (GtkNotebookPage*)child->data) break;
316 page_num++;
317 child = child->next;
318 }
319
320 wxASSERT( child );
321
322 delete nb_page->m_client;
323
324 // Amazingly, this is not necessary
325 // gtk_notebook_remove_page( GTK_NOTEBOOK(m_widget), page_num );
326
327 m_pages.DeleteObject( nb_page );
328
329 return TRUE;
330 }
331
332 bool wxNotebook::AddPage(wxWindow* win, const wxString& text,
333 bool bSelect, int imageId)
334 {
335 // we've created the notebook page in AddChild(). Now we just have to set
336 // the caption for the page and set the others parameters.
337
338 wxNotebookPage *page = (wxNotebookPage *) NULL;
339
340 wxNode *node = m_pages.First();
341 while (node)
342 {
343 page = (wxNotebookPage*)node->Data();
344 if ( page->m_client == win ) break;
345 node = node->Next();
346 }
347
348 wxCHECK_MSG( page != NULL, FALSE, "Can't add a page whose parent is not the notebook!" );
349
350 if (imageId != -1)
351 {
352 wxASSERT( m_imageList != NULL );
353
354 const wxBitmap *bmp = m_imageList->GetBitmap(imageId);
355 GdkPixmap *pixmap = bmp->GetPixmap();
356 GdkBitmap *mask = (GdkBitmap*) NULL;
357 if ( bmp->GetMask() )
358 {
359 mask = bmp->GetMask()->GetBitmap();
360 }
361
362 GtkWidget *pixmapwid = gtk_pixmap_new (pixmap, mask );
363
364 gtk_box_pack_start(GTK_BOX(page->m_box), pixmapwid, FALSE, FALSE, 3);
365
366 gtk_widget_show(pixmapwid);
367 }
368
369 // then set the attributes
370 page->m_text = text;
371 if (page->m_text.IsEmpty()) page->m_text = "";
372 page->m_image = imageId;
373 page->m_label = (GtkLabel *)gtk_label_new(page->m_text);
374 gtk_box_pack_start( GTK_BOX(page->m_box), (GtkWidget *)page->m_label, FALSE, FALSE, 3);
375
376 // @@@: what does this do? do we still need it?
377 // gtk_misc_set_alignment(GTK_MISC(page->m_label), 0.0, 0.5);
378
379 gtk_widget_show((GtkWidget *)page->m_label);
380
381 if (bSelect) SetSelection(GetPageCount());
382
383 return TRUE;
384 }
385
386 wxWindow *wxNotebook::GetPage( int page ) const
387 {
388 wxNotebookPage* nb_page = GetNotebookPage(page);
389 if (!nb_page)
390 return (wxWindow *) NULL;
391 else
392 return nb_page->m_client;
393 }
394
395 void wxNotebook::AddChild( wxWindow *win )
396 {
397 m_children.Append(win);
398
399 wxNotebookPage *page = new wxNotebookPage();
400
401 page->m_id = GetPageCount();
402
403 page->m_box = gtk_hbox_new (FALSE, 0);
404 gtk_container_border_width(GTK_CONTAINER(page->m_box), 2);
405
406 page->m_client = win;
407 gtk_notebook_append_page( GTK_NOTEBOOK(m_widget), win->m_widget, page->m_box );
408
409 page->m_page =
410 (GtkNotebookPage*) (g_list_last(GTK_NOTEBOOK(m_widget)->children)->data);
411
412 page->m_parent = GTK_NOTEBOOK(m_widget);
413
414 gtk_signal_connect( GTK_OBJECT(win->m_widget), "size_allocate",
415 GTK_SIGNAL_FUNC(gtk_page_size_callback), (gpointer)win );
416
417 if (!page->m_page)
418 {
419 wxLogFatalError( "Notebook page creation error" );
420 return;
421 }
422
423 m_pages.Append( page );
424 }
425
426 // override these 2 functions to do nothing: everything is done in OnSize
427 void wxNotebook::SetConstraintSizes( bool WXUNUSED(recurse) )
428 {
429 // don't set the sizes of the pages - their correct size is not yet known
430 wxControl::SetConstraintSizes(FALSE);
431 }
432
433 bool wxNotebook::DoPhase( int WXUNUSED(nPhase) )
434 {
435 return TRUE;
436 }
437
438 //-----------------------------------------------------------------------------
439 // wxNotebookEvent
440 //-----------------------------------------------------------------------------
441
442 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent, wxCommandEvent)
443