*** empty log message ***
[wxWidgets.git] / src / os2 / dialog.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dialog.cpp
3 // Purpose: wxDialog class
4 // Author: AUTHOR
5 // Modified by:
6 // Created: ??/??/98
7 // RCS-ID: $Id$
8 // Copyright: (c) AUTHOR
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 #if wxUSE_COMMON_DIALOGS
29 #include <commdlg.h>
30 #endif
31
32 #define wxDIALOG_DEFAULT_X 300
33 #define wxDIALOG_DEFAULT_Y 300
34
35 // Lists to keep track of windows, so we can disable/enable them
36 // for modal dialogs
37 wxWindowList wxModalDialogs;
38 wxWindowList wxModelessWindows; // Frames and modeless dialogs
39 extern wxList WXDLLEXPORT wxPendingDelete;
40
41 #if !USE_SHARED_LIBRARY
42 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
43
44 BEGIN_EVENT_TABLE(wxDialog, wxPanel)
45 EVT_SIZE(wxDialog::OnSize)
46 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
47 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
48 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
49 EVT_CHAR_HOOK(wxDialog::OnCharHook)
50 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
51 EVT_CLOSE(wxDialog::OnCloseWindow)
52 END_EVENT_TABLE()
53 #endif
54
55 wxDialog::wxDialog()
56 {
57 m_isShown = FALSE;
58 m_modalShowing = FALSE;
59
60 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
61 }
62
63 bool wxDialog::Create(wxWindow *parent, wxWindowID id,
64 const wxString& title,
65 const wxPoint& pos,
66 const wxSize& size,
67 long style,
68 const wxString& name)
69 {
70 #if wxUSE_TOOLTIPS
71 m_hwndToolTip = 0;
72 #endif
73
74 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
75 SetName(name);
76
77 if (!parent)
78 wxTopLevelWindows.Append(this);
79
80 if (parent) parent->AddChild(this);
81
82 if ( id == -1 )
83 m_windowId = (int)NewControlId();
84 else
85 m_windowId = id;
86
87 int x = pos.x;
88 int y = pos.y;
89 int width = size.x;
90 int height = size.y;
91
92 if (x < 0) x = wxDIALOG_DEFAULT_X;
93 if (y < 0) y = wxDIALOG_DEFAULT_Y;
94
95 m_windowStyle = style;
96
97 m_isShown = FALSE;
98 m_modalShowing = FALSE;
99
100 if (width < 0)
101 width = 500;
102 if (height < 0)
103 height = 500;
104
105 // TODO: convert below to OS/2 PM code
106
107 // All dialogs should really have this style
108 // m_windowStyle |= wxTAB_TRAVERSAL;
109 //
110 // WXDWORD extendedStyle = MakeExtendedStyle(m_windowStyle);
111 // if (m_windowStyle & wxSTAY_ON_TOP)
112 // extendedStyle |= WS_EX_TOPMOST;
113 //
114 // Allows creation of dialogs with & without captions under MSWindows,
115 // resizeable or not (but a resizeable dialog always has caption -
116 // otherwise it would look too strange)
117 // const wxChar *dlg;
118 // if ( style & wxRESIZE_BORDER )
119 // dlg = T("wxResizeableDialog");
120 // else if ( style & wxCAPTION )
121 // dlg = T("wxCaptionDialog");
122 // else
123 // dlg = T("wxNoCaptionDialog");
124 // MSWCreate(m_windowId, parent, NULL, this, NULL,
125 // x, y, width, height,
126 // 0, // style is not used if we have dlg template
127 // dlg,
128 // extendedStyle);
129 //
130 // HWND hwnd = (HWND)GetHWND();
131 //
132 // if ( !hwnd )
133 // {
134 // wxLogError(T("Failed to create dialog."));
135 //
136 // return FALSE;
137 // }
138 //
139 // SubclassWin(GetHWND());
140 //
141 // SetWindowText(hwnd, title);
142 // SetFont(wxSystemSettings::GetSystemFont(wxSYS_DEFAULT_GUI_FONT));
143 //
144 return TRUE;
145 }
146
147 void wxDialog::SetModal(bool flag)
148 {
149 if ( flag )
150 m_windowStyle |= wxDIALOG_MODAL ;
151 else if ( m_windowStyle & wxDIALOG_MODAL )
152 m_windowStyle -= wxDIALOG_MODAL ;
153
154 wxModelessWindows.DeleteObject(this);
155 if (!flag)
156 wxModelessWindows.Append(this);
157 }
158
159 wxDialog::~wxDialog()
160 {
161 m_isBeingDeleted = TRUE;
162
163 wxTopLevelWindows.DeleteObject(this);
164
165 Show(FALSE);
166
167 if (m_modalShowing)
168 {
169 if (GetParent() && GetParent()->GetHWND())
170 // TODO: bring the parent to the top
171 return;
172 }
173
174 m_modalShowing = FALSE;
175 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
176 wxModelessWindows.DeleteObject(this);
177
178
179 // If this is the last top-level window, exit.
180 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
181 {
182 wxTheApp->SetTopWindow(NULL);
183
184 if (wxTheApp->GetExitOnFrameDelete())
185 {
186 // TODO: exit
187 }
188 }
189 }
190
191 // By default, pressing escape cancels the dialog
192 void wxDialog::OnCharHook(wxKeyEvent& event)
193 {
194 if (GetHWND())
195 {
196 if (event.m_keyCode == WXK_ESCAPE)
197 {
198 // Behaviour changed in 2.0: we'll send a Cancel message
199 // to the dialog instead of Close.
200 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
201 cancelEvent.SetEventObject( this );
202 GetEventHandler()->ProcessEvent(cancelEvent);
203
204 return;
205 }
206 }
207 // We didn't process this event.
208 event.Skip();
209 }
210
211 void wxDialog::OnPaint(wxPaintEvent& event)
212 {
213 // No: if you call the default procedure, it makes
214 // the following painting code not work.
215 // wxWindow::OnPaint(event);
216 }
217
218 void wxDialog::Fit()
219 {
220 wxWindow::Fit();
221 }
222
223 void wxDialog::Iconize(bool WXUNUSED(iconize))
224 {
225 // Windows dialog boxes can't be iconized
226 }
227
228 bool wxDialog::IsIconized() const
229 {
230 return FALSE;
231 }
232
233 void wxDialog::DoSetClientSize(int width, int height)
234 {
235 // TODO: Convert the below to OS/2 PM code
236
237 // HWND hWnd = (HWND) GetHWND();
238 // RECT rect;
239 // ::GetClientRect(hWnd, &rect);
240 //
241 // RECT rect2;
242 // GetWindowRect(hWnd, &rect2);
243 //
244 // Find the difference between the entire window (title bar and all)
245 // and the client area; add this to the new client size to move the
246 // window
247 // int actual_width = rect2.right - rect2.left - rect.right + width;
248 // int actual_height = rect2.bottom - rect2.top - rect.bottom + height;
249
250 // MoveWindow(hWnd, rect2.left, rect2.top, actual_width, actual_height, TRUE);
251 //
252 // wxSizeEvent event(wxSize(actual_width, actual_height), m_windowId);
253 // event.SetEventObject( this );
254 // GetEventHandler()->ProcessEvent(event);
255 }
256 void wxDialog::GetPosition(int *x, int *y) const
257 {
258 // TODO: Convert
259 // HWND hWnd = (HWND) GetHWND();
260 // RECT rect;
261 // GetWindowRect(hWnd, &rect);
262
263 // *x = rect.left;
264 // *y = rect.top;
265 }
266
267 bool wxDialog::IsShown() const
268 {
269 return m_isShown;
270 }
271
272 bool wxDialog::IsModal() const
273 {
274 return wxModalDialogs.Find((wxDialog *)this) != 0; // const_cast
275 }
276
277 bool wxDialog::Show(bool show)
278 {
279 // TODO: This is involved code, look at msw port for details
280 return FALSE;
281 }
282
283 void wxDialog::SetTitle(const wxString& title)
284 {
285 ::WinSetWindowText((HWND) GetHWND(), title.c_str());
286 }
287
288 wxString wxDialog::GetTitle() const
289 {
290 ::WinQueryWindowText((HWND) GetHWND(), 1000, wxBuffer);
291 return wxString(wxBuffer);
292 }
293
294 void wxDialog::Centre(int direction)
295 {
296 int x_offset,y_offset ;
297 int display_width, display_height;
298 int width, height, x, y;
299 wxWindow *parent = GetParent();
300 if ((direction & wxCENTER_FRAME) && parent)
301 {
302 parent->GetPosition(&x_offset,&y_offset) ;
303 parent->GetSize(&display_width,&display_height) ;
304 }
305 else
306 {
307 wxDisplaySize(&display_width, &display_height);
308 x_offset = 0 ;
309 y_offset = 0 ;
310 }
311
312 GetSize(&width, &height);
313 GetPosition(&x, &y);
314
315 if (direction & wxHORIZONTAL)
316 x = (int)((display_width - width)/2);
317 if (direction & wxVERTICAL)
318 y = (int)((display_height - height)/2);
319
320 SetSize(x+x_offset, y+y_offset, width, height);
321 }
322
323 // Replacement for Show(TRUE) for modal dialogs - returns return code
324 int wxDialog::ShowModal()
325 {
326 m_windowStyle |= wxDIALOG_MODAL;
327 Show(TRUE);
328 return GetReturnCode();
329 }
330
331 void wxDialog::EndModal(int retCode)
332 {
333 SetReturnCode(retCode);
334 // TODO modal un-showing
335 Show(FALSE);
336 }
337
338 // Define for each class of dialog and control
339 WXHBRUSH wxDialog::OnCtlColor(WXHDC pDC, WXHWND pWnd, WXUINT nCtlColor,
340 WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
341 {
342 return 0;
343 }
344 // Standard buttons
345 void wxDialog::OnOK(wxCommandEvent& event)
346 {
347 if ( Validate() && TransferDataFromWindow() )
348 {
349 if ( IsModal() )
350 EndModal(wxID_OK);
351 else
352 {
353 SetReturnCode(wxID_OK);
354 this->Show(FALSE);
355 }
356 }
357 }
358
359 void wxDialog::OnApply(wxCommandEvent& event)
360 {
361 if (Validate())
362 TransferDataFromWindow();
363 // TODO probably need to disable the Apply button until things change again
364 }
365
366 void wxDialog::OnCancel(wxCommandEvent& event)
367 {
368 if ( IsModal() )
369 EndModal(wxID_CANCEL);
370 else
371 {
372 SetReturnCode(wxID_CANCEL);
373 this->Show(FALSE);
374 }
375 }
376
377 void wxDialog::OnCloseWindow(wxCloseEvent& event)
378 {
379 // We'll send a Cancel message by default,
380 // which may close the dialog.
381 // Check for looping if the Cancel event handler calls Close().
382
383 // Note that if a cancel button and handler aren't present in the dialog,
384 // nothing will happen when you close the dialog via the window manager, or
385 // via Close().
386 // We wouldn't want to destroy the dialog by default, since the dialog may have been
387 // created on the stack.
388 // However, this does mean that calling dialog->Close() won't delete the dialog
389 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
390 // sure to destroy the dialog.
391 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
392
393 static wxList closing;
394
395 if ( closing.Member(this) )
396 return;
397
398 closing.Append(this);
399
400 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
401 cancelEvent.SetEventObject( this );
402 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
403
404 closing.DeleteObject(this);
405 }
406
407 // Destroy the window (delayed, if a managed window)
408 bool wxDialog::Destroy()
409 {
410 if (!wxPendingDelete.Member(this))
411 wxPendingDelete.Append(this);
412 return TRUE;
413 }
414
415 void wxDialog::OnSize(wxSizeEvent& WXUNUSED(event))
416 {
417 // if we're using constraints - do use them
418 #if wxUSE_CONSTRAINTS
419 if ( GetAutoLayout() )
420 {
421 Layout();
422 }
423 #endif
424 }
425
426 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& event)
427 {
428 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
429 Refresh();
430 }
431
432 MRESULT wxDialog::OS2WindowProc(HWND hwnd, WXUINT message, WXWPARAM wParam, WXLPARAM lParam)
433 {
434 MRESULT rc = 0;
435 bool processed = FALSE;
436
437 switch ( message )
438 {
439 case WM_CLOSE:
440 // if we can't close, tell the system that we processed the
441 // message - otherwise it would close us
442 processed = !Close();
443 break;
444 }
445
446 if ( !processed )
447 rc = wxWindow::OS2WindowProc(hwnd, message, wParam, lParam);
448
449 return rc;
450 }
451