]> git.saurik.com Git - wxWidgets.git/blame - src/generic/choicbkg.cpp
Introduced invalidation of ranges for later optimization code
[wxWidgets.git] / src / generic / choicbkg.cpp
CommitLineData
f5e0b4bc
WS
1///////////////////////////////////////////////////////////////////////////////
2// Name: generic/choicbkg.cpp
3// Purpose: generic implementation of wxChoicebook
4// Author: Vadim Zeitlin
5// Modified by: Wlodzimierz ABX Skiba from generic/listbkg.cpp
6// Created: 15.09.04
7// RCS-ID: $Id$
8// Copyright: (c) Vadim Zeitlin, Wlodzimierz Skiba
9// Licence: wxWindows licence
10///////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
f5e0b4bc
WS
20// For compilers that support precompilation, includes "wx.h".
21#include "wx/wxprec.h"
22
23#ifdef __BORLANDC__
24 #pragma hdrstop
25#endif
26
27#if wxUSE_CHOICEBOOK
28
29#include "wx/choice.h"
30#include "wx/choicebk.h"
31#include "wx/imaglist.h"
32#include "wx/settings.h"
33
f5e0b4bc
WS
34// ----------------------------------------------------------------------------
35// various wxWidgets macros
36// ----------------------------------------------------------------------------
37
1f30c176
WS
38// check that the page index is valid
39#define IS_VALID_PAGE(nPage) ((nPage) < GetPageCount())
40
41// ----------------------------------------------------------------------------
42// event table
43// ----------------------------------------------------------------------------
44
f5e0b4bc
WS
45IMPLEMENT_DYNAMIC_CLASS(wxChoicebook, wxControl)
46IMPLEMENT_DYNAMIC_CLASS(wxChoicebookEvent, wxNotifyEvent)
47
48const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING = wxNewEventType();
49const wxEventType wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED = wxNewEventType();
50const int wxID_CHOICEBOOKCHOICE = wxNewId();
51
61c083e7 52BEGIN_EVENT_TABLE(wxChoicebook, wxBookCtrlBase)
f5e0b4bc
WS
53 EVT_SIZE(wxChoicebook::OnSize)
54 EVT_CHOICE(wxID_CHOICEBOOKCHOICE, wxChoicebook::OnChoiceSelected)
55END_EVENT_TABLE()
56
57// ============================================================================
58// wxChoicebook implementation
59// ============================================================================
60
61// ----------------------------------------------------------------------------
62// wxChoicebook creation
63// ----------------------------------------------------------------------------
64
65void wxChoicebook::Init()
66{
67 m_choice = NULL;
68 m_selection = wxNOT_FOUND;
69}
70
71bool
72wxChoicebook::Create(wxWindow *parent,
73 wxWindowID id,
74 const wxPoint& pos,
75 const wxSize& size,
76 long style,
77 const wxString& name)
78{
79 if ( (style & wxCHB_ALIGN_MASK) == wxCHB_DEFAULT )
80 {
81 style |= wxCHB_TOP;
82 }
83
84 // no border for this control, it doesn't look nice together with
85 // wxChoice border
86 style &= ~wxBORDER_MASK;
87 style |= wxBORDER_NONE;
88
89 if ( !wxControl::Create(parent, id, pos, size, style,
90 wxDefaultValidator, name) )
91 return false;
92
93 m_choice = new wxChoice
94 (
95 this,
96 wxID_CHOICEBOOKCHOICE,
97 wxDefaultPosition,
98 wxDefaultSize
99 );
100
101 return true;
102}
103
104// ----------------------------------------------------------------------------
105// wxChoicebook geometry management
106// ----------------------------------------------------------------------------
107
108wxSize wxChoicebook::GetChoiceSize() const
109{
110 const wxSize sizeClient = GetClientSize(),
9f29226d 111 sizeChoice = m_choice->GetBestFittingSize();
f5e0b4bc
WS
112
113 wxSize size;
114 if ( IsVertical() )
115 {
116 size.x = sizeClient.x;
117 size.y = sizeChoice.y;
118 }
119 else // left/right aligned
120 {
121 size.x = sizeChoice.x;
122 size.y = sizeClient.y;
123 }
124
125 return size;
126}
127
128wxRect wxChoicebook::GetPageRect() const
129{
9f29226d 130 const wxSize sizeChoice = m_choice->GetBestFittingSize();
f5e0b4bc 131
2997ca30 132 wxPoint pt;
42841dfc 133 wxRect rectPage(pt, GetClientSize());
f5e0b4bc
WS
134 switch ( GetWindowStyle() & wxCHB_ALIGN_MASK )
135 {
136 default:
137 wxFAIL_MSG( _T("unexpected wxChoicebook alignment") );
138 // fall through
139
140 case wxCHB_TOP:
159e6235 141 rectPage.y = sizeChoice.y + GetInternalBorder();
f5e0b4bc
WS
142 // fall through
143
144 case wxCHB_BOTTOM:
159e6235 145 rectPage.height -= sizeChoice.y + GetInternalBorder();
f5e0b4bc
WS
146 break;
147
148 case wxCHB_LEFT:
159e6235 149 rectPage.x = sizeChoice.x + GetInternalBorder();
f5e0b4bc
WS
150 // fall through
151
152 case wxCHB_RIGHT:
159e6235 153 rectPage.width -= sizeChoice.x + GetInternalBorder();
f5e0b4bc
WS
154 break;
155 }
156
157 return rectPage;
158}
159
160void wxChoicebook::OnSize(wxSizeEvent& event)
161{
162 event.Skip();
163
164 if ( !m_choice )
165 {
166 // we're not fully created yet
167 return;
168 }
169
170 // resize the choice control and the page area to fit inside our new size
171 const wxSize sizeClient = GetClientSize(),
172 sizeChoice = GetChoiceSize();
173
174 wxPoint posChoice;
175 switch ( GetWindowStyle() & wxCHB_ALIGN_MASK )
176 {
177 default:
178 wxFAIL_MSG( _T("unexpected wxChoicebook alignment") );
179 // fall through
180
181 case wxCHB_TOP:
182 case wxCHB_LEFT:
183 // posChoice is already ok
184 break;
185
186 case wxCHB_BOTTOM:
187 posChoice.y = sizeClient.y - sizeChoice.y;
188 break;
189
190 case wxCHB_RIGHT:
191 posChoice.x = sizeClient.x - sizeChoice.x;
192 break;
193 }
194
9f29226d
WS
195 m_choice->Move(posChoice);
196 m_choice->SetSize(sizeChoice);
f5e0b4bc 197
bb08a4a1 198 // resize the currently shown page
f5e0b4bc
WS
199 if ( m_selection != wxNOT_FOUND )
200 {
201 wxWindow *page = m_pages[m_selection];
202 wxCHECK_RET( page, _T("NULL page in wxChoicebook?") );
f5e0b4bc 203 page->SetSize(GetPageRect());
f5e0b4bc
WS
204 }
205}
206
207wxSize wxChoicebook::CalcSizeFromPage(const wxSize& sizePage) const
208{
159e6235 209 // we need to add the size of the choice control and the border between
f5e0b4bc
WS
210 const wxSize sizeChoice = GetChoiceSize();
211
212 wxSize size = sizePage;
213 if ( IsVertical() )
214 {
159e6235 215 size.y += sizeChoice.y + GetInternalBorder();
f5e0b4bc
WS
216 }
217 else // left/right aligned
218 {
159e6235 219 size.x += sizeChoice.x + GetInternalBorder();
f5e0b4bc
WS
220 }
221
222 return size;
223}
224
225
226// ----------------------------------------------------------------------------
227// accessing the pages
228// ----------------------------------------------------------------------------
229
230bool wxChoicebook::SetPageText(size_t n, const wxString& strText)
231{
232 m_choice->SetString(n, strText);
233
234 return true;
235}
236
237wxString wxChoicebook::GetPageText(size_t n) const
238{
239 return m_choice->GetString(n);
240}
241
242int wxChoicebook::GetPageImage(size_t WXUNUSED(n)) const
243{
244 wxFAIL_MSG( _T("wxChoicebook::GetPageImage() not implemented") );
245
9f29226d 246 return wxNOT_FOUND;
f5e0b4bc
WS
247}
248
249bool wxChoicebook::SetPageImage(size_t WXUNUSED(n), int WXUNUSED(imageId))
250{
251 wxFAIL_MSG( _T("wxChoicebook::SetPageImage() not implemented") );
252
253 return false;
254}
255
256// ----------------------------------------------------------------------------
257// image list stuff
258// ----------------------------------------------------------------------------
259
260void wxChoicebook::SetImageList(wxImageList *imageList)
261{
262 // TODO: can be implemented in form of static bitmap near choice control
263
61c083e7 264 wxBookCtrlBase::SetImageList(imageList);
f5e0b4bc
WS
265}
266
267// ----------------------------------------------------------------------------
268// selection
269// ----------------------------------------------------------------------------
270
271int wxChoicebook::GetSelection() const
272{
273 return m_selection;
274}
275
276int wxChoicebook::SetSelection(size_t n)
277{
1f30c176
WS
278 wxCHECK_MSG( IS_VALID_PAGE(n), wxNOT_FOUND,
279 wxT("invalid page index in wxChoicebook::SetSelection()") );
f5e0b4bc 280
1f30c176 281 const int oldSel = m_selection;
f5e0b4bc 282
1f30c176 283 if ( int(n) != m_selection )
f5e0b4bc 284 {
1f30c176
WS
285 wxChoicebookEvent event(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGING, m_windowId);
286 event.SetSelection(n);
287 event.SetOldSelection(m_selection);
288 event.SetEventObject(this);
289 if ( !GetEventHandler()->ProcessEvent(event) || event.IsAllowed() )
290 {
291 if ( m_selection != wxNOT_FOUND )
292 m_pages[m_selection]->Hide();
293
294 wxWindow *page = m_pages[n];
295 page->SetSize(GetPageRect());
296 page->Show();
297
716dc245 298 // change m_selection now to ignore the selection change event
1f30c176
WS
299 m_selection = n;
300 m_choice->Select(n);
301
302 // program allows the page change
303 event.SetEventType(wxEVT_COMMAND_CHOICEBOOK_PAGE_CHANGED);
304 (void)GetEventHandler()->ProcessEvent(event);
305 }
f5e0b4bc
WS
306 }
307
1f30c176 308 return oldSel;
f5e0b4bc
WS
309}
310
f5e0b4bc
WS
311// ----------------------------------------------------------------------------
312// adding/removing the pages
313// ----------------------------------------------------------------------------
314
315bool
316wxChoicebook::InsertPage(size_t n,
317 wxWindow *page,
318 const wxString& text,
319 bool bSelect,
320 int imageId)
321{
61c083e7 322 if ( !wxBookCtrlBase::InsertPage(n, page, text, bSelect, imageId) )
f5e0b4bc
WS
323 return false;
324
325 m_choice->Insert(text, n);
326
716dc245
WS
327 // if the inserted page is before the selected one, we must update the
328 // index of the selected page
329 if ( int(n) <= m_selection )
f5e0b4bc 330 {
716dc245
WS
331 // one extra page added
332 m_selection++;
333 m_choice->Select(m_selection);
f5e0b4bc 334 }
716dc245
WS
335
336 // some page should be selected: either this one or the first one if there
337 // is still no selection
159e6235 338 int selNew = wxNOT_FOUND;
716dc245
WS
339 if ( bSelect )
340 selNew = n;
159e6235 341 else if ( m_selection == wxNOT_FOUND )
716dc245
WS
342 selNew = 0;
343
344 if ( selNew != m_selection )
f5e0b4bc 345 page->Hide();
716dc245 346
159e6235 347 if ( selNew != wxNOT_FOUND )
716dc245 348 SetSelection(selNew);
f5e0b4bc
WS
349
350 InvalidateBestSize();
351 return true;
352}
353
354wxWindow *wxChoicebook::DoRemovePage(size_t page)
355{
4a10ea8b 356 const size_t page_count = GetPageCount();
61c083e7 357 wxWindow *win = wxBookCtrlBase::DoRemovePage(page);
bb08a4a1 358
f5e0b4bc
WS
359 if ( win )
360 {
361 m_choice->Delete(page);
bb08a4a1
WS
362
363 if (m_selection >= (int)page)
364 {
365 // force new sel valid if possible
366 int sel = m_selection - 1;
367 if (page_count == 1)
368 sel = wxNOT_FOUND;
369 else if ((page_count == 2) || (sel == -1))
370 sel = 0;
371
372 // force sel invalid if deleting current page - don't try to hide it
373 m_selection = (m_selection == (int)page) ? wxNOT_FOUND : m_selection - 1;
374
375 if ((sel != wxNOT_FOUND) && (sel != m_selection))
376 SetSelection(sel);
377 }
f5e0b4bc
WS
378 }
379
380 return win;
381}
382
383
384bool wxChoicebook::DeleteAllPages()
385{
386 m_choice->Clear();
61c083e7 387 return wxBookCtrlBase::DeleteAllPages();
f5e0b4bc
WS
388}
389
390// ----------------------------------------------------------------------------
391// wxChoicebook events
392// ----------------------------------------------------------------------------
393
394void wxChoicebook::OnChoiceSelected(wxCommandEvent& eventChoice)
395{
396 const int selNew = eventChoice.GetSelection();
397
398 if ( selNew == m_selection )
399 {
400 // this event can only come from our own Select(m_selection) below
401 // which we call when the page change is vetoed, so we should simply
402 // ignore it
403 return;
404 }
405
bb08a4a1 406 SetSelection(selNew);
f5e0b4bc 407
716dc245
WS
408 // change wasn't allowed, return to previous state
409 if (m_selection != selNew)
410 m_choice->Select(m_selection);
f5e0b4bc
WS
411}
412
413#endif // wxUSE_CHOICEBOOK