]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dialog.cpp
Reverted/commented out unsuccessful defer fix
[wxWidgets.git] / src / os2 / dialog.cpp
... / ...
CommitLineData
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#include "wx/evtloop.h"
28#include "wx/ptr_scpd.h"
29
30#define wxDIALOG_DEFAULT_X 300
31#define wxDIALOG_DEFAULT_Y 300
32
33#define wxDIALOG_DEFAULT_WIDTH 500
34#define wxDIALOG_DEFAULT_HEIGHT 500
35
36IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
37
38BEGIN_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
45 EVT_CLOSE(wxDialog::OnCloseWindow)
46END_EVENT_TABLE()
47
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
83void wxDialog::Init()
84{
85 m_pOldFocus = (wxWindow *)NULL;
86 m_isShown = FALSE;
87 m_pWindowDisabler = (wxWindowDisabler *)NULL;
88 m_modalData = NULL;
89 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
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)
101{
102 Init();
103 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
104
105 //
106 // Save focus before doing anything which can potentially change it
107 //
108 m_pOldFocus = FindFocus();
109
110 //
111 // All dialogs should really have this style
112 //
113 lStyle |= wxTAB_TRAVERSAL;
114
115 if (!wxTopLevelWindow::Create( pParent
116 ,vId
117 ,rsTitle
118 ,rPos
119 ,rSize
120 ,lStyle
121 ,rsName
122 ))
123 return FALSE;
124 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
125
126 //
127 // Must defer setting the title until after dialog is created and sized
128 //
129 if (!rsTitle.IsNull())
130 SetTitle(rsTitle);
131 return TRUE;
132} // end of wxDialog::Create
133
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
150void wxDialog::SetModal(
151 bool WXUNUSED(bFlag)
152)
153{
154 // nothing to do, obsolete method
155} // end of wxDialog::SetModal
156
157wxDialog::~wxDialog()
158{
159 m_isBeingDeleted = TRUE;
160
161 // this will also reenable all the other windows for a modal dialog
162 Show(false);
163} // end of wxDialog::~wxDialog
164
165//
166// By default, pressing escape cancels the dialog
167//
168void wxDialog::OnCharHook(
169 wxKeyEvent& rEvent
170)
171{
172 if (GetHWND())
173 {
174 if (rEvent.m_keyCode == WXK_ESCAPE)
175 {
176 //
177 // Behaviour changed in 2.0: we'll send a Cancel message
178 // to the dialog instead of Close.
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);
192 return;
193 }
194 }
195 // We didn't process this event.
196 rEvent.Skip();
197}
198
199// ----------------------------------------------------------------------------
200// showing the dialogs
201// ----------------------------------------------------------------------------
202
203bool wxDialog::IsModalShowing() const
204{
205 return IsModal();
206} // end of wxDialog::IsModalShowing
207
208
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 )
216 {
217 // next try the main app window
218 parent = wxTheApp->GetTopWindow();
219 }
220
221 // finally, check if the parent we found is really suitable
222 if ( !parent || parent == (wxWindow *)this || !parent->IsShown() )
223 {
224 // don't use this one
225 parent = NULL;
226 }
227
228 return parent;
229}
230
231bool wxDialog::Show(
232 bool bShow
233)
234{
235 if ( bShow == IsShown() )
236 return false;
237
238 if (!bShow && m_modalData )
239 {
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
242 // if they stay disabled Windows will activate another window (one
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
247 if (m_pWindowDisabler)
248 {
249 delete m_pWindowDisabler;
250 m_pWindowDisabler = NULL;
251 }
252#endif
253 }
254
255 if (bShow)
256 {
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();
261 }
262
263 wxDialogBase::Show(bShow);
264
265 if (GetTitle().c_str())
266 ::WinSetWindowText((HWND)GetHwnd(), (PSZ)GetTitle().c_str());
267
268 if ( bShow )
269 {
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
276 Layout();
277 }
278
279 return true;
280} // end of wxDialog::Show
281
282//
283// Replacement for Show(TRUE) for modal dialogs - returns return code
284//
285int wxDialog::ShowModal()
286{
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 )
297 {
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 }
346 }
347
348 return GetReturnCode();
349} // end of wxDialog::ShowModal
350
351void wxDialog::EndModal(
352 int nRetCode
353)
354{
355 wxASSERT_MSG( IsModal(), _T("EndModal() called for non modal dialog") );
356
357 m_endModalCalled = true;
358 SetReturnCode(nRetCode);
359
360 Hide();
361} // end of wxDialog::EndModal
362
363void wxDialog::EndDialog(int rc)
364{
365 if ( IsModal() )
366 EndModal(rc);
367 else
368 Hide();
369}
370
371// ----------------------------------------------------------------------------
372// wxWin event handlers
373// ----------------------------------------------------------------------------
374
375void wxDialog::OnApply(
376 wxCommandEvent& rEvent
377)
378{
379 if (Validate())
380 TransferDataFromWindow();
381} // end of wxDialog::OnApply
382
383// Standard buttons
384void wxDialog::OnOK(
385 wxCommandEvent& rEvent
386)
387{
388 if ( Validate() && TransferDataFromWindow() )
389 {
390 EndDialog(wxID_OK);
391 }
392} // end of wxDialog::OnOK
393
394void wxDialog::OnCancel(
395 wxCommandEvent& rEvent
396)
397{
398 EndDialog(wxID_CANCEL);
399} // end of wxDialog::OnCancel
400
401void wxDialog::OnCloseWindow(
402 wxCloseEvent& rEvent
403)
404{
405 //
406 // We'll send a Cancel message by default, which may close the dialog.
407 // Check for looping if the Cancel event handler calls Close().
408 //
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.
418 //
419
420 //
421 // Ugh??? This is not good but until I figure out a global list it'll have to do
422 //
423 static wxList closing;
424
425 if ( closing.Member(this) )
426 return;
427
428 closing.Append(this);
429
430 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
431
432 vCancelEvent.SetEventObject( this );
433 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
434
435 closing.DeleteObject(this);
436} // end of wxDialog::OnCloseWindow
437
438void wxDialog::OnSysColourChanged(
439 wxSysColourChangedEvent& rEvent
440)
441{
442 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
443 Refresh();
444} // end of wxDialog::OnSysColourChanged
445
446MRESULT wxDialog::OS2WindowProc(
447 WXUINT uMessage
448, WXWPARAM wParam
449, WXLPARAM lParam
450)
451{
452 MRESULT rc = 0;
453 bool bProcessed = FALSE;
454
455 switch (uMessage)
456 {
457 case WM_CLOSE:
458 //
459 // If we can't close, tell the system that we processed the
460 // message - otherwise it would close us
461 //
462 bProcessed = !Close();
463 break;
464 }
465
466 if (!bProcessed)
467 rc = wxWindow::OS2WindowProc( uMessage
468 ,wParam
469 ,lParam
470 );
471 return rc;
472} // end of wxDialog::OS2WindowProc
473