dialog.mm 4.8 KB

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