Commit of merge
[wxWidgets.git] / src / os2 / dialog.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dialog.cpp
3 // Purpose: wxDialog class
4 // Author: David Webster
5 // Modified by:
6 // Created: 10/14/99
7 // RCS-ID: $Id$
8 // Copyright: (c) David Webster
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifndef WX_PRECOMP
16 #include "wx/dialog.h"
17 #include "wx/utils.h"
18 #include "wx/frame.h"
19 #include "wx/app.h"
20 #include "wx/settings.h"
21 #include "wx/intl.h"
22 #include "wx/log.h"
23 #endif
24
25 #include "wx/os2/private.h"
26 #include "wx/log.h"
27
28 #define wxDIALOG_DEFAULT_X 300
29 #define wxDIALOG_DEFAULT_Y 300
30
31 #define wxDIALOG_DEFAULT_WIDTH 500
32 #define wxDIALOG_DEFAULT_HEIGHT 500
33
34 wxWindowList wxModalDialogs;
35
36 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
37
38 BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
39 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
40 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
41 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
42 EVT_CHAR_HOOK(wxDialog::OnCharHook)
43 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
44 EVT_CLOSE(wxDialog::OnCloseWindow)
45 END_EVENT_TABLE()
46
47 void wxDialog::Init()
48 {
49 m_pOldFocus = (wxWindow *)NULL;
50 m_isShown = FALSE;
51 m_pWindowDisabler = (wxWindowDisabler *)NULL;
52 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
53 } // end of wxDialog::Init
54
55 bool wxDialog::Create(
56 wxWindow* pParent
57 , wxWindowID vId
58 , const wxString& rsTitle
59 , const wxPoint& rPos
60 , const wxSize& rSize
61 , long lStyle
62 , const wxString& rsName
63 )
64 {
65 long lX = rPos.x;
66 long lY = rPos.y;
67 long lWidth = rSize.x;
68 long lHeight = rSize.y;
69 const char* zDlg;
70 WXDWORD dwExtendedStyle = 0L;
71 HWND hWnd;
72
73 Init();
74 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
75
76 //
77 // Save focus before doing anything which can potentially change it
78 //
79 m_pOldFocus = FindFocus();
80
81 //
82 // All dialogs should really have this style
83 //
84 lStyle |= wxTAB_TRAVERSAL;
85
86 if (!wxTopLevelWindow::Create( pParent
87 ,vId
88 ,rsTitle
89 ,rPos
90 ,rSize
91 ,lStyle
92 ,rsName
93 ))
94 return FALSE;
95 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
96
97 //
98 // Must defer setting the title until after dialog is created and sized
99 //
100 if (!rsTitle.IsNull())
101 SetTitle(rsTitle);
102 return TRUE;
103 } // end of wxDialog::Create
104
105 void wxDialog::SetModal(
106 bool bFlag
107 )
108 {
109 if (bFlag)
110 {
111 m_windowStyle |= wxDIALOG_MODAL ;
112 wxModelessWindows.DeleteObject(this);
113 }
114 else
115 {
116 m_windowStyle &= ~wxDIALOG_MODAL ;
117 wxModelessWindows.Append(this);
118 }
119 } // end of wxDialog::SetModal
120
121 wxDialog::~wxDialog()
122 {
123 m_isBeingDeleted = TRUE;
124 Show(FALSE);
125 } // end of wxDialog::~wxDialog
126
127 //
128 // By default, pressing escape cancels the dialog
129 //
130 void wxDialog::OnCharHook(
131 wxKeyEvent& rEvent
132 )
133 {
134 if (GetHWND())
135 {
136 if (rEvent.m_keyCode == WXK_ESCAPE)
137 {
138 //
139 // Behaviour changed in 2.0: we'll send a Cancel message
140 // to the dialog instead of Close.
141 //
142 wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
143 ,wxID_CANCEL
144 );
145
146 vCancelEvent.SetEventObject( this );
147 GetEventHandler()->ProcessEvent(vCancelEvent);
148
149 //
150 // Ensure that there is another message for this window so the
151 // ShowModal loop will exit and won't get stuck in GetMessage().
152 //
153 ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0);
154 return;
155 }
156 }
157 // We didn't process this event.
158 rEvent.Skip();
159 }
160
161 // ----------------------------------------------------------------------------
162 // showing the dialogs
163 // ----------------------------------------------------------------------------
164
165 bool wxDialog::IsModal() const
166 {
167 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
168 } // end of wxDialog::IsModal
169
170 bool wxDialog::IsModalShowing() const
171 {
172 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
173 } // end of wxDialog::IsModalShowing
174
175 void wxDialog::DoShowModal()
176 {
177 wxWindow* pParent = GetParent();
178 wxWindow* pOldFocus = m_pOldFocus;
179 HWND hWndOldFocus = 0;
180
181 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
182 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
183
184 wxModalDialogs.Append(this);
185 if (pOldFocus)
186 hWndOldFocus = (HWND)pOldFocus->GetHWND();
187
188 //
189 // Remember where the focus was
190 //
191 if (!pOldFocus)
192 {
193 pOldFocus = pParent;
194 if (pParent)
195 hWndOldFocus = GetHwndOf(pParent);
196 }
197
198 //
199 // Disable all other app windows
200 //
201 wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?"));
202
203 m_pWindowDisabler = new wxWindowDisabler(this);
204
205 //
206 // Enter the modal loop
207 //
208 while ( IsModalShowing() )
209 {
210 #if wxUSE_THREADS
211 wxMutexGuiLeaveOrEnter();
212 #endif // wxUSE_THREADS
213
214 while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
215 ;
216
217 // a message came or no more idle processing to do
218 wxTheApp->DoMessage();
219 }
220
221 //
222 // Snd restore focus
223 // Note that this code MUST NOT access the dialog object's data
224 // in case the object has been deleted (which will be the case
225 // for a modal dialog that has been destroyed before calling EndModal).
226 //
227 if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus))
228 {
229 //
230 // This is likely to prove that the object still exists
231 //
232 if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus)
233 pOldFocus->SetFocus();
234 }
235 } // end of wxDialog::DoShowModal
236
237 bool wxDialog::Show(
238 bool bShow
239 )
240 {
241 if (!bShow)
242 {
243 //
244 // If we had disabled other app windows, reenable them back now because
245 // if they stay disabled Windows will activate another window (one
246 // which is enabled, anyhow) and we will lose activation
247 //
248 if (m_pWindowDisabler)
249 {
250 delete m_pWindowDisabler;
251 m_pWindowDisabler = NULL;
252 }
253 }
254
255 //
256 // ShowModal() may be called for already shown dialog
257 //
258 if (!wxDialogBase::Show(bShow) && !(bShow && IsModal()))
259 {
260 //
261 // Nothing to do
262 //
263 return FALSE;
264 }
265
266 if (bShow)
267 {
268 //
269 // Usually will result in TransferDataToWindow() being called
270 //
271 InitDialog();
272 }
273
274 if (GetTitle().c_str())
275 ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str());
276 if (IsModal())
277 {
278 if (bShow)
279 {
280 //
281 // Modal dialog needs a parent window, so try to find one
282 //
283 if (!GetParent())
284 {
285 wxWindow* pParent = wxTheApp->GetTopWindow();
286
287 if ( pParent && pParent != this && pParent->IsShown() )
288 {
289 //
290 // Use it
291 //
292 m_parent = pParent;
293
294 }
295 }
296 DoShowModal();
297 }
298 else // end of modal dialog
299 {
300 //
301 // This will cause IsModalShowing() return FALSE and our local
302 // message loop will terminate
303 //
304 wxModalDialogs.DeleteObject(this);
305 }
306 }
307 return TRUE;
308 } // end of wxDialog::Show
309
310 //
311 // Replacement for Show(TRUE) for modal dialogs - returns return code
312 //
313 int wxDialog::ShowModal()
314 {
315 if (!IsModal())
316 {
317 SetModal(TRUE);
318 }
319 Show(TRUE);
320 return GetReturnCode();
321 } // end of wxDialog::ShowModal
322
323 void wxDialog::EndModal(
324 int nRetCode
325 )
326 {
327 SetReturnCode(nRetCode);
328 Show(FALSE);
329 } // end of wxDialog::EndModal
330
331 // ----------------------------------------------------------------------------
332 // wxWin event handlers
333 // ----------------------------------------------------------------------------
334
335 void wxDialog::OnApply(
336 wxCommandEvent& rEvent
337 )
338 {
339 if (Validate())
340 TransferDataFromWindow();
341 } // end of wxDialog::OnApply
342
343 // Standard buttons
344 void wxDialog::OnOK(
345 wxCommandEvent& rEvent
346 )
347 {
348 if ( Validate() && TransferDataFromWindow() )
349 {
350 EndModal(wxID_OK);
351 }
352 } // end of wxDialog::OnOK
353
354 void wxDialog::OnCancel(
355 wxCommandEvent& rEvent
356 )
357 {
358 EndModal(wxID_CANCEL);
359 } // end of wxDialog::OnCancel
360
361 void wxDialog::OnCloseWindow(
362 wxCloseEvent& rEvent
363 )
364 {
365 //
366 // We'll send a Cancel message by default,
367 // which may close the dialog.
368 // Check for looping if the Cancel event handler calls Close().
369 //
370 // Note that if a cancel button and handler aren't present in the dialog,
371 // nothing will happen when you close the dialog via the window manager, or
372 // via Close().
373 // We wouldn't want to destroy the dialog by default, since the dialog may have been
374 // created on the stack.
375 // However, this does mean that calling dialog->Close() won't delete the dialog
376 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
377 // sure to destroy the dialog.
378 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
379 //
380
381 //
382 // Ugh??? This is not good but until I figure out a global list it'll have to do
383 //
384 static wxList closing;
385
386 if ( closing.Member(this) )
387 return;
388
389 closing.Append(this);
390
391 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
392
393 vCancelEvent.SetEventObject( this );
394 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
395
396 closing.DeleteObject(this);
397 } // end of wxDialog::OnCloseWindow
398
399 void wxDialog::OnSysColourChanged(
400 wxSysColourChangedEvent& rEvent
401 )
402 {
403 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
404 Refresh();
405 } // end of wxDialog::OnSysColourChanged
406
407 MRESULT wxDialog::OS2WindowProc(
408 WXUINT uMessage
409 , WXWPARAM wParam
410 , WXLPARAM lParam
411 )
412 {
413 MRESULT rc = 0;
414 bool bProcessed = FALSE;
415
416 switch (uMessage)
417 {
418 case WM_CLOSE:
419 //
420 // If we can't close, tell the system that we processed the
421 // message - otherwise it would close us
422 //
423 bProcessed = !Close();
424 break;
425 }
426
427 if (!bProcessed)
428 rc = wxWindow::OS2WindowProc( uMessage
429 ,wParam
430 ,lParam
431 );
432 return rc;
433 } // end of wxDialog::OS2WindowProc
434