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