]> git.saurik.com Git - wxWidgets.git/blob - src/mac/carbon/dialog.cpp
Include wx/stopwatch.h according to precompiled headers of wx/wx.h (with other minor...
[wxWidgets.git] / src / mac / carbon / dialog.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/mac/carbon/dialog.cpp
3 // Purpose: wxDialog class
4 // Author: Stefan Csomor
5 // Modified by:
6 // Created: 1998-01-01
7 // RCS-ID: $Id$
8 // Copyright: (c) Stefan Csomor
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #include "wx/wxprec.h"
13
14 #include "wx/dialog.h"
15
16 #ifndef WX_PRECOMP
17 #include "wx/app.h"
18 #include "wx/utils.h"
19 #include "wx/frame.h"
20 #include "wx/settings.h"
21 #endif // WX_PRECOMP
22
23 #include "wx/mac/uma.h"
24
25
26 // Lists to keep track of windows, so we can disable/enable them
27 // for modal dialogs
28 wxList wxModalDialogs;
29
30 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
31
32 BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
33 EVT_BUTTON(wxID_OK, wxDialog::OnOK)
34 EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
35 EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
36
37 EVT_CHAR_HOOK(wxDialog::OnCharHook)
38
39 EVT_SYS_COLOUR_CHANGED(wxDialog::OnSysColourChanged)
40
41 EVT_CLOSE(wxDialog::OnCloseWindow)
42 END_EVENT_TABLE()
43
44
45 void wxDialog::Init()
46 {
47 m_isModalStyle = false;
48 }
49
50 bool wxDialog::Create( wxWindow *parent,
51 wxWindowID id,
52 const wxString& title,
53 const wxPoint& pos,
54 const wxSize& size,
55 long style,
56 const wxString& name )
57 {
58 SetExtraStyle( GetExtraStyle() | wxTOPLEVEL_EX_DIALOG );
59
60 // All dialogs should really have this style...
61 style |= wxTAB_TRAVERSAL;
62
63 // ...but not these styles
64 style &= ~(wxYES | wxOK | wxNO); // | wxCANCEL
65
66 if ( !wxTopLevelWindow::Create( parent, id, title, pos, size, style, name ) )
67 return false;
68
69 #if TARGET_API_MAC_OSX
70 HIViewRef growBoxRef = 0 ;
71 OSStatus err = HIViewFindByID( HIViewGetRoot( (WindowRef)m_macWindow ), kHIViewWindowGrowBoxID, &growBoxRef );
72 if ( err == noErr && growBoxRef != 0 )
73 HIGrowBoxViewSetTransparent( growBoxRef, true ) ;
74 #endif
75
76 return true;
77 }
78
79 void wxDialog::SetModal( bool flag )
80 {
81 if ( flag )
82 {
83 m_isModalStyle = true;
84
85 wxModelessWindows.DeleteObject( this );
86
87 #if TARGET_CARBON
88 SetWindowModality( (WindowRef)MacGetWindowRef(), kWindowModalityAppModal, NULL ) ;
89 #endif
90 }
91 else
92 {
93 m_isModalStyle = false;
94
95 wxModelessWindows.Append( this );
96 }
97 }
98
99 wxDialog::~wxDialog()
100 {
101 m_isBeingDeleted = true;
102 Show(false);
103 }
104
105 // By default, pressing escape cancels the dialog; on mac command-stop does the same thing
106 void wxDialog::OnCharHook(wxKeyEvent& event)
107 {
108 if (( event.m_keyCode == WXK_ESCAPE ||
109 ( event.m_keyCode == '.' && event.MetaDown() ) )
110 && FindWindow(wxID_CANCEL) )
111 {
112 // Behaviour changed in 2.0: we'll send a Cancel message
113 // to the dialog instead of Close.
114 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
115 cancelEvent.SetEventObject( this );
116 GetEventHandler()->ProcessEvent(cancelEvent);
117
118 return;
119 }
120
121 // We didn't process this event.
122 event.Skip();
123 }
124
125 bool wxDialog::IsModal() const
126 {
127 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
128 // return m_isModalStyle;
129 }
130
131
132 bool wxDialog::IsModalShowing() const
133 {
134 return wxModalDialogs.Find((wxDialog *)this) != NULL; // const_cast
135 }
136
137 bool wxDialog::Show(bool show)
138 {
139 if ( !wxDialogBase::Show(show) )
140 // nothing to do
141 return false;
142
143 if ( show )
144 // usually will result in TransferDataToWindow() being called
145 InitDialog();
146
147 if ( m_isModalStyle )
148 {
149 if ( show )
150 {
151 DoShowModal();
152 }
153 else // end of modal dialog
154 {
155 // this will cause IsModalShowing() return false and our local
156 // message loop will terminate
157 wxModalDialogs.DeleteObject(this);
158 }
159 }
160
161 return true;
162 }
163
164 #if !TARGET_CARBON
165 extern bool s_macIsInModalLoop ;
166 #endif
167
168 void wxDialog::DoShowModal()
169 {
170 wxCHECK_RET( !IsModalShowing(), wxT("DoShowModal() called twice") );
171
172 wxModalDialogs.Append(this);
173
174 SetFocus() ;
175
176 #if TARGET_CARBON
177 BeginAppModalStateForWindow( (WindowRef) MacGetWindowRef()) ;
178 #else
179 // TODO : test whether parent gets disabled
180 bool formerModal = s_macIsInModalLoop ;
181 s_macIsInModalLoop = true ;
182 #endif
183
184 while ( IsModalShowing() )
185 {
186 wxTheApp->MacDoOneEvent() ;
187 // calls process idle itself
188 }
189
190 #if TARGET_CARBON
191 EndAppModalStateForWindow( (WindowRef) MacGetWindowRef() ) ;
192 #else
193 // TODO probably reenable the parent window if any
194 s_macIsInModalLoop = formerModal ;
195 #endif
196 }
197
198
199 // Replacement for Show(true) for modal dialogs - returns return code
200 int wxDialog::ShowModal()
201 {
202 if ( !m_isModalStyle )
203 SetModal(true);
204
205 Show(true);
206
207 return GetReturnCode();
208 }
209
210 // NB: this function (surprizingly) may be called for both modal and modeless
211 // dialogs and should work for both of them
212 void wxDialog::EndModal(int retCode)
213 {
214 SetReturnCode(retCode);
215 Show(false);
216 SetModal(false);
217 }
218
219 // Standard buttons
220 void wxDialog::OnOK(wxCommandEvent& WXUNUSED(event))
221 {
222 if ( Validate() && TransferDataFromWindow() )
223 EndModal(wxID_OK);
224 }
225
226 void wxDialog::OnApply(wxCommandEvent& WXUNUSED(event))
227 {
228 if (Validate())
229 TransferDataFromWindow();
230
231 // TODO probably need to disable the Apply button until things change again
232 }
233
234 void wxDialog::OnCancel(wxCommandEvent& WXUNUSED(event))
235 {
236 EndModal(wxID_CANCEL);
237 }
238
239 void wxDialog::OnCloseWindow(wxCloseEvent& WXUNUSED(event))
240 {
241 // We'll send a Cancel message by default,
242 // which may close the dialog.
243 // Check for looping if the Cancel event handler calls Close().
244
245 // Note that if a cancel button and handler aren't present in the dialog,
246 // nothing will happen when you close the dialog via the window manager, or
247 // via Close().
248 // We wouldn't want to destroy the dialog by default, since the dialog may have been
249 // created on the stack.
250 // However, this does mean that calling dialog->Close() won't delete the dialog
251 // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
252 // sure to destroy the dialog.
253 // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
254
255 static wxList closing;
256
257 if ( closing.Member(this) )
258 return;
259
260 closing.Append(this);
261
262 wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
263 cancelEvent.SetEventObject( this );
264 GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
265
266 closing.DeleteObject(this);
267 }
268
269 void wxDialog::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(event))
270 {
271 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
272 Refresh();
273 }