]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dialog.cpp
precompiled headers 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"
598dc9b7
SN
27#include "wx/evtloop.h"
28#include "wx/ptr_scpd.h"
27476f73 29
27476f73
DW
30#define wxDIALOG_DEFAULT_X 300
31#define wxDIALOG_DEFAULT_Y 300
0e320a79 32
c9cb56f7
DW
33#define wxDIALOG_DEFAULT_WIDTH 500
34#define wxDIALOG_DEFAULT_HEIGHT 500
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
598dc9b7
SN
47// ----------------------------------------------------------------------------
48// wxDialogModalData
49// ----------------------------------------------------------------------------
50
51// this is simply a container for any data we need to implement modality which
52// allows us to avoid changing wxDialog each time the implementation changes
53class wxDialogModalData
54{
55public:
56 wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { }
57
58 void RunLoop()
59 {
60 m_evtLoop.Run();
61 }
62
63 void ExitLoop()
64 {
65 m_evtLoop.Exit();
66 }
67
68private:
69 wxModalEventLoop m_evtLoop;
70};
71
72wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData);
73
74// ============================================================================
75// implementation
76// ============================================================================
77
78// ----------------------------------------------------------------------------
79// wxDialog construction
80// ----------------------------------------------------------------------------
81
c9cb56f7 82void wxDialog::Init()
0e320a79 83{
c9cb56f7 84 m_pOldFocus = (wxWindow *)NULL;
27476f73 85 m_isShown = FALSE;
c9cb56f7 86 m_pWindowDisabler = (wxWindowDisabler *)NULL;
ee22d7f3 87 m_modalData = NULL;
a756f210 88 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
c9cb56f7
DW
89} // end of wxDialog::Init
90
91bool wxDialog::Create(
92 wxWindow* pParent
93, wxWindowID vId
94, const wxString& rsTitle
95, const wxPoint& rPos
96, const wxSize& rSize
97, long lStyle
98, const wxString& rsName
99)
0e320a79 100{
c9cb56f7 101 Init();
5d44b24e 102 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
c9cb56f7
DW
103
104 //
5d44b24e 105 // Save focus before doing anything which can potentially change it
c9cb56f7 106 //
5d44b24e 107 m_pOldFocus = FindFocus();
c9cb56f7
DW
108
109 //
5d44b24e 110 // All dialogs should really have this style
c9cb56f7 111 //
5d44b24e
DW
112 lStyle |= wxTAB_TRAVERSAL;
113
114 if (!wxTopLevelWindow::Create( pParent
115 ,vId
116 ,rsTitle
117 ,rPos
118 ,rSize
119 ,lStyle
120 ,rsName
121 ))
c9cb56f7 122 return FALSE;
a756f210 123 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
c9b9e020
DW
124
125 //
126 // Must defer setting the title until after dialog is created and sized
127 //
128 if (!rsTitle.IsNull())
129 SetTitle(rsTitle);
27476f73 130 return TRUE;
c9cb56f7 131} // end of wxDialog::Create
0e320a79 132
c9cb56f7
DW
133void wxDialog::SetModal(
134 bool bFlag
135)
0e320a79 136{
c9cb56f7 137 if (bFlag)
5d44b24e 138 {
27476f73 139 m_windowStyle |= wxDIALOG_MODAL ;
5d44b24e
DW
140 wxModelessWindows.DeleteObject(this);
141 }
142 else
143 {
144 m_windowStyle &= ~wxDIALOG_MODAL ;
145 wxModelessWindows.Append(this);
146 }
c9cb56f7 147} // end of wxDialog::SetModal
0e320a79
DW
148
149wxDialog::~wxDialog()
150{
27476f73 151 m_isBeingDeleted = TRUE;
27476f73 152 Show(FALSE);
c9cb56f7 153} // end of wxDialog::~wxDialog
0e320a79 154
c9cb56f7 155//
0e320a79 156// By default, pressing escape cancels the dialog
c9cb56f7
DW
157//
158void wxDialog::OnCharHook(
159 wxKeyEvent& rEvent
160)
0e320a79 161{
27476f73
DW
162 if (GetHWND())
163 {
c9cb56f7 164 if (rEvent.m_keyCode == WXK_ESCAPE)
27476f73 165 {
c9cb56f7 166 //
27476f73
DW
167 // Behaviour changed in 2.0: we'll send a Cancel message
168 // to the dialog instead of Close.
c9cb56f7
DW
169 //
170 wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
171 ,wxID_CANCEL
172 );
173
174 vCancelEvent.SetEventObject( this );
175 GetEventHandler()->ProcessEvent(vCancelEvent);
176
177 //
178 // Ensure that there is another message for this window so the
179 // ShowModal loop will exit and won't get stuck in GetMessage().
180 //
181 ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0);
27476f73
DW
182 return;
183 }
184 }
185 // We didn't process this event.
c9cb56f7 186 rEvent.Skip();
27476f73
DW
187}
188
5d44b24e
DW
189// ----------------------------------------------------------------------------
190// showing the dialogs
191// ----------------------------------------------------------------------------
27476f73
DW
192
193bool wxDialog::IsModal() const
194{
c9cb56f7
DW
195 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
196} // end of wxDialog::IsModal
0e320a79 197
c9cb56f7 198bool wxDialog::IsModalShowing() const
0e320a79 199{
ee22d7f3 200 return m_modalData != NULL; // const_cast
c9cb56f7 201} // end of wxDialog::IsModalShowing
0e320a79 202
c9cb56f7 203void wxDialog::DoShowModal()
0e320a79 204{
c9cb56f7
DW
205 wxWindow* pParent = GetParent();
206 wxWindow* pOldFocus = m_pOldFocus;
207 HWND hWndOldFocus = 0;
0e320a79 208
c9cb56f7
DW
209 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
210 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
211
c9cb56f7
DW
212 if (pOldFocus)
213 hWndOldFocus = (HWND)pOldFocus->GetHWND();
0e320a79 214
c9cb56f7
DW
215 //
216 // Remember where the focus was
217 //
218 if (!pOldFocus)
219 {
220 pOldFocus = pParent;
221 if (pParent)
222 hWndOldFocus = GetHwndOf(pParent);
223 }
224
225 //
226 // Disable all other app windows
227 //
228 wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?"));
229
2b5f62a0
VZ
230 //
231 // Before entering the modal loop, reset the "is in OnIdle()" flag (see
232 // comment in app.cpp)
233 //
234 extern bool gbInOnIdle;
235 bool bWasInOnIdle = gbInOnIdle;
236
237 gbInOnIdle = FALSE;
238
598dc9b7 239 // enter the modal loop
c9cb56f7 240 {
598dc9b7
SN
241 wxDialogModalDataTiedPtr modalData(&m_modalData,
242 new wxDialogModalData(this));
243 modalData->RunLoop();
c9cb56f7 244 }
2b5f62a0 245 gbInOnIdle = bWasInOnIdle;
c9cb56f7
DW
246
247 //
598dc9b7 248 // and restore focus
c9cb56f7
DW
249 // Note that this code MUST NOT access the dialog object's data
250 // in case the object has been deleted (which will be the case
251 // for a modal dialog that has been destroyed before calling EndModal).
252 //
253 if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus))
254 {
255 //
256 // This is likely to prove that the object still exists
257 //
258 if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus)
259 pOldFocus->SetFocus();
260 }
261} // end of wxDialog::DoShowModal
262
263bool wxDialog::Show(
264 bool bShow
265)
0e320a79 266{
c9cb56f7
DW
267 if (!bShow)
268 {
269 //
270 // If we had disabled other app windows, reenable them back now because
271 // if they stay disabled Windows will activate another window (one
f3e4a2a4
DW
272 // which is enabled, anyhow) and we will lose activation. We really don't
273 // do this in OS/2 since PM does this for us.
c9cb56f7
DW
274 //
275 if (m_pWindowDisabler)
276 {
277 delete m_pWindowDisabler;
278 m_pWindowDisabler = NULL;
279 }
ee22d7f3
SN
280 if ( m_modalData )
281 m_modalData->ExitLoop();
c9cb56f7 282 }
0e320a79 283
c9cb56f7
DW
284 //
285 // ShowModal() may be called for already shown dialog
286 //
287 if (!wxDialogBase::Show(bShow) && !(bShow && IsModal()))
288 {
289 //
290 // Nothing to do
291 //
292 return FALSE;
293 }
294
295 if (bShow)
296 {
ee22d7f3
SN
297 // dialogs don't get WM_SIZE message after creation unlike most (all?)
298 // other windows and so could start their life non laid out correctly
299 // if we didn't call Layout() from here
300 //
301 // NB: normally we should call it just the first time but doing it
302 // every time is simpler than keeping a flag
303// Layout();
304
c9cb56f7
DW
305 //
306 // Usually will result in TransferDataToWindow() being called
307 //
308 InitDialog();
309 }
310
c9b9e020
DW
311 if (GetTitle().c_str())
312 ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str());
c9cb56f7
DW
313 if (IsModal())
314 {
315 if (bShow)
316 {
317 //
318 // Modal dialog needs a parent window, so try to find one
319 //
320 if (!GetParent())
321 {
322 wxWindow* pParent = wxTheApp->GetTopWindow();
323
324 if ( pParent && pParent != this && pParent->IsShown() )
325 {
326 //
327 // Use it
328 //
329 m_parent = pParent;
330
331 }
332 }
333 DoShowModal();
334 }
c9cb56f7 335 }
5d44b24e 336 return TRUE;
c9cb56f7
DW
337} // end of wxDialog::Show
338
339//
0e320a79 340// Replacement for Show(TRUE) for modal dialogs - returns return code
c9cb56f7 341//
0e320a79
DW
342int wxDialog::ShowModal()
343{
c9cb56f7
DW
344 if (!IsModal())
345 {
346 SetModal(TRUE);
347 }
27476f73
DW
348 Show(TRUE);
349 return GetReturnCode();
c9cb56f7 350} // end of wxDialog::ShowModal
0e320a79 351
c9cb56f7
DW
352void wxDialog::EndModal(
353 int nRetCode
354)
0e320a79 355{
c9cb56f7 356 SetReturnCode(nRetCode);
27476f73 357 Show(FALSE);
c9cb56f7 358} // end of wxDialog::EndModal
0e320a79 359
5d44b24e
DW
360// ----------------------------------------------------------------------------
361// wxWin event handlers
362// ----------------------------------------------------------------------------
363
c9cb56f7
DW
364void wxDialog::OnApply(
365 wxCommandEvent& rEvent
366)
27476f73 367{
c9cb56f7
DW
368 if (Validate())
369 TransferDataFromWindow();
370} // end of wxDialog::OnApply
371
0e320a79 372// Standard buttons
c9cb56f7
DW
373void wxDialog::OnOK(
374 wxCommandEvent& rEvent
375)
0e320a79 376{
27476f73
DW
377 if ( Validate() && TransferDataFromWindow() )
378 {
c9cb56f7 379 EndModal(wxID_OK);
27476f73 380 }
c9cb56f7 381} // end of wxDialog::OnOK
0e320a79 382
c9cb56f7
DW
383void wxDialog::OnCancel(
384 wxCommandEvent& rEvent
385)
0e320a79 386{
c9cb56f7
DW
387 EndModal(wxID_CANCEL);
388} // end of wxDialog::OnCancel
0e320a79 389
c9cb56f7
DW
390void wxDialog::OnCloseWindow(
391 wxCloseEvent& rEvent
392)
0e320a79 393{
c9cb56f7 394 //
0e320a79
DW
395 // We'll send a Cancel message by default,
396 // which may close the dialog.
397 // Check for looping if the Cancel event handler calls Close().
c9cb56f7 398 //
0e320a79
DW
399 // Note that if a cancel button and handler aren't present in the dialog,
400 // nothing will happen when you close the dialog via the window manager, or
401 // via Close().
402 // We wouldn't want to destroy the dialog by default, since the dialog may have been
403 // created on the stack.
404 // However, this does mean that calling dialog->Close() won't delete the dialog
405 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
406 // sure to destroy the dialog.
407 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
c9cb56f7 408 //
0e320a79 409
c9cb56f7
DW
410 //
411 // Ugh??? This is not good but until I figure out a global list it'll have to do
412 //
0e320a79 413 static wxList closing;
c3d43472 414
0e320a79
DW
415 if ( closing.Member(this) )
416 return;
c3d43472 417
0e320a79 418 closing.Append(this);
c3d43472 419
c9cb56f7
DW
420 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
421
422 vCancelEvent.SetEventObject( this );
423 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
0e320a79
DW
424
425 closing.DeleteObject(this);
c9cb56f7 426} // end of wxDialog::OnCloseWindow
0e320a79 427
c9cb56f7
DW
428void wxDialog::OnSysColourChanged(
429 wxSysColourChangedEvent& rEvent
430)
27476f73 431{
a756f210 432 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
c9cb56f7
DW
433 Refresh();
434} // end of wxDialog::OnSysColourChanged
435
436MRESULT wxDialog::OS2WindowProc(
437 WXUINT uMessage
438, WXWPARAM wParam
439, WXLPARAM lParam
440)
0e320a79 441{
c9cb56f7
DW
442 MRESULT rc = 0;
443 bool bProcessed = FALSE;
27476f73 444
c9cb56f7 445 switch (uMessage)
27476f73
DW
446 {
447 case WM_CLOSE:
c9cb56f7
DW
448 //
449 // If we can't close, tell the system that we processed the
27476f73 450 // message - otherwise it would close us
c9cb56f7
DW
451 //
452 bProcessed = !Close();
27476f73
DW
453 break;
454 }
455
c9cb56f7
DW
456 if (!bProcessed)
457 rc = wxWindow::OS2WindowProc( uMessage
458 ,wParam
459 ,lParam
460 );
27476f73 461 return rc;
c9cb56f7 462} // end of wxDialog::OS2WindowProc
27476f73 463