1 /////////////////////////////////////////////////////////////////////////////
4 // Author: Robert Roebling
6 // Copyright: (c) 1998 Robert Roebling, Vadim Zeitlin
7 // Licence: wxWindows licence
8 /////////////////////////////////////////////////////////////////////////////
11 #pragma implementation "notebook.h"
14 #include "wx/notebook.h"
17 #include "wx/imaglist.h"
21 //-----------------------------------------------------------------------------
23 //-----------------------------------------------------------------------------
25 class wxNotebookPage
: public wxObject
33 m_page
= (GtkNotebookPage
*) NULL
;
34 m_client
= (wxWindow
*) NULL
;
35 m_parent
= (GtkNotebook
*) NULL
;
36 m_box
= (GtkWidget
*) NULL
;
42 GtkNotebookPage
*m_page
;
45 GtkNotebook
*m_parent
;
46 GtkWidget
*m_box
; // in which the label and image are packed
49 //-----------------------------------------------------------------------------
51 //-----------------------------------------------------------------------------
53 static void gtk_notebook_page_change_callback(GtkNotebook
*WXUNUSED(widget
),
54 GtkNotebookPage
*WXUNUSED(page
),
58 wxNotebook
*notebook
= (wxNotebook
*)data
;
60 int old
= notebook
->GetSelection();
62 // TODO: emulate PAGE_CHANGING event
64 wxNotebookEvent
event( wxEVT_COMMAND_NOTEBOOK_PAGE_CHANGED
,
65 notebook
->GetId(), nPage
, old
);
66 event
.SetEventObject( notebook
);
67 notebook
->GetEventHandler()->ProcessEvent( event
);
70 //-----------------------------------------------------------------------------
72 //-----------------------------------------------------------------------------
74 static void gtk_page_size_callback( GtkWidget
*WXUNUSED(widget
), GtkAllocation
* alloc
, wxWindow
*win
)
76 if ((win
->m_x
== alloc
->x
) &&
77 (win
->m_y
== alloc
->y
) &&
78 (win
->m_width
== alloc
->width
) &&
79 (win
->m_height
== alloc
->height
))
84 win
->SetSize( alloc
->x
, alloc
->y
, alloc
->width
, alloc
->height
);
87 //-----------------------------------------------------------------------------
88 // InsertChild callback for wxNotebook
89 //-----------------------------------------------------------------------------
91 static void wxInsertChildInNotebook( wxNotebook
* parent
, wxWindow
* child
)
93 wxNotebookPage
*page
= new wxNotebookPage();
95 page
->m_id
= parent
->GetPageCount();
97 page
->m_box
= gtk_hbox_new (FALSE
, 0);
98 gtk_container_border_width(GTK_CONTAINER(page
->m_box
), 2);
100 GtkNotebook
*notebook
= GTK_NOTEBOOK(parent
->m_widget
);
102 page
->m_client
= child
;
103 gtk_notebook_append_page( notebook
, child
->m_widget
, page
->m_box
);
105 page
->m_page
= (GtkNotebookPage
*) (g_list_last(notebook
->children
)->data
);
107 page
->m_parent
= notebook
;
109 gtk_signal_connect( GTK_OBJECT(child
->m_widget
), "size_allocate",
110 GTK_SIGNAL_FUNC(gtk_page_size_callback
), (gpointer
)child
);
114 wxLogFatalError( "Notebook page creation error" );
118 parent
->m_pages
.Append( page
);
121 //-----------------------------------------------------------------------------
123 //-----------------------------------------------------------------------------
125 IMPLEMENT_DYNAMIC_CLASS(wxNotebook
,wxControl
)
127 void wxNotebook::Init()
129 m_imageList
= (wxImageList
*) NULL
;
130 m_pages
.DeleteContents( TRUE
);
134 wxNotebook::wxNotebook()
139 wxNotebook::wxNotebook( wxWindow
*parent
, wxWindowID id
,
140 const wxPoint
& pos
, const wxSize
& size
,
141 long style
, const wxString
& name
)
144 Create( parent
, id
, pos
, size
, style
, name
);
147 wxNotebook::~wxNotebook()
149 // don't generate change page events any more
150 if (m_idHandler
!= 0)
151 gtk_signal_disconnect(GTK_OBJECT(m_widget
), m_idHandler
);
156 bool wxNotebook::Create(wxWindow
*parent
, wxWindowID id
,
157 const wxPoint
& pos
, const wxSize
& size
,
158 long style
, const wxString
& name
)
161 m_insertCallback
= (wxInsertChildFunction
)wxInsertChildInNotebook
;
163 PreCreation( parent
, id
, pos
, size
, style
, name
);
165 m_widget
= gtk_notebook_new();
167 gtk_notebook_set_scrollable( GTK_NOTEBOOK(m_widget
), 1 );
169 m_idHandler
= gtk_signal_connect (
170 GTK_OBJECT(m_widget
), "switch_page",
171 GTK_SIGNAL_FUNC(gtk_notebook_page_change_callback
),
174 m_parent
->AddChild( this );
176 (m_parent
->m_insertCallback
)( m_parent
, this );
185 int wxNotebook::GetSelection() const
187 wxCHECK_MSG( m_widget
!= NULL
, -1, "invalid notebook" );
189 if (m_pages
.Number() == 0) return -1;
191 GtkNotebookPage
*g_page
= GTK_NOTEBOOK(m_widget
)->cur_page
;
192 if (!g_page
) return -1;
194 wxNotebookPage
*page
= (wxNotebookPage
*) NULL
;
196 wxNode
*node
= m_pages
.First();
199 page
= (wxNotebookPage
*)node
->Data();
201 if ((page
->m_page
== g_page
) || (page
->m_page
== (GtkNotebookPage
*)NULL
))
203 // page->m_page is NULL directly after gtk_notebook_append. gtk emits
204 // "switch_page" then and we ask for GetSelection() in the handler for
205 // "switch_page". otherwise m_page should never be NULL. all this
206 // might also be wrong.
212 wxCHECK_MSG( node
!= NULL
, -1, "wxNotebook: no selection?" );
217 int wxNotebook::GetPageCount() const
219 return m_pages
.Number();
222 int wxNotebook::GetRowCount() const
227 wxString
wxNotebook::GetPageText( int page
) const
229 wxCHECK_MSG( m_widget
!= NULL
, "", "invalid notebook" );
231 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
233 return nb_page
->m_text
;
238 int wxNotebook::GetPageImage( int page
) const
240 wxCHECK_MSG( m_widget
!= NULL
, 0, "invalid notebook" );
242 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
244 return nb_page
->m_image
;
249 wxNotebookPage
* wxNotebook::GetNotebookPage(int page
) const
251 wxCHECK_MSG( m_widget
!= NULL
, (wxNotebookPage
*)NULL
, "invalid notebook" );
253 wxNotebookPage
*nb_page
= (wxNotebookPage
*) NULL
;
255 wxNode
*node
= m_pages
.First();
258 nb_page
= (wxNotebookPage
*)node
->Data();
259 if (nb_page
->m_id
== page
)
264 wxLogDebug( "Notebook page %d not found!", page
);
266 return (wxNotebookPage
*) NULL
;
269 int wxNotebook::SetSelection( int page
)
271 wxCHECK_MSG( m_widget
!= NULL
, -1, "invalid notebook" );
273 int selOld
= GetSelection();
274 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
276 if (!nb_page
) return -1;
279 GList
*child
= GTK_NOTEBOOK(m_widget
)->children
;
282 if (nb_page
->m_page
== (GtkNotebookPage
*)child
->data
) break;
287 if (!child
) return -1;
289 gtk_notebook_set_page( GTK_NOTEBOOK(m_widget
), page_num
);
294 void wxNotebook::AdvanceSelection( bool bForward
)
296 wxCHECK_RET( m_widget
!= NULL
, "invalid notebook" );
298 int sel
= GetSelection();
299 int max
= GetPageCount();
302 SetSelection( sel
== max
? 0 : sel
+ 1 );
304 SetSelection( sel
== 0 ? max
: sel
- 1 );
307 void wxNotebook::SetImageList( wxImageList
* imageList
)
309 m_imageList
= imageList
;
312 bool wxNotebook::SetPageText( int page
, const wxString
&text
)
314 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid notebook" );
316 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
318 if (!nb_page
) return FALSE
;
320 nb_page
->m_text
= text
;
325 bool wxNotebook::SetPageImage( int page
, int image
)
327 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
329 if (!nb_page
) return FALSE
;
331 nb_page
->m_image
= image
;
336 void wxNotebook::SetPageSize( const wxSize
&WXUNUSED(size
) )
338 wxFAIL_MSG( "wxNotebook::SetPageSize not implemented" );
341 void wxNotebook::SetPadding( const wxSize
&WXUNUSED(padding
) )
343 wxFAIL_MSG( "wxNotebook::SetPadding not implemented" );
346 bool wxNotebook::DeleteAllPages()
348 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid notebook" );
350 wxNode
*page_node
= m_pages
.First();
353 wxNotebookPage
*page
= (wxNotebookPage
*)page_node
->Data();
355 DeletePage( page
->m_id
);
357 page_node
= m_pages
.First();
363 bool wxNotebook::DeletePage( int page
)
365 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
366 if (!nb_page
) return FALSE
;
369 GList
*child
= GTK_NOTEBOOK(m_widget
)->children
;
372 if (nb_page
->m_page
== (GtkNotebookPage
*)child
->data
) break;
377 wxCHECK_MSG( child
!= NULL
, FALSE
, "illegal notebook index" );
379 delete nb_page
->m_client
;
381 m_pages
.DeleteObject( nb_page
);
386 bool wxNotebook::RemovePage( int page
)
388 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
389 if (!nb_page
) return FALSE
;
392 GList
*child
= GTK_NOTEBOOK(m_widget
)->children
;
395 if (nb_page
->m_page
== (GtkNotebookPage
*)child
->data
) break;
400 wxCHECK_MSG( child
!= NULL
, FALSE
, "illegal notebook index" );
402 gtk_notebook_remove_page( GTK_NOTEBOOK(m_widget
), page_num
);
404 m_pages
.DeleteObject( nb_page
);
409 bool wxNotebook::AddPage(wxWindow
* win
, const wxString
& text
,
410 bool bSelect
, int imageId
)
412 wxCHECK_MSG( m_widget
!= NULL
, FALSE
, "invalid notebook" );
414 // we've created the notebook page in AddChild(). Now we just have to set
415 // the caption for the page and set the others parameters.
417 wxNotebookPage
*page
= (wxNotebookPage
*) NULL
;
419 wxNode
*node
= m_pages
.First();
422 page
= (wxNotebookPage
*)node
->Data();
423 if ( page
->m_client
== win
) break;
427 wxCHECK_MSG( page
!= NULL
, FALSE
, "Can't add a page whose parent is not the notebook!" );
431 wxASSERT( m_imageList
!= NULL
);
433 const wxBitmap
*bmp
= m_imageList
->GetBitmap(imageId
);
434 GdkPixmap
*pixmap
= bmp
->GetPixmap();
435 GdkBitmap
*mask
= (GdkBitmap
*) NULL
;
436 if ( bmp
->GetMask() )
438 mask
= bmp
->GetMask()->GetBitmap();
441 GtkWidget
*pixmapwid
= gtk_pixmap_new (pixmap
, mask
);
443 gtk_box_pack_start(GTK_BOX(page
->m_box
), pixmapwid
, FALSE
, FALSE
, 3);
445 gtk_widget_show(pixmapwid
);
448 // then set the attributes
450 if (page
->m_text
.IsEmpty()) page
->m_text
= "";
451 page
->m_image
= imageId
;
452 page
->m_label
= (GtkLabel
*)gtk_label_new(page
->m_text
);
453 gtk_box_pack_start( GTK_BOX(page
->m_box
), (GtkWidget
*)page
->m_label
, FALSE
, FALSE
, 3);
455 // @@@: what does this do? do we still need it?
456 // gtk_misc_set_alignment(GTK_MISC(page->m_label), 0.0, 0.5);
458 gtk_widget_show((GtkWidget
*)page
->m_label
);
460 if (bSelect
) SetSelection(GetPageCount());
465 wxWindow
*wxNotebook::GetPage( int page
) const
467 wxCHECK_MSG( m_widget
!= NULL
, (wxWindow
*) NULL
, "invalid notebook" );
469 wxNotebookPage
* nb_page
= GetNotebookPage(page
);
471 return (wxWindow
*) NULL
;
473 return nb_page
->m_client
;
476 // override these 2 functions to do nothing: everything is done in OnSize
477 void wxNotebook::SetConstraintSizes( bool WXUNUSED(recurse
) )
479 // don't set the sizes of the pages - their correct size is not yet known
480 wxControl::SetConstraintSizes(FALSE
);
483 bool wxNotebook::DoPhase( int WXUNUSED(nPhase
) )
488 void wxNotebook::ApplyWidgetStyle()
491 gtk_widget_set_style( m_widget
, m_widgetStyle
);
494 //-----------------------------------------------------------------------------
496 //-----------------------------------------------------------------------------
498 IMPLEMENT_DYNAMIC_CLASS(wxNotebookEvent
, wxCommandEvent
)