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"
37 #include "wx/settings.h"
39 // ----------------------------------------------------------------------------
41 // ----------------------------------------------------------------------------
43 // margin between the list and the page, should be bigger than wxStaticLine
45 const wxCoord MARGIN
= 5;
47 // ----------------------------------------------------------------------------
48 // various wxWindows macros
49 // ----------------------------------------------------------------------------
51 IMPLEMENT_DYNAMIC_CLASS(wxListbook
, wxControl
)
52 IMPLEMENT_DYNAMIC_CLASS(wxListbookEvent
, wxNotifyEvent
)
54 const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
= wxNewEventType();
55 const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
= wxNewEventType();
57 BEGIN_EVENT_TABLE(wxListbook
, wxBookCtrl
)
58 EVT_SIZE(wxListbook::OnSize
)
60 EVT_LIST_ITEM_SELECTED(wxID_ANY
, wxListbook::OnListSelected
)
63 // ============================================================================
64 // wxListbook implementation
65 // ============================================================================
67 // ----------------------------------------------------------------------------
68 // wxListbook creation
69 // ----------------------------------------------------------------------------
71 void wxListbook::Init()
75 m_selection
= wxNOT_FOUND
;
79 wxListbook::Create(wxWindow
*parent
,
86 if ( (style
& wxLB_ALIGN_MASK
) == wxLB_DEFAULT
)
92 #endif // __WXMAC__/!__WXMAC__
95 if ( !wxControl::Create(parent
, id
, pos
, size
, style
,
96 wxDefaultValidator
, name
) )
99 m_list
= new wxListView
105 wxLC_ICON
| wxLC_SINGLE_SEL
108 m_line
= new wxStaticLine
114 IsVertical() ? wxLI_HORIZONTAL
: wxLI_VERTICAL
120 // ----------------------------------------------------------------------------
121 // wxListbook geometry management
122 // ----------------------------------------------------------------------------
124 wxSize
wxListbook::GetListSize() const
126 const wxSize sizeClient
= GetClientSize();
128 // we need to find the longest/tallest label
129 wxCoord widthMax
= 0,
131 const int count
= m_list
->GetItemCount();
134 for ( int i
= 0; i
< count
; i
++ )
137 m_list
->GetItemRect(i
, r
);
139 wxCoord w
= r
.x
+ r
.width
,
152 size
.x
= sizeClient
.x
;
155 if ( widthMax
>= sizeClient
.x
)
157 // account for the scrollbar
158 size
.y
+= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y
);
161 else // left/right aligned
163 // +10 is due to an apparent bug in wxListCtrl::GetItemRect() but I
164 // can't fix it there right now so just add a fudge here...
165 size
.x
= widthMax
+ 10;
166 size
.y
= sizeClient
.y
;
168 if ( heightMax
>= sizeClient
.y
)
170 // account for the scrollbar
171 size
.x
+= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
178 wxRect
wxListbook::GetPageRect() const
180 const wxSize sizeList
= GetListSize();
182 wxRect
rectPage(wxPoint(0, 0), GetClientSize());
183 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
186 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
190 rectPage
.y
= sizeList
.y
+ MARGIN
;
194 rectPage
.height
-= sizeList
.y
+ MARGIN
;
198 rectPage
.x
= sizeList
.x
+ MARGIN
;
202 rectPage
.width
-= sizeList
.x
+ MARGIN
;
209 void wxListbook::OnSize(wxSizeEvent
& event
)
215 // we're not fully created yet
219 // resize the list control and the page area to fit inside our new size
220 const wxSize sizeClient
= GetClientSize(),
221 sizeList
= GetListSize();
224 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
227 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
232 // posList is already ok
236 posList
.y
= sizeClient
.y
- sizeList
.y
;
240 posList
.x
= sizeClient
.x
- sizeList
.x
;
244 m_list
->SetSize(posList
.x
, posList
.y
, sizeList
.x
, sizeList
.y
);
248 wxRect
rectLine(wxPoint(0, 0), sizeClient
);
250 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
253 rectLine
.y
= sizeList
.y
+ 1;
254 rectLine
.height
= MARGIN
- 2;
258 rectLine
.height
= MARGIN
- 2;
259 rectLine
.y
= sizeClient
.y
- sizeList
.y
- rectLine
.height
;
263 rectLine
.x
= sizeList
.x
+ 1;
264 rectLine
.width
= MARGIN
- 2;
268 rectLine
.width
= MARGIN
- 2;
269 rectLine
.x
= sizeClient
.x
- sizeList
.x
- rectLine
.width
;
273 m_line
->SetSize(rectLine
);
276 // we should always have some selection if possible
277 if ( m_selection
== wxNOT_FOUND
&& GetPageCount() )
282 if ( m_selection
!= wxNOT_FOUND
)
284 wxWindow
*page
= m_pages
[m_selection
];
285 wxCHECK_RET( page
, _T("NULL page in wxListbook?") );
287 page
->SetSize(GetPageRect());
288 if ( !page
->IsShown() )
295 wxSize
wxListbook::CalcSizeFromPage(const wxSize
& sizePage
) const
297 // we need to add the size of the list control and the margin
298 const wxSize sizeList
= GetListSize();
300 wxSize size
= sizePage
;
303 size
.y
+= sizeList
.y
+ MARGIN
;
305 else // left/right aligned
307 size
.x
+= sizeList
.x
+ MARGIN
;
314 // ----------------------------------------------------------------------------
315 // accessing the pages
316 // ----------------------------------------------------------------------------
318 bool wxListbook::SetPageText(size_t n
, const wxString
& strText
)
320 m_list
->SetItemText(n
, strText
);
325 wxString
wxListbook::GetPageText(size_t n
) const
327 return m_list
->GetItemText(n
);
330 int wxListbook::GetPageImage(size_t WXUNUSED(n
)) const
332 wxFAIL_MSG( _T("wxListbook::GetPageImage() not implemented") );
337 bool wxListbook::SetPageImage(size_t n
, int imageId
)
339 return m_list
->SetItemImage(n
, imageId
, imageId
);
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
346 void wxListbook::SetImageList(wxImageList
*imageList
)
348 m_list
->SetImageList(imageList
, wxIMAGE_LIST_NORMAL
);
350 wxBookCtrl::SetImageList(imageList
);
353 // ----------------------------------------------------------------------------
355 // ----------------------------------------------------------------------------
357 int wxListbook::GetSelection() const
362 int wxListbook::SetSelection(size_t n
)
364 wxCHECK_MSG( n
< GetPageCount(), wxNOT_FOUND
,
365 _T("invalid page index in wxListbook::SetSelection()") );
367 int selOld
= m_selection
;
369 if ( (int)n
!= m_selection
)
373 m_list
->Select(m_selection
);
374 m_list
->Focus(m_selection
);
381 // ----------------------------------------------------------------------------
382 // adding/removing the pages
383 // ----------------------------------------------------------------------------
386 wxListbook::InsertPage(size_t n
,
388 const wxString
& text
,
392 if ( !wxBookCtrl::InsertPage(n
, page
, text
, bSelect
, imageId
) )
395 m_list
->InsertItem(n
, text
, imageId
);
402 else // don't select this page
404 // it will be shown only when selected
411 wxWindow
*wxListbook::DoRemovePage(size_t page
)
413 wxWindow
*win
= wxBookCtrl::DoRemovePage(page
);
416 m_list
->DeleteItem(page
);
422 // ----------------------------------------------------------------------------
424 // ----------------------------------------------------------------------------
426 void wxListbook::OnListSelected(wxListEvent
& eventList
)
428 const int selNew
= eventList
.GetIndex();
430 if ( selNew
== m_selection
)
432 // this event can only come from our own Select(m_selection) below
433 // which we call when the page change is vetoed, so we should simply
438 // first send "change in progress" event which may be vetoed by user
439 wxListbookEvent
eventIng(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
, GetId());
441 eventIng
.SetEventObject(this);
442 eventIng
.SetSelection(selNew
);
443 eventIng
.SetOldSelection(m_selection
);
444 if ( GetEventHandler()->ProcessEvent(eventIng
) && !eventIng
.IsAllowed() )
446 m_list
->Select(m_selection
);
450 // change allowed: do change the page and notify the user about it
451 if ( m_selection
!= wxNOT_FOUND
)
452 m_pages
[m_selection
]->Hide();
453 wxWindow
*page
= m_pages
[m_selection
= selNew
];
454 page
->SetSize(GetPageRect());
457 wxListbookEvent
eventEd(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
, GetId());
459 eventEd
.SetEventObject(this);
460 eventEd
.SetSelection(selNew
);
461 eventEd
.SetOldSelection(m_selection
);
463 (void)GetEventHandler()->ProcessEvent(eventEd
);
466 #endif // wxUSE_LISTBOOK