// Author: David Elliott
// Modified by:
// Created: 2002/12/15
-// RCS-ID: $Id:
+// RCS-ID: $Id$
// Copyright: 2002 David Elliott
-// Licence: wxWindows license
+// Licence: wxWidgets licence
/////////////////////////////////////////////////////////////////////////////
+#include "wx/wxprec.h"
+
#include "wx/dialog.h"
-#include "wx/app.h"
-#include "wx/settings.h"
-#include "wx/log.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/log.h"
+ #include "wx/app.h"
+ #include "wx/settings.h"
+#endif //WX_PRECOMP
+
+#include "wx/cocoa/autorelease.h"
+#include "wx/cocoa/string.h"
#import <AppKit/NSPanel.h>
#import <AppKit/NSApplication.h>
+#import <AppKit/NSEvent.h>
+#import <Foundation/NSRunLoop.h>
// Lists to keep track of windows, so we can disable/enable them
// for modal dialogs
IMPLEMENT_DYNAMIC_CLASS(wxDialog, wxTopLevelWindow)
-BEGIN_EVENT_TABLE(wxDialog, wxDialogBase)
- EVT_BUTTON(wxID_OK, wxDialog::OnOK)
- EVT_BUTTON(wxID_APPLY, wxDialog::OnApply)
- EVT_BUTTON(wxID_CANCEL, wxDialog::OnCancel)
- EVT_CLOSE(wxDialog::OnCloseWindow)
-END_EVENT_TABLE()
-
WX_IMPLEMENT_COCOA_OWNER(wxDialog,NSPanel,NSWindow,NSWindow)
void wxDialog::Init()
{
- SetBackgroundColour(wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE));
+ m_isModal = false;
+ SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE));
}
bool wxDialog::Create(wxWindow *parent, wxWindowID winid,
long style,
const wxString& name)
{
+ wxAutoNSAutoreleasePool pool;
wxTopLevelWindows.Append(this);
if(!CreateBase(parent,winid,pos,size,style,wxDefaultValidator,name))
if (parent)
parent->AddChild(this);
- NSRect cocoaRect = NSMakeRect(300,300,200,200);
+ unsigned int cocoaStyle = NSWindowStyleForWxStyle(style);
- unsigned int cocoaStyle = 0;
- cocoaStyle |= NSTitledWindowMask;
- cocoaStyle |= NSClosableWindowMask;
- cocoaStyle |= NSMiniaturizableWindowMask;
- cocoaStyle |= NSResizableWindowMask;
+ NSRect cocoaRect = MakeInitialNSWindowContentRect(pos,size,cocoaStyle);
m_cocoaNSWindow = NULL;
SetNSPanel([[NSPanel alloc] initWithContentRect:cocoaRect styleMask:cocoaStyle backing:NSBackingStoreBuffered defer:NO]);
// Because we do not release on close, the following release matches the
// above alloc and thus the retain count will be 1.
[m_cocoaNSWindow release];
- wxLogDebug("wxDialog m_cocoaNSWindow retainCount=%d",[m_cocoaNSWindow retainCount]);
+ wxLogTrace(wxTRACE_COCOA_RetainRelease,wxT("wxDialog m_cocoaNSWindow retainCount=%d"),[m_cocoaNSWindow retainCount]);
+ [m_cocoaNSWindow setTitle:wxNSStringWithWxString(title)];
+ [m_cocoaNSWindow setHidesOnDeactivate:NO];
return true;
}
wxDialog::~wxDialog()
{
- wxLogDebug("Destroying");
- // setReleasedWhenClosed: NO
- [m_cocoaNSWindow close];
- SetNSPanel(NULL);
+ DisassociateNSPanel(GetNSPanel());
}
-void wxDialog::Cocoa_close(void)
+void wxDialog::CocoaDelegate_windowWillClose(void)
{
m_closed = true;
/* Actually, this isn't true anymore */
- wxLogDebug("Woah: Dialogs are not generally closed");
+ wxLogTrace(wxTRACE_COCOA,wxT("Woah: Dialogs are not generally closed"));
}
void wxDialog::SetModal(bool flag)
{
- if ( flag )
- {
- wxModelessWindows.DeleteObject(this);
- m_windowStyle |= wxDIALOG_MODAL ;
- }
- else
- {
- m_windowStyle &= ~wxDIALOG_MODAL ;
- wxModelessWindows.Append(this);
- }
+ wxFAIL_MSG( wxT("wxDialog:SetModal obsolete now") );
}
bool wxDialog::Show(bool show)
{
+ if(m_isShown == show)
+ return false;
+
if(show)
- InitDialog();
- if(IsModal())
{
- if(show)
- {
- wxModalDialogs.Append(this);
- wxLogDebug("runModal");
- [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow];
- wxLogDebug("runModal END");
+ wxAutoNSAutoreleasePool pool;
+
+ if (CanDoLayoutAdaptation())
+ DoLayoutAdaptation();
+
+ InitDialog();
+ if(IsModal())
+ { // ShowModal() will show the dialog
+ m_isShown = true;
+ return true;
}
- else
- {
- wxLogDebug("abortModal");
+ }
+ else
+ {
+ if(IsModal())
+ { // this doesn't hide the dialog, base class Show(false) does.
+ wxLogTrace(wxTRACE_COCOA,wxT("abortModal"));
[wxTheApp->GetNSApplication() abortModal];
wxModalDialogs.DeleteObject(this);
+ m_isModal = false;
}
}
- return true;
+ return wxTopLevelWindow::Show(show);
}
-// Replacement for Show(TRUE) for modal dialogs - returns return code
+// Shows the dialog and begins a modal event loop. When the event loop
+// is stopped (via EndModal()) it returns the exit code.
int wxDialog::ShowModal()
{
- if(!IsModal())
- SetModal(true);
+ wxCHECK_MSG(!IsModal(),GetReturnCode(),wxT("wxDialog::ShowModal called within its own modal loop"));
+
+ // Show(true) will set m_isShown = true
+ m_isShown = false;
+ m_isModal = true;
+ wxModalDialogs.Append(this);
+
+ wxLogTrace(wxTRACE_COCOA,wxT("runModal"));
+ NSApplication *theNSApp = wxTheApp->GetNSApplication();
+ // If the app hasn't started, flush the event queue
+ // If we don't do this, the Dock doesn't get the message that
+ // the app has started so will refuse to activate it.
+ if(![theNSApp isRunning])
+ {
+ // We should only do a few iterations so one pool should be okay
+ wxAutoNSAutoreleasePool pool;
+ while(NSEvent *event = [theNSApp
+ nextEventMatchingMask:NSAnyEventMask
+ untilDate:[NSDate distantPast]
+ inMode:NSDefaultRunLoopMode
+ dequeue: YES])
+ {
+ [theNSApp sendEvent: event];
+ }
+ }
+
Show(true);
+ do {
+ wxAutoNSAutoreleasePool pool;
+ [wxTheApp->GetNSApplication() runModalForWindow:m_cocoaNSWindow];
+ } while(0);
+ wxLogTrace(wxTRACE_COCOA,wxT("runModal END"));
+
return GetReturnCode();
}
-// EndModal will work for any dialog
void wxDialog::EndModal(int retCode)
{
+ wxASSERT_MSG(IsModal(), wxT("EndModal() should only be used within ShowModal()"));
SetReturnCode(retCode);
Show(false);
}
-
-bool wxDialog::IsModal() const
-{
- return (GetWindowStyleFlag() & wxDIALOG_MODAL);
-}
-
-void wxDialog::OnCloseWindow(wxCloseEvent& event)
-{
- // We'll send a Cancel message by default,
- // which may close the dialog.
- // Check for looping if the Cancel event handler calls Close().
-
- // Note that if a cancel button and handler aren't present in the dialog,
- // nothing will happen when you close the dialog via the window manager, or
- // via Close().
- // We wouldn't want to destroy the dialog by default, since the dialog may have been
- // created on the stack.
- // However, this does mean that calling dialog->Close() won't delete the dialog
- // unless the handler for wxID_CANCEL does so. So use Destroy() if you want to be
- // sure to destroy the dialog.
- // The default OnCancel (above) simply ends a modal dialog, and hides a modeless dialog.
- // ALWAYS VETO THIS EVENT!!!!
- event.Veto();
-
- static wxList closing;
-
- if ( closing.Member(this) )
- {
- wxLogDebug("WARNING: Attempting to recursively call Close for dialog");
- return;
- }
-
- closing.Append(this);
-
- wxLogDebug("Sending Cancel Event");
- wxCommandEvent cancelEvent(wxEVT_COMMAND_BUTTON_CLICKED, wxID_CANCEL);
- cancelEvent.SetEventObject( this );
- GetEventHandler()->ProcessEvent(cancelEvent); // This may close the dialog
-
- closing.DeleteObject(this);
-}
-
-// Standard buttons
-void wxDialog::OnOK(wxCommandEvent& event)
-{
- if ( Validate() && TransferDataFromWindow() )
- {
- EndModal(wxID_OK);
- }
-}
-
-void wxDialog::OnApply(wxCommandEvent& event)
-{
- if (Validate())
- TransferDataFromWindow();
- // TODO probably need to disable the Apply button until things change again
-}
-
-void wxDialog::OnCancel(wxCommandEvent& event)
-{
- wxLogDebug("Cancelled!");
- EndModal(wxID_CANCEL);
-}
-