1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: generic/listbkg.cpp
3 // Purpose: generic implementation of wxListbook
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
12 // ============================================================================
14 // ============================================================================
16 // ----------------------------------------------------------------------------
18 // ----------------------------------------------------------------------------
20 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "listbook.h"
24 // For compilers that support precompilation, includes "wx.h".
25 #include "wx/wxprec.h"
33 #include "wx/listctrl.h"
34 #include "wx/statline.h"
35 #include "wx/listbook.h"
36 #include "wx/imaglist.h"
38 // ----------------------------------------------------------------------------
40 // ----------------------------------------------------------------------------
42 // margin between the list and the page, should be bigger than wxStaticLine
44 const wxCoord MARGIN
= 5;
46 // ----------------------------------------------------------------------------
47 // various wxWindows macros
48 // ----------------------------------------------------------------------------
50 IMPLEMENT_DYNAMIC_CLASS(wxListbook
, wxControl
)
51 IMPLEMENT_DYNAMIC_CLASS(wxListbookEvent
, wxNotifyEvent
)
53 const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
= wxNewEventType();
54 const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
= wxNewEventType();
56 BEGIN_EVENT_TABLE(wxListbook
, wxBookCtrl
)
57 EVT_SIZE(wxListbook
::OnSize
)
59 EVT_LIST_ITEM_SELECTED(wxID_ANY
, wxListbook
::OnListSelected
)
62 // ============================================================================
63 // wxListbook implementation
64 // ============================================================================
66 // ----------------------------------------------------------------------------
67 // wxListbook creation
68 // ----------------------------------------------------------------------------
70 void wxListbook
::Init()
74 m_selection
= wxNOT_FOUND
;
78 wxListbook
::Create(wxWindow
*parent
,
85 if ( (style
& wxLB_ALIGN_MASK
) == wxLB_DEFAULT
)
91 #endif // __WXMAC__/!__WXMAC__
94 if ( !wxControl
::Create(parent
, id
, pos
, size
, style
,
95 wxDefaultValidator
, name
) )
98 m_list
= new wxListView
104 wxLC_ICON
| wxLC_SINGLE_SEL
107 m_line
= new wxStaticLine
113 IsVertical() ? wxLI_HORIZONTAL
: wxLI_VERTICAL
119 // ----------------------------------------------------------------------------
120 // wxListbook geometry management
121 // ----------------------------------------------------------------------------
123 wxSize wxListbook
::GetListSize() const
125 const wxSize sizeClient
= GetClientSize();
127 // we need to find the longest/tallest label
128 wxCoord widthMax
= 0,
130 const int count
= m_list
->GetItemCount();
133 for ( int i
= 0; i
< count
; i
++ )
136 m_list
->GetItemRect(i
, r
);
138 wxCoord w
= r
.x
+ r
.width
,
151 size
.x
= sizeClient
.x
;
154 else // left/right aligned
156 size
.x
= widthMax
+ 10;
157 size
.y
= sizeClient
.y
;
163 wxRect wxListbook
::GetPageRect() const
165 const wxSize sizeList
= GetListSize();
167 wxRect
rectPage(wxPoint(0, 0), GetClientSize());
168 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
171 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
175 rectPage
.y
= sizeList
.y
+ MARGIN
;
179 rectPage
.height
-= sizeList
.y
+ MARGIN
;
183 rectPage
.x
= sizeList
.x
+ MARGIN
;
187 rectPage
.width
-= sizeList
.x
+ MARGIN
;
194 void wxListbook
::OnSize(wxSizeEvent
& event
)
196 // resize the list control and the page area to fit inside our new size
197 const wxSize sizeClient
= GetClientSize(),
198 sizeList
= GetListSize();
201 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
204 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
209 // posList is already ok
213 posList
.y
= sizeClient
.y
- sizeList
.y
;
217 posList
.x
= sizeClient
.x
- sizeList
.x
;
221 m_list
->SetSize(posList
.x
, posList
.y
, sizeList
.x
, sizeList
.y
);
225 wxRect
rectLine(wxPoint(0, 0), sizeClient
);
227 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
230 rectLine
.y
= sizeList
.y
+ 1;
231 rectLine
.height
= MARGIN
- 2;
235 rectLine
.height
= MARGIN
- 2;
236 rectLine
.y
= sizeClient
.y
- sizeList
.y
- rectLine
.height
;
240 rectLine
.x
= sizeList
.x
+ 1;
241 rectLine
.width
= MARGIN
- 2;
245 rectLine
.width
= MARGIN
- 2;
246 rectLine
.x
= sizeClient
.x
- sizeList
.x
- rectLine
.width
;
250 m_line
->SetSize(rectLine
);
253 // we should always have some selection if possible
254 if ( m_selection
== wxNOT_FOUND
&& GetPageCount() )
259 if ( m_selection
!= wxNOT_FOUND
)
261 wxWindow
*page
= m_pages
[m_selection
];
262 wxCHECK_RET( page
, _T("NULL page in wxListbook?") );
264 page
->SetSize(GetPageRect());
265 if ( !page
->IsShown() )
274 wxSize wxListbook
::CalcSizeFromPage(const wxSize
& sizePage
) const
276 // we need to add the size of the list control and the margin
277 const wxSize sizeList
= GetListSize();
279 wxSize size
= sizePage
;
282 size
.y
+= sizeList
.y
+ MARGIN
;
284 else // left/right aligned
286 size
.x
+= sizeList
.x
+ MARGIN
;
293 // ----------------------------------------------------------------------------
294 // accessing the pages
295 // ----------------------------------------------------------------------------
297 bool wxListbook
::SetPageText(size_t n
, const wxString
& strText
)
299 m_list
->SetItemText(n
, strText
);
304 wxString wxListbook
::GetPageText(size_t n
) const
306 return m_list
->GetItemText(n
);
309 int wxListbook
::GetPageImage(size_t WXUNUSED(n
)) const
311 wxFAIL_MSG( _T("wxListbook::GetPageImage() not implemented") );
316 bool wxListbook
::SetPageImage(size_t n
, int imageId
)
318 return m_list
->SetItemImage(n
, imageId
, imageId
);
321 // ----------------------------------------------------------------------------
323 // ----------------------------------------------------------------------------
325 void wxListbook
::SetImageList(wxImageList
*imageList
)
327 m_list
->SetImageList(imageList
, wxIMAGE_LIST_NORMAL
);
329 wxBookCtrl
::SetImageList(imageList
);
332 // ----------------------------------------------------------------------------
334 // ----------------------------------------------------------------------------
336 int wxListbook
::GetSelection() const
341 int wxListbook
::SetSelection(size_t n
)
343 wxCHECK_MSG( n
< GetPageCount(), wxNOT_FOUND
,
344 _T("invalid page index in wxListbook::SetSelection()") );
346 int selOld
= m_selection
;
348 if ( (int)n
!= m_selection
)
352 m_list
->Select(m_selection
);
353 m_list
->Focus(m_selection
);
360 // ----------------------------------------------------------------------------
361 // adding/removing the pages
362 // ----------------------------------------------------------------------------
365 wxListbook
::InsertPage(size_t n
,
367 const wxString
& text
,
371 if ( !wxBookCtrl
::InsertPage(n
, page
, text
, bSelect
, imageId
) )
374 m_list
->InsertItem(n
, text
, imageId
);
381 else // don't select this page
383 // it will be shown only when selected
390 wxWindow
*wxListbook
::DoRemovePage(size_t page
)
392 wxWindow
*win
= wxBookCtrl
::DoRemovePage(page
);
395 m_list
->DeleteItem(page
);
401 // ----------------------------------------------------------------------------
403 // ----------------------------------------------------------------------------
405 void wxListbook
::OnListSelected(wxListEvent
& eventList
)
407 const int selNew
= eventList
.GetIndex();
409 if ( selNew
== m_selection
)
411 // this event can only come from our own Select(m_selection) below
412 // which we call when the page change is vetoed, so we should simply
417 // first send "change in progress" event which may be vetoed by user
418 wxListbookEvent
eventIng(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
, GetId());
420 eventIng
.SetEventObject(this);
421 eventIng
.SetSelection(selNew
);
422 eventIng
.SetOldSelection(m_selection
);
423 if ( GetEventHandler()->ProcessEvent(eventIng
) && !eventIng
.IsAllowed() )
425 m_list
->Select(m_selection
);
429 // change allowed: do change the page and notify the user about it
430 if ( m_selection
!= wxNOT_FOUND
)
431 m_pages
[m_selection
]->Hide();
432 wxWindow
*page
= m_pages
[m_selection
= selNew
];
433 page
->SetSize(GetPageRect());
436 wxListbookEvent
eventEd(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
, GetId());
438 eventEd
.SetEventObject(this);
439 eventEd
.SetSelection(selNew
);
440 eventEd
.SetOldSelection(m_selection
);
442 (void)GetEventHandler()->ProcessEvent(eventEd
);
445 #endif // wxUSE_LISTBOOK