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