]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/dialog.cpp
fixed refresh problem due to rounding errors
[wxWidgets.git] / src / mac / carbon / 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 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxPanel)
31
32 BEGIN_EVENT_TABLE(wxDialog, wxPanel)
33 EVT_SIZE(wxDialog::OnSize)
34 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
35 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
36 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
37 EVT_CHAR_HOOK(wxDialog::OnCharHook)
38 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
39 EVT_CLOSE(wxDialog::OnCloseWindow)
40 END_EVENT_TABLE()
41
42
43 wxDialog::wxDialog()
44 {
45 m_isShown = FALSE;
46 m_modalShowing = FALSE;
47 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
48 }
49
50 bool wxDialog::Create(wxWindow *parent, wxWindowID id,
51 const wxString& title,
52 const wxPoint& pos,
53 const wxSize& size,
54 long style,
55 const wxString& name)
56 {
57 m_windowStyle = style;
58 m_isShown = FALSE;
59 m_modalShowing = FALSE;
60
61 #if wxUSE_TOOLTIPS
62 m_hwndToolTip = 0;
63 #endif
64 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
65 SetName(name);
66
67 if (!parent)
68 wxTopLevelWindows.Append(this);
69
70 if (parent) parent->AddChild(this);
71
72 if ( id == -1 )
73 m_windowId = (int)NewControlId();
74 else
75 m_windowId = id;
76
77 Rect theBoundsRect;
78
79 m_x = (int)pos.x;
80 m_y = (int)pos.y;
81 if ( m_y < 50 )
82 m_y = 50 ;
83 if ( m_x < 20 )
84 m_x = 20 ;
85
86 m_width = size.x;
87 if (m_width == -1)
88 m_width = 20;
89 m_height = size.y;
90 if (m_height == -1)
91 m_height = 20;
92
93 ::SetRect(&theBoundsRect, m_x, m_y, m_x + m_width, m_y + m_height);
94 m_macWindowData = new MacWindowData() ;
95
96 WindowClass wclass = kMovableModalWindowClass ;
97 WindowAttributes attr = kWindowNoAttributes ;
98
99 if ( ( m_windowStyle & wxMINIMIZE_BOX ) || ( m_windowStyle & wxMAXIMIZE_BOX ) )
100 {
101 attr |= kWindowFullZoomAttribute ;
102 attr |= kWindowResizableAttribute ;
103 }
104
105 UMACreateNewWindow( wclass , attr , &theBoundsRect , &m_macWindowData->m_macWindow ) ;
106 wxAssociateWinWithMacWindow( m_macWindowData->m_macWindow , this ) ;
107 wxString label ;
108 if( wxApp::s_macDefaultEncodingIsPC )
109 label = wxMacMakeMacStringFromPC( title ) ;
110 else
111 label = title ;
112 UMASetWTitleC( m_macWindowData->m_macWindow , label ) ;
113 m_macWindowData->m_macWindowBackgroundTheme = kThemeBrushDialogBackgroundActive ;
114 UMACreateRootControl( m_macWindowData->m_macWindow , &m_macWindowData->m_macRootControl ) ;
115 m_macWindowData->m_macFocus = NULL ;
116 return TRUE;
117 }
118
119 void wxDialog::SetModal(bool flag)
120 {
121 if ( flag )
122 m_windowStyle |= wxDIALOG_MODAL ;
123 else
124 if ( m_windowStyle & wxDIALOG_MODAL )
125 m_windowStyle -= wxDIALOG_MODAL ;
126
127 wxModelessWindows.DeleteObject(this);
128 if (!flag)
129 wxModelessWindows.Append(this);
130 }
131
132 wxDialog::~wxDialog()
133 {
134 m_isBeingDeleted = TRUE ;
135 wxTopLevelWindows.DeleteObject(this);
136
137 m_modalShowing = FALSE;
138
139 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
140 wxModelessWindows.DeleteObject(this);
141
142 // If this is the last top-level window, exit.
143 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
144 {
145 wxTheApp->SetTopWindow(NULL);
146
147 if (wxTheApp->GetExitOnFrameDelete())
148 {
149 wxTheApp->ExitMainLoop() ;
150 }
151 }
152 }
153
154 // By default, pressing escape cancels the dialog
155 void wxDialog::OnCharHook(wxKeyEvent& event)
156 {
157 if (event.m_keyCode == WXK_ESCAPE)
158 {
159 // Behaviour changed in 2.0: we'll send a Cancel message
160 // to the dialog instead of Close.
161 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
162 cancelEvent.SetEventObject( this );
163 GetEventHandler()->ProcessEvent(cancelEvent);
164
165 return;
166 }
167 // We didn't process this event.
168 event.Skip();
169 }
170
171 void wxDialog::Iconize(bool WXUNUSED(iconize))
172 {
173 // mac dialogs cannot be iconized
174 }
175
176 bool wxDialog::IsIconized() const
177 {
178 // mac dialogs cannot be iconized
179 return FALSE;
180 }
181
182 void wxDialog::DoSetClientSize(int width, int height)
183 {
184 wxWindow::DoSetClientSize( width , height ) ;
185 }
186
187 void wxDialog::GetPosition(int *x, int *y) const
188 {
189 DoGetPosition( x , y ) ;
190 }
191
192 bool wxDialog::IsShown() const
193 {
194 return m_isShown;
195 }
196
197 bool wxDialog::IsModal() const
198 {
199 return wxModalDialogs.Find((wxDialog *)this) != 0; // const_cast
200 }
201
202
203 extern bool s_macIsInModalLoop ;
204
205 bool wxDialog::Show(bool show)
206 {
207 m_isShown = show;
208
209 if (show)
210 InitDialog();
211
212 bool modal = ((GetWindowStyleFlag() & wxDIALOG_MODAL) == wxDIALOG_MODAL) ;
213
214 #if WXGARBAGE_COLLECTION_ON /* MATTHEW: GC */
215 if (!modal)
216 {
217 if (show)
218 {
219 if (!wxModelessWindows.Find(this))
220 wxModelessWindows.Append(this);
221 }
222 else
223 wxModelessWindows.DeleteObject(this);
224 }
225 if (show)
226 {
227 if (!wxTopLevelWindows.Find(this))
228 wxTopLevelWindows.Append(this);
229 }
230 else
231 wxTopLevelWindows.DeleteObject(this);
232 #endif
233
234 if ( modal )
235 {
236 s_macIsInModalLoop = true ;
237 if (show)
238 {
239 if (m_modalShowing)
240 {
241 // BringWindowToTop((HWND) GetHWND());
242 return TRUE;
243 }
244
245 m_modalShowing = TRUE;
246 // if we don't do it, some window might be deleted while we have pointers
247 // to them in our disabledWindows list and the program will crash when it
248 // will try to reenable them after the modal dialog end
249 wxTheApp->DeletePendingObjects();
250
251 UMAShowWindow( m_macWindowData->m_macWindow ) ;
252 UMASelectWindow( m_macWindowData->m_macWindow ) ;
253
254 if (!wxModalDialogs.Member(this))
255 wxModalDialogs.Append(this);
256
257 while (wxModalDialogs.Member(this) )
258 {
259 wxTheApp->MacDoOneEvent() ;
260 }
261 }
262 else
263 {
264 wxModalDialogs.DeleteObject(this);
265 UMAHideWindow( m_macWindowData->m_macWindow ) ;
266 }
267 s_macIsInModalLoop = false ;
268 }
269 else // !modal
270 {
271 if (show)
272 {
273 UMAShowWindow( m_macWindowData->m_macWindow ) ;
274 UMASelectWindow( m_macWindowData->m_macWindow ) ;
275 }
276 else
277 {
278 UMAHideWindow( m_macWindowData->m_macWindow ) ;
279 }
280 }
281 return TRUE ;
282 }
283
284 void wxDialog::SetTitle(const wxString& title)
285 {
286 wxWindow::SetTitle( title ) ;
287 }
288
289 wxString wxDialog::GetTitle() const
290 {
291 return wxWindow::GetTitle() ;
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 Show(FALSE);
335 }
336
337 // Standard buttons
338 void wxDialog::OnOK(wxCommandEvent& event)
339 {
340 if ( Validate() && TransferDataFromWindow() )
341 {
342 if ( IsModal() )
343 EndModal(wxID_OK);
344 else
345 {
346 SetReturnCode(wxID_OK);
347 this->Show(FALSE);
348 }
349 }
350 }
351
352 void wxDialog::OnApply(wxCommandEvent& event)
353 {
354 if (Validate())
355 TransferDataFromWindow();
356 // TODO probably need to disable the Apply button until things change again
357 }
358
359 void wxDialog::OnCancel(wxCommandEvent& event)
360 {
361 if ( IsModal() )
362 EndModal(wxID_CANCEL);
363 else
364 {
365 SetReturnCode(wxID_CANCEL);
366 this->Show(FALSE);
367 }
368 }
369
370 void wxDialog::OnPaint(wxPaintEvent& event)
371 {
372 // No: if you call the default procedure, it makes
373 // the following painting code not work.
374 // wxWindow::OnPaint(event);
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 void wxDialog::Fit()
433 {
434 wxWindow::Fit();
435 }
436