]> git.saurik.com Git - wxWidgets.git/blame - src/common/dlgcmn.cpp
wxBusyInfo interface moved to generic to make space for possible native implementatio...
[wxWidgets.git] / src / common / dlgcmn.cpp
CommitLineData
e37feda2
VZ
1/////////////////////////////////////////////////////////////////////////////
2// Name: 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
65571936 9// Licence: wxWindows licence
e37feda2
VZ
10/////////////////////////////////////////////////////////////////////////////
11
12// ============================================================================
13// declarations
14// ============================================================================
15
16// ----------------------------------------------------------------------------
17// headers
18// ----------------------------------------------------------------------------
19
e37feda2
VZ
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#ifndef WX_PRECOMP
f6bcfd97 28 #include "wx/button.h"
e37feda2
VZ
29 #include "wx/dialog.h"
30 #include "wx/dcclient.h"
9f3a38fc 31 #include "wx/intl.h"
e37feda2 32 #include "wx/settings.h"
9f3a38fc 33 #include "wx/stattext.h"
92afa2b1 34 #include "wx/sizer.h"
f6bcfd97 35 #include "wx/button.h"
7d9f12f3 36 #include "wx/containr.h"
e37feda2
VZ
37#endif
38
897b24cf
WS
39#include "wx/statline.h"
40#include "wx/sysopt.h"
41
5d1b4919
VZ
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
50class wxTextWrapper
51{
52public:
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
0db7dfb0
VZ
59 // we don't need it, but just to avoid compiler warnings
60 virtual ~wxTextWrapper() { }
61
5d1b4919
VZ
62protected:
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
69private:
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// ----------------------------------------------------------------------------
92afa2b1 98// wxDialogBase
5d1b4919 99// ----------------------------------------------------------------------------
e37feda2 100
5d1b4919 101// FIXME - temporary hack in absence of wxTopLevelWindow, should be always used
7d9f12f3
VS
102#ifdef wxTopLevelWindowNative
103BEGIN_EVENT_TABLE(wxDialogBase, wxTopLevelWindow)
104 WX_EVENT_TABLE_CONTROL_CONTAINER(wxDialogBase)
105END_EVENT_TABLE()
106
107WX_DELEGATE_TO_CONTROL_CONTAINER(wxDialogBase)
108#endif
109
110void wxDialogBase::Init()
111{
112 m_returnCode = 0;
9ceeecb9 113 m_affirmativeId = wxID_OK;
c6ece595
VZ
114 m_escapeId = wxID_ANY;
115
e4b713a2
VZ
116 // the dialogs have this flag on by default to prevent the events from the
117 // dialog controls from reaching the parent frame which is usually
118 // undesirable and can lead to unexpected and hard to find bugs
119 SetExtraStyle(GetExtraStyle() | wxWS_EX_BLOCK_EVENTS);
120
7d9f12f3
VS
121#ifdef wxTopLevelWindowNative // FIXME - temporary hack, should be always used!
122 m_container.SetContainerWindow(this);
123#endif
124}
125
5d1b4919 126#if wxUSE_STATTEXT
1e6feb95 127
5d1b4919 128void wxTextWrapper::Wrap(wxWindow *win, const wxString& text, int widthMax)
e37feda2 129{
5d1b4919
VZ
130 const wxChar *lastSpace = NULL;
131 wxString line;
132
133 const wxChar *lineStart = text.c_str();
134 for ( const wxChar *p = lineStart; ; p++ )
135 {
136 if ( IsStartOfNewLine() )
137 {
138 OnNewLine();
139
140 lastSpace = NULL;
141 line.clear();
142 lineStart = p;
143 }
144
145 if ( *p == _T('\n') || *p == _T('\0') )
146 {
147 DoOutputLine(line);
148
149 if ( *p == _T('\0') )
150 break;
151 }
152 else // not EOL
153 {
154 if ( *p == _T(' ') )
155 lastSpace = p;
156
157 line += *p;
68379eaf 158
5d1b4919
VZ
159 if ( widthMax >= 0 && lastSpace )
160 {
161 int width;
162 win->GetTextExtent(line, &width, NULL);
68379eaf 163
5d1b4919
VZ
164 if ( width > widthMax )
165 {
166 // remove the last word from this line
167 line.erase(lastSpace - lineStart, p + 1 - lineStart);
168 DoOutputLine(line);
169
170 // go back to the last word of this line which we didn't
171 // output yet
172 p = lastSpace;
173 }
174 }
175 //else: no wrapping at all or impossible to wrap
176 }
177 }
178}
179
cfd1ac21
MW
180class wxTextSizerWrapper : public wxTextWrapper
181{
182public:
183 wxTextSizerWrapper(wxWindow *win)
184 {
185 m_win = win;
186 m_hLine = 0;
187 }
188
189 wxSizer *CreateSizer(const wxString& text, int widthMax)
190 {
191 m_sizer = new wxBoxSizer(wxVERTICAL);
192 Wrap(m_win, text, widthMax);
193 return m_sizer;
194 }
195
196protected:
197 virtual void OnOutputLine(const wxString& line)
198 {
199 if ( !line.empty() )
200 {
201 m_sizer->Add(new wxStaticText(m_win, wxID_ANY, line));
202 }
203 else // empty line, no need to create a control for it
204 {
205 if ( !m_hLine )
206 m_hLine = m_win->GetCharHeight();
207
208 m_sizer->Add(5, m_hLine);
209 }
210 }
211
212private:
213 wxWindow *m_win;
214 wxSizer *m_sizer;
215 int m_hLine;
216};
217
5d1b4919
VZ
218wxSizer *wxDialogBase::CreateTextSizer(const wxString& message)
219{
2b5f62a0
VZ
220 // I admit that this is complete bogus, but it makes
221 // message boxes work for pda screens temporarily..
5d1b4919
VZ
222 int widthMax = -1;
223 const bool is_pda = wxSystemSettings::GetScreenType() <= wxSYS_SCREEN_PDA;
2b5f62a0
VZ
224 if (is_pda)
225 {
5d1b4919 226 widthMax = wxSystemSettings::GetMetric( wxSYS_SCREEN_X ) - 25;
2b5f62a0 227 }
68379eaf 228
5d1b4919
VZ
229 // '&' is used as accel mnemonic prefix in the wxWidgets controls but in
230 // the static messages created by CreateTextSizer() (used by wxMessageBox,
231 // for example), we don't want this special meaning, so we need to quote it
232 wxString text(message);
233 text.Replace(_T("&"), _T("&&"));
68379eaf 234
cfd1ac21 235 wxTextSizerWrapper wrapper(this);
b730516c 236
cfd1ac21
MW
237 return wrapper.CreateSizer(text, widthMax);
238}
5d1b4919 239
cfd1ac21
MW
240class wxLabelWrapper : public wxTextWrapper
241{
242public:
243 void WrapLabel(wxWindow *text, int widthMax)
244 {
245 m_text.clear();
246 Wrap(text, text->GetLabel(), widthMax);
247 text->SetLabel(m_text);
248 }
a350a488 249
cfd1ac21
MW
250protected:
251 virtual void OnOutputLine(const wxString& line)
252 {
253 m_text += line;
254 }
a350a488 255
cfd1ac21
MW
256 virtual void OnNewLine()
257 {
258 m_text += _T('\n');
259 }
68379eaf 260
cfd1ac21
MW
261private:
262 wxString m_text;
263};
68379eaf 264
dec48aa5 265void
a351409e 266#if defined(__WXGTK__) && !defined(__WXUNIVERSAL__)
dec48aa5
VZ
267wxStaticText
268#else
269wxStaticTextBase
270#endif
271::Wrap(int width)
5d1b4919 272{
cfd1ac21 273 wxLabelWrapper wrapper;
5d1b4919 274 wrapper.WrapLabel(this, width);
e37feda2 275}
b730516c 276
5d1b4919 277#endif // wxUSE_STATTEXT
1e6feb95 278
897b24cf 279wxSizer *wxDialogBase::CreateButtonSizer( long flags, bool separated, wxCoord distance )
e37feda2 280{
102c0454 281#ifdef __SMARTPHONE__
897b24cf
WS
282 wxUnusedVar(separated);
283 wxUnusedVar(distance);
284
102c0454
JS
285 wxDialog* dialog = (wxDialog*) this;
286 if (flags & wxOK){
287 dialog->SetLeftMenu(wxID_OK);
288 }
289
290 if (flags & wxCANCEL){
291 dialog->SetRightMenu(wxID_CANCEL);
292 }
293
294 if (flags & wxYES){
295 dialog->SetLeftMenu(wxID_YES);
296 }
297
298 if (flags & wxNO){
299 dialog->SetLeftMenu(wxID_NO);
300 }
301 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
302 return sizer;
897b24cf
WS
303
304#else // !__SMARTPHONE__
305
306#ifdef __POCKETPC__
307 // PocketPC guidelines recommend for Ok/Cancel dialogs to use
308 // OK button located inside caption bar and implement Cancel functionality
309 // through Undo outside dialog. As native behaviour this will be default
310 // here but can be easily replaced with real wxButtons
311 // with "wince.dialog.real-ok-cancel" option set to 1
312 if ( ((flags & ~(wxCANCEL|wxNO_DEFAULT))== wxOK) &&
313 (wxSystemOptions::GetOptionInt(wxT("wince.dialog.real-ok-cancel"))==0)
314 )
315 {
316 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
317 return sizer;
318 }
319#endif // __POCKETPC__
320
321#if wxUSE_BUTTON
322
323 wxSizer* buttonSizer = CreateStdDialogButtonSizer( flags );
324
325 // Mac Human Interface Guidelines recommend not to use static lines as grouping elements
326#if wxUSE_STATLINE && !defined(__WXMAC__)
327 if(!separated)
328 return buttonSizer;
329
330 wxBoxSizer *topsizer = new wxBoxSizer( wxVERTICAL );
331 topsizer->Add( new wxStaticLine( this, wxID_ANY ), 0, wxEXPAND | wxBOTTOM, distance );
332 topsizer->Add( buttonSizer, 0, wxEXPAND );
333 return topsizer;
334
335#else // !wxUSE_STATLINE
336
337 wxUnusedVar(separated);
338 wxUnusedVar(distance);
339 return buttonSizer;
340
341#endif // wxUSE_STATLINE/!wxUSE_STATLINE
342
343#else // !wxUSE_BUTTON
344
345 wxUnusedVar(separated);
346 wxUnusedVar(distance);
347 wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
348 return sizer;
349
350#endif // wxUSE_BUTTON/!wxUSE_BUTTON
351
352#endif // __SMARTPHONE__/!__SMARTPHONE__
acf2ac37 353}
68379eaf 354
897b24cf
WS
355#if wxUSE_BUTTON
356
acf2ac37
RR
357wxStdDialogButtonSizer *wxDialogBase::CreateStdDialogButtonSizer( long flags )
358{
359 wxStdDialogButtonSizer *sizer = new wxStdDialogButtonSizer();
897b24cf 360
acf2ac37 361 wxButton *ok = NULL;
acf2ac37
RR
362 wxButton *yes = NULL;
363 wxButton *no = NULL;
52069700 364
acf2ac37 365 if (flags & wxOK){
331c1816 366 ok = new wxButton(this, wxID_OK);
52069700 367 sizer->AddButton(ok);
2b5f62a0 368 }
52069700 369
acf2ac37 370 if (flags & wxCANCEL){
331c1816 371 wxButton *cancel = new wxButton(this, wxID_CANCEL);
52069700 372 sizer->AddButton(cancel);
b5b49e42 373 }
52069700 374
acf2ac37 375 if (flags & wxYES){
331c1816 376 yes = new wxButton(this, wxID_YES);
52069700 377 sizer->AddButton(yes);
e37feda2 378 }
52069700 379
acf2ac37 380 if (flags & wxNO){
331c1816 381 no = new wxButton(this, wxID_NO);
52069700 382 sizer->AddButton(no);
e37feda2 383 }
52069700 384
acf2ac37 385 if (flags & wxHELP){
331c1816 386 wxButton *help = new wxButton(this, wxID_HELP);
52069700 387 sizer->AddButton(help);
e37feda2 388 }
52069700 389
b730516c
RD
390 if (flags & wxNO_DEFAULT)
391 {
392 if (no)
393 {
394 no->SetDefault();
395 no->SetFocus();
396 }
397 }
398 else
92afa2b1
RR
399 {
400 if (ok)
401 {
402 ok->SetDefault();
403 ok->SetFocus();
404 }
405 else if (yes)
406 {
407 yes->SetDefault();
408 yes->SetFocus();
409 }
410 }
d30814cd 411
9ceeecb9
JS
412 if (flags & wxOK)
413 SetAffirmativeId(wxID_OK);
414 else if (flags & wxYES)
415 SetAffirmativeId(wxID_YES);
b730516c 416
d30814cd
MB
417 sizer->Realize();
418
acf2ac37 419 return sizer;
e37feda2
VZ
420}
421
1e6feb95 422#endif // wxUSE_BUTTON