]> git.saurik.com Git - wxWidgets.git/blob - src/mac/dialog.cpp
Committing in .
[wxWidgets.git] / src / mac / 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 #ifdef __GNUG__
13 #pragma implementation "dialog.h"
14 #endif
15
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
22 #include <wx/mac/uma.h>
23
24 // Lists to keep track of windows, so we can disable/enable them
25 // for modal dialogs
26 wxList wxModalDialogs;
27 wxList wxModelessWindows; // Frames and modeless dialogs
28 extern wxList wxPendingDelete;
29
30 #if !USE_SHARED_LIBRARY
31 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
32
33 BEGIN_EVENT_TABLE(wxDialog, wxPanel)
34 EVT_SIZE(wxDialog::OnSize)
35 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
36 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
37 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
38 EVT_CHAR_HOOK(wxDialog::OnCharHook)
39 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
40 EVT_CLOSE(wxDialog::OnCloseWindow)
41 END_EVENT_TABLE()
42
43 #endif
44
45 wxDialog::wxDialog()
46 {
47 m_isShown = FALSE;
48 m_modalShowing = FALSE;
49 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
50 }
51
52 bool wxDialog::Create(wxWindow *parent, wxWindowID id,
53 const wxString& title,
54 const wxPoint& pos,
55 const wxSize& size,
56 long style,
57 const wxString& name)
58 {
59 m_windowStyle = style;
60 m_isShown = FALSE;
61 m_modalShowing = FALSE;
62
63 #if wxUSE_TOOLTIPS
64 m_hwndToolTip = 0;
65 #endif
66 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
67 SetName(name);
68
69 if (!parent)
70 wxTopLevelWindows.Append(this);
71
72 if (parent) parent->AddChild(this);
73
74 if ( id == -1 )
75 m_windowId = (int)NewControlId();
76 else
77 m_windowId = id;
78
79 Rect theBoundsRect;
80
81 m_x = (int)pos.x;
82 m_y = (int)pos.y;
83 if ( m_y < 50 )
84 m_y = 50 ;
85 if ( m_x < 20 )
86 m_x = 20 ;
87
88 m_width = size.x;
89 if (m_width == -1)
90 m_width = 20;
91 m_height = size.y;
92 if (m_height == -1)
93 m_height = 20;
94
95 ::SetRect(&theBoundsRect, m_x, m_y, m_x + m_width, m_y + m_height);
96 m_macWindowData = new MacWindowData() ;
97
98 WindowClass wclass = kMovableModalWindowClass ;
99 WindowAttributes attr = kWindowNoAttributes ;
100
101 if ( ( m_windowStyle & wxMINIMIZE_BOX ) || ( m_windowStyle & wxMAXIMIZE_BOX ) )
102 {
103 attr |= kWindowFullZoomAttribute ;
104 attr |= kWindowResizableAttribute ;
105 }
106
107 UMACreateNewWindow( wclass , attr , &theBoundsRect , &m_macWindowData->m_macWindow ) ;
108 wxAssociateWinWithMacWindow( m_macWindowData->m_macWindow , this ) ;
109 wxString label ;
110 if( wxApp::s_macDefaultEncodingIsPC )
111 label = wxMacMakeMacStringFromPC( title ) ;
112 else
113 label = title ;
114 UMASetWTitleC( m_macWindowData->m_macWindow , label ) ;
115 m_macWindowData->m_macWindowBackgroundTheme = kThemeBrushDialogBackgroundActive ;
116 UMACreateRootControl( m_macWindowData->m_macWindow , &m_macWindowData->m_macRootControl ) ;
117 m_macWindowData->m_macFocus = NULL ;
118 return TRUE;
119 }
120
121 void wxDialog::SetModal(bool flag)
122 {
123 if ( flag )
124 m_windowStyle |= wxDIALOG_MODAL ;
125 else
126 if ( m_windowStyle & wxDIALOG_MODAL )
127 m_windowStyle -= wxDIALOG_MODAL ;
128
129 wxModelessWindows.DeleteObject(this);
130 if (!flag)
131 wxModelessWindows.Append(this);
132 }
133
134 wxDialog::~wxDialog()
135 {
136 m_isBeingDeleted = TRUE ;
137 wxTopLevelWindows.DeleteObject(this);
138
139 m_modalShowing = FALSE;
140
141 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
142 wxModelessWindows.DeleteObject(this);
143
144 // If this is the last top-level window, exit.
145 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
146 {
147 wxTheApp->SetTopWindow(NULL);
148
149 if (wxTheApp->GetExitOnFrameDelete())
150 {
151 wxTheApp->ExitMainLoop() ;
152 }
153 }
154 }
155
156 // By default, pressing escape cancels the dialog
157 void wxDialog::OnCharHook(wxKeyEvent& event)
158 {
159 if (event.m_keyCode == WXK_ESCAPE)
160 {
161 // Behaviour changed in 2.0: we'll send a Cancel message
162 // to the dialog instead of Close.
163 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
164 cancelEvent.SetEventObject( this );
165 GetEventHandler()->ProcessEvent(cancelEvent);
166
167 return;
168 }
169 // We didn't process this event.
170 event.Skip();
171 }
172
173 void wxDialog::Iconize(bool WXUNUSED(iconize))
174 {
175 // mac dialogs cannot be iconized
176 }
177
178 bool wxDialog::IsIconized() const
179 {
180 // mac dialogs cannot be iconized
181 return FALSE;
182 }
183
184 void wxDialog::DoSetClientSize(int width, int height)
185 {
186 wxWindow::DoSetClientSize( width , height ) ;
187 }
188
189 void wxDialog::GetPosition(int *x, int *y) const
190 {
191 DoGetPosition( x , y ) ;
192 }
193
194 bool wxDialog::IsShown() const
195 {
196 return m_isShown;
197 }
198
199 bool wxDialog::IsModal() const
200 {
201 return wxModalDialogs.Find((wxDialog *)this) != 0; // const_cast
202 }
203
204
205 extern bool s_macIsInModalLoop ;
206
207 bool wxDialog::Show(bool show)
208 {
209 m_isShown = show;
210
211 if (show)
212 InitDialog();
213
214 bool modal = ((GetWindowStyleFlag() & wxDIALOG_MODAL) == wxDIALOG_MODAL) ;
215
216 #if WXGARBAGE_COLLECTION_ON /* MATTHEW: GC */
217 if (!modal)
218 {
219 if (show)
220 {
221 if (!wxModelessWindows.Find(this))
222 wxModelessWindows.Append(this);
223 }
224 else
225 wxModelessWindows.DeleteObject(this);
226 }
227 if (show)
228 {
229 if (!wxTopLevelWindows.Find(this))
230 wxTopLevelWindows.Append(this);
231 }
232 else
233 wxTopLevelWindows.DeleteObject(this);
234 #endif
235
236 if ( modal )
237 {
238 s_macIsInModalLoop = true ;
239 if (show)
240 {
241 if (m_modalShowing)
242 {
243 // BringWindowToTop((HWND) GetHWND());
244 return TRUE;
245 }
246
247 m_modalShowing = TRUE;
248 // if we don't do it, some window might be deleted while we have pointers
249 // to them in our disabledWindows list and the program will crash when it
250 // will try to reenable them after the modal dialog end
251 wxTheApp->DeletePendingObjects();
252
253 UMAShowWindow( m_macWindowData->m_macWindow ) ;
254 UMASelectWindow( m_macWindowData->m_macWindow ) ;
255
256 if (!wxModalDialogs.Member(this))
257 wxModalDialogs.Append(this);
258
259 while (wxModalDialogs.Member(this) )
260 {
261 wxTheApp->MacDoOneEvent() ;
262 }
263 }
264 else
265 {
266 wxModalDialogs.DeleteObject(this);
267 UMAHideWindow( m_macWindowData->m_macWindow ) ;
268 }
269 s_macIsInModalLoop = false ;
270 }
271 else // !modal
272 {
273 if (show)
274 {
275 UMAShowWindow( m_macWindowData->m_macWindow ) ;
276 UMASelectWindow( m_macWindowData->m_macWindow ) ;
277 }
278 else
279 {
280 UMAHideWindow( m_macWindowData->m_macWindow ) ;
281 }
282 }
283 return TRUE ;
284 }
285
286 void wxDialog::SetTitle(const wxString& title)
287 {
288 wxWindow::SetTitle( title ) ;
289 }
290
291 wxString wxDialog::GetTitle() const
292 {
293 return wxWindow::GetTitle() ;
294 }
295
296 void wxDialog::Centre(int direction)
297 {
298 int x_offset,y_offset ;
299 int display_width, display_height;
300 int width, height, x, y;
301 wxWindow *parent = GetParent();
302 if ((direction & wxCENTER_FRAME) && parent)
303 {
304 parent->GetPosition(&x_offset,&y_offset) ;
305 parent->GetSize(&display_width,&display_height) ;
306 }
307 else
308 {
309 wxDisplaySize(&display_width, &display_height);
310 x_offset = 0 ;
311 y_offset = 0 ;
312 }
313
314 GetSize(&width, &height);
315 GetPosition(&x, &y);
316
317 if (direction & wxHORIZONTAL)
318 x = (int)((display_width - width)/2);
319 if (direction & wxVERTICAL)
320 y = (int)((display_height - height)/2);
321
322 SetSize(x+x_offset, y+y_offset, width, height);
323 }
324
325 // Replacement for Show(TRUE) for modal dialogs - returns return code
326 int wxDialog::ShowModal()
327 {
328 m_windowStyle |= wxDIALOG_MODAL;
329 Show(TRUE);
330 return GetReturnCode();
331 }
332
333 void wxDialog::EndModal(int retCode)
334 {
335 SetReturnCode(retCode);
336 Show(FALSE);
337 }
338
339 // Standard buttons
340 void wxDialog::OnOK(wxCommandEvent& event)
341 {
342 if ( Validate() && TransferDataFromWindow() )
343 {
344 if ( IsModal() )
345 EndModal(wxID_OK);
346 else
347 {
348 SetReturnCode(wxID_OK);
349 this->Show(FALSE);
350 }
351 }
352 }
353
354 void wxDialog::OnApply(wxCommandEvent& event)
355 {
356 if (Validate())
357 TransferDataFromWindow();
358 // TODO probably need to disable the Apply button until things change again
359 }
360
361 void wxDialog::OnCancel(wxCommandEvent& event)
362 {
363 if ( IsModal() )
364 EndModal(wxID_CANCEL);
365 else
366 {
367 SetReturnCode(wxID_CANCEL);
368 this->Show(FALSE);
369 }
370 }
371
372 void wxDialog::OnPaint(wxPaintEvent& event)
373 {
374 // No: if you call the default procedure, it makes
375 // the following painting code not work.
376 // wxWindow::OnPaint(event);
377 }
378
379 void wxDialog::OnCloseWindow(wxCloseEvent& event)
380 {
381 // We'll send a Cancel message by default,
382 // which may close the dialog.
383 // Check for looping if the Cancel event handler calls Close().
384
385 // Note that if a cancel button and handler aren't present in the dialog,
386 // nothing will happen when you close the dialog via the window manager, or
387 // via Close().
388 // We wouldn't want to destroy the dialog by default, since the dialog may have been
389 // created on the stack.
390 // However, this does mean that calling dialog->Close() won't delete the dialog
391 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
392 // sure to destroy the dialog.
393 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
394
395 static wxList closing;
396
397 if ( closing.Member(this) )
398 return;
399
400 closing.Append(this);
401
402 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
403 cancelEvent.SetEventObject( this );
404 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
405
406 closing.DeleteObject(this);
407 }
408
409 // Destroy the window (delayed, if a managed window)
410 bool wxDialog::Destroy()
411 {
412 if (!wxPendingDelete.Member(this))
413 wxPendingDelete.Append(this);
414 return TRUE;
415 }
416
417 void wxDialog::OnSize(wxSizeEvent& WXUNUSED(event))
418 {
419 // if we're using constraints - do use them
420 #if wxUSE_CONSTRAINTS
421 if ( GetAutoLayout() )
422 {
423 Layout();
424 }
425 #endif
426 }
427
428 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& event)
429 {
430 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
431 Refresh();
432 }
433
434 void wxDialog::Fit()
435 {
436 wxWindow::Fit();
437 }
438