removed #ifdef wxTopLevelWindowNative -- it's now defined for all ports
[wxWidgets.git] / src / common / dlgcmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/dlgcmn.cpp
3 // Purpose: common (to all ports) wxDialog functions
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 28.06.99
7 // RCS-ID: $Id$
8 // Copyright: (c) Vadim Zeitlin
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 #include "wx/dialog.h"
28
29 #ifndef WX_PRECOMP
30 #include "wx/button.h"
31 #include "wx/dcclient.h"
32 #include "wx/intl.h"
33 #include "wx/settings.h"
34 #include "wx/stattext.h"
35 #include "wx/sizer.h"
36 #include "wx/containr.h"
37 #endif
38
39 #include "wx/statline.h"
40 #include "wx/sysopt.h"
41
42 #if wxUSE_STATTEXT
43
44 // ----------------------------------------------------------------------------
45 // wxTextWrapper
46 // ----------------------------------------------------------------------------
47
48 // this class is used to wrap the text on word boundary: wrapping is done by
49 // calling OnStartLine() and OnOutputLine() functions
50 class wxTextWrapper
51 {
52 public:
53 wxTextWrapper() { m_eol = false; }
54
55 // win is used for getting the font, text is the text to wrap, width is the
56 // max line width or -1 to disable wrapping
57 void Wrap(wxWindow *win, const wxString& text, int widthMax);
58
59 // we don't need it, but just to avoid compiler warnings
60 virtual ~wxTextWrapper() { }
61
62 protected:
63 // line may be empty
64 virtual void OnOutputLine(const wxString& line) = 0;
65
66 // called at the start of every new line (except the very first one)
67 virtual void OnNewLine() { }
68
69 private:
70 // call OnOutputLine() and set m_eol to true
71 void DoOutputLine(const wxString& line)
72 {
73 OnOutputLine(line);
74
75 m_eol = true;
76 }
77
78 // this function is a destructive inspector: when it returns true it also
79 // resets the flag to false so calling it again woulnd't return true any
80 // more
81 bool IsStartOfNewLine()
82 {
83 if ( !m_eol )
84 return false;
85
86 m_eol = false;
87
88 return true;
89 }
90
91
92 bool m_eol;
93 };
94
95 #endif // wxUSE_STATTEXT
96
97 // ----------------------------------------------------------------------------
98 // wxDialogBase
99 // ----------------------------------------------------------------------------
100
101 BEGIN_EVENT_TABLE(wxDialogBase, wxTopLevelWindow)
102 WX_EVENT_TABLE_CONTROL_CONTAINER(wxDialogBase)
103 END_EVENT_TABLE()
104
105 WX_DELEGATE_TO_CONTROL_CONTAINER(wxDialogBase, wxTopLevelWindow)
106
107 void wxDialogBase::Init()
108 {
109 m_returnCode = 0;
110 m_affirmativeId = wxID_OK;
111 m_escapeId = wxID_ANY;
112
113 // the dialogs have this flag on by default to prevent the events from the
114 // dialog controls from reaching the parent frame which is usually
115 // undesirable and can lead to unexpected and hard to find bugs
116 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
117
118 m_container.SetContainerWindow(this);
119 }
120
121 #if wxUSE_STATTEXT
122
123 void wxTextWrapper::Wrap(wxWindow *win, const wxString& text, int widthMax)
124 {
125 const wxChar *lastSpace = NULL;
126 wxString line;
127
128 const wxChar *lineStart = text.c_str();
129 for ( const wxChar *p = lineStart; ; p++ )
130 {
131 if ( IsStartOfNewLine() )
132 {
133 OnNewLine();
134
135 lastSpace = NULL;
136 line.clear();
137 lineStart = p;
138 }
139
140 if ( *p == _T('\n') || *p == _T('\0') )
141 {
142 DoOutputLine(line);
143
144 if ( *p == _T('\0') )
145 break;
146 }
147 else // not EOL
148 {
149 if ( *p == _T(' ') )
150 lastSpace = p;
151
152 line += *p;
153
154 if ( widthMax >= 0 && lastSpace )
155 {
156 int width;
157 win->GetTextExtent(line, &width, NULL);
158
159 if ( width > widthMax )
160 {
161 // remove the last word from this line
162 line.erase(lastSpace - lineStart, p + 1 - lineStart);
163 DoOutputLine(line);
164
165 // go back to the last word of this line which we didn't
166 // output yet
167 p = lastSpace;
168 }
169 }
170 //else: no wrapping at all or impossible to wrap
171 }
172 }
173 }
174
175 class wxTextSizerWrapper : public wxTextWrapper
176 {
177 public:
178 wxTextSizerWrapper(wxWindow *win)
179 {
180 m_win = win;
181 m_hLine = 0;
182 }
183
184 wxSizer *CreateSizer(const wxString& text, int widthMax)
185 {
186 m_sizer = new wxBoxSizer(wxVERTICAL);
187 Wrap(m_win, text, widthMax);
188 return m_sizer;
189 }
190
191 protected:
192 virtual void OnOutputLine(const wxString& line)
193 {
194 if ( !line.empty() )
195 {
196 m_sizer->Add(new wxStaticText(m_win, wxID_ANY, line));
197 }
198 else // empty line, no need to create a control for it
199 {
200 if ( !m_hLine )
201 m_hLine = m_win->GetCharHeight();
202
203 m_sizer->Add(5, m_hLine);
204 }
205 }
206
207 private:
208 wxWindow *m_win;
209 wxSizer *m_sizer;
210 int m_hLine;
211 };
212
213 wxSizer *wxDialogBase::CreateTextSizer(const wxString& message)
214 {
215 // I admit that this is complete bogus, but it makes
216 // message boxes work for pda screens temporarily..
217 int widthMax = -1;
218 const bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
219 if (is_pda)
220 {
221 widthMax = wxSystemSettings::GetMetric( wxSYS_SCREEN_X ) - 25;
222 }
223
224 // '&' is used as accel mnemonic prefix in the wxWidgets controls but in
225 // the static messages created by CreateTextSizer() (used by wxMessageBox,
226 // for example), we don't want this special meaning, so we need to quote it
227 wxString text(message);
228 text.Replace(_T("&"), _T("&&"));
229
230 wxTextSizerWrapper wrapper(this);
231
232 return wrapper.CreateSizer(text, widthMax);
233 }
234
235 class wxLabelWrapper : public wxTextWrapper
236 {
237 public:
238 void WrapLabel(wxWindow *text, int widthMax)
239 {
240 m_text.clear();
241 Wrap(text, text->GetLabel(), widthMax);
242 text->SetLabel(m_text);
243 }
244
245 protected:
246 virtual void OnOutputLine(const wxString& line)
247 {
248 m_text += line;
249 }
250
251 virtual void OnNewLine()
252 {
253 m_text += _T('\n');
254 }
255
256 private:
257 wxString m_text;
258 };
259
260 // NB: don't "factor out" the scope operator, SGI MIPSpro 7.3 (but not 7.4)
261 // gets confused if it doesn't immediately follow the class name
262 void
263 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
264 wxStaticText::
265 #else
266 wxStaticTextBase::
267 #endif
268 Wrap(int width)
269 {
270 wxLabelWrapper wrapper;
271 wrapper.WrapLabel(this, width);
272 }
273
274 #endif // wxUSE_STATTEXT
275
276 wxSizer *wxDialogBase::CreateButtonSizer( long flags, bool separated, wxCoord distance )
277 {
278 #ifdef __SMARTPHONE__
279 wxUnusedVar(separated);
280 wxUnusedVar(distance);
281
282 wxDialog* dialog = (wxDialog*) this;
283 if (flags & wxOK){
284 dialog->SetLeftMenu(wxID_OK);
285 }
286
287 if (flags & wxCANCEL){
288 dialog->SetRightMenu(wxID_CANCEL);
289 }
290
291 if (flags & wxYES){
292 dialog->SetLeftMenu(wxID_YES);
293 }
294
295 if (flags & wxNO){
296 dialog->SetLeftMenu(wxID_NO);
297 }
298 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
299 return sizer;
300
301 #else // !__SMARTPHONE__
302
303 #ifdef __POCKETPC__
304 // PocketPC guidelines recommend for Ok/Cancel dialogs to use
305 // OK button located inside caption bar and implement Cancel functionality
306 // through Undo outside dialog. As native behaviour this will be default
307 // here but can be easily replaced with real wxButtons
308 // with "wince.dialog.real-ok-cancel" option set to 1
309 if ( ((flags & ~(wxCANCEL|wxNO_DEFAULT))== wxOK) &&
310 (wxSystemOptions::GetOptionInt(wxT("wince.dialog.real-ok-cancel"))==0)
311 )
312 {
313 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
314 return sizer;
315 }
316 #endif // __POCKETPC__
317
318 #if wxUSE_BUTTON
319
320 wxSizer* buttonSizer = CreateStdDialogButtonSizer( flags );
321
322 // Mac Human Interface Guidelines recommend not to use static lines as grouping elements
323 #if wxUSE_STATLINE && !defined(__WXMAC__)
324 if(!separated)
325 return buttonSizer;
326
327 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
328 topsizer->Add( new wxStaticLine( this, wxID_ANY ), 0, wxEXPAND | wxBOTTOM, distance );
329 topsizer->Add( buttonSizer, 0, wxEXPAND );
330 return topsizer;
331
332 #else // !wxUSE_STATLINE
333
334 wxUnusedVar(separated);
335 wxUnusedVar(distance);
336 return buttonSizer;
337
338 #endif // wxUSE_STATLINE/!wxUSE_STATLINE
339
340 #else // !wxUSE_BUTTON
341
342 wxUnusedVar(separated);
343 wxUnusedVar(distance);
344 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
345 return sizer;
346
347 #endif // wxUSE_BUTTON/!wxUSE_BUTTON
348
349 #endif // __SMARTPHONE__/!__SMARTPHONE__
350 }
351
352 #if wxUSE_BUTTON
353
354 wxStdDialogButtonSizer *wxDialogBase::CreateStdDialogButtonSizer( long flags )
355 {
356 wxStdDialogButtonSizer *sizer = new wxStdDialogButtonSizer();
357
358 wxButton *ok = NULL;
359 wxButton *yes = NULL;
360 wxButton *no = NULL;
361
362 if (flags & wxOK){
363 ok = new wxButton(this, wxID_OK);
364 sizer->AddButton(ok);
365 }
366
367 if (flags & wxCANCEL){
368 wxButton *cancel = new wxButton(this, wxID_CANCEL);
369 sizer->AddButton(cancel);
370 }
371
372 if (flags & wxYES){
373 yes = new wxButton(this, wxID_YES);
374 sizer->AddButton(yes);
375 }
376
377 if (flags & wxNO){
378 no = new wxButton(this, wxID_NO);
379 sizer->AddButton(no);
380 }
381
382 if (flags & wxHELP){
383 wxButton *help = new wxButton(this, wxID_HELP);
384 sizer->AddButton(help);
385 }
386
387 if (flags & wxNO_DEFAULT)
388 {
389 if (no)
390 {
391 no->SetDefault();
392 no->SetFocus();
393 }
394 }
395 else
396 {
397 if (ok)
398 {
399 ok->SetDefault();
400 ok->SetFocus();
401 }
402 else if (yes)
403 {
404 yes->SetDefault();
405 yes->SetFocus();
406 }
407 }
408
409 if (flags & wxOK)
410 SetAffirmativeId(wxID_OK);
411 else if (flags & wxYES)
412 SetAffirmativeId(wxID_YES);
413
414 sizer->Realize();
415
416 return sizer;
417 }
418
419 #endif // wxUSE_BUTTON