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 wxWidgets 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();
56 const int wxID_LISTBOOKLISTVIEW
= wxNewId();
58 BEGIN_EVENT_TABLE(wxListbook
, wxBookCtrl
)
59 EVT_SIZE(wxListbook::OnSize
)
60 EVT_LIST_ITEM_SELECTED(wxID_LISTBOOKLISTVIEW
, wxListbook::OnListSelected
)
63 // ============================================================================
64 // wxListbook implementation
65 // ============================================================================
67 // ----------------------------------------------------------------------------
68 // wxListbook creation
69 // ----------------------------------------------------------------------------
71 void wxListbook::Init()
74 #if wxUSE_LINE_IN_LISTBOOK
76 #endif // wxUSE_LINE_IN_LISTBOOK
77 m_selection
= wxNOT_FOUND
;
81 wxListbook::Create(wxWindow
*parent
,
88 if ( (style
& wxLB_ALIGN_MASK
) == wxLB_DEFAULT
)
94 #endif // __WXMAC__/!__WXMAC__
97 // no border for this control, it doesn't look nice together with
99 style
&= ~wxBORDER_MASK
;
100 style
|= wxBORDER_NONE
;
102 if ( !wxControl::Create(parent
, id
, pos
, size
, style
,
103 wxDefaultValidator
, name
) )
106 m_list
= new wxListView
109 wxID_LISTBOOKLISTVIEW
,
112 wxLC_ICON
| wxLC_SINGLE_SEL
|
113 (IsVertical() ? wxLC_ALIGN_LEFT
: wxLC_ALIGN_TOP
)
116 #if wxUSE_LINE_IN_LISTBOOK
117 m_line
= new wxStaticLine
123 IsVertical() ? wxLI_HORIZONTAL
: wxLI_VERTICAL
125 #endif // wxUSE_LINE_IN_LISTBOOK
128 // On XP with themes enabled the GetViewRect used in GetListSize to
129 // determine the space needed for the list view will incorrectly return
130 // (0,0,0,0) the first time. So send a pending event so OnSize wiull be
131 // called again after the window is ready to go. Technically we don't
132 // need to do this on non-XP windows, but if things are already sized
133 // correctly then nothing changes and so there is no harm.
135 GetEventHandler()->AddPendingEvent(evt
);
140 // ----------------------------------------------------------------------------
141 // wxListbook geometry management
142 // ----------------------------------------------------------------------------
144 wxSize
wxListbook::GetListSize() const
146 const wxSize sizeClient
= GetClientSize(),
147 sizeList
= m_list
->GetViewRect().GetSize();
152 size
.x
= sizeClient
.x
;
155 else // left/right aligned
158 size
.y
= sizeClient
.y
;
164 wxRect
wxListbook::GetPageRect() const
166 const wxSize sizeList
= m_list
->GetSize();
168 wxRect
rectPage(wxPoint(0, 0), GetClientSize());
169 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
172 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
176 rectPage
.y
= sizeList
.y
+ MARGIN
;
180 rectPage
.height
-= sizeList
.y
+ MARGIN
;
184 rectPage
.x
= sizeList
.x
+ MARGIN
;
188 rectPage
.width
-= sizeList
.x
+ MARGIN
;
195 void wxListbook::OnSize(wxSizeEvent
& event
)
201 // we're not fully created yet
205 // resize the list control and the page area to fit inside our new size
206 const wxSize sizeClient
= GetClientSize(),
207 sizeList
= GetListSize();
210 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
213 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
218 // posList is already ok
222 posList
.y
= sizeClient
.y
- sizeList
.y
;
226 posList
.x
= sizeClient
.x
- sizeList
.x
;
230 m_list
->Move(posList
.x
, posList
.y
);
231 m_list
->SetClientSize(sizeList
.x
, sizeList
.y
);
233 #if wxUSE_LINE_IN_LISTBOOK
236 wxRect
rectLine(wxPoint(0, 0), sizeClient
);
238 switch ( GetWindowStyle() & wxLB_ALIGN_MASK
)
241 rectLine
.y
= sizeList
.y
+ 1;
242 rectLine
.height
= MARGIN
- 2;
246 rectLine
.height
= MARGIN
- 2;
247 rectLine
.y
= sizeClient
.y
- sizeList
.y
- rectLine
.height
;
251 rectLine
.x
= sizeList
.x
+ 1;
252 rectLine
.width
= MARGIN
- 2;
256 rectLine
.width
= MARGIN
- 2;
257 rectLine
.x
= sizeClient
.x
- sizeList
.x
- rectLine
.width
;
261 m_line
->SetSize(rectLine
);
263 #endif // wxUSE_LINE_IN_LISTBOOK
265 // we should always have some selection if possible
266 if ( m_selection
== wxNOT_FOUND
&& GetPageCount() )
271 if ( m_selection
!= wxNOT_FOUND
)
273 wxWindow
*page
= m_pages
[m_selection
];
274 wxCHECK_RET( page
, _T("NULL page in wxListbook?") );
276 page
->SetSize(GetPageRect());
277 if ( !page
->IsShown() )
284 wxSize
wxListbook::CalcSizeFromPage(const wxSize
& sizePage
) const
286 // we need to add the size of the list control and the margin
287 const wxSize sizeList
= GetListSize();
289 wxSize size
= sizePage
;
292 size
.y
+= sizeList
.y
+ MARGIN
;
294 else // left/right aligned
296 size
.x
+= sizeList
.x
+ MARGIN
;
303 // ----------------------------------------------------------------------------
304 // accessing the pages
305 // ----------------------------------------------------------------------------
307 bool wxListbook::SetPageText(size_t n
, const wxString
& strText
)
309 m_list
->SetItemText(n
, strText
);
314 wxString
wxListbook::GetPageText(size_t n
) const
316 return m_list
->GetItemText(n
);
319 int wxListbook::GetPageImage(size_t WXUNUSED(n
)) const
321 wxFAIL_MSG( _T("wxListbook::GetPageImage() not implemented") );
326 bool wxListbook::SetPageImage(size_t n
, int imageId
)
328 return m_list
->SetItemImage(n
, imageId
, imageId
);
331 // ----------------------------------------------------------------------------
333 // ----------------------------------------------------------------------------
335 void wxListbook::SetImageList(wxImageList
*imageList
)
337 m_list
->SetImageList(imageList
, wxIMAGE_LIST_NORMAL
);
339 wxBookCtrl::SetImageList(imageList
);
342 // ----------------------------------------------------------------------------
344 // ----------------------------------------------------------------------------
346 int wxListbook::GetSelection() const
351 int wxListbook::SetSelection(size_t n
)
353 wxCHECK_MSG( n
< GetPageCount(), wxNOT_FOUND
,
354 _T("invalid page index in wxListbook::SetSelection()") );
356 int selOld
= m_selection
;
358 if ( (int)n
!= m_selection
)
363 // change m_selection only now, otherwise OnListSelected() would ignore
364 // the selection change event
372 // ----------------------------------------------------------------------------
373 // adding/removing the pages
374 // ----------------------------------------------------------------------------
377 wxListbook::InsertPage(size_t n
,
379 const wxString
& text
,
383 if ( !wxBookCtrl::InsertPage(n
, page
, text
, bSelect
, imageId
) )
386 m_list
->InsertItem(n
, text
, imageId
);
393 else // don't select this page
395 // it will be shown only when selected
399 InvalidateBestSize();
403 wxWindow
*wxListbook::DoRemovePage(size_t page
)
405 wxWindow
*win
= wxBookCtrl::DoRemovePage(page
);
408 m_list
->DeleteItem(page
);
414 // ----------------------------------------------------------------------------
416 // ----------------------------------------------------------------------------
418 void wxListbook::OnListSelected(wxListEvent
& eventList
)
420 const int selNew
= eventList
.GetIndex();
422 if ( selNew
== m_selection
)
424 // this event can only come from our own Select(m_selection) below
425 // which we call when the page change is vetoed, so we should simply
430 // first send "change in progress" event which may be vetoed by user
431 wxListbookEvent
eventIng(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING
, GetId());
433 eventIng
.SetEventObject(this);
434 eventIng
.SetSelection(selNew
);
435 eventIng
.SetOldSelection(m_selection
);
436 if ( GetEventHandler()->ProcessEvent(eventIng
) && !eventIng
.IsAllowed() )
438 m_list
->Select(m_selection
);
442 // change allowed: do change the page and notify the user about it
443 if ( m_selection
!= wxNOT_FOUND
)
444 m_pages
[m_selection
]->Hide();
445 wxWindow
*page
= m_pages
[m_selection
= selNew
];
446 page
->SetSize(GetPageRect());
449 wxListbookEvent
eventEd(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED
, GetId());
451 eventEd
.SetEventObject(this);
452 eventEd
.SetSelection(selNew
);
453 eventEd
.SetOldSelection(m_selection
);
455 (void)GetEventHandler()->ProcessEvent(eventEd
);
458 #endif // wxUSE_LISTBOOK