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