It won't be an easy solution, since it's a pretty complex class, but I would suggest that you subclass NSDocumentController
and register your own which disables opening beyond a certain number of documents. This will allow you to prevent things like opening files by dropping them on the application's icon in the dock or opening in the finder, both of which bypass the Open
menu item.
You will still need to override the GUI/menu activation code to prevent Open...
from being available when you have a document open already, but that's just to make sure you don't confuse the user.
Your document controller needs to be created before any other document controllers, but that's easy to do by placing a DocumentController
instance in your MainMenu.xib
and making sure the class is set to your subclass. (This will cause it to call -sharedDocumentController
, which will create an instance of yours.)
In your document controller, then, you will need to override:
- makeDocumentForURL:withContentsOfURL:ofType:error:
- makeUntitledDocumentOfType:error:
- makeDocumentWithContentsOfURL:ofType:error:
to check and see if a document is already open and return nil, setting the error pointer to a newly created error that shows an appropriate message (NSLocalizedDescriptionKey
).
That should take care of cases of drag-and-drop, applescript,etc.
EDIT As for your additional request of the close/save prompt on an opening event, that's a nastier problem. You could:
- Save off the information (basically the arguments for the
make
requests) - Send the
-closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo:
withself
as a delegate and a newly-created routine as the selector - When you receive the selector, then either clear out the saved arguments, or re-execute the commands with the arguments you saved.
Note that step 2 and 3 might need to be done on delay with performSelector
I haven't tried this myself (the rest I've done before), but it seems like it should work.