OS/2 scrolling support for controls
[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, wxTopLevelWindow)
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::GetSystemColour(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::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
96 return TRUE;
97 } // end of wxDialog::Create
98
99 void wxDialog::SetModal(
100 bool bFlag
101 )
102 {
103 if (bFlag)
104 {
105 m_windowStyle |= wxDIALOG_MODAL ;
106 wxModelessWindows.DeleteObject(this);
107 }
108 else
109 {
110 m_windowStyle &= ~wxDIALOG_MODAL ;
111 wxModelessWindows.Append(this);
112 }
113 } // end of wxDialog::SetModal
114
115 wxDialog::~wxDialog()
116 {
117 m_isBeingDeleted = TRUE;
118 Show(FALSE);
119 } // end of wxDialog::~wxDialog
120
121 //
122 // By default, pressing escape cancels the dialog
123 //
124 void wxDialog::OnCharHook(
125 wxKeyEvent& rEvent
126 )
127 {
128 if (GetHWND())
129 {
130 if (rEvent.m_keyCode == WXK_ESCAPE)
131 {
132 //
133 // Behaviour changed in 2.0: we'll send a Cancel message
134 // to the dialog instead of Close.
135 //
136 wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
137 ,wxID_CANCEL
138 );
139
140 vCancelEvent.SetEventObject( this );
141 GetEventHandler()->ProcessEvent(vCancelEvent);
142
143 //
144 // Ensure that there is another message for this window so the
145 // ShowModal loop will exit and won't get stuck in GetMessage().
146 //
147 ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0);
148 return;
149 }
150 }
151 // We didn't process this event.
152 rEvent.Skip();
153 }
154
155 // ----------------------------------------------------------------------------
156 // showing the dialogs
157 // ----------------------------------------------------------------------------
158
159 bool wxDialog::IsModal() const
160 {
161 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
162 } // end of wxDialog::IsModal
163
164 bool wxDialog::IsModalShowing() const
165 {
166 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
167 } // end of wxDialog::IsModalShowing
168
169 void wxDialog::DoShowModal()
170 {
171 wxWindow* pParent = GetParent();
172 wxWindow* pOldFocus = m_pOldFocus;
173 HWND hWndOldFocus = 0;
174
175 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
176 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
177
178 wxModalDialogs.Append(this);
179 if (pOldFocus)
180 hWndOldFocus = (HWND)pOldFocus->GetHWND();
181
182 //
183 // Remember where the focus was
184 //
185 if (!pOldFocus)
186 {
187 pOldFocus = pParent;
188 if (pParent)
189 hWndOldFocus = GetHwndOf(pParent);
190 }
191
192 //
193 // Disable all other app windows
194 //
195 wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?"));
196
197 m_pWindowDisabler = new wxWindowDisabler(this);
198
199 //
200 // Enter the modal loop
201 //
202 while ( IsModalShowing() )
203 {
204 #if wxUSE_THREADS
205 wxMutexGuiLeaveOrEnter();
206 #endif // wxUSE_THREADS
207
208 while ( !wxTheApp->Pending() && wxTheApp->ProcessIdle() )
209 ;
210
211 // a message came or no more idle processing to do
212 wxTheApp->DoMessage();
213 }
214
215 //
216 // Snd restore focus
217 // Note that this code MUST NOT access the dialog object's data
218 // in case the object has been deleted (which will be the case
219 // for a modal dialog that has been destroyed before calling EndModal).
220 //
221 if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus))
222 {
223 //
224 // This is likely to prove that the object still exists
225 //
226 if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus)
227 pOldFocus->SetFocus();
228 }
229 } // end of wxDialog::DoShowModal
230
231 bool wxDialog::Show(
232 bool bShow
233 )
234 {
235 if (!bShow)
236 {
237 //
238 // If we had disabled other app windows, reenable them back now because
239 // if they stay disabled Windows will activate another window (one
240 // which is enabled, anyhow) and we will lose activation
241 //
242 if (m_pWindowDisabler)
243 {
244 delete m_pWindowDisabler;
245 m_pWindowDisabler = NULL;
246 }
247 }
248
249 //
250 // ShowModal() may be called for already shown dialog
251 //
252 if (!wxDialogBase::Show(bShow) && !(bShow && IsModal()))
253 {
254 //
255 // Nothing to do
256 //
257 return FALSE;
258 }
259
260 if (bShow)
261 {
262 //
263 // Usually will result in TransferDataToWindow() being called
264 //
265 InitDialog();
266 }
267
268 if (IsModal())
269 {
270 if (bShow)
271 {
272 //
273 // Modal dialog needs a parent window, so try to find one
274 //
275 if (!GetParent())
276 {
277 wxWindow* pParent = wxTheApp->GetTopWindow();
278
279 if ( pParent && pParent != this && pParent->IsShown() )
280 {
281 //
282 // Use it
283 //
284 m_parent = pParent;
285
286 }
287 }
288 DoShowModal();
289 }
290 else // end of modal dialog
291 {
292 //
293 // This will cause IsModalShowing() return FALSE and our local
294 // message loop will terminate
295 //
296 wxModalDialogs.DeleteObject(this);
297 }
298 }
299 return TRUE;
300 } // end of wxDialog::Show
301
302 //
303 // Replacement for Show(TRUE) for modal dialogs - returns return code
304 //
305 int wxDialog::ShowModal()
306 {
307 if (!IsModal())
308 {
309 SetModal(TRUE);
310 }
311 Show(TRUE);
312 return GetReturnCode();
313 } // end of wxDialog::ShowModal
314
315 void wxDialog::EndModal(
316 int nRetCode
317 )
318 {
319 SetReturnCode(nRetCode);
320 Show(FALSE);
321 } // end of wxDialog::EndModal
322
323 // ----------------------------------------------------------------------------
324 // wxWin event handlers
325 // ----------------------------------------------------------------------------
326
327 void wxDialog::OnApply(
328 wxCommandEvent& rEvent
329 )
330 {
331 if (Validate())
332 TransferDataFromWindow();
333 } // end of wxDialog::OnApply
334
335 // Standard buttons
336 void wxDialog::OnOK(
337 wxCommandEvent& rEvent
338 )
339 {
340 if ( Validate() && TransferDataFromWindow() )
341 {
342 EndModal(wxID_OK);
343 }
344 } // end of wxDialog::OnOK
345
346 void wxDialog::OnCancel(
347 wxCommandEvent& rEvent
348 )
349 {
350 EndModal(wxID_CANCEL);
351 } // end of wxDialog::OnCancel
352
353 void wxDialog::OnCloseWindow(
354 wxCloseEvent& rEvent
355 )
356 {
357 //
358 // We'll send a Cancel message by default,
359 // which may close the dialog.
360 // Check for looping if the Cancel event handler calls Close().
361 //
362 // Note that if a cancel button and handler aren't present in the dialog,
363 // nothing will happen when you close the dialog via the window manager, or
364 // via Close().
365 // We wouldn't want to destroy the dialog by default, since the dialog may have been
366 // created on the stack.
367 // However, this does mean that calling dialog->Close() won't delete the dialog
368 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
369 // sure to destroy the dialog.
370 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
371 //
372
373 //
374 // Ugh??? This is not good but until I figure out a global list it'll have to do
375 //
376 static wxList closing;
377
378 if ( closing.Member(this) )
379 return;
380
381 closing.Append(this);
382
383 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
384
385 vCancelEvent.SetEventObject( this );
386 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
387
388 closing.DeleteObject(this);
389 } // end of wxDialog::OnCloseWindow
390
391 void wxDialog::OnSysColourChanged(
392 wxSysColourChangedEvent& rEvent
393 )
394 {
395 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
396 Refresh();
397 } // end of wxDialog::OnSysColourChanged
398
399 MRESULT wxDialog::OS2WindowProc(
400 WXUINT uMessage
401 , WXWPARAM wParam
402 , WXLPARAM lParam
403 )
404 {
405 MRESULT rc = 0;
406 bool bProcessed = FALSE;
407
408 switch (uMessage)
409 {
410 case WM_CLOSE:
411 //
412 // If we can't close, tell the system that we processed the
413 // message - otherwise it would close us
414 //
415 bProcessed = !Close();
416 break;
417 }
418
419 if (!bProcessed)
420 rc = wxWindow::OS2WindowProc( uMessage
421 ,wParam
422 ,lParam
423 );
424 return rc;
425 } // end of wxDialog::OS2WindowProc
426