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