a small cosmetic fix for single choice dialog
[wxWidgets.git] / src / generic / choicdgg.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: choicdgg.cpp
3 // Purpose: Choice dialogs
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 04/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "choicdgg.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include <stdio.h>
25 #include "wx/utils.h"
26 #include "wx/dialog.h"
27 #include "wx/button.h"
28 #include "wx/listbox.h"
29 #include "wx/stattext.h"
30 #include "wx/intl.h"
31 #include "wx/dcclient.h"
32 #include "wx/settings.h"
33 #endif
34
35 #if wxUSE_STATLINE
36 #include "wx/statline.h"
37 #endif
38
39 #include "wx/generic/choicdgg.h"
40
41 #define wxID_LISTBOX 3000
42
43 wxString wxGetSingleChoice( const wxString& message, const wxString& caption, int n,
44 const wxString *choices, wxWindow *parent,
45 int WXUNUSED(x), int WXUNUSED(y), bool WXUNUSED(centre),
46 int WXUNUSED(width), int WXUNUSED(height) )
47 {
48 wxSingleChoiceDialog dialog(parent, message, caption, n, choices);
49 if ( dialog.ShowModal() == wxID_OK )
50 return dialog.GetStringSelection();
51 else
52 return _T("");
53 }
54
55 // Overloaded for backward compatibility
56 wxString wxGetSingleChoice( const wxString& message, const wxString& caption, int n,
57 char *choices[], wxWindow *parent,
58 int x, int y, bool centre,
59 int width, int height )
60 {
61 wxString *strings = new wxString[n];
62 int i;
63 for ( i = 0; i < n; i++)
64 {
65 strings[i] = choices[i];
66 }
67 wxString ans(wxGetSingleChoice(message, caption, n, (const wxString *)strings, parent,
68 x, y, centre, width, height));
69 delete[] strings;
70 return ans;
71 }
72
73 int wxGetSingleChoiceIndex( const wxString& message, const wxString& caption, int n,
74 const wxString *choices, wxWindow *parent,
75 int WXUNUSED(x), int WXUNUSED(y), bool WXUNUSED(centre),
76 int WXUNUSED(width), int WXUNUSED(height) )
77 {
78 wxSingleChoiceDialog dialog(parent, message, caption, n, choices);
79 if ( dialog.ShowModal() == wxID_OK )
80 return dialog.GetSelection();
81 else
82 return -1;
83 }
84
85 // Overloaded for backward compatibility
86 int wxGetSingleChoiceIndex( const wxString& message, const wxString& caption, int n,
87 wxChar *choices[], wxWindow *parent,
88 int x, int y, bool centre,
89 int width, int height )
90 {
91 wxString *strings = new wxString[n];
92 for ( int i = 0; i < n; i++)
93 strings[i] = choices[i];
94 int ans = wxGetSingleChoiceIndex(message, caption, n, (const wxString *)strings, parent,
95 x, y, centre, width, height);
96 delete[] strings;
97 return ans;
98 }
99
100 wxChar *wxGetSingleChoiceData( const wxString& message, const wxString& caption, int n,
101 const wxString *choices, wxChar **client_data, wxWindow *parent,
102 int WXUNUSED(x), int WXUNUSED(y), bool WXUNUSED(centre),
103 int WXUNUSED(width), int WXUNUSED(height) )
104 {
105 wxSingleChoiceDialog dialog(parent, message, caption, n, choices, client_data);
106 if ( dialog.ShowModal() == wxID_OK )
107 return dialog.GetSelectionClientData();
108 else
109 return NULL;
110 }
111
112 // Overloaded for backward compatibility
113 wxChar *wxGetSingleChoiceData( const wxString& message, const wxString& caption, int n,
114 wxChar *choices[], wxChar **client_data, wxWindow *parent,
115 int x, int y, bool centre,
116 int width, int height )
117 {
118 wxString *strings = new wxString[n];
119 int i;
120 for ( i = 0; i < n; i++)
121 {
122 strings[i] = choices[i];
123 }
124 wxChar *data = wxGetSingleChoiceData(message, caption, n, (const wxString *)strings, client_data, parent,
125 x, y, centre, width, height);
126 delete[] strings;
127 return data;
128 }
129
130
131 /* Multiple choice dialog contributed by Robert Cowell
132 *
133
134 The new data passed are in the "int nsel" and "int * selection"
135
136 The idea is to make a multiple selection from list of strings.
137 The returned value is the total number selected. initialily there
138 are nsel selected, with indices stored in
139 selection[0],...,selection[nsel-1] which appear highlighted to
140 begin with. On exit with value i
141 selection[0..i-1] contains the indices of the selected items.
142 (Some prior selectecions might be deselected.)
143 Thus selection must be as big as choices, in case all items are
144 selected.
145
146 */
147 /*
148 int wxGetMultipleChoice(const wxString& message, const wxString& caption,
149 int n, const wxString *choices,
150 int nsel, int * selection,
151 wxWindow *parent , int x , int y, bool centre,
152 int width, int height)
153 {
154 return -1;
155 }
156 */
157
158 // wxSingleChoiceDialog
159
160 #if !USE_SHARED_LIBRARY
161 BEGIN_EVENT_TABLE(wxSingleChoiceDialog, wxDialog)
162 EVT_BUTTON(wxID_OK, wxSingleChoiceDialog::OnOK)
163 EVT_LISTBOX_DCLICK(wxID_LISTBOX, wxSingleChoiceDialog::OnListBoxDClick)
164 END_EVENT_TABLE()
165
166 IMPLEMENT_CLASS(wxSingleChoiceDialog, wxDialog)
167 #endif
168
169 #define wxCHOICEDLG_DIALOG_STYLE (wxDEFAULT_DIALOG_STYLE | \
170 wxDIALOG_MODAL | \
171 wxTAB_TRAVERSAL)
172
173 wxSingleChoiceDialog::wxSingleChoiceDialog(wxWindow *parent,
174 const wxString& message,
175 const wxString& caption,
176 int n,
177 const wxString *choices,
178 char **clientData,
179 long style,
180 const wxPoint& pos)
181 : wxDialog(parent, -1, caption, pos, wxDefaultSize,
182 wxCHOICEDLG_DIALOG_STYLE)
183 {
184 Create(parent, message, caption, n, choices, clientData, style);
185 }
186
187 wxSingleChoiceDialog::wxSingleChoiceDialog(wxWindow *parent,
188 const wxString& message,
189 const wxString& caption,
190 const wxStringList& choices,
191 wxChar **clientData,
192 long style,
193 const wxPoint& pos)
194 : wxDialog(parent, -1, caption, pos, wxDefaultSize,
195 wxCHOICEDLG_DIALOG_STYLE)
196 {
197 Create(parent, message, caption, choices, clientData, style);
198 }
199
200 bool wxSingleChoiceDialog::Create(wxWindow *parent,
201 const wxString& message,
202 const wxString& caption,
203 const wxStringList& choices,
204 char **clientData,
205 long style,
206 const wxPoint& pos)
207 {
208 wxString *strings = new wxString[choices.Number()];
209 int i;
210 for ( i = 0; i < choices.Number(); i++)
211 {
212 strings[i] = (char *)choices.Nth(i)->Data();
213 }
214 bool ans = Create(parent, message, caption, choices.Number(), strings, clientData, style, pos);
215 delete[] strings;
216 return ans;
217 }
218
219 bool wxSingleChoiceDialog::Create( wxWindow *WXUNUSED(parent),
220 const wxString& message,
221 const wxString& WXUNUSED(caption),
222 int n,
223 const wxString *choices,
224 char **clientData,
225 long style,
226 const wxPoint& WXUNUSED(pos) )
227 {
228 m_dialogStyle = style;
229 m_selection = 0;
230 m_clientData = NULL;
231
232 // dialog layout constants
233 static const int LAYOUT_X_MARGIN = 5;
234 static const int LAYOUT_Y_MARGIN = 5;
235 static const int MARGIN_BETWEEN_BUTTONS = 3*LAYOUT_X_MARGIN;
236
237 // calc the message size
238 // ---------------------
239
240 // TODO this should be factored out to a common function (also used in
241 // msgdlgg.cpp)
242 wxClientDC dc(this);
243 dc.SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
244
245 wxArrayString lines;
246 wxString curLine;
247 long height, width, heightTextMax = 0, widthTextMax = 0;
248 for ( const char *pc = message; ; pc++ ) {
249 if ( *pc == '\n' || *pc == '\0' ) {
250 dc.GetTextExtent(curLine, &width, &height);
251 if ( width > widthTextMax )
252 widthTextMax = width;
253 if ( height > heightTextMax )
254 heightTextMax = height;
255
256 lines.Add(curLine);
257
258 if ( *pc == '\n' ) {
259 curLine.Empty();
260 }
261 else {
262 // the end of string
263 break;
264 }
265 }
266 else {
267 curLine += *pc;
268 }
269 }
270
271 size_t nLineCount = lines.Count();
272 long hTotalMsg = heightTextMax*nLineCount;
273
274 // calc the button size
275 // --------------------
276
277 bool hasCancel = FALSE;
278
279 // always create the OK button - the code below supposes we do have buttons
280 // and besides the user should have some way to close this dialog
281 wxASSERT_MSG( style & wxOK, _T("this dialog should have OK button") );
282
283 wxString labelOk(_("OK"));
284 long wButton = 0;
285 dc.GetTextExtent(labelOk, &width, NULL);
286 if ( width > wButton )
287 wButton = width;
288
289 wxString labelCancel;
290 if ( style & wxCANCEL )
291 {
292 labelCancel = _("Cancel");
293 dc.GetTextExtent(labelCancel, &width, NULL);
294 if ( width > wButton )
295 wButton = width;
296
297 hasCancel = TRUE;
298 }
299
300 if ( wButton < 75 )
301 wButton = 75;
302 else
303 wButton += 10;
304
305 long hButton = wButton*23/75;
306 long wTotalButtons = wButton;
307 if ( hasCancel )
308 {
309 wTotalButtons *= 2; // second button
310 wTotalButtons += MARGIN_BETWEEN_BUTTONS; // margin between the 2
311 }
312
313 // listbox and stat line
314 // ---------------------
315
316 // make the listbox at least as tall as the message - otherwise it looks
317 // ugly (the lower limit of 300 for the width is arbitrary OTOH)
318 //
319 // NB: we write "n + 2" because the horiz. scrollbar also takes some place
320 long hListbox = wxMax((n + 2) * heightTextMax, hTotalMsg),
321 wListbox = wxMax(300, wxMax(wTotalButtons, widthTextMax));
322
323 #if wxUSE_STATLINE
324 // arbitrary...
325 long hStatLine = 5;
326 #endif
327
328 // now the complete dialog size
329 // ----------------------------
330
331 long hDialog = 2*LAYOUT_Y_MARGIN + // top margin
332 hTotalMsg + // message
333 2*LAYOUT_Y_MARGIN + // margin between text and listbox
334 hListbox + // listbox
335 #if wxUSE_STATLINE
336 LAYOUT_Y_MARGIN + // margin
337 hStatLine + // separator line
338 #endif
339 2*LAYOUT_Y_MARGIN + // margin between listbox and buttons
340 hButton + // button(s)
341 LAYOUT_Y_MARGIN; // bottom margin
342
343 long wDialog = wxMax(wListbox, wxMax(wTotalButtons, widthTextMax)) +
344 4*LAYOUT_X_MARGIN; // 2 from each side
345
346 // create the controls
347 // -------------------
348
349 // message
350 wxStaticText *text;
351 int y = 2*LAYOUT_Y_MARGIN;
352 for ( size_t nLine = 0; nLine < nLineCount; nLine++ )
353 {
354 text = new wxStaticText(this, -1, lines[nLine],
355 wxPoint(2*LAYOUT_X_MARGIN, y),
356 wxSize(widthTextMax, heightTextMax));
357 y += heightTextMax;
358 }
359
360 y += 2*LAYOUT_X_MARGIN;
361
362 // listbox
363 m_listbox = new wxListBox( this, wxID_LISTBOX,
364 wxPoint(2*LAYOUT_X_MARGIN, y),
365 wxSize(wListbox, hListbox),
366 n, choices,
367 wxLB_HSCROLL);
368 y += hListbox;
369
370 if ( clientData )
371 {
372 for (int i = 0; i < n; i++)
373 m_listbox->SetClientData(i, clientData[i]);
374 }
375
376 // separator line
377 #if wxUSE_STATLINE
378 (void) new wxStaticLine( this, -1,
379 wxPoint(0, y + LAYOUT_Y_MARGIN),
380 wxSize(wDialog, hStatLine) );
381
382 y += LAYOUT_Y_MARGIN + hStatLine;
383 #endif
384
385 // buttons
386
387 y += 2*LAYOUT_X_MARGIN;
388
389 // NB: create [Ok] first to get the right tab order
390
391 wxButton *ok = (wxButton *) NULL;
392 wxButton *cancel = (wxButton *) NULL;
393
394 long x = wDialog / 2;
395 if ( hasCancel )
396 x -= MARGIN_BETWEEN_BUTTONS / 2 + wButton;
397 else
398 x -= wButton / 2;
399
400 ok = new wxButton( this, wxID_OK, labelOk,
401 wxPoint(x, y),
402 wxSize(wButton, hButton) );
403
404 if ( hasCancel )
405 {
406 x += MARGIN_BETWEEN_BUTTONS + wButton;
407 cancel = new wxButton( this, wxID_CANCEL, labelCancel,
408 wxPoint(x, y),
409 wxSize(wButton, hButton) );
410 }
411
412 ok->SetDefault();
413 ok->SetFocus();
414
415 SetClientSize( wDialog, hDialog );
416
417 Centre( wxBOTH );
418
419 return TRUE;
420 }
421
422 // Set the selection
423 void wxSingleChoiceDialog::SetSelection(int sel)
424 {
425 m_listbox->SetSelection(sel);
426 m_selection = sel;
427 }
428
429 void wxSingleChoiceDialog::OnOK(wxCommandEvent& WXUNUSED(event))
430 {
431 m_selection = m_listbox->GetSelection();
432 m_stringSelection = m_listbox->GetStringSelection();
433 m_clientData = m_listbox->GetClientData(m_selection);
434
435 EndModal(wxID_OK);
436 }
437
438 void wxSingleChoiceDialog::OnListBoxDClick(wxCommandEvent& WXUNUSED(event))
439 {
440 m_selection = m_listbox->GetSelection();
441 m_stringSelection = m_listbox->GetStringSelection();
442 m_clientData = m_listbox->GetClientData(m_selection);
443
444 EndModal(wxID_OK);
445 }
446