]> git.saurik.com Git - wxWidgets.git/blob - src/mac/dialog.cpp
fixed menu accelerators
[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 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
59 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
60 SetName(name);
61
62 if (!parent)
63 wxTopLevelWindows.Append(this);
64
65 if (parent) parent->AddChild(this);
66
67 if ( id == -1 )
68 m_windowId = (int)NewControlId();
69 else
70 m_windowId = id;
71
72 Rect theBoundsRect;
73
74 m_x = (int)pos.x;
75 m_y = (int)pos.y;
76 if ( m_y < 50 )
77 m_y = 50 ;
78 if ( m_x < 20 )
79 m_x = 20 ;
80
81 m_width = size.x;
82 if (m_width == -1)
83 m_width = 20;
84 m_height = size.y;
85 if (m_height == -1)
86 m_height = 20;
87
88 ::SetRect(&theBoundsRect, m_x, m_y, m_x + m_width, m_y + m_height);
89 m_macWindowData = new MacWindowData() ;
90
91 WindowClass wclass = kMovableModalWindowClass ;
92 WindowAttributes attr = kWindowNoAttributes ;
93
94 if ( ( m_windowStyle & wxMINIMIZE_BOX ) || ( m_windowStyle & wxMAXIMIZE_BOX ) )
95 {
96 attr |= kWindowFullZoomAttribute ;
97 attr |= kWindowResizableAttribute ;
98 }
99
100 UMACreateNewWindow( wclass , attr , &theBoundsRect , &m_macWindowData->m_macWindow ) ;
101 wxAssociateWinWithMacWindow( m_macWindowData->m_macWindow , this ) ;
102 wxString label ;
103 if( wxApp::s_macDefaultEncodingIsPC )
104 label = wxMacMakeMacStringFromPC( title ) ;
105 else
106 label = title ;
107 UMASetWTitleC( m_macWindowData->m_macWindow , label ) ;
108 m_macWindowData->m_macWindowBackgroundTheme = kThemeBrushDialogBackgroundActive ;
109 UMACreateRootControl( m_macWindowData->m_macWindow , &m_macWindowData->m_macRootControl ) ;
110 m_macWindowData->m_macFocus = NULL ;
111 m_macShown = false ;
112 return TRUE;
113 }
114
115 void wxDialog::SetModal(bool flag)
116 {
117 if ( flag )
118 m_windowStyle |= wxDIALOG_MODAL ;
119 else
120 if ( m_windowStyle & wxDIALOG_MODAL )
121 m_windowStyle -= wxDIALOG_MODAL ;
122
123 wxModelessWindows.DeleteObject(this);
124 if (!flag)
125 wxModelessWindows.Append(this);
126 }
127
128 wxDialog::~wxDialog()
129 {
130 wxTopLevelWindows.DeleteObject(this);
131
132 if ( (GetWindowStyleFlag() & wxDIALOG_MODAL) != wxDIALOG_MODAL )
133 wxModelessWindows.DeleteObject(this);
134
135 // If this is the last top-level window, exit.
136 if (wxTheApp && (wxTopLevelWindows.Number() == 0))
137 {
138 wxTheApp->SetTopWindow(NULL);
139
140 if (wxTheApp->GetExitOnFrameDelete())
141 {
142 wxTheApp->ExitMainLoop() ;
143 }
144 }
145 }
146
147 // By default, pressing escape cancels the dialog
148 void wxDialog::OnCharHook(wxKeyEvent& event)
149 {
150 if (event.m_keyCode == WXK_ESCAPE)
151 {
152 // Behaviour changed in 2.0: we'll send a Cancel message
153 // to the dialog instead of Close.
154 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
155 cancelEvent.SetEventObject( this );
156 GetEventHandler()->ProcessEvent(cancelEvent);
157
158 return;
159 }
160 // We didn't process this event.
161 event.Skip();
162 }
163
164 void wxDialog::Iconize(bool WXUNUSED(iconize))
165 {
166 // TODO
167 }
168
169 bool wxDialog::IsIconized() const
170 {
171 // TODO
172 return FALSE;
173 }
174
175 extern bool s_macIsInModalLoop ;
176
177 bool wxDialog::Show(bool show)
178 {
179 if ( m_macShown == show )
180 return TRUE ;
181
182 m_macShown = show ;
183
184 bool modal = ((GetWindowStyleFlag() & wxDIALOG_MODAL) == wxDIALOG_MODAL) ;
185
186 if ( modal )
187 {
188 s_macIsInModalLoop = true ;
189 if (show)
190 {
191 // if we don't do it, some window might be deleted while we have pointers
192 // to them in our disabledWindows list and the program will crash when it
193 // will try to reenable them after the modal dialog end
194 wxTheApp->DeletePendingObjects();
195
196 UMAShowWindow( m_macWindowData->m_macWindow ) ;
197 UMASelectWindow( m_macWindowData->m_macWindow ) ;
198
199 if (!wxModalDialogs.Member(this))
200 wxModalDialogs.Append(this);
201
202 while (wxModalDialogs.Member(this) )
203 {
204 wxTheApp->MacDoOneEvent() ;
205 }
206 }
207 else
208 {
209 wxModalDialogs.DeleteObject(this);
210 UMAHideWindow( m_macWindowData->m_macWindow ) ;
211 }
212 s_macIsInModalLoop = false ;
213 }
214 else // !modal
215 {
216 if (show)
217 {
218 UMAShowWindow( m_macWindowData->m_macWindow ) ;
219 UMASelectWindow( m_macWindowData->m_macWindow ) ;
220 }
221 else
222 {
223 UMAHideWindow( m_macWindowData->m_macWindow ) ;
224 }
225 }
226 return TRUE ;
227 }
228
229
230 // Replacement for Show(TRUE) for modal dialogs - returns return code
231 int wxDialog::ShowModal()
232 {
233 m_windowStyle |= wxDIALOG_MODAL;
234 Show(TRUE);
235 return GetReturnCode();
236 }
237
238 void wxDialog::EndModal(int retCode)
239 {
240 SetReturnCode(retCode);
241 // TODO modal un-showing
242 Show(FALSE);
243 }
244
245 // Standard buttons
246 void wxDialog::OnOK(wxCommandEvent& event)
247 {
248 if ( Validate() && TransferDataFromWindow() )
249 {
250 if ( IsModal() )
251 EndModal(wxID_OK);
252 else
253 {
254 SetReturnCode(wxID_OK);
255 this->Show(FALSE);
256 }
257 }
258 }
259
260 void wxDialog::OnApply(wxCommandEvent& event)
261 {
262 if (Validate())
263 TransferDataFromWindow();
264 // TODO probably need to disable the Apply button until things change again
265 }
266
267 void wxDialog::OnCancel(wxCommandEvent& event)
268 {
269 if ( IsModal() )
270 EndModal(wxID_CANCEL);
271 else
272 {
273 SetReturnCode(wxID_CANCEL);
274 this->Show(FALSE);
275 }
276 }
277
278 void wxDialog::OnCloseWindow(wxCloseEvent& event)
279 {
280 // We'll send a Cancel message by default,
281 // which may close the dialog.
282 // Check for looping if the Cancel event handler calls Close().
283
284 // Note that if a cancel button and handler aren't present in the dialog,
285 // nothing will happen when you close the dialog via the window manager, or
286 // via Close().
287 // We wouldn't want to destroy the dialog by default, since the dialog may have been
288 // created on the stack.
289 // However, this does mean that calling dialog->Close() won't delete the dialog
290 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
291 // sure to destroy the dialog.
292 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
293
294 static wxList closing;
295
296 if ( closing.Member(this) )
297 return;
298
299 closing.Append(this);
300
301 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
302 cancelEvent.SetEventObject( this );
303 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
304
305 closing.DeleteObject(this);
306 }
307
308 // Destroy the window (delayed, if a managed window)
309 bool wxDialog::Destroy()
310 {
311 if (!wxPendingDelete.Member(this))
312 wxPendingDelete.Append(this);
313 return TRUE;
314 }
315
316 void wxDialog::OnSize(wxSizeEvent& WXUNUSED(event))
317 {
318 // if we're using constraints - do use them
319 #if wxUSE_CONSTRAINTS
320 if ( GetAutoLayout() ) {
321 Layout();
322 }
323 #endif
324 }
325
326 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& event)
327 {
328 SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
329 Refresh();
330 }
331
332 void wxDialog::Fit()
333 {
334 wxWindow::Fit();
335 }
336
337 wxSizer *wxDialog::CreateTextSizer( const wxString &message )
338 {
339 wxBoxSizer *box = new wxBoxSizer( wxVERTICAL );
340
341 // get line height for empty lines
342 int y = 0;
343 wxFont new_font( GetFont() );
344 if (!new_font.Ok()) new_font = *wxSWISS_FONT;
345 GetTextExtent( "H", (int*)NULL, &y, (int*)NULL, (int*)NULL, &new_font );
346
347 wxString line;
348 for (size_t pos = 0; pos < message.Len(); pos++)
349 {
350 if (message[pos] == _T('\n'))
351 {
352 if (!line.IsEmpty())
353 {
354 wxStaticText *s1 = new wxStaticText( this, -1, line );
355 box->Add( s1 );
356 line = _T("");
357 }
358 else
359 {
360 box->Add( 5, y );
361 }
362 }
363 else
364 {
365 line += message[pos];
366 }
367 }
368
369 // remaining text behind last '\n'
370 if (!line.IsEmpty())
371 {
372 wxStaticText *s2 = new wxStaticText( this, -1, line );
373 box->Add( s2 );
374 }
375
376 return box;
377 }
378
379 wxSizer *wxDialog::CreateButtonSizer( long flags )
380 {
381 wxBoxSizer *box = new wxBoxSizer( wxHORIZONTAL );
382
383 #if defined(__WXMSW__) || defined(__WXMAC__)
384 int margin = 6;
385 #else
386 int margin = 10;
387 #endif
388
389 wxButton *ok = (wxButton *) NULL;
390 wxButton *cancel = (wxButton *) NULL;
391 wxButton *yes = (wxButton *) NULL;
392 wxButton *no = (wxButton *) NULL;
393
394 // always show an OK button, unless only YES_NO is given
395 if ((flags & wxYES_NO) == 0) flags = flags | wxOK;
396
397 if (flags & wxYES_NO)
398 {
399 yes = new wxButton( this, wxID_YES, _("Yes") );
400 box->Add( yes, 0, wxLEFT|wxRIGHT, margin );
401 no = new wxButton( this, wxID_NO, _("No") );
402 box->Add( no, 0, wxLEFT|wxRIGHT, margin );
403 } else
404 if (flags & wxYES)
405 {
406 yes = new wxButton( this, wxID_YES, _("Yes") );
407 box->Add( yes, 0, wxLEFT|wxRIGHT, margin );
408 } else
409 if (flags & wxNO)
410 {
411 no = new wxButton( this, wxID_NO, _("No") );
412 box->Add( no, 0, wxLEFT|wxRIGHT, margin );
413 }
414
415 if (flags & wxOK)
416 {
417 ok = new wxButton( this, wxID_OK, _("OK") );
418 box->Add( ok, 0, wxLEFT|wxRIGHT, margin );
419 }
420
421 if (flags & wxFORWARD)
422 box->Add( new wxButton( this, wxID_FORWARD, _("Forward") ), 0, wxLEFT|wxRIGHT, margin );
423
424 if (flags & wxBACKWARD)
425 box->Add( new wxButton( this, wxID_BACKWARD, _("Backward") ), 0, wxLEFT|wxRIGHT, margin );
426
427 if (flags & wxSETUP)
428 box->Add( new wxButton( this, wxID_SETUP, _("Setup") ), 0, wxLEFT|wxRIGHT, margin );
429
430 if (flags & wxMORE)
431 box->Add( new wxButton( this, wxID_MORE, _("More...") ), 0, wxLEFT|wxRIGHT, margin );
432
433 if (flags & wxHELP)
434 box->Add( new wxButton( this, wxID_HELP, _("Help") ), 0, wxLEFT|wxRIGHT, margin );
435
436 if (flags & wxCANCEL)
437 {
438 cancel = new wxButton( this, wxID_CANCEL, _("Cancel") );
439 box->Add( cancel, 0, wxLEFT|wxRIGHT, margin );
440 }
441
442 if ((flags & wxNO_DEFAULT) == 0)
443 {
444 if (ok)
445 {
446 ok->SetDefault();
447 ok->SetFocus();
448 }
449 else if (yes)
450 {
451 yes->SetDefault();
452 yes->SetFocus();
453 }
454 }
455
456 return box;
457 }
458