]> git.saurik.com Git - wxWidgets.git/blame - src/generic/listbkg.cpp
added wxTextCtrl::HitTest(); implemented it for MSW
[wxWidgets.git] / src / generic / listbkg.cpp
CommitLineData
e9c0df38
VZ
1///////////////////////////////////////////////////////////////////////////////
2// Name: generic/listbkg.cpp
3// Purpose: generic implementation of wxListbook
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 19.08.03
7// RCS-ID: $Id$
8// Copyright: (c) 2003 Vadim Zeitlin <vadim@wxwindows.org>
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
20#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
21 #pragma implementation "listbook.h"
22#endif
23
24// For compilers that support precompilation, includes "wx.h".
25#include "wx/wxprec.h"
26
27#ifdef __BORLANDC__
28 #pragma hdrstop
29#endif
30
31#if wxUSE_LISTBOOK
32
33#include "wx/listctrl.h"
34#include "wx/statline.h"
35#include "wx/listbook.h"
5b24f0d3 36#include "wx/imaglist.h"
c59da60a 37#include "wx/settings.h"
e9c0df38
VZ
38
39// ----------------------------------------------------------------------------
40// constants
41// ----------------------------------------------------------------------------
42
43// margin between the list and the page, should be bigger than wxStaticLine
44// size
45const wxCoord MARGIN = 5;
46
47// ----------------------------------------------------------------------------
48// various wxWindows macros
49// ----------------------------------------------------------------------------
50
51IMPLEMENT_DYNAMIC_CLASS(wxListbook, wxControl)
52IMPLEMENT_DYNAMIC_CLASS(wxListbookEvent, wxNotifyEvent)
53
54const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING = wxNewEventType();
55const wxEventType wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED = wxNewEventType();
f29395d0 56const int wxID_LISTBOOKLISTVIEW = wxNewId();
e9c0df38
VZ
57
58BEGIN_EVENT_TABLE(wxListbook, wxBookCtrl)
59 EVT_SIZE(wxListbook::OnSize)
f29395d0 60 EVT_LIST_ITEM_SELECTED(wxID_LISTBOOKLISTVIEW, wxListbook::OnListSelected)
e9c0df38
VZ
61END_EVENT_TABLE()
62
63// ============================================================================
64// wxListbook implementation
65// ============================================================================
66
67// ----------------------------------------------------------------------------
68// wxListbook creation
69// ----------------------------------------------------------------------------
70
71void wxListbook::Init()
72{
73 m_list = NULL;
ef0120c1 74#if wxUSE_LINE_IN_LISTBOOK
e9c0df38 75 m_line = NULL;
ef0120c1 76#endif // wxUSE_LINE_IN_LISTBOOK
e9c0df38
VZ
77 m_selection = wxNOT_FOUND;
78}
79
80bool
81wxListbook::Create(wxWindow *parent,
82 wxWindowID id,
83 const wxPoint& pos,
84 const wxSize& size,
85 long style,
86 const wxString& name)
87{
88 if ( (style & wxLB_ALIGN_MASK) == wxLB_DEFAULT )
89 {
90#ifdef __WXMAC__
91 style |= wxLB_TOP;
92#else // !__WXMAC__
93 style |= wxLB_LEFT;
94#endif // __WXMAC__/!__WXMAC__
95 }
96
ef0120c1
VZ
97 // no border for this control, it doesn't look nice together with
98 // wxListCtrl border
99 style &= ~wxBORDER_MASK;
100 style |= wxBORDER_NONE;
101
e9c0df38
VZ
102 if ( !wxControl::Create(parent, id, pos, size, style,
103 wxDefaultValidator, name) )
104 return false;
105
106 m_list = new wxListView
107 (
108 this,
f29395d0 109 wxID_LISTBOOKLISTVIEW,
e9c0df38
VZ
110 wxDefaultPosition,
111 wxDefaultSize,
ef0120c1 112 wxLC_ICON | wxLC_SINGLE_SEL |
4a06b348 113 (IsVertical() ? wxLC_ALIGN_LEFT : wxLC_ALIGN_TOP)
e9c0df38
VZ
114 );
115
ef0120c1 116#if wxUSE_LINE_IN_LISTBOOK
e9c0df38
VZ
117 m_line = new wxStaticLine
118 (
119 this,
120 -1,
121 wxDefaultPosition,
122 wxDefaultSize,
123 IsVertical() ? wxLI_HORIZONTAL : wxLI_VERTICAL
124 );
ef0120c1 125#endif // wxUSE_LINE_IN_LISTBOOK
e9c0df38 126
a9092ede
RD
127#ifdef __WXMSW__
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.
134 wxSizeEvent evt;
135 GetEventHandler()->AddPendingEvent(evt);
136#endif
e9c0df38
VZ
137 return true;
138}
139
140// ----------------------------------------------------------------------------
141// wxListbook geometry management
142// ----------------------------------------------------------------------------
143
144wxSize wxListbook::GetListSize() const
145{
4a06b348
VZ
146 const wxSize sizeClient = GetClientSize(),
147 sizeList = m_list->GetViewRect().GetSize();
e9c0df38
VZ
148
149 wxSize size;
150 if ( IsVertical() )
151 {
152 size.x = sizeClient.x;
4a06b348 153 size.y = sizeList.y;
e9c0df38
VZ
154 }
155 else // left/right aligned
156 {
4a06b348 157 size.x = sizeList.x;
e9c0df38
VZ
158 size.y = sizeClient.y;
159 }
160
161 return size;
162}
163
164wxRect wxListbook::GetPageRect() const
165{
ae03fa2c 166 const wxSize sizeList = m_list->GetSize();
e9c0df38
VZ
167
168 wxRect rectPage(wxPoint(0, 0), GetClientSize());
169 switch ( GetWindowStyle() & wxLB_ALIGN_MASK )
170 {
171 default:
172 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
173 // fall through
174
175 case wxLB_TOP:
176 rectPage.y = sizeList.y + MARGIN;
177 // fall through
178
179 case wxLB_BOTTOM:
180 rectPage.height -= sizeList.y + MARGIN;
181 break;
182
183 case wxLB_LEFT:
184 rectPage.x = sizeList.x + MARGIN;
185 // fall through
186
187 case wxLB_RIGHT:
188 rectPage.width -= sizeList.x + MARGIN;
189 break;
190 }
191
192 return rectPage;
193}
194
195void wxListbook::OnSize(wxSizeEvent& event)
196{
f1160963
VZ
197 event.Skip();
198
199 if ( !m_list )
200 {
201 // we're not fully created yet
202 return;
203 }
204
e9c0df38
VZ
205 // resize the list control and the page area to fit inside our new size
206 const wxSize sizeClient = GetClientSize(),
207 sizeList = GetListSize();
208
209 wxPoint posList;
210 switch ( GetWindowStyle() & wxLB_ALIGN_MASK )
211 {
212 default:
213 wxFAIL_MSG( _T("unexpected wxListbook alignment") );
214 // fall through
215
216 case wxLB_TOP:
217 case wxLB_LEFT:
218 // posList is already ok
219 break;
220
221 case wxLB_BOTTOM:
222 posList.y = sizeClient.y - sizeList.y;
223 break;
224
225 case wxLB_RIGHT:
226 posList.x = sizeClient.x - sizeList.x;
227 break;
228 }
229
ae03fa2c
VZ
230 m_list->Move(posList.x, posList.y);
231 m_list->SetClientSize(sizeList.x, sizeList.y);
e9c0df38 232
ef0120c1 233#if wxUSE_LINE_IN_LISTBOOK
e9c0df38
VZ
234 if ( m_line )
235 {
236 wxRect rectLine(wxPoint(0, 0), sizeClient);
237
238 switch ( GetWindowStyle() & wxLB_ALIGN_MASK )
239 {
240 case wxLB_TOP:
241 rectLine.y = sizeList.y + 1;
242 rectLine.height = MARGIN - 2;
243 break;
244
245 case wxLB_BOTTOM:
246 rectLine.height = MARGIN - 2;
247 rectLine.y = sizeClient.y - sizeList.y - rectLine.height;
248 break;
249
250 case wxLB_LEFT:
251 rectLine.x = sizeList.x + 1;
252 rectLine.width = MARGIN - 2;
253 break;
254
255 case wxLB_RIGHT:
256 rectLine.width = MARGIN - 2;
257 rectLine.x = sizeClient.x - sizeList.x - rectLine.width;
258 break;
259 }
260
261 m_line->SetSize(rectLine);
262 }
ef0120c1 263#endif // wxUSE_LINE_IN_LISTBOOK
e9c0df38
VZ
264
265 // we should always have some selection if possible
266 if ( m_selection == wxNOT_FOUND && GetPageCount() )
267 {
268 SetSelection(0);
269 }
270
271 if ( m_selection != wxNOT_FOUND )
272 {
273 wxWindow *page = m_pages[m_selection];
274 wxCHECK_RET( page, _T("NULL page in wxListbook?") );
275
276 page->SetSize(GetPageRect());
277 if ( !page->IsShown() )
278 {
279 page->Show();
280 }
281 }
e9c0df38
VZ
282}
283
284wxSize wxListbook::CalcSizeFromPage(const wxSize& sizePage) const
285{
286 // we need to add the size of the list control and the margin
287 const wxSize sizeList = GetListSize();
288
289 wxSize size = sizePage;
290 if ( IsVertical() )
291 {
292 size.y += sizeList.y + MARGIN;
293 }
294 else // left/right aligned
295 {
296 size.x += sizeList.x + MARGIN;
297 }
298
299 return size;
300}
301
302
303// ----------------------------------------------------------------------------
304// accessing the pages
305// ----------------------------------------------------------------------------
306
307bool wxListbook::SetPageText(size_t n, const wxString& strText)
308{
309 m_list->SetItemText(n, strText);
310
311 return true;
312}
313
314wxString wxListbook::GetPageText(size_t n) const
315{
316 return m_list->GetItemText(n);
317}
318
319int wxListbook::GetPageImage(size_t WXUNUSED(n)) const
320{
321 wxFAIL_MSG( _T("wxListbook::GetPageImage() not implemented") );
322
323 return -1;
324}
325
326bool wxListbook::SetPageImage(size_t n, int imageId)
327{
328 return m_list->SetItemImage(n, imageId, imageId);
329}
330
331// ----------------------------------------------------------------------------
332// image list stuff
333// ----------------------------------------------------------------------------
334
335void wxListbook::SetImageList(wxImageList *imageList)
336{
337 m_list->SetImageList(imageList, wxIMAGE_LIST_NORMAL);
338
339 wxBookCtrl::SetImageList(imageList);
340}
341
342// ----------------------------------------------------------------------------
343// selection
344// ----------------------------------------------------------------------------
345
346int wxListbook::GetSelection() const
347{
348 return m_selection;
349}
350
351int wxListbook::SetSelection(size_t n)
352{
353 wxCHECK_MSG( n < GetPageCount(), wxNOT_FOUND,
354 _T("invalid page index in wxListbook::SetSelection()") );
355
356 int selOld = m_selection;
357
358 if ( (int)n != m_selection )
359 {
360 m_selection = n;
361
362 m_list->Select(m_selection);
363 m_list->Focus(m_selection);
364 }
365
366 return selOld;
367}
368
369
370// ----------------------------------------------------------------------------
371// adding/removing the pages
372// ----------------------------------------------------------------------------
373
374bool
375wxListbook::InsertPage(size_t n,
376 wxWindow *page,
377 const wxString& text,
378 bool bSelect,
379 int imageId)
380{
381 if ( !wxBookCtrl::InsertPage(n, page, text, bSelect, imageId) )
382 return false;
383
384 m_list->InsertItem(n, text, imageId);
385
386 if ( bSelect )
387 {
388 m_list->Select(n);
389 m_list->Focus(n);
390 }
391 else // don't select this page
392 {
393 // it will be shown only when selected
394 page->Hide();
395 }
396
397 return true;
398}
399
400wxWindow *wxListbook::DoRemovePage(size_t page)
401{
402 wxWindow *win = wxBookCtrl::DoRemovePage(page);
403 if ( win )
404 {
405 m_list->DeleteItem(page);
406 }
407
408 return win;
409}
410
411// ----------------------------------------------------------------------------
412// wxListbook events
413// ----------------------------------------------------------------------------
414
415void wxListbook::OnListSelected(wxListEvent& eventList)
416{
417 const int selNew = eventList.GetIndex();
418
419 if ( selNew == m_selection )
420 {
421 // this event can only come from our own Select(m_selection) below
422 // which we call when the page change is vetoed, so we should simply
423 // ignore it
424 return;
425 }
426
427 // first send "change in progress" event which may be vetoed by user
428 wxListbookEvent eventIng(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGING, GetId());
429
430 eventIng.SetEventObject(this);
431 eventIng.SetSelection(selNew);
432 eventIng.SetOldSelection(m_selection);
433 if ( GetEventHandler()->ProcessEvent(eventIng) && !eventIng.IsAllowed() )
434 {
435 m_list->Select(m_selection);
436 return;
437 }
438
439 // change allowed: do change the page and notify the user about it
440 if ( m_selection != wxNOT_FOUND )
441 m_pages[m_selection]->Hide();
442 wxWindow *page = m_pages[m_selection = selNew];
443 page->SetSize(GetPageRect());
444 page->Show();
445
446 wxListbookEvent eventEd(wxEVT_COMMAND_LISTBOOK_PAGE_CHANGED, GetId());
447
448 eventEd.SetEventObject(this);
449 eventEd.SetSelection(selNew);
450 eventEd.SetOldSelection(m_selection);
451
452 (void)GetEventHandler()->ProcessEvent(eventEd);
453}
454
455#endif // wxUSE_LISTBOOK
456