]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/os2/dialog.cpp
Optimized sizers to not call CalcMin more often than neccessary
[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 EVT_CLOSE(wxDialog::OnCloseWindow)
45END_EVENT_TABLE()
46
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
82void wxDialog::Init()
83{
84 m_pOldFocus = (wxWindow *)NULL;
85 m_isShown = FALSE;
86 m_pWindowDisabler = (wxWindowDisabler *)NULL;
87 m_modalData = NULL;
88 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
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)
100{
101 Init();
102 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
103
104 //
105 // Save focus before doing anything which can potentially change it
106 //
107 m_pOldFocus = FindFocus();
108
109 //
110 // All dialogs should really have this style
111 //
112 lStyle |= wxTAB_TRAVERSAL;
113
114 if (!wxTopLevelWindow::Create( pParent
115 ,vId
116 ,rsTitle
117 ,rPos
118 ,rSize
119 ,lStyle
120 ,rsName
121 ))
122 return FALSE;
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
133void wxDialog::SetModal(
134 bool bFlag
135)
136{
137 if (bFlag)
138 {
139 m_windowStyle |= wxDIALOG_MODAL ;
140 wxModelessWindows.DeleteObject(this);
141 }
142 else
143 {
144 m_windowStyle &= ~wxDIALOG_MODAL ;
145 wxModelessWindows.Append(this);
146 }
147} // end of wxDialog::SetModal
148
149wxDialog::~wxDialog()
150{
151 m_isBeingDeleted = TRUE;
152 Show(FALSE);
153} // end of wxDialog::~wxDialog
154
155//
156// By default, pressing escape cancels the dialog
157//
158void wxDialog::OnCharHook(
159 wxKeyEvent& rEvent
160)
161{
162 if (GetHWND())
163 {
164 if (rEvent.m_keyCode == WXK_ESCAPE)
165 {
166 //
167 // Behaviour changed in 2.0: we'll send a Cancel message
168 // to the dialog instead of Close.
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);
182 return;
183 }
184 }
185 // We didn't process this event.
186 rEvent.Skip();
187}
188
189// ----------------------------------------------------------------------------
190// showing the dialogs
191// ----------------------------------------------------------------------------
192
193bool wxDialog::IsModal() const
194{
195 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
196} // end of wxDialog::IsModal
197
198bool wxDialog::IsModalShowing() const
199{
200 return m_modalData != NULL; // const_cast
201} // end of wxDialog::IsModalShowing
202
203void wxDialog::DoShowModal()
204{
205 wxWindow* pParent = GetParent();
206 wxWindow* pOldFocus = m_pOldFocus;
207 HWND hWndOldFocus = 0;
208
209 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
210 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
211
212 if (pOldFocus)
213 hWndOldFocus = (HWND)pOldFocus->GetHWND();
214
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
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
239 // enter the modal loop
240 {
241 wxDialogModalDataTiedPtr modalData(&m_modalData,
242 new wxDialogModalData(this));
243 modalData->RunLoop();
244 }
245 gbInOnIdle = bWasInOnIdle;
246
247 //
248 // and restore focus
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)
266{
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
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.
274 //
275 if (m_pWindowDisabler)
276 {
277 delete m_pWindowDisabler;
278 m_pWindowDisabler = NULL;
279 }
280 if ( m_modalData )
281 m_modalData->ExitLoop();
282 }
283
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 {
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
305 //
306 // Usually will result in TransferDataToWindow() being called
307 //
308 InitDialog();
309 }
310
311 if (GetTitle().c_str())
312 ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str());
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 }
335 }
336 return TRUE;
337} // end of wxDialog::Show
338
339//
340// Replacement for Show(TRUE) for modal dialogs - returns return code
341//
342int wxDialog::ShowModal()
343{
344 if (!IsModal())
345 {
346 SetModal(TRUE);
347 }
348 Show(TRUE);
349 return GetReturnCode();
350} // end of wxDialog::ShowModal
351
352void wxDialog::EndModal(
353 int nRetCode
354)
355{
356 SetReturnCode(nRetCode);
357 Show(FALSE);
358} // end of wxDialog::EndModal
359
360// ----------------------------------------------------------------------------
361// wxWin event handlers
362// ----------------------------------------------------------------------------
363
364void wxDialog::OnApply(
365 wxCommandEvent& rEvent
366)
367{
368 if (Validate())
369 TransferDataFromWindow();
370} // end of wxDialog::OnApply
371
372// Standard buttons
373void wxDialog::OnOK(
374 wxCommandEvent& rEvent
375)
376{
377 if ( Validate() && TransferDataFromWindow() )
378 {
379 EndModal(wxID_OK);
380 }
381} // end of wxDialog::OnOK
382
383void wxDialog::OnCancel(
384 wxCommandEvent& rEvent
385)
386{
387 EndModal(wxID_CANCEL);
388} // end of wxDialog::OnCancel
389
390void wxDialog::OnCloseWindow(
391 wxCloseEvent& rEvent
392)
393{
394 //
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().
398 //
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.
408 //
409
410 //
411 // Ugh??? This is not good but until I figure out a global list it'll have to do
412 //
413 static wxList closing;
414
415 if ( closing.Member(this) )
416 return;
417
418 closing.Append(this);
419
420 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
421
422 vCancelEvent.SetEventObject( this );
423 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
424
425 closing.DeleteObject(this);
426} // end of wxDialog::OnCloseWindow
427
428void wxDialog::OnSysColourChanged(
429 wxSysColourChangedEvent& rEvent
430)
431{
432 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
433 Refresh();
434} // end of wxDialog::OnSysColourChanged
435
436MRESULT wxDialog::OS2WindowProc(
437 WXUINT uMessage
438, WXWPARAM wParam
439, WXLPARAM lParam
440)
441{
442 MRESULT rc = 0;
443 bool bProcessed = FALSE;
444
445 switch (uMessage)
446 {
447 case WM_CLOSE:
448 //
449 // If we can't close, tell the system that we processed the
450 // message - otherwise it would close us
451 //
452 bProcessed = !Close();
453 break;
454 }
455
456 if (!bProcessed)
457 rc = wxWindow::OS2WindowProc( uMessage
458 ,wParam
459 ,lParam
460 );
461 return rc;
462} // end of wxDialog::OS2WindowProc
463