I’m trying to figure out a way to have a window in my MainMenu.xib that will display info from all the currently open documents in my app. Probably a table that lists the the name of each open document and a value from a text field from each document.
It seems simple, even simple to describe, but I can’t figure out where to start.
Whichever method you use to open a file could call a method on the app delegate, letting it know that it has opened. And if you have a delegate of your document’s window, you could implement -windowWillClose: to call a method letting the app delegate know that. If the text field can change, you’re going to need it to call an app delegate method each time it changes.
Getting there, slowly. I have a document based app that I built following the “People Docs” app in chapter 22. I figured out how to call a method in the App Delegate from a document window (the “tellMeMore” example), but I can’t figure out how to get values from the document window to the app delegate. The appDelegate script tells me the variables are undefined - of course, because they are defined in the CustomDocument script.
I haven’t gotten to the point of figuring out how to call the method automatically when a file is opened yet. I figured I’d better figure out how to get values across first.
Progress - I got the values from the document to the AppDelegate using stringValue() of the text fields instead of the variables.
Now I want it to happen automatically when the file is opened. How do I call a method on the AppDelegate script from the file open method on the document script?
At first I put it in the file open handler:
readFromData_ofType_error_(theData, typeName, outError)
but the first file I opened after launching always gave me this error:
Unrecognized function stringValue. (error -10000)
The error went away with subsequent files, but the second file gave me the string value from the first file, the third gave me the value from the second, etc. When I changed the value of the text field it always gave me the value of the text field from the second to the last opened document window, not the current key window.
I figured it was because it was calling the handler before the window was open so I put it in
windowDidBecomeKey_(aNotification) instead. Now I think I’m getting somewhere.
on fileIsOpen()
set my theShapeName to stringValue() of theShapeField
set my theShapeQuan to stringValue() of theQuanField
set my theShapePrice to stringValue() of thePriceField
log theShapeName
log theShapeQuan
log theShapePrice
theUpdate()
end fileIsOpen
on theUpdate()
log theShapeName
log theShapeQuan
log theShapePrice
tell arrayController1
set theCollection to arrangedObjects() as list
set theNewData to {theQuan:theShapeQuan, theShape:theShapeName, thePrice:theShapePrice}
set theCollection to theCollection & {theNewData}
removeObjects_(arrangedObjects())
addObjects_(theCollection)
end tell
end theUpdate
When I call fileIsOpen() in the MainMenu.xib script from the windowDidBecomeKey_(aNotification) in the document script, the variables log correctly for each open doc. But when I want to populate a table in my window on the MainMenu.xib I get the error “Can’t get arrangedObjects of missing value. (error -1728)”.
If I call theUpdate() from a button on the MainMenu.xib window it logs those variables as (null). It does populate the table but it’s blank.
So I seem to have the variables right but my arrayController doesn’t work, or my arrayController works but my variables are missing value.
How do I communicate between my xibs (am I saying that right)?
Getting closer - I figured out how to reference the variables with “current application’s NSApp’s delegate()'s theShapeName()”
but referencing the array controller that way doesn’t seem to work.
tell current application's NSApp's delegate()'s arrayController1
set theCollection to arrangedObjects() as list
set theNewGallery to {theQuan:theShapeQuan, theShape:theShapeName, thePrice:theTotal}
set theCollection to theCollection & {theNewGallery}
removeObjects_(arrangedObjects())
addObjects_(theCollection)
end tell
Before it was “Can’t get arrangedObjects of missing value.”
This gives me “Unrecognized function arrangedObjects.”
Why do you add the new item to the current list, remove everything from the array controller and and add everything again? This does actually the same thing
tell arrayController1 to addObject:{theQuan:theShapeQuan, theShape:theShapeName, thePrice:theShapePrice}
Hi Stefan - Thanks. I got that from a tutorial somewhere and it’s always worked so I never looked for a way to shorten it.
There must be some fundamental concept I’m not understanding. When I call a method on the app delegate script from the application script, I can set the properties contained in the app delegate script. They aren’t declared in the document script so I know I’m setting the right variables.
property theShapeName : missing value
on methodCalledFromDoc()
set my theShapeName to "Something"
log theShapeName
end methodCalledFromDoc
Log shows “Something”, but the text field on the main menu window that is bound to that property stays blank.
This tells me I haven’t really set the value, even though the log tells me I did.
on methodCalledFromMainMenu()
log theShapeName
end methodCalledFromMainMenu
Log shows “(null)”
This confirms that I haven’t really set the value.
So then I have to
on methodCalledFromMainMenu()
set my theShapeName to current application's NSApp's delegate()'s theShapeName()
log theShapeName
end methodCalledFromMainMenu
Log shows “Something”.
So I have to physically click a button on the app delegate window to force the properties to set? Why can’t I set the properties and populate the app delegate window from the document window?
FWIW, I opened a copy of People Docs, added a window to MainMenu.xib with a text field bound to theShapeName, added your handler and property to the app delegate, then added a button to the document window calling this:
on doIt_(sender)
current application's NSApp's delegate()'s methodCalledFromDoc()
current application's NSLog("%@","called")
end doIt:
And it worked fine. So you might check your code and connections.
Alright, so you’re saying it should work, so I must have some wires crossed. I think I need to start over. It’s a real mess now after all my trials and errors.
I tried exactly what you did with the People Docs and I was able to call the method and it did set the property and the text field bound to it, like you said it would and like it should.
So I started a new document based project and built it, very carefully, to do nothing but call a method on MainMenu script from the CustomDocument script to set the value of a property declared in the MainMenu script. According to the log it worked. Then I made a window in the MainMenu.xib, added a text field bound to that property, and it STILL didn’t change when I set the property! Log says the property is set, text field bound to that property says it isn’t.
So I disconnected everything and reconnected them again exactly as they were… and it DID work! Jeez!
But I still couldn’t set the value of the property in the MainMenu.xib to the value of a property in the document.xib. I finally figured out how to declare a property in the MainMenu script that refers to the other script like this:
property theTextIWantToReplace : missing value
property theDocScript : missing value
on transferIt()
set my theDocScript to current application's CustomDocument's alloc()'s init() --(CustomDocument is name of the document script minus .applescript)
set my theTextIWantToReplace to theDocScript's theTextFromTheDoc() as text
end transferIt
so I can refer to the properties in the other script. That was really hard to find an example of, so hopefully this will help someone else in my boat.
Now I have to see if I can talk to an array controller in the other script.
Wow, I hope I’m not being a pest.
Here’s my latest glitch:
The Document script:
property theTextFromTheDoc : "I Like Turtles"
on transferFromHere_(sender)
set my theTextFromTheDoc to "I Like Cows"
current application's NSApp's delegate()'s transferToHere()
end transferFromHere_
The MainMenu script:
property theTextIWantToReplace : missing value
on transferToHere()
set my theTextIWantToReplace to theDocScript's theTextFromTheDoc()
log theTextIWantToReplace
end transferToHere
the result is “I Like Turtles”, not “I like Cows”. How can this be? I set the value of the property before I passed it. If I log it before calling the script in the MainMenu the value is “I Like Cows”, but when I refer to it from the other script it’s the original value.
That’s what I’m trying to do. The only problem is that the value I want to set the app delegate property to is contained in the document. How do I get that value over to the app delegate? Am I making any sense?