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