1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/os2/dialog.cpp
3 // Purpose:     wxDialog class
4 // Author:      David Webster
5 // Modified by:
6 // Created:     10/14/99
7 // Copyright:   (c) David Webster
8 // Licence:     wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // For compilers that support precompilation, includes "wx.h".
12 #include "wx/wxprec.h"
13 
14 #include "wx/dialog.h"
15 
16 #ifndef WX_PRECOMP
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/evtloop.h"
27 #include "wx/scopedptr.h"
28 #include "wx/modalhook.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 
36 
37 // ----------------------------------------------------------------------------
38 // wxDialogModalData
39 // ----------------------------------------------------------------------------
40 
41 // this is simply a container for any data we need to implement modality which
42 // allows us to avoid changing wxDialog each time the implementation changes
43 class wxDialogModalData
44 {
45 public:
wxDialogModalData(wxDialog * dialog)46     wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { }
47 
RunLoop()48     void RunLoop()
49     {
50         m_evtLoop.Run();
51     }
52 
ExitLoop()53     void ExitLoop()
54     {
55         m_evtLoop.Exit();
56     }
57 
58 private:
59     wxModalEventLoop m_evtLoop;
60 };
61 
62 wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData);
63 
64 // ============================================================================
65 // implementation
66 // ============================================================================
67 
68 // ----------------------------------------------------------------------------
69 // wxDialog construction
70 // ----------------------------------------------------------------------------
71 
Init()72 void wxDialog::Init()
73 {
74     m_pOldFocus = NULL;
75     m_isShown = false;
76     m_pWindowDisabler = NULL;
77     m_modalData = NULL;
78     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
79 } // end of wxDialog::Init
80 
Create(wxWindow * pParent,wxWindowID vId,const wxString & rsTitle,const wxPoint & rPos,const wxSize & rSize,long lStyle,const wxString & rsName)81 bool wxDialog::Create( wxWindow*       pParent,
82                        wxWindowID      vId,
83                        const wxString& rsTitle,
84                        const wxPoint&  rPos,
85                        const wxSize&   rSize,
86                        long            lStyle,
87                        const wxString& rsName )
88 {
89     Init();
90     SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
91 
92     //
93     // Save focus before doing anything which can potentially change it
94     //
95     m_pOldFocus = FindFocus();
96 
97     //
98     // All dialogs should really have this style
99     //
100     lStyle |= wxTAB_TRAVERSAL;
101 
102     if (!wxTopLevelWindow::Create( pParent
103                                   ,vId
104                                   ,rsTitle
105                                   ,rPos
106                                   ,rSize
107                                   ,lStyle
108                                   ,rsName
109                                  ))
110         return false;
111 
112     SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
113 
114     //
115     // Must defer setting the title until after dialog is created and sized
116     //
117     if ( !rsTitle.empty() )
118         SetTitle(rsTitle);
119     return true;
120 } // end of wxDialog::Create
121 
122 #if WXWIN_COMPATIBILITY_2_6
123 
124 // deprecated ctor
wxDialog(wxWindow * parent,const wxString & title,bool WXUNUSED (modal),int x,int y,int w,int h,long style,const wxString & name)125 wxDialog::wxDialog(wxWindow *parent,
126                    const wxString& title,
127                    bool WXUNUSED(modal),
128                    int x,
129                    int y,
130                    int w,
131                    int h,
132                    long style,
133                    const wxString& name)
134 {
135     Init();
136 
137     Create(parent, wxID_ANY, title, wxPoint(x, y), wxSize(w, h), style, name);
138 }
139 
SetModal(bool WXUNUSED (bFlag))140 void wxDialog::SetModal(bool WXUNUSED(bFlag))
141 {
142     // nothing to do, obsolete method
143 } // end of wxDialog::SetModal
144 
145 #endif // WXWIN_COMPATIBILITY_2_6
146 
~wxDialog()147 wxDialog::~wxDialog()
148 {
149     SendDestroyEvent();
150 
151     // this will also reenable all the other windows for a modal dialog
152     Show(false);
153 } // end of wxDialog::~wxDialog
154 
155 // ----------------------------------------------------------------------------
156 // showing the dialogs
157 // ----------------------------------------------------------------------------
158 
159 #if WXWIN_COMPATIBILITY_2_6
160 
IsModalShowing() const161 bool wxDialog::IsModalShowing() const
162 {
163     return IsModal();
164 } // end of wxDialog::IsModalShowing
165 
166 #endif // WXWIN_COMPATIBILITY_2_6
167 
Show(bool bShow)168 bool wxDialog::Show( bool bShow )
169 {
170     if ( bShow == IsShown() )
171         return false;
172 
173     if (!bShow && m_modalData )
174     {
175         // we need to do this before calling wxDialogBase version because if we
176         // had disabled other app windows, they must be reenabled right now as
177         // if they stay disabled Windows will activate another window (one
178         // which is enabled, anyhow) when we're hidden in the base class Show()
179         // and we will lose activation
180         m_modalData->ExitLoop();
181 #if 0
182         wxDELETE(m_pWindowDisabler);
183 #endif
184     }
185 
186     if (bShow)
187     {
188         if (CanDoLayoutAdaptation())
189             DoLayoutAdaptation();
190 
191         // this usually will result in TransferDataToWindow() being called
192         // which will change the controls values so do it before showing as
193         // otherwise we could have some flicker
194         InitDialog();
195     }
196 
197     wxDialogBase::Show(bShow);
198 
199     wxString title = GetTitle();
200     if (!title.empty())
201         ::WinSetWindowText((HWND)GetHwnd(), title.c_str());
202 
203     if ( bShow )
204     {
205         // dialogs don't get WM_SIZE message after creation unlike most (all?)
206         // other windows and so could start their life not laid out correctly
207         // if we didn't call Layout() from here
208         //
209         // NB: normally we should call it just the first time but doing it
210         //     every time is simpler than keeping a flag
211         Layout();
212     }
213 
214     return true;
215 } // end of wxDialog::Show
216 
217 //
218 // Replacement for Show(true) for modal dialogs - returns return code
219 //
ShowModal()220 int wxDialog::ShowModal()
221 {
222     WX_HOOK_MODAL_DIALOG();
223 
224     wxASSERT_MSG( !IsModal(), wxT("wxDialog::ShowModal() reentered?") );
225 
226     m_endModalCalled = false;
227 
228     Show();
229 
230     // EndModal may have been called from InitDialog handler (called from
231     // inside Show()), which would cause an infinite loop if we didn't take it
232     // into account
233     if ( !m_endModalCalled )
234     {
235         // modal dialog needs a parent window, so try to find one
236         wxWindow * const parent = GetParentForModalDialog();
237 
238         // remember where the focus was
239         wxWindow *oldFocus = m_pOldFocus;
240         if ( !oldFocus )
241         {
242             // VZ: do we really want to do this?
243             oldFocus = parent;
244         }
245 
246         // We have to remember the HWND because we need to check
247         // the HWND still exists (oldFocus can be garbage when the dialog
248         // exits, if it has been destroyed)
249         HWND hwndOldFocus = oldFocus ? GetHwndOf(oldFocus) : NULL;
250 
251 
252         //
253         // Before entering the modal loop, reset the "is in OnIdle()" flag (see
254         // comment in app.cpp)
255         //
256         extern bool                     gbInOnIdle;
257         bool                            bWasInOnIdle = gbInOnIdle;
258 
259         gbInOnIdle = false;
260 
261         // enter and run the modal loop
262         {
263             wxDialogModalDataTiedPtr modalData(&m_modalData,
264                                                new wxDialogModalData(this));
265             modalData->RunLoop();
266         }
267         gbInOnIdle = bWasInOnIdle;
268 
269         // and restore focus
270         // Note that this code MUST NOT access the dialog object's data
271         // in case the object has been deleted (which will be the case
272         // for a modal dialog that has been destroyed before calling EndModal).
273         if ( oldFocus && (oldFocus != this) && ::WinIsWindow(vHabmain, hwndOldFocus))
274         {
275             // This is likely to prove that the object still exists
276             if (wxFindWinFromHandle((WXHWND) hwndOldFocus) == oldFocus)
277                 oldFocus->SetFocus();
278         }
279     }
280 
281     return GetReturnCode();
282 } // end of wxDialog::ShowModal
283 
EndModal(int nRetCode)284 void wxDialog::EndModal(
285   int                               nRetCode
286 )
287 {
288     wxASSERT_MSG( IsModal(), wxT("EndModal() called for non modal dialog") );
289 
290     m_endModalCalled = true;
291     SetReturnCode(nRetCode);
292 
293     Hide();
294 } // end of wxDialog::EndModal
295 
OS2WindowProc(WXUINT uMessage,WXWPARAM wParam,WXLPARAM lParam)296 MRESULT wxDialog::OS2WindowProc( WXUINT uMessage, WXWPARAM wParam, WXLPARAM lParam )
297 {
298     MRESULT  rc = 0;
299     bool     bProcessed = false;
300 
301     switch (uMessage)
302     {
303         case WM_CLOSE:
304             //
305             // If we can't close, tell the system that we processed the
306             // message - otherwise it would close us
307             //
308             bProcessed = !Close();
309             break;
310     }
311 
312     if (!bProcessed)
313         rc = wxWindow::OS2WindowProc( uMessage
314                                      ,wParam
315                                      ,lParam
316                                     );
317     return rc;
318 } // end of wxDialog::OS2WindowProc
319