merging back XTI branch part 2
[wxWidgets.git] / src / common / radiocmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/radiocmn.cpp
3 // Purpose: wxRadioBox methods common to all ports
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 03.06.01
7 // RCS-ID: $Id$
8 // Copyright: (c) 2001 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
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_RADIOBOX
28
29 #ifndef WX_PRECOMP
30 #include "wx/radiobox.h"
31 #endif //WX_PRECOMP
32
33 #if wxUSE_TOOLTIPS
34 #include "wx/tooltip.h"
35 #endif // wxUSE_TOOLTIPS
36
37 #if wxUSE_HELP
38 #include "wx/cshelp.h"
39 #endif
40
41 // ============================================================================
42 // implementation
43 // ============================================================================
44
45 // ----------------------------------------------------------------------------
46 // XTI
47 // ----------------------------------------------------------------------------
48
49 // TODO: wxCONSTRUCTOR
50 #if 0 // wxUSE_EXTENDED_RTTI
51 wxDEFINE_FLAGS( wxRadioBoxStyle )
52
53 wxBEGIN_FLAGS( wxRadioBoxStyle )
54 // new style border flags, we put them first to
55 // use them for streaming out
56 wxFLAGS_MEMBER(wxBORDER_SIMPLE)
57 wxFLAGS_MEMBER(wxBORDER_SUNKEN)
58 wxFLAGS_MEMBER(wxBORDER_DOUBLE)
59 wxFLAGS_MEMBER(wxBORDER_RAISED)
60 wxFLAGS_MEMBER(wxBORDER_STATIC)
61 wxFLAGS_MEMBER(wxBORDER_NONE)
62
63 // old style border flags
64 wxFLAGS_MEMBER(wxSIMPLE_BORDER)
65 wxFLAGS_MEMBER(wxSUNKEN_BORDER)
66 wxFLAGS_MEMBER(wxDOUBLE_BORDER)
67 wxFLAGS_MEMBER(wxRAISED_BORDER)
68 wxFLAGS_MEMBER(wxSTATIC_BORDER)
69 wxFLAGS_MEMBER(wxBORDER)
70
71 // standard window styles
72 wxFLAGS_MEMBER(wxTAB_TRAVERSAL)
73 wxFLAGS_MEMBER(wxCLIP_CHILDREN)
74 wxFLAGS_MEMBER(wxTRANSPARENT_WINDOW)
75 wxFLAGS_MEMBER(wxWANTS_CHARS)
76 wxFLAGS_MEMBER(wxFULL_REPAINT_ON_RESIZE)
77 wxFLAGS_MEMBER(wxALWAYS_SHOW_SB )
78 wxFLAGS_MEMBER(wxVSCROLL)
79 wxFLAGS_MEMBER(wxHSCROLL)
80
81 wxFLAGS_MEMBER(wxRA_SPECIFY_COLS)
82 wxFLAGS_MEMBER(wxRA_HORIZONTAL)
83 wxFLAGS_MEMBER(wxRA_SPECIFY_ROWS)
84 wxFLAGS_MEMBER(wxRA_VERTICAL)
85
86 wxEND_FLAGS( wxRadioBoxStyle )
87
88 IMPLEMENT_DYNAMIC_CLASS_XTI(wxRadioBox, wxControl,"wx/radiobox.h")
89
90 wxBEGIN_PROPERTIES_TABLE(wxRadioBox)
91 wxEVENT_PROPERTY( Select , wxEVT_COMMAND_RADIOBOX_SELECTED , wxCommandEvent )
92 wxPROPERTY_FLAGS( WindowStyle , wxRadioBoxStyle , long , SetWindowStyleFlag , GetWindowStyleFlag , , 0 /*flags*/ , wxT("Helpstring") , wxT("group")) // style
93 wxEND_PROPERTIES_TABLE()
94
95 /*
96 selection
97 content
98 label
99 dimension
100 item
101 */
102
103 #endif
104
105
106 // ----------------------------------------------------------------------------
107 // wxRadioBoxBase
108 // ----------------------------------------------------------------------------
109
110 void wxRadioBoxBase::SetMajorDim(unsigned int majorDim, long style)
111 {
112 wxCHECK_RET( majorDim != 0, wxT("major radiobox dimension can't be 0") );
113
114 m_majorDim = majorDim;
115
116 int minorDim = (GetCount() + m_majorDim - 1) / m_majorDim;
117
118 if ( style & wxRA_SPECIFY_COLS )
119 {
120 m_numCols = majorDim;
121 m_numRows = minorDim;
122 }
123 else // wxRA_SPECIFY_ROWS
124 {
125 m_numCols = minorDim;
126 m_numRows = majorDim;
127 }
128 }
129
130 int wxRadioBoxBase::GetNextItem(int item, wxDirection dir, long style) const
131 {
132 const int itemStart = item;
133
134 int count = GetCount(),
135 numCols = GetColumnCount(),
136 numRows = GetRowCount();
137
138 bool horz = (style & wxRA_SPECIFY_COLS) != 0;
139
140 do
141 {
142 switch ( dir )
143 {
144 case wxUP:
145 if ( horz )
146 {
147 item -= numCols;
148 }
149 else // vertical layout
150 {
151 if ( !item-- )
152 item = count - 1;
153 }
154 break;
155
156 case wxLEFT:
157 if ( horz )
158 {
159 if ( !item-- )
160 item = count - 1;
161 }
162 else // vertical layout
163 {
164 item -= numRows;
165 }
166 break;
167
168 case wxDOWN:
169 if ( horz )
170 {
171 item += numCols;
172 }
173 else // vertical layout
174 {
175 if ( ++item == count )
176 item = 0;
177 }
178 break;
179
180 case wxRIGHT:
181 if ( horz )
182 {
183 if ( ++item == count )
184 item = 0;
185 }
186 else // vertical layout
187 {
188 item += numRows;
189 }
190 break;
191
192 default:
193 wxFAIL_MSG( wxT("unexpected wxDirection value") );
194 return wxNOT_FOUND;
195 }
196
197 // ensure that the item is in range [0..count)
198 if ( item < 0 )
199 {
200 // first map the item to the one in the same column but in the last
201 // row
202 item += count;
203
204 // now there are 2 cases: either it is the first item of the last
205 // row in which case we need to wrap again and get to the last item
206 // or we can just go to the previous item
207 if ( item % (horz ? numCols : numRows) )
208 item--;
209 else
210 item = count - 1;
211 }
212 else if ( item >= count )
213 {
214 // same logic as above
215 item -= count;
216
217 // ... except that we need to check if this is not the last item,
218 // not the first one
219 if ( (item + 1) % (horz ? numCols : numRows) )
220 item++;
221 else
222 item = 0;
223 }
224
225 wxASSERT_MSG( item < count && item >= 0,
226 wxT("logic error in wxRadioBox::GetNextItem()") );
227 }
228 // we shouldn't select the non-active items, continue looking for a
229 // visible and shown one unless we came back to the item we started from in
230 // which case bail out to avoid infinite loop
231 while ( !(IsItemShown(item) && IsItemEnabled(item)) && item != itemStart );
232
233 return item;
234 }
235
236 #if wxUSE_TOOLTIPS
237
238 void wxRadioBoxBase::SetItemToolTip(unsigned int item, const wxString& text)
239 {
240 wxASSERT_MSG( item < GetCount(), wxT("Invalid item index") );
241
242 // extend the array to have entries for all our items on first use
243 if ( !m_itemsTooltips )
244 {
245 m_itemsTooltips = new wxToolTipArray;
246 m_itemsTooltips->resize(GetCount());
247 }
248
249 wxToolTip *tooltip = (*m_itemsTooltips)[item];
250
251 bool changed = true;
252 if ( text.empty() )
253 {
254 if ( tooltip )
255 {
256 // delete the tooltip
257 wxDELETE(tooltip);
258 }
259 else // nothing to do
260 {
261 changed = false;
262 }
263 }
264 else // non empty tooltip text
265 {
266 if ( tooltip )
267 {
268 // just change the existing tooltip text, don't change the tooltip
269 tooltip->SetTip(text);
270 changed = false;
271 }
272 else // no tooltip yet
273 {
274 // create the new one
275 tooltip = new wxToolTip(text);
276 }
277 }
278
279 if ( changed )
280 {
281 (*m_itemsTooltips)[item] = tooltip;
282 DoSetItemToolTip(item, tooltip);
283 }
284 }
285
286 void
287 wxRadioBoxBase::DoSetItemToolTip(unsigned int WXUNUSED(item),
288 wxToolTip * WXUNUSED(tooltip))
289 {
290 // per-item tooltips not implemented by default
291 }
292
293 #endif // wxUSE_TOOLTIPS
294
295 wxRadioBoxBase::~wxRadioBoxBase()
296 {
297 #if wxUSE_TOOLTIPS
298 if ( m_itemsTooltips )
299 {
300 const size_t n = m_itemsTooltips->size();
301 for ( size_t i = 0; i < n; i++ )
302 delete (*m_itemsTooltips)[i];
303
304 delete m_itemsTooltips;
305 }
306 #endif // wxUSE_TOOLTIPS
307 }
308
309 #if wxUSE_HELP
310
311 // set helptext for a particular item
312 void wxRadioBoxBase::SetItemHelpText(unsigned int n, const wxString& helpText)
313 {
314 wxCHECK_RET( n < GetCount(), wxT("Invalid item index") );
315
316 if ( m_itemsHelpTexts.empty() )
317 {
318 // once-only initialization of the array: reserve space for all items
319 m_itemsHelpTexts.Add(wxEmptyString, GetCount());
320 }
321
322 m_itemsHelpTexts[n] = helpText;
323 }
324
325 // retrieve helptext for a particular item
326 wxString wxRadioBoxBase::GetItemHelpText( unsigned int n ) const
327 {
328 wxCHECK_MSG( n < GetCount(), wxEmptyString, wxT("Invalid item index") );
329
330 return m_itemsHelpTexts.empty() ? wxString() : m_itemsHelpTexts[n];
331 }
332
333 // return help text for the item for which wxEVT_HELP was generated.
334 wxString wxRadioBoxBase::DoGetHelpTextAtPoint(const wxWindow *derived,
335 const wxPoint& pt,
336 wxHelpEvent::Origin origin) const
337 {
338 int item;
339 switch ( origin )
340 {
341 case wxHelpEvent::Origin_HelpButton:
342 item = GetItemFromPoint(pt);
343 break;
344
345 case wxHelpEvent::Origin_Keyboard:
346 item = GetSelection();
347 break;
348
349 default:
350 wxFAIL_MSG( "unknown help even origin" );
351 // fall through
352
353 case wxHelpEvent::Origin_Unknown:
354 // this value is used when we're called from GetHelpText() for the
355 // radio box itself, so don't return item-specific text in this case
356 item = wxNOT_FOUND;
357 }
358
359 if ( item != wxNOT_FOUND )
360 {
361 wxString text = GetItemHelpText(static_cast<unsigned int>(item));
362 if( !text.empty() )
363 return text;
364 }
365
366 return derived->wxWindowBase::GetHelpTextAtPoint(pt, origin);
367 }
368
369 #endif // wxUSE_HELP
370
371 #endif // wxUSE_RADIOBOX