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