You are not logged in.
Pages:: 1
I have this simple script object running in Xcode
It has Textfield, cancel and ok button. I have set the cancel to action of terminate
and I use awakeForNib to set defaultValue for the Textfield. In Xcode I get a string
in log of the input string from Textfield.
So how could run the Nib as modal dialog in script bundle (scptd) or (scpt)...
I guess I will use NSBundle class and but the Nib inside the script bundle and load the
Nib from AppleScript.
What I like to do is... run the below code in Script Editor , any idea ??
And when I click the ok button the modal dialog will go away and return the value from textfield.
All this is new to me...
Applescript:
script AppDelegate
property parent : class "NSObject"
-- IBOutlets
property theWindow : missing value
property theMessage : "" -- textField
(**
* Prepares the receiver for service after it has been loaded from an
* Interface Builder archive, or nib file.
*)
on awakeFromNib()
set defaultMessage to (long user name of (system info))
theMessage's setStringValue_(defaultMessage)
end awakeFromNib
on displayMessage_(sender)
set theMessageValue to (theMessage's stringValue()) as text
log theMessageValue
end displayMessage_
on applicationWillFinishLaunching_(aNotification)
-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_
on applicationShouldTerminate_(sender)
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate_
end script
Last edited by Fredrik71 (2021-05-26 12:49:04 am)
if you are the expert, who will you call if its not your imagination.
Offline
What I like to do is... run the below code in Script Editor, any idea ??
I wonder how you are going to run the code like this directly from the Script editor? I think this is not possible, since all these handlers are of on idle type. That is, they will only work as a stay-open application. (the application enters the main loop, and then reacts to user actions in the application interface.)
You can write AppleScript analog of Xcode stay-open application normal way, using on run, on idle, on quit handlers. But, once again, it will work only as stay-open application. Here is skeleton:
Applescript:
use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions
property theMessage : "" -- textField
on run
my applicationWillFinishLaunching:"Welcome to myApplication!"
my awakeFromNib()
end run
on idle -- or on click (textfileld) handler
-- put here some code which reads and returns current value of your text field
-- if its old value was changed, then you can call on quit handler
return 1
end idle
on applicationWillFinishLaunching:aNotification
display dialog aNotification
end applicationWillFinishLaunching:
on awakeFromNib()
-- create here window
-- add some view (your textfield)
set defaultMessage to (long user name of (system info))
theMessage's setStringValue:defaultMessage
-- set here value of your textfield to theMessage
end awakeFromNib
on applicationShouldTerminate:sender
-- Insert code here to do any housekeeping before your application quits
return current application's NSTerminateNow
end applicationShouldTerminate:
on quit
my applicationShouldTerminate:me
end quit
Last edited by KniazidisR (2021-05-26 07:33:33 am)
Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB
Offline
@KniazidisR, Thanks...
In other post I ask if its was possible to load Nib (Interface Builder) to be used in a script.
The respond from Shane was it was possible... maybe I did missunderstood.
My approach was to make a complex UI in Interface Builder to be used in AppleScript.
Same way Shane did with Myriad Tables Lib. And maybe the only way possible is to build a
framework to call a class, methods...
I thought it maybe was possible to load a Nib with AppleScriptObjC calls from Script applet (scptd)
I do know PyObjC could do this, but on other hand they are applets (.app)
if you are the expert, who will you call if its not your imagination.
Offline
The respond from Shane was it was possible... maybe I did missunderstood.
It is possible:
Applescript:
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:"Window" owner:me topLevelObjects:(reference)
But then you have to deal with what's put in theArray, and any subviews. That means setting targets and possibly actions in code. Do-able but tedious.
My approach was to make a complex UI in Interface Builder to be used in AppleScript.
Same way Shane did with Myriad Tables Lib.
Myriad Tables does not use this approach. It's basically all written in Objective-C, with AppleScript used just to call the methods.
Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com
Offline
Applescript:
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:"Window" owner:me topLevelObjects:(reference)
Thanks for this. Somewhere I have already encountered this. Another thing is that how all this should be executed in the form of a script, not an application. After all, even xCode first creates an application and then executes it. I think this is impossible, even if you enclose all the code in an infinite repeat loop (analogous to the main loop). Or will it still work?
Last edited by KniazidisR (2021-05-26 11:06:49 pm)
Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB
Offline
Another thing is that how all this should be executed in the form of a script, not an application.
It needs to be a script bundle (.scptd file).
Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com
Offline
@Shane
Thanks...
I did this and my dialog com to live... but I need to understand how I could bind the property
and actions...
Applescript:
use framework "Foundation"
use framework "AppKit"
use scripting additions
property arguments : missing value
on run
if current application's NSThread's isMainThread() as boolean then
my performLoadNib:arguments
else
my performSelectorOnMainThread:"performLoadNib:" withObject:arguments waitUntilDone:true
end if
end run
on performLoadNib:arguments
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:"MainMenu" owner:me topLevelObjects:(reference)
end performLoadNib:
if you are the expert, who will you call if its not your imagination.
Offline
but I need to understand how I could bind the property
and actions...
First, don't use the term bind -- in cocoa, binding has a specific meaning.
You need to work out the relevant views from thisArray and any subviews, then use setAction: and setTarget:.
Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com
Offline
@Shane...
Thanks...
I will look into this methods, setAction: and setTarget:.
I do see from the log from theArray I have 5 objects.
I try to extract the names of this object
I use [applescript]log (theArray's objectAtIndex:0)'s |description|() as list[/AppleScript]
(*<NSMenu: 0x600001f1fd40>
Title: Main Menu
Open bounds: [t=900, l=2.1918e-314, b=900, r=6.95345e-310]
Supermenu: 0x0 (None), autoenable: YES
Items: (
"<NSMenuItem: 0x600002e227d0 Terminate, submenu: 0x600001f2ea80 (Terminate)>",
"<NSMenuItem: 0x600002e21180 File, submenu: 0x600001f1cc40 (File)>",
"<NSMenuItem: 0x600002e21110 Edit, submenu: 0x600001f2e0c0 (Edit)>",
"<NSMenuItem: 0x600002e22610 Format, submenu: 0x600001f1e740 (Format)>",
"<NSMenuItem: 0x600002e22450 View, submenu: 0x600001f2dd00 (View)>",
"<NSMenuItem: 0x600002e224c0 Window, submenu: 0x600001f1e700 (Window)>",
"<NSMenuItem: 0x600002e22530 Help, submenu: 0x600001f1dc80 (Help)>"
)*)
It looks like this is the NSWindow log (theArray's objectAtIndex:2)'s |description|() as list
(*<NSWindow: 0x7fa873522910>*)
Last edited by Fredrik71 (2021-05-27 12:46:32 am)
if you are the expert, who will you call if its not your imagination.
Offline
You should make a nib with just the elements you want, and not use MainMenu.nib.
Shane Stanley <sstanley@myriad-com.com.au>
www.macosxautomation.com/applescript/apps/
latenightsw.com
Offline
@Shane
That make sense, we do not need the MenuItems specially when the target dialog is modal.
This is a very interesting approach, why have I not seen this before
I have done similar things with PySide to print strings and load the python script from do shell script.
I guess it also are possible to have different Nib in same Script bundle there the main script
use different handlers to call them. In the end the main script will be shorter to make complex
UI with AppleScript. And that is the target for his approach.
if you are the expert, who will you call if its not your imagination.
Offline
This is properly not the way to do it... but theArray's objectAtIndex change every time the
script is running. So in other words sometimes I get textField in my Window sometimes not.
The code was made to see if I could hardcode a textfield to be part of a load of Nib window.
I guess the solution here would be to always pick the right item in the theArray.
The log say: (*<NSFontManager: 0x6000025486e0>*) when the textfield is show in window.
Applescript:
use framework "Foundation"
use framework "AppKit"
use scripting additions
property arguments : missing value
on run
if current application's NSThread's isMainThread() as boolean then
my performLoadNib:arguments
else
my performSelectorOnMainThread:"performLoadNib:" withObject:arguments waitUntilDone:true
end if
end run
on performLoadNib:arguments
set {theWidth, theHeight} to {600, 300}
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:"MainMenu" owner:me topLevelObjects:(reference)
set theTextfield to createTextfield("Textfield...", 20, 20, theWidth / 2, theHeight / 2)
set theWindow to (theArray's objectAtIndex:0)
theWindow's contentView()'s addSubview:theTextfield
theWindow's |window|'s |center|()
theWindow's |window|'s makeKeyAndOrderFront:me
end performLoadNib:
on createTextfield(theString, xMin, yMin, xLen, yLen)
set textFieldSize to current application's NSMakeRect(xMin, yMin, xLen, yLen)
set theTextfield to current application's NSTextField's alloc()'s initWithFrame:textFieldSize
theTextfield's setEditable:false
theTextfield's setStringValue:theString
theTextfield's setTextColor:(current application's NSColor's whiteColor)
theTextfield's setBezeled:true
theTextfield's setBezelStyle:(current application's NSTextFieldSquareBezel)
theTextfield's setBackgroundColor:(current application's NSColor's blackColor)
return theTextfield
end createTextfield
if you are the expert, who will you call if its not your imagination.
Offline
I find some code here on macscripter.net so I made a other script that always choose NSWindow.
[applescript]use framework "Foundation"
use framework "AppKit"
use scripting additions
property theWindow : missing value
property arguments : missing value
on run
if current application's NSThread's isMainThread() as boolean then
my performLoadNib:arguments
else
my performSelectorOnMainThread:"performLoadNib:" withObject:arguments waitUntilDone:true
end if
end run
on performLoadNib:arguments
set {theWidth, theHeight} to {600, 300}
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:"MainMenu" owner:me topLevelObjects:(reference)
set enumerator to theArray's objectEnumerator()
repeat
set nextObj to enumerator's nextObject()
if (nextObj's isKindOfClass:(current application's NSWindow's |class|())) then
set theWindow to nextObj
exit repeat
end if
end repeat
log theWindow's |description|() as text
-- set theWindow to (theArray's objectAtIndex:0)
set theTextfield to createTextfield("Textfield...", 20, 20, theWidth / 2, theHeight / 2)
theWindow's contentView()'s addSubview:theTextfield
theWindow's |window|'s |center|()
theWindow's |window|'s makeKeyAndOrderFront:me
end performLoadNib:
on createTextfield(theString, xMin, yMin, xLen, yLen)
set textFieldSize to current application's NSMakeRect(xMin, yMin, xLen, yLen)
set theTextfield to current application's NSTextField's alloc()'s initWithFrame:textFieldSize
theTextfield's setEditable:false
theTextfield's setStringValue:theString
theTextfield's setTextColor:(current application's NSColor's whiteColor)
theTextfield's setBezeled:true
theTextfield's setBezelStyle:(current application's NSTextFieldSquareBezel)
theTextfield's setBackgroundColor:(current application's NSColor's blackColor)
return theTextfield
end createTextfield[/AppleScript]
So I made a NSButton in Xcode for my NSWindow.
1. I bind the button to file's owner in binding inspector and name the 'buttonClicked:' in selector name field.
In my script above I add a handler
on buttonClicked:sender
display dialog "Click me!"
end buttonClicked:
So what have I learn... its possible to make UI in Xcode that has elements we could access by
hardcoding but also with handlers. The code above include 3 things.
1. NSWindow and NSButton made from Xcode
2. NSTextfield hardcoded to be included.
It means we could mix code from Xcode and AppleScriptObjC methods to hardcode UI.
Last edited by Fredrik71 (2021-05-27 08:20:33 am)
if you are the expert, who will you call if its not your imagination.
Offline
This code is maybe easier to follow.
1) I made a NSWindow and NSButton in Xcode.
2) NSButton is binding to file's owner in binding inspector and named 'buttonClicked:' in selector name field.
3) NSTextfield is hardcoded in ASObjC and added to the NSWindow.
performDialog is the main handler to call elements to add to the window.
handler that begins with create is help handlers to build elements.
buttonClicked is action.
To try this code or doing something similar you need to copy the nib file from Xcode to
your script bundle (scptd) resources folder.
Applescript:
use framework "Foundation"
use framework "AppKit"
use scripting additions
property arguments : missing value
on run
if current application's NSThread's isMainThread() as boolean then
my performDialog:arguments
else
my performSelectorOnMainThread:"performDialog:" withObject:arguments waitUntilDone:true
end if
end run
on performDialog:arguments
-- Call the window from the nib.
set theWindow to createWindowFromNib("MainMenu")
-- The frame size of the window
set theFrame to theWindow's frame()
set {theWidth, theHeight} to {item 1 of item 2 of theFrame, item 2 of item 2 of theFrame}
-- Hardcode the textfield
set theTextfield to createTextfield("This is a hardcoded textfield inside a NSWindow made from Xcode...", 20, 20, theWidth * 2 / 3, theHeight / 2)
theWindow's contentView()'s addSubview:theTextfield
theWindow's |center|()
theWindow's makeKeyAndOrderFront:me
end performDialog:
on buttonClicked:sender
display dialog "Click me!"
end buttonClicked:
on createWindowFromNib(theNibName)
set theWindow to missing value
set myBundle to my (NSBundle's bundleWithPath:(POSIX path of (path to me)))
set {theResult, theArray} to myBundle's loadNibNamed:theNibName owner:me topLevelObjects:(reference)
-- Get the class of NSWindow from the nib.
set enumerator to theArray's objectEnumerator()
repeat
set nextObj to enumerator's nextObject()
if (nextObj's isKindOfClass:(current application's NSWindow's |class|())) as boolean then
set theWindow to nextObj
exit repeat
end if
end repeat
-- log theWindow's |description|() as text
return theWindow
end createWindowFromNib
on createTextfield(theString, xMin, yMin, xLen, yLen)
set textFieldSize to current application's NSMakeRect(xMin, yMin, xLen, yLen)
set theTextfield to current application's NSTextField's alloc()'s initWithFrame:textFieldSize
theTextfield's setEditable:false
theTextfield's setStringValue:theString
theTextfield's setTextColor:(current application's NSColor's whiteColor)
theTextfield's setBezeled:true
theTextfield's setBezelStyle:(current application's NSTextFieldSquareBezel)
theTextfield's setBackgroundColor:(current application's NSColor's blackColor)
return theTextfield
end createTextfield
Last edited by Fredrik71 (2021-05-27 09:54:13 am)
if you are the expert, who will you call if its not your imagination.
Offline
Pages:: 1