Globally use "wxWindows licence" consistently.
[wxWidgets.git] / src / cocoa / dialog.mm
1 /////////////////////////////////////////////////////////////////////////////
2 // Name:        src/cocoa/dialog.mm
3 // Purpose:     wxDialog class
4 // Author:      David Elliott
5 // Modified by:
6 // Created:     2002/12/15
7 // RCS-ID:      $Id$
8 // Copyright:   2002 David Elliott
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/log.h"
18     #include "wx/app.h"
19     #include "wx/settings.h"
20 #endif //WX_PRECOMP
21
22 #include "wx/cocoa/autorelease.h"
23 #include "wx/cocoa/string.h"
24
25 #import <AppKit/NSPanel.h>
26 #import <AppKit/NSApplication.h>
27 #import <AppKit/NSEvent.h>
28 #import <Foundation/NSRunLoop.h>
29
30 // Lists to keep track of windows, so we can disable/enable them
31 // for modal dialogs
32 static wxWindowList wxModalDialogs;
33
34 IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
35
36 WX_IMPLEMENT_COCOA_OWNER(wxDialog,NSPanel,NSWindow,NSWindow)
37
38 void wxDialog::Init()
39 {
40     m_isModal = false;
41     SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
42 }
43
44 bool wxDialog::Create(wxWindow *parent, wxWindowID winid,
45            const wxString& title,
46            const wxPoint& pos,
47            const wxSize& size,
48            long style,
49            const wxString& name)
50 {
51     wxAutoNSAutoreleasePool pool;
52     wxTopLevelWindows.Append(this);
53
54     if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
55         return false;
56
57     if (parent)
58         parent->AddChild(this);
59
60     unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
61
62     NSRect cocoaRect = MakeInitialNSWindowContentRect(pos,size,cocoaStyle);
63
64     m_cocoaNSWindow = NULL;
65     SetNSPanel([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
66     // NOTE: SetNSWindow has retained the Cocoa object for this object.
67     // Because we do not release on close, the following release matches the
68     // above alloc and thus the retain count will be 1.
69     [m_cocoaNSWindow release];
70     wxLogTrace(wxTRACE_COCOA_RetainRelease,wxT("wxDialog m_cocoaNSWindow retainCount=%d"),[m_cocoaNSWindow retainCount]);
71     [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
72     [m_cocoaNSWindow setHidesOnDeactivate:NO];
73
74     return true;
75 }
76
77 wxDialog::~wxDialog()
78 {
79     DisassociateNSPanel(GetNSPanel());
80 }
81
82 void wxDialog::CocoaDelegate_windowWillClose(void)
83 {
84     m_closed = true;
85     /* Actually, this isn't true anymore */
86     wxLogTrace(wxTRACE_COCOA,wxT("Woah: Dialogs are not generally closed"));
87 }
88
89 void wxDialog::SetModal(bool flag)
90 {
91     wxFAIL_MSG( wxT("wxDialog:SetModal obsolete now") );
92 }
93
94 bool wxDialog::Show(bool show)
95 {
96     if(m_isShown == show)
97         return false;
98
99     if(show)
100     {
101         wxAutoNSAutoreleasePool pool;
102
103         if (CanDoLayoutAdaptation())
104                 DoLayoutAdaptation();
105
106         InitDialog();
107         if(IsModal())
108         {   // ShowModal() will show the dialog
109             m_isShown = true;
110             return true;
111         }
112     }
113     else
114     {
115         if(IsModal())
116         {   // this doesn't hide the dialog, base class Show(false) does.
117             wxLogTrace(wxTRACE_COCOA,wxT("abortModal"));
118             [wxTheApp->GetNSApplication() abortModal];
119             wxModalDialogs.DeleteObject(this);
120             m_isModal = false;
121         }
122     }
123     return wxTopLevelWindow::Show(show);
124 }
125
126 // Shows the dialog and begins a modal event loop.  When the event loop
127 // is stopped (via EndModal()) it returns the exit code.
128 int wxDialog::ShowModal()
129 {
130     wxCHECK_MSG(!IsModal(),GetReturnCode(),wxT("wxDialog::ShowModal called within its own modal loop"));
131
132     // Show(true) will set m_isShown = true
133     m_isShown = false;
134     m_isModal = true;
135     wxModalDialogs.Append(this);
136
137     wxLogTrace(wxTRACE_COCOA,wxT("runModal"));
138     NSApplication *theNSApp = wxTheApp->GetNSApplication();
139     // If the app hasn't started, flush the event queue
140     // If we don't do this, the Dock doesn't get the message that
141     // the app has started so will refuse to activate it.
142     if(![theNSApp isRunning])
143     {
144         // We should only do a few iterations so one pool should be okay
145         wxAutoNSAutoreleasePool pool;
146         while(NSEvent *event = [theNSApp
147                     nextEventMatchingMask:NSAnyEventMask
148                     untilDate:[NSDate distantPast]
149                     inMode:NSDefaultRunLoopMode
150                     dequeue: YES])
151         {
152             [theNSApp sendEvent: event];
153         }
154     }
155
156     Show(true);
157     do {
158         wxAutoNSAutoreleasePool pool;
159         [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow];
160     } while(0);
161     wxLogTrace(wxTRACE_COCOA,wxT("runModal END"));
162
163     return GetReturnCode();
164 }
165
166 void wxDialog::EndModal(int retCode)
167 {
168     wxASSERT_MSG(IsModal(), wxT("EndModal() should only be used within ShowModal()"));
169     SetReturnCode(retCode);
170     Show(false);
171 }