1///////////////////////////////////////////////////////////////////////////// 2// Name: src/cocoa/dialog.mm 3// Purpose: wxDialog class 4// Author: David Elliott 5// Modified by: 6// Created: 2002/12/15 7// Copyright: 2002 David Elliott 8// Licence: wxWindows licence 9///////////////////////////////////////////////////////////////////////////// 10 11#include "wx/wxprec.h" 12 13#include "wx/dialog.h" 14 15#ifndef WX_PRECOMP 16 #include "wx/log.h" 17 #include "wx/app.h" 18 #include "wx/settings.h" 19#endif //WX_PRECOMP 20 21#include "wx/modalhook.h" 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 32static wxWindowList wxModalDialogs; 33 34IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow) 35 36WX_IMPLEMENT_COCOA_OWNER(wxDialog,NSPanel,NSWindow,NSWindow) 37 38void wxDialog::Init() 39{ 40 m_isModal = false; 41 SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE)); 42} 43 44bool 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 77wxDialog::~wxDialog() 78{ 79 DisassociateNSPanel(GetNSPanel()); 80} 81 82void 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 89void wxDialog::SetModal(bool flag) 90{ 91 wxFAIL_MSG( wxT("wxDialog:SetModal obsolete now") ); 92} 93 94bool 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. 128int wxDialog::ShowModal() 129{ 130 WX_HOOK_MODAL_DIALOG(); 131 132 wxCHECK_MSG(!IsModal(),GetReturnCode(),wxT("wxDialog::ShowModal called within its own modal loop")); 133 134 // Show(true) will set m_isShown = true 135 m_isShown = false; 136 m_isModal = true; 137 wxModalDialogs.Append(this); 138 139 wxLogTrace(wxTRACE_COCOA,wxT("runModal")); 140 NSApplication *theNSApp = wxTheApp->GetNSApplication(); 141 // If the app hasn't started, flush the event queue 142 // If we don't do this, the Dock doesn't get the message that 143 // the app has started so will refuse to activate it. 144 if(![theNSApp isRunning]) 145 { 146 // We should only do a few iterations so one pool should be okay 147 wxAutoNSAutoreleasePool pool; 148 while(NSEvent *event = [theNSApp 149 nextEventMatchingMask:NSAnyEventMask 150 untilDate:[NSDate distantPast] 151 inMode:NSDefaultRunLoopMode 152 dequeue: YES]) 153 { 154 [theNSApp sendEvent: event]; 155 } 156 } 157 158 Show(true); 159 do { 160 wxAutoNSAutoreleasePool pool; 161 [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow]; 162 } while(0); 163 wxLogTrace(wxTRACE_COCOA,wxT("runModal END")); 164 165 return GetReturnCode(); 166} 167 168void wxDialog::EndModal(int retCode) 169{ 170 wxASSERT_MSG(IsModal(), wxT("EndModal() should only be used within ShowModal()")); 171 SetReturnCode(retCode); 172 Show(false); 173} 174