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