Preventing the "Save on Exit" dialogue on exit of a Cocoa Document Application - cocoa

Hi
I have a Cocoa document based application that I have been building, that allows you to open seperate views and interact with a webview component. However, when ever you have interacted with it, and then go to close the application, a message comes down saying:
"Do you want to save the changes you made in the document “Untitled”?
"Your changes will be lost if you don’t save them."
I wish to make it that when my application is closed, this message is not shown. I do not need any auto-saves or saving options. How do I prevent this message been shown and disable it?
Thanks in advance for any help and support.
Sam

Recently I had the exact same wish to prevent the save dialog from showing up. What I did is put the following method in my custom document class that inherits NSDocument
-(BOOL)isDocumentEdited {
return NO;
}

Related

Trigger a script (AppleScript or JXA) on .app running?

I have a small computer lab for students to use fairly unsupervised, with a printer attached on the network. I am trying to implement a simple scripting additions alert dialog with all the rules about the printer that I need to pop up when they select print from any number of different applications.
I am trying to attach the script directly to the printer itself in the User/Library/Printer directory, (xxx.xxx.xxx.xxx.app) so any browser, or pdf viewer, etc. will get the message displayed when they try to run the printer.
I have tried using automator with applescript, I have tried renaming the printer and calling the applescript the name of the printer, so far no good.
What am I missing?
In this answer I will show how to create a JavaScript for Automation (JXA) applet that listens for app-launch and screensaver-stop notifications and then displays an alert when it receives one, thereby producing the desired outcome described in the question. I also describe how this approach can be adapted to trigger an AppleScript script, which would produce the specific behavior described in the title of the question.
Instructions
Open the Script Editor app and create a new document
From the pop-up near the top-left of the window, select JavaScript instead of AppleScript
Paste in the code provided below
Save the script as an applet by changing the 'File Format' to 'Application' in the save panel and enabling the 'Stay open after run handler' option.
Run the applet by choosing 'Run Application' from the 'Script' menu
Launch an app and notice an alert
Start and then stop the screensaver and notice an alert
Code
var me = Application.currentApplication(); me.includeStandardAdditions = true
ObjC.import('Cocoa')
ObjC.registerSubclass({
name: 'MainController',
methods: {
'appDidLaunch:': {
types: ['void', ['id']],
implementation: function(notification) {
var appName = notification.userInfo.objectForKey('NSApplicationName').js
me.activate()
me.displayAlert(`Hello, ${appName}!`, {message: 'Nice to meet you.'})
Application(appName).activate()
}
},
'screensaverDidStop:': {
types: ['void', ['id']],
implementation: function(notification) {
me.activate()
me.displayAlert('Goodbye, screensaver!', {message: 'It was nice knowing you.'})
}
}
}
})
var controller = $.MainController.new
$.NSWorkspace.sharedWorkspace.notificationCenter.addObserverSelectorNameObject(controller, 'appDidLaunch:', $.NSWorkspaceDidLaunchApplicationNotification, undefined)
$.NSDistributedNotificationCenter.defaultCenter.addObserverSelectorNameObject(controller, 'screensaverDidStop:', 'com.apple.screensaver.didstop', undefined)
Discussion
First, the applet code creates a new class named 'MainController', which implements two methods, 'appDidLaunch:' and 'screensaverDidStop:'. These methods are implemented to use the 'display alert' functionality from Standard Additions.
Next, the applet code instantiates an object of this class, and registers that instance as on observer of the notifications that are posted when apps are launched, and when the screensaver stops.
The applet continues to run after the JXA code executes, and when the events occur, the JXA functions are invoked.
Next Steps
If you want to run an AppleScript script from JXA, you can refer to the answer to this question.
If you want to make it harder to quit the applet accidentally, you can make the applet a 'UI Element' by setting the LSUIElement key to 'true' in the applet's Info.plist.
Finally, you might want to add the applet to the user's Login Items so that it starts automatically after a reboot.

parent & child browsers view got switched during automated execution by HP UFT

I am facing a strange issue with my test automation scripts when executed through HP UFT 12.01
Our AUT is a web based application developed in actimize. During my test flow, lets say at 5th step i need to invoke a popup browser (child) from my main page. The new popup browser will not have any menus or back/fwd buttons.
3 out of 10 executions, during 5th step my main browser gets refreshed to invoke the popup and when popup rendered fully, contents and views got switched now. i.e., main browser has the contents which are supposed to display in popup window (with menu bar and back/fwd buttons) and pop-up window has main page contents (without menu bar, back/fwd buttons) & state when i performed click operation.
This is strange and i could not really conclude if its browser issue or UFT issue. I have also checked with functional team and they never faced, so this is happening only through UFT execution and speculating it could be UFT issue.. any help pls?
This sounds like it could be either:
1) an actual bug in your UAT
2) a problem with QTP object identification.
If it's #2, here's some things to check. First, make sure that QTP can correctly and reliably identify the two different "browsers". (i.e. while both are on the screen, use the "Highlight in Application" button found the Object Repository window while each of the objects is selected. I would try this for both a normal run and immediately after the browsers get switched (use a break point if necessary)
If there is a problem with QTP identifying the windows incorrectly, then you might want to add additional Description properties to the test object in the OR so that it can lock onto the right one more reliably. I usually use GUISpy to spy on something on the page, then in Object hierarchy I click on the top object (the browser), then click "Copy identification properties to the Clipboard" button, then paste the results into a notepad. Find one of those properties that uniquely identifies the browser objects from anything else. Sometimes I have to use the URL property (with some REGEX magic to isolate the specific page without making it TOO specific)

LoginWindowUI.nib

I'm new into this.. trying to create a simple app for macosx, basically I want this app to startup right after the user login with username/password..
and it's just a simple app has a window & that window displays a warning message and then have two buttons "agree" & "decline"
if the user hit agree then it will continue to the login process.. works as "LOG IN button"
if the user hit Decline then it will go back to the loginwindow..works like "CANCEL button"
but since am new into Xcode.. I have already created the app with both buttons.. but don't know how to add IBAction and Outlets!..
Any ideas?..
Thanks
This should give you an idea. Also, since you are new to ios/mac dev, I would suggest you to read the documents from Apple that will provide you with a wealth of information. Additionally, read the FAQ of the site to get a better understanding how SO functions.

How do I dismiss an NSPanel when creating or opening a new document?

I am working on a document-based Cocoa application. At startup, the user is presented with a "welcome panel" (of type NSPanel) with buttons for common actions like "Create New Document" and "Open Existing Document". These actions are linked to the first responder's newDocument: and openDocument: actions, respectively, just like the matching items in the File menu.
Everything works as expected...with three caveats:
The welcome panel is not dismissed when creating or opening a new document.
Document windows do not have focus when they are created.
Open document windows do not have the open file represented in the window title bar; likewise, new document windows do not get created with titles like "Untitled", "Untitled 2", "Untitled 3", etc., as expected. (I'm mentioning this not only because it's annoying, but because it may yield some insight into what's going wrong.)
I have partially solved #1 by making my application controller a delegate of the welcome panel. When clicking the "Open Existing Document" button, the panel resigns its key status (since a file browser dialog is being opened), so I can close the panel in the delegate's windowDidResignKey: method. However, I can't figure out how to close the panel when creating a new document, since I can't find a notification that is posted, or a delegate method that is called, when creating a new document. And ultimately, #2 is still a problem, since the document windows don't gain focus when they're created.
I have only subclassed NSDocument -- I'm not using a custom document or window controller at all. I've also tried changing the panel to an NSWindow, thinking that an NSWindow may behave differently, but the same problems are occurring.
Make a custom document controller, and have it know about your Starting Points panel's controller, and hide the window in addDocument: and show it again (if no other documents remain) in removeDocument:.
This is what we did in Adium Xtras Creator. That code is under a BSD license (unlike Adium proper), so you can borrow it if you want.
Instead of linking to the first responder's default actions, just create custom action method in your window controller and set your buttons to trigger those actions. In your method, you need to close the welcome window and then create a new document.
Something like this:
- (IBAction)createNewDocument:(id)sender
{
//this will close the window if you're using NSWindowController
[self close];
[[NSDocumentController sharedDocumentController] newDocument:sender];
}
Or if you're not using an NSWindowController for your welcome window you can just message the window directly:
- (IBAction)createNewDocument:(id)sender
{
//assume you have a "window" outlet connected to your welcome window
[window orderOut:sender];
[[NSDocumentController sharedDocumentController] newDocument:sender];
}

How do you display a dialog from a hidden window application?

I have developed a COM component (dll) that implements an Edit() method displaying a WTL modal dialog.
The complete interface to this COM component corresponds to a software standard used in the chemical process industry (CAPE-OPEN) and as a result this COM component is supposed to be usable by a range of 3rd party executables that are out of my control.
My component works as expected in many of these EXEs, but for one in particular the Edit() method just hangs without the dialog appearing.
However, if I make a call to ::MessageBox() immediately before DoModal() the dialog displays and behaves correctly after first showing the MessageBox.
I have a suspicion that the problem may be something to do with this particular EXE running as a 'hidden window application'.
I have tried using both NULL and the return value from ::GetConsoleWindow() as the dialog's parent, neither have worked.
The dialog itself is an ATL/WTL CPropertySheetImpl.
The parent application (EXE) in question is out of my control as it is developed by a (mildly hostile) 3rd party.
I do know that I can successfully call ::MessageBox() or display the standard Windows File Dialog from my COM component, and that after doing so I am then able to display my custom dialog. I'm just unable to display my custom dialog without first displaying a 'standard' dialog.
Can anyone suggest how I might get it to display the dialog without first showing an unnecessary MessageBox? I know it is possible because I've seen this EXE display the dialogs from other COM components corresponding to the same interface.
Are you using a parent for the Dialog? e.g.
MyDialog dialog(pParent);
dialog.DoModal();
If you are, try removing the parent. Especially if the parent is the desktop window.
Depending on how the "hidden window" application works, it might not be able to display a window. For example, services don't have a "main message loop", and thus are not able to process messages sent to windows in the process. i.e, the application displaying the window should have something like this:
while(GetMessage(&msg, NULL, 0, 0))
{
if(!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
in WinMain.
This isn't supposed to be reliable - but try ::GetDesktopWindow() as the parent (it returns a HWND).
Be warned - if your app crashes, it will bring down the desktop with it. But i'd be interested to see if it works.
It turns out I was mistaken:
If I create my dialog with a NULL parent then it is not displayed, and hangs the parent application
However if I create my dialog with ::GetConsoleWindow() as the parent then the dialog is displayed; it just fooled me because it was displayed behind the window of the application that launched the parent application
So now I just have to find out how to bring my dialog to the front.
Thanks for the answers ;-)
Whatever you do, do not use the desktop window as the parent for your modal dialog box.
See here for explanation: http://blogs.msdn.com/b/oldnewthing/archive/2004/02/24/79212.aspx
To quote the rationale:
Put this together: If the owner of a
modal dialog is the desktop, then the
desktop becomes disabled, which
disables all of its descendants. In
other words, it disables every window
in the system. Even the one you're
trying to display!

Resources