]> git.saurik.com Git - wxWidgets.git/blame - src/os2/dialog.cpp
added UTF-16/32-[LB]E conversions; got rid of wxCharacterSet and simplified and fixed...
[wxWidgets.git] / src / os2 / dialog.cpp
CommitLineData
0e320a79
DW
1/////////////////////////////////////////////////////////////////////////////
2// Name: dialog.cpp
3// Purpose: wxDialog class
fb46a9a6 4// Author: David Webster
0e320a79 5// Modified by:
fb46a9a6 6// Created: 10/14/99
0e320a79 7// RCS-ID: $Id$
fb46a9a6
DW
8// Copyright: (c) David Webster
9// Licence: wxWindows licence
0e320a79
DW
10/////////////////////////////////////////////////////////////////////////////
11
27476f73
DW
12// For compilers that support precompilation, includes "wx.h".
13#include "wx/wxprec.h"
0e320a79 14
27476f73 15#ifndef WX_PRECOMP
0e320a79
DW
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"
27476f73
DW
21#include "wx/intl.h"
22#include "wx/log.h"
23#endif
24
25#include "wx/os2/private.h"
26#include "wx/log.h"
598dc9b7
SN
27#include "wx/evtloop.h"
28#include "wx/ptr_scpd.h"
27476f73 29
27476f73
DW
30#define wxDIALOG_DEFAULT_X 300
31#define wxDIALOG_DEFAULT_Y 300
0e320a79 32
c9cb56f7
DW
33#define wxDIALOG_DEFAULT_WIDTH 500
34#define wxDIALOG_DEFAULT_HEIGHT 500
35
27476f73 36wxWindowList wxModalDialogs;
0e320a79 37
5d44b24e 38IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
27476f73 39
d491523b 40BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
5d44b24e
DW
41 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
42 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
43 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
44 EVT_CHAR_HOOK(wxDialog::OnCharHook)
45 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
46 EVT_CLOSE(wxDialog::OnCloseWindow)
47END_EVENT_TABLE()
0e320a79 48
598dc9b7
SN
49// ----------------------------------------------------------------------------
50// wxDialogModalData
51// ----------------------------------------------------------------------------
52
53// this is simply a container for any data we need to implement modality which
54// allows us to avoid changing wxDialog each time the implementation changes
55class wxDialogModalData
56{
57public:
58 wxDialogModalData(wxDialog *dialog) : m_evtLoop(dialog) { }
59
60 void RunLoop()
61 {
62 m_evtLoop.Run();
63 }
64
65 void ExitLoop()
66 {
67 m_evtLoop.Exit();
68 }
69
70private:
71 wxModalEventLoop m_evtLoop;
72};
73
74wxDEFINE_TIED_SCOPED_PTR_TYPE(wxDialogModalData);
75
76// ============================================================================
77// implementation
78// ============================================================================
79
80// ----------------------------------------------------------------------------
81// wxDialog construction
82// ----------------------------------------------------------------------------
83
c9cb56f7 84void wxDialog::Init()
0e320a79 85{
c9cb56f7 86 m_pOldFocus = (wxWindow *)NULL;
27476f73 87 m_isShown = FALSE;
c9cb56f7 88 m_pWindowDisabler = (wxWindowDisabler *)NULL;
a756f210 89 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
c9cb56f7
DW
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)
0e320a79 101{
c9cb56f7
DW
102 long lX = rPos.x;
103 long lY = rPos.y;
104 long lWidth = rSize.x;
105 long lHeight = rSize.y;
106 const char* zDlg;
107 WXDWORD dwExtendedStyle = 0L;
108 HWND hWnd;
109
110 Init();
5d44b24e 111 SetExtraStyle(GetExtraStyle() | wxTOPLEVEL_EX_DIALOG);
c9cb56f7
DW
112
113 //
5d44b24e 114 // Save focus before doing anything which can potentially change it
c9cb56f7 115 //
5d44b24e 116 m_pOldFocus = FindFocus();
c9cb56f7
DW
117
118 //
5d44b24e 119 // All dialogs should really have this style
c9cb56f7 120 //
5d44b24e
DW
121 lStyle |= wxTAB_TRAVERSAL;
122
123 if (!wxTopLevelWindow::Create( pParent
124 ,vId
125 ,rsTitle
126 ,rPos
127 ,rSize
128 ,lStyle
129 ,rsName
130 ))
c9cb56f7 131 return FALSE;
a756f210 132 SetFont(wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
c9b9e020
DW
133
134 //
135 // Must defer setting the title until after dialog is created and sized
136 //
137 if (!rsTitle.IsNull())
138 SetTitle(rsTitle);
27476f73 139 return TRUE;
c9cb56f7 140} // end of wxDialog::Create
0e320a79 141
c9cb56f7
DW
142void wxDialog::SetModal(
143 bool bFlag
144)
0e320a79 145{
c9cb56f7 146 if (bFlag)
5d44b24e 147 {
27476f73 148 m_windowStyle |= wxDIALOG_MODAL ;
5d44b24e
DW
149 wxModelessWindows.DeleteObject(this);
150 }
151 else
152 {
153 m_windowStyle &= ~wxDIALOG_MODAL ;
154 wxModelessWindows.Append(this);
155 }
c9cb56f7 156} // end of wxDialog::SetModal
0e320a79
DW
157
158wxDialog::~wxDialog()
159{
27476f73 160 m_isBeingDeleted = TRUE;
27476f73 161 Show(FALSE);
c9cb56f7 162} // end of wxDialog::~wxDialog
0e320a79 163
c9cb56f7 164//
0e320a79 165// By default, pressing escape cancels the dialog
c9cb56f7
DW
166//
167void wxDialog::OnCharHook(
168 wxKeyEvent& rEvent
169)
0e320a79 170{
27476f73
DW
171 if (GetHWND())
172 {
c9cb56f7 173 if (rEvent.m_keyCode == WXK_ESCAPE)
27476f73 174 {
c9cb56f7 175 //
27476f73
DW
176 // Behaviour changed in 2.0: we'll send a Cancel message
177 // to the dialog instead of Close.
c9cb56f7
DW
178 //
179 wxCommandEvent vCancelEvent( wxEVT_COMMAND_BUTTON_CLICKED
180 ,wxID_CANCEL
181 );
182
183 vCancelEvent.SetEventObject( this );
184 GetEventHandler()->ProcessEvent(vCancelEvent);
185
186 //
187 // Ensure that there is another message for this window so the
188 // ShowModal loop will exit and won't get stuck in GetMessage().
189 //
190 ::WinPostMsg(GetHwnd(), WM_NULL, 0, 0);
27476f73
DW
191 return;
192 }
193 }
194 // We didn't process this event.
c9cb56f7 195 rEvent.Skip();
27476f73
DW
196}
197
5d44b24e
DW
198// ----------------------------------------------------------------------------
199// showing the dialogs
200// ----------------------------------------------------------------------------
27476f73
DW
201
202bool wxDialog::IsModal() const
203{
c9cb56f7
DW
204 return (GetWindowStyleFlag() & wxDIALOG_MODAL) != 0;
205} // end of wxDialog::IsModal
0e320a79 206
c9cb56f7 207bool wxDialog::IsModalShowing() const
0e320a79 208{
c9cb56f7
DW
209 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
210} // end of wxDialog::IsModalShowing
0e320a79 211
c9cb56f7 212void wxDialog::DoShowModal()
0e320a79 213{
c9cb56f7
DW
214 wxWindow* pParent = GetParent();
215 wxWindow* pOldFocus = m_pOldFocus;
216 HWND hWndOldFocus = 0;
0e320a79 217
c9cb56f7
DW
218 wxCHECK_RET( !IsModalShowing(), _T("DoShowModal() called twice") );
219 wxCHECK_RET( IsModal(), _T("can't DoShowModal() modeless dialog") );
220
221 wxModalDialogs.Append(this);
222 if (pOldFocus)
223 hWndOldFocus = (HWND)pOldFocus->GetHWND();
0e320a79 224
c9cb56f7
DW
225 //
226 // Remember where the focus was
227 //
228 if (!pOldFocus)
229 {
230 pOldFocus = pParent;
231 if (pParent)
232 hWndOldFocus = GetHwndOf(pParent);
233 }
234
235 //
236 // Disable all other app windows
237 //
238 wxASSERT_MSG(!m_pWindowDisabler, _T("disabling windows twice?"));
239
f3e4a2a4
DW
240 //
241 // Disables other app windows and window proc message processing
242 // until WinDismissDlg called
243 //
244 ::WinProcessDlg((HWND)GetHwnd());
c9cb56f7 245
2b5f62a0
VZ
246 //
247 // Before entering the modal loop, reset the "is in OnIdle()" flag (see
248 // comment in app.cpp)
249 //
250 extern bool gbInOnIdle;
251 bool bWasInOnIdle = gbInOnIdle;
252
253 gbInOnIdle = FALSE;
254
598dc9b7 255 // enter the modal loop
c9cb56f7 256 {
598dc9b7
SN
257 wxDialogModalDataTiedPtr modalData(&m_modalData,
258 new wxDialogModalData(this));
259 modalData->RunLoop();
c9cb56f7 260 }
2b5f62a0 261 gbInOnIdle = bWasInOnIdle;
c9cb56f7
DW
262
263 //
598dc9b7 264 // and restore focus
c9cb56f7
DW
265 // Note that this code MUST NOT access the dialog object's data
266 // in case the object has been deleted (which will be the case
267 // for a modal dialog that has been destroyed before calling EndModal).
268 //
269 if (pOldFocus && (pOldFocus != this) && ::WinIsWindow(vHabmain, hWndOldFocus))
270 {
271 //
272 // This is likely to prove that the object still exists
273 //
274 if (wxFindWinFromHandle((WXHWND) hWndOldFocus) == pOldFocus)
275 pOldFocus->SetFocus();
276 }
277} // end of wxDialog::DoShowModal
278
279bool wxDialog::Show(
280 bool bShow
281)
0e320a79 282{
c9cb56f7
DW
283 if (!bShow)
284 {
285 //
286 // If we had disabled other app windows, reenable them back now because
287 // if they stay disabled Windows will activate another window (one
f3e4a2a4
DW
288 // which is enabled, anyhow) and we will lose activation. We really don't
289 // do this in OS/2 since PM does this for us.
c9cb56f7
DW
290 //
291 if (m_pWindowDisabler)
292 {
293 delete m_pWindowDisabler;
294 m_pWindowDisabler = NULL;
295 }
296 }
0e320a79 297
c9cb56f7
DW
298 //
299 // ShowModal() may be called for already shown dialog
300 //
301 if (!wxDialogBase::Show(bShow) && !(bShow && IsModal()))
302 {
303 //
304 // Nothing to do
305 //
306 return FALSE;
307 }
308
309 if (bShow)
310 {
311 //
312 // Usually will result in TransferDataToWindow() being called
313 //
314 InitDialog();
315 }
316
c9b9e020
DW
317 if (GetTitle().c_str())
318 ::WinSetWindowText((HWND)GetHwnd(), GetTitle().c_str());
c9cb56f7
DW
319 if (IsModal())
320 {
321 if (bShow)
322 {
323 //
324 // Modal dialog needs a parent window, so try to find one
325 //
326 if (!GetParent())
327 {
328 wxWindow* pParent = wxTheApp->GetTopWindow();
329
330 if ( pParent && pParent != this && pParent->IsShown() )
331 {
332 //
333 // Use it
334 //
335 m_parent = pParent;
336
337 }
338 }
339 DoShowModal();
340 }
341 else // end of modal dialog
342 {
343 //
344 // This will cause IsModalShowing() return FALSE and our local
345 // message loop will terminate
346 //
347 wxModalDialogs.DeleteObject(this);
348 }
349 }
5d44b24e 350 return TRUE;
c9cb56f7
DW
351} // end of wxDialog::Show
352
353//
0e320a79 354// Replacement for Show(TRUE) for modal dialogs - returns return code
c9cb56f7 355//
0e320a79
DW
356int wxDialog::ShowModal()
357{
c9cb56f7
DW
358 if (!IsModal())
359 {
360 SetModal(TRUE);
361 }
27476f73
DW
362 Show(TRUE);
363 return GetReturnCode();
c9cb56f7 364} // end of wxDialog::ShowModal
0e320a79 365
c9cb56f7
DW
366void wxDialog::EndModal(
367 int nRetCode
368)
0e320a79 369{
c9cb56f7 370 SetReturnCode(nRetCode);
27476f73 371 Show(FALSE);
f3e4a2a4 372 ::WinDismissDlg((HWND)GetHwnd(), nRetCode);
c9cb56f7 373} // end of wxDialog::EndModal
0e320a79 374
5d44b24e
DW
375// ----------------------------------------------------------------------------
376// wxWin event handlers
377// ----------------------------------------------------------------------------
378
c9cb56f7
DW
379void wxDialog::OnApply(
380 wxCommandEvent& rEvent
381)
27476f73 382{
c9cb56f7
DW
383 if (Validate())
384 TransferDataFromWindow();
385} // end of wxDialog::OnApply
386
0e320a79 387// Standard buttons
c9cb56f7
DW
388void wxDialog::OnOK(
389 wxCommandEvent& rEvent
390)
0e320a79 391{
27476f73
DW
392 if ( Validate() && TransferDataFromWindow() )
393 {
c9cb56f7 394 EndModal(wxID_OK);
27476f73 395 }
c9cb56f7 396} // end of wxDialog::OnOK
0e320a79 397
c9cb56f7
DW
398void wxDialog::OnCancel(
399 wxCommandEvent& rEvent
400)
0e320a79 401{
c9cb56f7
DW
402 EndModal(wxID_CANCEL);
403} // end of wxDialog::OnCancel
0e320a79 404
c9cb56f7
DW
405void wxDialog::OnCloseWindow(
406 wxCloseEvent& rEvent
407)
0e320a79 408{
c9cb56f7 409 //
0e320a79
DW
410 // We'll send a Cancel message by default,
411 // which may close the dialog.
412 // Check for looping if the Cancel event handler calls Close().
c9cb56f7 413 //
0e320a79
DW
414 // Note that if a cancel button and handler aren't present in the dialog,
415 // nothing will happen when you close the dialog via the window manager, or
416 // via Close().
417 // We wouldn't want to destroy the dialog by default, since the dialog may have been
418 // created on the stack.
419 // However, this does mean that calling dialog->Close() won't delete the dialog
420 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
421 // sure to destroy the dialog.
422 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
c9cb56f7 423 //
0e320a79 424
c9cb56f7
DW
425 //
426 // Ugh??? This is not good but until I figure out a global list it'll have to do
427 //
0e320a79 428 static wxList closing;
c3d43472 429
0e320a79
DW
430 if ( closing.Member(this) )
431 return;
c3d43472 432
0e320a79 433 closing.Append(this);
c3d43472 434
c9cb56f7
DW
435 wxCommandEvent vCancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
436
437 vCancelEvent.SetEventObject( this );
438 GetEventHandler()->ProcessEvent(vCancelEvent); // This may close the dialog
0e320a79
DW
439
440 closing.DeleteObject(this);
c9cb56f7 441} // end of wxDialog::OnCloseWindow
0e320a79 442
c9cb56f7
DW
443void wxDialog::OnSysColourChanged(
444 wxSysColourChangedEvent& rEvent
445)
27476f73 446{
a756f210 447 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
c9cb56f7
DW
448 Refresh();
449} // end of wxDialog::OnSysColourChanged
450
451MRESULT wxDialog::OS2WindowProc(
452 WXUINT uMessage
453, WXWPARAM wParam
454, WXLPARAM lParam
455)
0e320a79 456{
c9cb56f7
DW
457 MRESULT rc = 0;
458 bool bProcessed = FALSE;
27476f73 459
c9cb56f7 460 switch (uMessage)
27476f73
DW
461 {
462 case WM_CLOSE:
c9cb56f7
DW
463 //
464 // If we can't close, tell the system that we processed the
27476f73 465 // message - otherwise it would close us
c9cb56f7
DW
466 //
467 bProcessed = !Close();
27476f73
DW
468 break;
469 }
470
c9cb56f7
DW
471 if (!bProcessed)
472 rc = wxWindow::OS2WindowProc( uMessage
473 ,wParam
474 ,lParam
475 );
27476f73 476 return rc;
c9cb56f7 477} // end of wxDialog::OS2WindowProc
27476f73 478