No — it’s both or nothing.
I’m all set, then. But is there an NSView I could use to add a text box?
Sure — look in Dialog Toolkit Plus for the createFieldMainThread:
and createLabelMainThread:
handlers.
Also, if you’re not using checkboxClicked:
, just cut it out, plus the two checkbox calls setTarget:
and setAction:
.
I may be in over my head with this, but I can’t make it work. What am I doing wrong?
use framework "Carbon" -- AEInteractWithUser() is in Carbon
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use script "Myriad Tables Lib" version "1.0.7"
use scripting additions
property NSTextField : a reference to current application's NSTextField
property NSLeftTextAlignment : a reference to 0
property NSNoTitle : a reference to 0
property NSRegularControlSize : a reference to 0
property NSCenterTextAlignment : a reference to 2
property NSPathStylePopUp : a reference to 2
property NSRightTextAlignment : a reference to 1
property defaultRows : {1, 2}
property checkState : 1
property theCheckbox : missing value
property thePopup : missing value
property theAccessoryView : missing value
property emailList : {{}}
set popupList to {}
set myDate to (current date)
repeat with x from 1 to 5
set myDate to myDate + 1 * days
set the end of popupList to date string of myDate
end repeat
set defaultDate to item 1 of popupList
set tablePrompt to "Select the date, email addresses and indicate if there are ads on the page"
set selectedRows to {1, 2}
set {enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} to ¬
{"Label Entry Text", "Placeholder Text", 10, 10, 17, 10, true}
set {labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} to ¬
{"labelString", 0, 0, 50, "right", true, 12, true}
repeat
if current application's NSThread's isMainThread() as boolean then
my createCheckBoxMainThread:{"Page has other editorial", "checkboxClicked:", checkState}
my createPopupMainThread:{popupList, defaultDate}
my buildAccessoryViewMainThread:{theCheckbox, thePopup}
--my createFieldMainThread:{enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs}
my createLabelMainThread:{labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType}
else
my performSelectorOnMainThread:"createCheckBoxMainThread:" withObject:{"Page has other editorial", "checkboxClicked:", checkState} waitUntilDone:true
my performSelectorOnMainThread:"createPopupMainThread:" withObject:{popupList, defaultDate} waitUntilDone:true
my performSelectorOnMainThread:"buildAccessoryViewMainThread:" withObject:{theCheckbox, thePopup} waitUntilDone:true
my performSelectorOnMainThread:"createLabelMainThread:" withObject:{labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} waitUntilDone:true
my performSelectorOnMainThread:"createFieldMainThread:" withObject:{enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} waitUntilDone:true
end if
set theTable to make new table with data emailList ¬
with title ¬
"TV Highlights and grid pages" with prompt tablePrompt ¬
multiple selections allowed true ¬
can add and delete true ¬
editable columns {1, 2} ¬
column headings {"Label", "Address"} ¬
row numbering false ¬
initially selected rows selectedRows ¬
without empty selection allowed
modify table theTable ¬
OK button name ¬
"Okay" cancel button name ¬
"Cancel" extra button name ¬
"Refresh" highlighted rows {} ¬
alternate backgrounds false ¬
row dragging false ¬
without column reordering
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
set tableResult to display table theTable ¬
with extended results
set selectedRows to rows selected of tableResult
set buttonClicked to button number of tableResult
set emailAddresses to values selected of tableResult
log emailAddresses
set finalPosition to final position of tableResult
set fullList to values returned of tableResult
set otherEdOnPage to theCheckbox's state() as boolean
if otherEdOnPage then
set checkState to 1
else
set checkState to 0
end if
set theCheckbox to missing value -- to avoid error messages when saving
set pubDate to thePopup's title() as text
set thePopup to missing value
if buttonClicked is 1 then --OK
set confirmationPrompt to {"Please confirm notification:", ""}
set displayAddresses to my stripNamesFromAddresses(emailAddresses)
set AppleScript's text item delimiters to {", "}
set displayAddresses to displayAddresses as text
set the end of confirmationPrompt to "Send to: " & displayAddresses
set confirmationtext to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set the end of confirmationtext to "The page has other editorial so I won't release."
else
set the end of confirmationtext to "I can release when OK'd."
end if
set AppleScript's text item delimiters to {return}
set userResponse to display dialog confirmationPrompt as text ¬
default answer confirmationtext as text ¬
buttons {"Cancel", "Refresh", "Confirm"} ¬
default button 3 ¬
with title ¬
"Email Confirmation" giving up after 60
if the button returned of userResponse is "Confirm" then
set emailText to text returned of userResponse
exit repeat
else
if the button returned of userResponse is "Refresh" then
set confirmationtext to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set the end of confirmationtext to "The page has other editorial so I won't release."
else
set the end of confirmationtext to "I can release when OK'd."
end if
set tablePrompt to (confirmationPrompt as text) & return & return & confirmationtext as text
end if
end if
else if buttonClicked is 3 then
return
end if
end repeat
on stripNamesFromAddresses(emailAddresses)
log emailAddresses
set newAddressList to {}
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {": "}
repeat with thisAddress in emailAddresses
set the end of newAddressList to item 2 of thisAddress as text
log newAddressList
end repeat
set AppleScript's text item delimiters to saveTID
return newAddressList
end stripNamesFromAddresses
on createCheckBoxMainThread:theArg
set {theTitle, theAction, theDefault} to theArg as list
-- build a checkbox
set my theCheckbox to current application's NSButton's alloc()'s initWithFrame:{{10, 10}, {320, 20}}
tell theCheckbox
its setButtonType:(current application's NSSwitchButton)
its setTitle:theTitle
its setTarget:me
-- its setAction:theAction -- a handler in this script
its setState:theDefault
end tell
end createCheckBoxMainThread:
on createPopupMainThread:theArg
set {entryList, defaultValue} to theArg as list
set my thePopup to current application's NSPopUpButton's alloc()'s initWithFrame:{{10, 30}, {300, 35}} pullsDown:false
thePopup's addItemsWithTitles:entryList
thePopup's selectItemWithTitle:defaultValue
end createPopupMainThread:
on buildAccessoryViewMainThread:theControls
set my theAccessoryView to current application's NSView's alloc()'s initWithFrame:{{0, 0}, {320, 60}}
repeat with aControl in theControls
(theAccessoryView's addSubview:aControl)
end repeat
end buildAccessoryViewMainThread:
on createFieldMainThread:theArg
set {placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} to theArg as list
set theTop to theBottom + 22 + extraHeight
set theField to (NSTextField's alloc()'s initWithFrame:{{theLeft, theBottom}, {theWidth, theTop - theBottom}})
tell theField
(its setEditable:true)
(its setBezeled:true)
its (cell()'s setPlaceholderString:placeHolder)
if extraHeight > 0 then its (cell()'s setWraps:true)
its setStringValue:enteredText
if acceptsTabs then its setDelegate:me
end tell
-- return theField, the top of the field
set my handlerResult to {theField, theTop}
end createFieldMainThread:
on createLabelMainThread:theArg
set {labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} to theArg as list
-- create label, set size and make font
set theLabel to (NSTextField's alloc()'s initWithFrame:{{theLeft, theBottom}, {maxWidth, 17}})
set theFont to my fontOfControlSize:controlSize boldType:boldType
-- format label
if alignment begins with "r" then
theLabel's setAlignment:NSRightTextAlignment
else if alignment begins with "c" then
theLabel's setAlignment:NSCenterTextAlignment
else
theLabel's setAlignment:NSLeftTextAlignment
end if
tell theLabel
its setFont:theFont
its setPreferredMaxLayoutWidth:maxWidth
(its setStringValue:labelString)
(its setEditable:false)
(its setSelectable:true)
(its setBordered:false)
(its setDrawsBackground:false)
its (cell()'s setWraps:wrapsBool)
end tell
-- size label
theLabel's setFrameSize:(theLabel's fittingSize())
-- set alignment
set theFrame to theLabel's frame()
if class of theFrame is record then
set {width:newWidth, height:theHeight} to theFrame's |size|
else
set {newWidth, theHeight} to item 2 of theFrame
end if
if alignment begins with "r" then
set theOrigin to {theLeft + maxWidth - newWidth, theBottom}
else if alignment begins with "c" then
set theOrigin to {(theLeft + (maxWidth - newWidth) / 2), theBottom}
else
set theOrigin to {theLeft, theBottom}
end if
theLabel's setFrameOrigin:theOrigin
-- return theLabel, the top of the label, and its width
set my handlerResult to {theLabel, theBottom + theHeight, newWidth}
end createLabelMainThread:
The geometry is all askew, but this should give you something to work from:
use framework "Carbon" -- AEInteractWithUser() is in Carbon
use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use script "Myriad Tables Lib" version "1.0.7"
use scripting additions
property NSTextField : a reference to current application's NSTextField
property NSLeftTextAlignment : a reference to 0
property NSNoTitle : a reference to 0
property NSRegularControlSize : a reference to 0
property NSCenterTextAlignment : a reference to 2
property NSPathStylePopUp : a reference to 2
property NSRightTextAlignment : a reference to 1
property defaultRows : {1, 2}
property checkState : 1
property theCheckbox : missing value
property thePopup : missing value
property handlerResult : missing value
property theAccessoryView : missing value
property emailList : {{}}
set popupList to {}
set myDate to (current date)
repeat with x from 1 to 5
set myDate to myDate + 1 * days
set the end of popupList to date string of myDate
end repeat
set defaultDate to item 1 of popupList
set tablePrompt to "Select the date, email addresses and indicate if there are ads on the page"
set selectedRows to {1, 2}
set {enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} to ¬
{"Label Entry Text", "Placeholder Text", 10, 10, 17, 10, true}
set {labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} to ¬
{"labelString", 0, 0, 50, "right", true, 12, true}
repeat
if current application's NSThread's isMainThread() as boolean then
my createCheckBoxMainThread:{"Page has other editorial", "checkboxClicked:", checkState}
my createPopupMainThread:{popupList, defaultDate}
my createFieldMainThread:{enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs}
set {theField, theBottom} to handlerResult
my createLabelMainThread:{labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType}
set {theLabel, theBottom, newWidth} to handlerResult
my buildAccessoryViewMainThread:{theLabel, theField, theCheckbox, thePopup}
else
my performSelectorOnMainThread:"createCheckBoxMainThread:" withObject:{"Page has other editorial", "checkboxClicked:", checkState} waitUntilDone:true
my performSelectorOnMainThread:"createPopupMainThread:" withObject:{popupList, defaultDate} waitUntilDone:true
my performSelectorOnMainThread:"createFieldMainThread:" withObject:{enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} waitUntilDone:true
set {theField, theBottom} to handlerResult
my performSelectorOnMainThread:"createLabelMainThread:" withObject:{labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} waitUntilDone:true
set {theLabel, theBottom, newWidth} to handlerResult
my performSelectorOnMainThread:"buildAccessoryViewMainThread:" withObject:{theLabel, theField, theCheckbox, thePopup} waitUntilDone:true
end if
set theTable to make new table with data emailList ¬
with title ¬
"TV Highlights and grid pages" with prompt tablePrompt ¬
multiple selections allowed true ¬
can add and delete true ¬
editable columns {1, 2} ¬
column headings {"Label", "Address"} ¬
row numbering false ¬
initially selected rows selectedRows ¬
without empty selection allowed
modify table theTable ¬
OK button name ¬
"Okay" cancel button name ¬
"Cancel" extra button name ¬
"Refresh" highlighted rows {} ¬
alternate backgrounds false ¬
row dragging false ¬
without column reordering
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
set tableResult to display table theTable ¬
with extended results
set selectedRows to rows selected of tableResult
set buttonClicked to button number of tableResult
set emailAddresses to values selected of tableResult
log emailAddresses
set finalPosition to final position of tableResult
set fullList to values returned of tableResult
set otherEdOnPage to theCheckbox's state() as boolean
if otherEdOnPage then
set checkState to 1
else
set checkState to 0
end if
set theCheckbox to missing value -- to avoid error messages when saving
set pubDate to thePopup's title() as text
set thePopup to missing value
if buttonClicked is 1 then --OK
set confirmationPrompt to {"Please confirm notification:", ""}
set displayAddresses to my stripNamesFromAddresses(emailAddresses)
set AppleScript's text item delimiters to {", "}
set displayAddresses to displayAddresses as text
set the end of confirmationPrompt to "Send to: " & displayAddresses
set confirmationtext to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set the end of confirmationtext to "The page has other editorial so I won't release."
else
set the end of confirmationtext to "I can release when OK'd."
end if
set AppleScript's text item delimiters to {return}
set userResponse to display dialog confirmationPrompt as text ¬
default answer confirmationtext as text ¬
buttons {"Cancel", "Refresh", "Confirm"} ¬
default button 3 ¬
with title ¬
"Email Confirmation" giving up after 60
if the button returned of userResponse is "Confirm" then
set emailText to text returned of userResponse
exit repeat
else
if the button returned of userResponse is "Refresh" then
set confirmationtext to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set the end of confirmationtext to "The page has other editorial so I won't release."
else
set the end of confirmationtext to "I can release when OK'd."
end if
set tablePrompt to (confirmationPrompt as text) & return & return & confirmationtext as text
end if
end if
else if buttonClicked is 3 then
return
end if
end repeat
on stripNamesFromAddresses(emailAddresses)
log emailAddresses
set newAddressList to {}
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {": "}
repeat with thisAddress in emailAddresses
set the end of newAddressList to item 2 of thisAddress as text
log newAddressList
end repeat
set AppleScript's text item delimiters to saveTID
return newAddressList
end stripNamesFromAddresses
on createCheckBoxMainThread:theArg
set {theTitle, theAction, theDefault} to theArg as list
-- build a checkbox
set my theCheckbox to current application's NSButton's alloc()'s initWithFrame:{{10, 10}, {320, 20}}
tell theCheckbox
its setButtonType:(current application's NSSwitchButton)
its setTitle:theTitle
its setTarget:me
-- its setAction:theAction -- a handler in this script
its setState:theDefault
end tell
end createCheckBoxMainThread:
on createPopupMainThread:theArg
set {entryList, defaultValue} to theArg as list
set my thePopup to current application's NSPopUpButton's alloc()'s initWithFrame:{{10, 30}, {300, 35}} pullsDown:false
thePopup's addItemsWithTitles:entryList
thePopup's selectItemWithTitle:defaultValue
end createPopupMainThread:
on buildAccessoryViewMainThread:theControls
set my theAccessoryView to current application's NSView's alloc()'s initWithFrame:{{0, 0}, {320, 60}}
repeat with aControl in theControls
(theAccessoryView's addSubview:aControl)
end repeat
end buildAccessoryViewMainThread:
on createFieldMainThread:theArg
set {enteredText, placeHolder, theLeft, theBottom, theWidth, extraHeight, acceptsTabs} to theArg as list
set theTop to theBottom + 22 + extraHeight
set theField to (NSTextField's alloc()'s initWithFrame:{{theLeft, theBottom}, {theWidth, theTop - theBottom}})
tell theField
(its setEditable:true)
(its setBezeled:true)
its (cell()'s setPlaceholderString:placeHolder)
if extraHeight > 0 then its (cell()'s setWraps:true)
its setStringValue:enteredText
if acceptsTabs then its setDelegate:me
end tell
-- return theField, the top of the field
set my handlerResult to {theField, theTop}
end createFieldMainThread:
on createLabelMainThread:theArg
set {labelString, theLeft, theBottom, maxWidth, alignment, wrapsBool, controlSize, boldType} to theArg as list
-- create label, set size and make font
set theLabel to (NSTextField's alloc()'s initWithFrame:{{theLeft, theBottom}, {maxWidth, 17}})
-- format label
if alignment begins with "r" then
theLabel's setAlignment:NSRightTextAlignment
else if alignment begins with "c" then
theLabel's setAlignment:NSCenterTextAlignment
else
theLabel's setAlignment:NSLeftTextAlignment
end if
tell theLabel
its setPreferredMaxLayoutWidth:maxWidth
(its setStringValue:labelString)
(its setEditable:false)
(its setSelectable:true)
(its setBordered:false)
(its setDrawsBackground:false)
its (cell()'s setWraps:wrapsBool)
end tell
-- size label
theLabel's setFrameSize:(theLabel's fittingSize())
-- set alignment
set theFrame to theLabel's frame()
if class of theFrame is record then
set {width:newWidth, height:theHeight} to theFrame's |size|
else
set {newWidth, theHeight} to item 2 of theFrame
end if
if alignment begins with "r" then
set theOrigin to {theLeft + maxWidth - newWidth, theBottom}
else if alignment begins with "c" then
set theOrigin to {(theLeft + (maxWidth - newWidth) / 2), theBottom}
else
set theOrigin to {theLeft, theBottom}
end if
theLabel's setFrameOrigin:theOrigin
-- return theLabel, the top of the label, and its width
set my handlerResult to {theLabel, theBottom + theHeight, newWidth}
end createLabelMainThread:
Actually, @estockly, a better approach would be to use Display Dialog Toolkit itself to build the controls. Then you just need your own handler to build the accessory view, which you then pass on.
So here’s such a script. The first part is from Align sample.scpt
, which builds a dialog of various widgets. But once the script has created the controls, instead of showing them in a DDT window, it adds them to an accessory view and passes that to some of your Myriad Tables code.
This is a lot simpler: you can build your accessory view as a DDT dialog first, and you don’t need to deal with nearly as much ASObjC code yourself. Just remember the size limit is 600 x 200:
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use script "Dialog Toolkit Plus" version "1.1.0"
use script "Myriad Tables Lib" version "1.0.9"
property theAccessoryView : missing value
-- This code is from the Dialog Toolkit Plus sample "Aligned sample.scpt"
set accViewWidth to 400
set {theButtons, minWidth} to create buttons {"Cancel", "Maybe", "It All Depends", "OK"} default button "OK" cancel button "Cancel" with equal widths
if minWidth > accViewWidth then set accViewWidth to minWidth -- make sure buttons fit
-- to make it look better, we can get the length of the longest label we will use, and use that to align the controls
set theLabelStrings to {"This job is for:", "Operator's name:"}
set maxLabelWidth to max width for labels theLabelStrings
set controlLeft to maxLabelWidth + 8
-- start from the bottom with a checkbox
set {theCheckbox, theTop, newWidth} to create checkbox "One side only" left inset controlLeft bottom 0 max width accViewWidth without initial state
-- then a labeled popup
set {colorPopup, popupLabel, theTop} to create labeled popup {"Red", "Green", "Blue"} left inset 0 bottom (theTop + 8) popup width 100 max width accViewWidth label text (item 1 of theLabelStrings) popup left controlLeft initial choice "Green"
-- then a labeled field
set {operatorField, operatorLabel, theTop, fieldLeft} to create side labeled field (short user name of (system info)) placeholder text "Your name" left inset 0 bottom (theTop + 12) total width accViewWidth label text (item 2 of theLabelStrings) field left controlLeft
-- then a small explanatory label
set {messageLabel, theTop} to create label "More text goes in here" bottom theTop + 12 max width accViewWidth control size small size
-- then a bold message
set {boldLabel, theTop} to create label "Send for output" bottom theTop + 8 max width accViewWidth control size regular size with bold type
-- make list of controls and pass to display command
set allControls to {theCheckbox, colorPopup, popupLabel, operatorField, operatorLabel, boldLabel, messageLabel}
-- create accessory view, passing controls plus size (as {width, height})
if current application's NSThread's isMainThread() as boolean then
my createAccessoryViewMainThread:{allControls, {accViewWidth, theTop}}
else
my performSelectorOnMainThread:"createAccessoryViewMainThread:" withObject:{allControls, {accViewWidth, theTop}} waitUntilDone:true
end if
-- now do the table
set emailList to {{}}
set popupList to {}
set myDate to (current date)
repeat with x from 1 to 5
set myDate to myDate + 1 * days
set the end of popupList to date string of myDate
end repeat
set defaultDate to item 1 of popupList
set tablePrompt to "Select the date, email addresses and indicate if there are ads on the page"
set selectedRows to {1, 2}
set theTable to make new table with data emailList ¬
with title ¬
"TV Highlights and grid pages" with prompt tablePrompt ¬
multiple selections allowed true ¬
can add and delete true ¬
editable columns {1, 2} ¬
column headings {"Label", "Address"} ¬
row numbering false ¬
initially selected rows selectedRows ¬
without empty selection allowed
modify table theTable ¬
OK button name ¬
"Okay" cancel button name ¬
"Cancel" extra button name ¬
"Refresh" highlighted rows {} ¬
alternate backgrounds false ¬
row dragging false ¬
without column reordering
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
set tableResult to display table theTable ¬
with extended results
on createAccessoryViewMainThread:theArg
set {theControls, theSize} to theArg as list
set my theAccessoryView to current application's NSView's alloc()'s initWithFrame:{{0, 0}, theSize}
repeat with aControl in theControls
(theAccessoryView's addSubview:aControl)
end repeat
end createAccessoryViewMainThread:
This is excellent, Shane. I think I have two options that I can make work!
So it worked. Shane, thanks for the tools and the guidance!
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use script "Dialog Toolkit Plus"
use script "Myriad Tables Lib"
property theAccessoryView : missing value
property checkState : missing value
property emailList : {{"Email Name", "email@address.com"}, ¬
{"Email Name", "email@address.com"}, ¬
{"Email Name", "email@address.com"}, ¬
{"Email Name", "email@address.com"}, ¬
{"Email Name", "email@address.com"}, ¬
{"Email Name", "email@address.com"}}
property selectedRows : {}
if selectedRows is {} then set selectedRows to {1, 2}
if checkState is missing value then set checkState to false
set popupList to {}
set myDate to (current date)
repeat with x from 1 to 7
set myDate to myDate + 1 * days
set the end of popupList to date string of myDate
end repeat
set defaultDate to item 1 of popupList
set selectedDate to defaultDate
set defaultEmailText to "Click 'Refresh' to see email text..."
set confirmationText to ""
repeat
set accViewWidth to 420
set theLabelStrings to {"Pub date:", " Email Text:"}
set maxLabelWidth to max width for labels theLabelStrings
set controlLeft to maxLabelWidth + 8
---- then a small explanatory label
--set {boldLabel, theTop} to create label " " bottom 0 max width accViewWidth control size regular size with bold type
-- a labeled field
set {operatorField, operatorLabel, theTop} to create top labeled field confirmationText placeholder text defaultEmailText bottom 0 field width accViewWidth extra height 60 label text "Email Text" with accepts linebreak and tab
-- a checkbox
set {theCheckbox, theTop, newWidth} to create checkbox "Page has other editorial" left inset controlLeft bottom (theTop + 20) max width accViewWidth initial state checkState
-- a labeled popup
set {colorPopup, popupLabel, theTop} to create labeled popup popupList left inset 20 bottom (theTop + 10) popup width 220 max width accViewWidth label text (item 1 of theLabelStrings) popup left controlLeft initial choice selectedDate
-- make list of controls and pass to display command
set allControls to {operatorField, operatorLabel, theCheckbox, colorPopup, popupLabel}
-- create accessory view, passing controls plus size (as {width, height})
if current application's NSThread's isMainThread() as boolean then
my createAccessoryViewMainThread:{allControls, {accViewWidth, theTop}}
else
my performSelectorOnMainThread:"createAccessoryViewMainThread:" withObject:{allControls, {accViewWidth, theTop}} waitUntilDone:true
end if
-- now do the table
set popupList to {}
set myDate to (current date)
repeat with x from 1 to 5
set myDate to myDate + 1 * days
set the end of popupList to date string of myDate
end repeat
set defaultDate to item 1 of popupList
set tablePrompt to "Select the date, email addresses.
Indicate if there are ads on the page"
set theTable to make new table with data emailList ¬
with title ¬
"TV Highlights and grid pages" with prompt tablePrompt ¬
multiple selections allowed true ¬
can add and delete true ¬
editable columns {1, 2} ¬
column headings {"Label", "Address"} ¬
row numbering false ¬
initially selected rows selectedRows ¬
without empty selection allowed
modify table theTable ¬
OK button name ¬
"Okay" cancel button name ¬
"Cancel" extra button name ¬
"Refresh" highlighted rows {} ¬
alternate backgrounds false ¬
initial position {30, 30} ¬
row dragging false ¬
without column reordering
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
set tableResult to display table theTable ¬
with extended results
set selectedRows to rows selected of tableResult
set buttonClicked to button number of tableResult
set emailAddresses to values selected of tableResult
log emailAddresses
set finalPosition to final position of tableResult
set fullList to values returned of tableResult
log tableResult
set otherEdOnPage to theCheckbox's state() as boolean
set theCheckbox to missing value -- to avoid error messages when saving
set thePopup to missing value
set pubDate to colorPopup's title() as text
set selectedDate to pubDate
if buttonClicked is 1 then
exit repeat
else if buttonClicked is 2 then
set confirmationText to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set checkState to true
set the end of confirmationText to return & return & "The page has other editorial so I won't release."
else
set checkState to false
set the end of confirmationText to return & return & "I can release when OK'd."
end if
set defaultEmailText to confirmationText as text
set confirmationText to defaultEmailText
else
return tableResult
end if
end repeat
on createAccessoryViewMainThread:theArg
set {theControls, theSize} to theArg as list
set my theAccessoryView to current application's NSView's alloc()'s initWithFrame:{{0, 0}, theSize}
repeat with aControl in theControls
(theAccessoryView's addSubview:aControl)
end repeat
end createAccessoryViewMainThread:
FWIW, you could also insert theCheckbox's setState:1
in there to get the checkbox selected initially. Strictly speaking it should be done on the main thread, but I suspect you can get away without the whole handler business.
It’s not checked on first run, which is fine, but it is checked on subsequent runs (since Properties still persist down here).
I’m using true and false rather than 1 and 0, but that’s fine, right?
I’m still tweaking, here’s the newest version.
But while we’re on the topic, when a row is added to a table is it possible to specify a default value? In this case it wouldn’t help that much, but I have other tables with multiple columns, but only one or two need to be changed from the default if the user adds a row.
use AppleScript version "2.4"
use scripting additions
use framework "Foundation"
use framework "AppKit"
use script "Dialog Toolkit Plus"
use script "Myriad Tables Lib"
property theAccessoryView : missing value
property checkState : missing value
property selectedRows : {}
property emailList : {{}}
set rowTemplate to {{1, {"To", "cc", "bcc"}}, "", ""}
set subjectText to ""
if selectedRows is {} then set selectedRows to {1, 2}
if checkState is missing value then set checkState to false
set myDate to (current date)
set tableTitle to date string of myDate & ": TV Grid and Highlights page"
set pubDateList to {}
repeat with x from 1 to 7
set myDate to myDate + 1 * days
set the end of pubDateList to date string of myDate
end repeat
set defaultDate to item 1 of pubDateList
set selectedDate to defaultDate
set defaultEmailText to "Click 'Refresh' to see email text..."
set confirmationText to ""
repeat
-- This code is from the Dialog Toolkit Plus sample "Aligned sample.scpt"
set accViewWidth to 440
set theLabelStrings to {"Pub date:", ("Email: " & subjectText)}
-- to make it look better, we can get the length of the longest label we will use, and use that to align the controls
set maxLabelWidth to max width for labels theLabelStrings
set popUpLabel to ("Pick a date: ")
set controlLeft to 8
-- a labeled field
set {operatorField, operatorLabel, theTop} to create top labeled field confirmationText placeholder text defaultEmailText bottom 0 field width accViewWidth extra height 50 label text ("Email: " & subjectText) with accepts linebreak and tab
-- a checkbox
set {theCheckbox, theTop, newWidth} to create checkbox "Page has other editorial" left inset controlLeft bottom (theTop + 20) max width accViewWidth initial state checkState
set {colorPopup, popUpLabel, theTop} to create labeled popup pubDateList left inset 0 bottom (theTop + 20) popup width 220 max width accViewWidth label text popUpLabel popup left 0 initial choice selectedDate
-- a spacer
set {spacer, theTop} to create label " " bottom theTop + 0 max width accViewWidth control size regular size with bold type
-- make list of controls and pass to display command
set allControls to {operatorField, operatorLabel, theCheckbox, colorPopup, popUpLabel, spacer}
-- create accessory view, passing controls plus size (as {width, height})
if current application's NSThread's isMainThread() as boolean then
my createAccessoryViewMainThread:{allControls, {accViewWidth, theTop}}
else
my performSelectorOnMainThread:"createAccessoryViewMainThread:" withObject:{allControls, {accViewWidth, theTop}} waitUntilDone:true
end if
set tablePrompt to "Select the date, email addresses.
Indicate if there are ads on the page"
set theTable to make new table with data emailList ¬
with title tableTitle ¬
with prompt tablePrompt ¬
multiple selections allowed true ¬
row template rowTemplate ¬
can add and delete false ¬
editable columns {1, 2, 3} ¬
column headings {"cc", "Label", "Address"} ¬
row numbering false ¬
initially selected rows selectedRows ¬
without empty selection allowed
modify table theTable ¬
OK button name ¬
"Okay" cancel button name ¬
"Cancel" extra button name ¬
"Refresh" highlighted rows {} ¬
alternate backgrounds false ¬
initial position {30, 30} ¬
row dragging false ¬
without column reordering
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
set tableResult to display table theTable ¬
with extended results
set selectedRows to rows selected of tableResult
set buttonClicked to button number of tableResult
set emailAddresses to values selected of tableResult
log emailAddresses
set finalPosition to final position of tableResult
set fullList to values returned of tableResult
log tableResult
set otherEdOnPage to theCheckbox's state() as boolean
set theCheckbox to missing value -- to avoid error messages when saving
set thePopup to missing value
set pubDate to colorPopup's title() as text
set pubDay to word 1 of pubDate
set subjectText to pubDay & "'s TV Highlights are ready and the grid is on the page"
set selectedDate to pubDate
set confirmationText to {"The TV grid and highlights page for " & pubDate & " is ready for print. ", ""}
if otherEdOnPage then
set checkState to true
set the end of confirmationText to return & return & "The page has other editorial so I won't release."
else
set checkState to false
set the end of confirmationText to return & return & "I can release when OK'd."
end if
set defaultEmailText to confirmationText as text
set confirmationText to defaultEmailText
if buttonClicked is 1 then
--return {confirmationText, subjectText, emailAddresses}
exit repeat
else if buttonClicked is 2 then
set defaultEmailText to confirmationText as text
set confirmationText to defaultEmailText
else
return tableResult
end if
end repeat
set {toAddresses, ccAddresses, bccAddresses} to stripNamesFromAddresses(emailAddresses)
ComposeOutlookMessage(toAddresses, ccAddresses, bccAddresses, subjectText, confirmationText)
on createAccessoryViewMainThread:theArg
set {theControls, theSize} to theArg as list
set my theAccessoryView to current application's NSView's alloc()'s initWithFrame:{{0, 0}, theSize}
repeat with aControl in theControls
(theAccessoryView's addSubview:aControl)
end repeat
end createAccessoryViewMainThread:
on ComposeOutlookMessage(toAddresses, ccAddresses, bccAddresses, messageSubject, messageBody)
set messageBody to FixOutlookBodyText(messageBody)
set AppleScript's text item delimiters to ""
tell application "Microsoft Outlook"
set the newMessage to (make new outgoing message with properties {content:messageBody, subject:messageSubject})
repeat with thisAddressee in toAddresses
make new recipient at newMessage with properties {email address:{name:"", address:thisAddressee}}
end repeat
repeat with thisAddressee in ccAddresses
make new cc recipient at newMessage with properties {email address:{name:"", address:thisAddressee}}
end repeat
repeat with thisAddressee in bccAddresses
make new bcc recipient at newMessage with properties {email address:{name:"", address:thisAddressee}}
end repeat
set thisMessage to open newMessage
activate
end tell
end ComposeOutlookMessage
on stripNamesFromAddresses(emailAddresses)
log emailAddresses
set {toAddresses, ccAddresses, bccAddresses} to {{}, {}, {}}
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {": "}
repeat with thisAddress in emailAddresses
set addressType to item 1 of thisAddress as text
if addressType is "To" then
set the end of toAddresses to item 3 of thisAddress as text
else if addressType is "cc" then
set the end of ccAddresses to item 3 of thisAddress as text
else
set the end of bccAddresses to item 3 of thisAddress as text
end if
end repeat
set AppleScript's text item delimiters to saveTID
return {toAddresses, ccAddresses, bccAddresses}
end stripNamesFromAddresses
on FixOutlookBodyText(textToFix)
set textToFix to paragraphs of textToFix
set saveTID to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"</P>" & return & "<P>"}
set textToFix to textToFix as text
set textToFix to "<P>" & textToFix & "</P>"
set AppleScript's text item delimiters to saveTID
return textToFix
end FixOutlookBodyText
You know, it could be possible to use a combination of the Extra button (or an accessory view) and √ boxes to allow a user to delete rows on the fly.
It works in that it gets converted to an integer when bridged, but using an integer is arguably more correct. Checkboxes aren’t always boolean in nature, in that they can be configured to have an indeterminate state (signified by a negative integer).
Sounds like a feature request.
Yes, come to think of it, that’s exactly what that sounds like
yes, in one case I’ve used the extra button to do this, but in other cases I’ve run out of buttons so I guess I’ll have to dive into the murky world of accessory views. Thanks for the suggestion!
Here’s another question that could be come a feature request or two.
Is it possible for an MT table launched while a specific application is running to only be visible when that application is frontmost/active? Lots of apps have palettes that behave that way.
Ideally I’d like to have an MT Table that changes the displayed list based on which app is frontmost.
I’m using MT to create script palettes. I’m finding them potentially easier to use and definitely faster to execute than FastScripts; apple’s script menu or even script palettes and menus in some apps (inDesign; TextWranger; Script Debugger).
Is it possible for an MT table launched while a specific application is running to only be visible when that application is frontmost/active? Lots of apps have palettes that behave that way.
That’s something you have to control from your app. It’s not that hard to do — there’s a chapter about it in my book (chapter 16).
Feature request:
With empty selection allowed set to false, the extra button, if it is present, should still be enabled/clickable. Or at least the behaviour of the extra button should be controlled independently of the behaviour of the OK button.
With empty selection allowed set to false, the extra button, if it is present, should still be enabled/clickable.
But then empty selection would be allowed.
Or at least the behaviour of the extra button should be controlled independently of the behaviour of the OK button.
Can you give me examples of how that might be useful? It does add a significant amount of extra complication, so there’d have to be more value than just saving a follow-up dialog for invalid entry.
I often use the extra button as a “Refresh,” which gets a new set of table data to display.
For example, say the user is selecting a file to download from a list of files on the server. This would give the user the option of refreshing the list to see any new files added without having to select an item to download that the user doesn’t want to download.
It looks like if there are duplicate values in a popup menu in myriad tables, the first instance is removed, is that correct?
I’m trying to make this work easier for the user. Most of the selections in this list would Sunday’s; but a few of them would be weekdays (which may or may not include Sunday), and several would always be Wednesdays.
So the effect I’m trying to get is for the popup menu to display the next three Sundays; then every day of the week (including Sundays) below.
Instead it displays the full list without Sundays.
Is removing the first instance of duplicates at the beginning of a popup list intentional?
I’d prefer to display them with dupes, or if that’s not practical, keep the first instance and remove subsequent instances.
use scripting additions
use script "Myriad Tables Lib" version "1.0.7"
set rowTemplate to {"", {popup menu, {"Sunday, July 7, 2019", ¬
"Sunday, July 14, 2019", ¬
"Sunday, July 21, 2019", ¬
"Sunday, July 7, 2019", ¬
"Monday, July 8, 2019", ¬
"Tuesday, July 9, 2019", ¬
"Wednesday, July 10, 2019", ¬
"Thursday, July 11, 2019", ¬
"Friday, July 12, 2019", ¬
"Saturday, July 13, 2019", ¬
"Sunday, July 14, 2019", ¬
"Monday, July 15, 2019", ¬
"Tuesday, July 16, 2019", ¬
"Wednesday, July 17, 2019", ¬
"Thursday, July 18, 2019", ¬
"Friday, July 19, 2019", ¬
"Saturday, July 20, 2019", ¬
"Sunday, July 21, 2019", ¬
"Monday, July 22, 2019", ¬
"Tuesday, July 23, 2019", ¬
"Wednesday, July 24, 2019", ¬
"Thursday, July 25, 2019", ¬
"Friday, July 26, 2019", ¬
"Saturday, July 27, 2019"}}}
set {dateList, firstSunday, firstWednesday, firstDate, sundayList} to {{"Sunday, July 7, 2019", ¬
"Monday, July 8, 2019", ¬
"Tuesday, July 9, 2019", ¬
"Wednesday, July 10, 2019", ¬
"Thursday, July 11, 2019", ¬
"Friday, July 12, 2019", ¬
"Saturday, July 13, 2019", ¬
"Sunday, July 14, 2019", ¬
"Monday, July 15, 2019", ¬
"Tuesday, July 16, 2019", ¬
"Wednesday, July 17, 2019", ¬
"Thursday, July 18, 2019", ¬
"Friday, July 19, 2019", ¬
"Saturday, July 20, 2019", ¬
"Sunday, July 21, 2019", ¬
"Monday, July 22, 2019", ¬
"Tuesday, July 23, 2019", ¬
"Wednesday, July 24, 2019", ¬
"Thursday, July 25, 2019", ¬
"Friday, July 26, 2019", ¬
"Saturday, July 27, 2019"}, ¬
"Sunday, July 14, 2019", ¬
"Wednesday, July 10, 2019", ¬
"Monday, July 8, 2019", ¬
{"Sunday, July 7, 2019", ¬
"Sunday, July 14, 2019", ¬
"Sunday, July 21, 2019"}}
set dateListPubList to {}
set the end of dateListPubList to {"What's on TV Coverage Plan", firstSunday}
set the end of dateListPubList to {"What's on TV", firstDate}
set the end of dateListPubList to {"Calendar Letters", firstSunday}
set the end of dateListPubList to {"What's on TV This Week", firstSunday}
set the end of dateListPubList to {"TV Ratings", firstWednesday}
set tableData to dateListPubList
set tableTitle to ""
set tableResult to display table with data tableData ¬
with title tableTitle row template rowTemplate
return values selected of tableResult