Myriad Tables Questions

Just to refine that point a bit: it’s involved only if downloaded via an application (an LSQuarantineAgent like Safari, Mail, Transmission, etc). Gatekeeper isn’t involved if you download via, say, cURL or package managers like brew and macports, nor if you transfer across SSH.

Also bear in mind that you (or anyone else, even as standard user) can run anything downloaded even via Safari (et al) even if Gatekeeper is set to App Store only simply by using xattr (see the man page or DM me) to remove the quarantine bit.

This is great for users that don’t want to be pestered by all that malarky. Great for malware authors, too.

True, we’ve not seen much commodity malware on the Mac to date, but as a certain sceptical Scot once said, don’t expect the past to be a reliable guide to the future! :wink:

1 Like

Version 1.0.9 of Myriad Tables Lib is now available here:
https://www.macosxautomation.com/applescript/apps/Script_Libs.html

This version fixes issues in Dark Mode when running in macOS 10.14. It also adds the ability to have a text column displayed securely with letters appearing as bullet characters, and German localization has been added.

1 Like

I have, but it seems that all it offers is a single checkbox. I have no idea what an NS View is. (I avoided using it because the documentation warned me off)

Would it be possible to include more examples of accessory view in the samples? Could they include popup menus or text fields or radio buttons?

If so, Accessory View might work out to be exactly what I need.

FWIW, here’s the dialog I’d like that I’m now doing with Myriad Tables but isn’t very user friendly. It now takes three dialogs (Choose from list; a table; a dialog with text box)

The dialog should provide a selection of date. (Currently I use a list of dates in Choose From list, then go on to the next dialog. A pop-up menu with a default selection would be perfect)

Next the dialog should display a list of email names/address that include address that’s been included recently. (never a big number of addresses, maybe 4 0r 5). The user should be able to select which addresses to include. The initial selection should be based on day of week and recipients from last run (this is a piece of cake with myriad tables)

There should be a radio button pair indicating if Advertising yes/no.

Next there should be a text field with text generated based on the defaults. A refresh button would regenerate that text based on user’s current selections in this dialog.

There should be three buttons: Cancel, refresh, continue.

So essentially I want accessory view a popup menu, then a table, then two radio buttons, then a text field.

So it’s like a combo between Dialog Toolkit and Myriad Tables.

If I can get this one going I’ve got a few other UI scripts that show the user a series of dialogs that could be consolidated into a single dialog interface.

I can’t seem to get columns to display date & time values as anything but a short date string/user format short.

If I run the below in SD the time column shows me a short date string and no time. Whatever I seem to set the date format to doesn’t have any effect. My language and region settings in System Preferences are what you’d expect – pretty much the default. It shows me a long and short format for date and time values.

use AppleScript version "2.4"
use scripting additions
use script "Myriad Tables Lib"

set theDate to (current date)
set theData to {{"Commencement", theDate}, {"Coffee Break", theDate + 360}, {"Keynote", theDate + 720}, {"Lunch", theDate + 1080}}
set theTable to make new table with data theData column headings {"Event", "Time"} with prompt "This should show times." with title "Testing Date and Time Formats" with empty selection allowed
modify columns in table theTable columns list {2} date format {user format none, user format full}
display table theTable

If I run the above code in SE I get Error “The bundle “SMSTableDialogBuilder” couldn’t be loaded.”

That’s because you’re setting the date format parameter, which takes a string (and falls back to short date format). You should be setting the user date format parameter.

Script Editor under 10.14 and later cannot load third-party frameworks. You need to use Script Debugger.

With a bit of Facespan and Xcode thrown in :grinning:

But you’re on the right track: the code in Dialog Toolkit Plus shows you how to generate the various controls, and the checkbox accessory view sample shows how to add them to a Myriad Tables dialog.

It’s not simple — it’s complicated by the need for a lot of code to run on the main thread, which means even less feedback than usual — but it’s also not rocket science. You build and size the controls you want, add them to an NSView, and then pass that view for the accessory view. And because of the threading/performSelector thing, you often have to use properties to pass values around.

Here’s a rough example of melding some more code from Dialog Toolkit Plus to show both a check box and popup:

use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use script "Myriad Tables Lib" version "1.0.9"
use scripting additions

property theCheckbox : missing value
property thePopup : missing value
property theAccessoryView : missing value

set popupList to {"Fred", "Frieda", "George", "Georgina"}
-- Manipulation of views should be done on the main thread
if current application's NSThread's isMainThread() as boolean then
	my createCheckBoxMainThread:{"Check me", "checkboxClicked:"}
	my createPopupMainThread:{popupList, "Georgina"}
	my buildAccessoryViewMainThread:{theCheckbox, thePopup}
else
	my performSelectorOnMainThread:"createCheckBoxMainThread:" withObject:{"Check me", "checkboxClicked:"} waitUntilDone:true
	my performSelectorOnMainThread:"createPopupMainThread:" withObject:{popupList, "Georgina"} waitUntilDone:true
	my performSelectorOnMainThread:"buildAccessoryViewMainThread:" withObject:{theCheckbox, thePopup} waitUntilDone:true
end if

-- make a table and add the accessory view
set theTable to make new table with data {"One", "Two", "Three", "Four", "Five"}
modify table theTable accessory view theAccessoryView
set theAccessoryView to missing value -- to avoid error messages when saving
display table theTable
-- get the state of the checkbox
set theState to theCheckbox's state() as boolean
set theCheckbox to missing value -- to avoid error messages when saving
set theValue to thePopup's title() as text
set thePopup to missing value
display dialog theValue

on createCheckBoxMainThread:theArg
	set {theTitle, theAction} to theArg as list
	-- build a checkbox
	set my theCheckbox to current application's NSButton's alloc()'s initWithFrame:{{10, 10}, {150, 18}}
	tell theCheckbox
		its setButtonType:(current application's NSSwitchButton)
		its setTitle:theTitle
		its setTarget:me
		its setAction:theAction -- a handler in this script
	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, 35}, {150, 26}} 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}, {160, 60}}
	repeat with aControl in theControls
		(theAccessoryView's addSubview:aControl)
	end repeat
end buildAccessoryViewMainThread:

-- this is called when the checkbox is clicked
on checkboxClicked:sender
	-- make an alert and show it as a sheet over the table window
	set theWindow to sender's |window|()
	set theAlert to current application's NSAlert's alloc()'s init()
	theAlert's setMessageText:"You clicked the checkbox"
	theAlert's setInformativeText:"Now close this sheet"
	theAlert's beginSheetModalForWindow:theWindow completionHandler:(missing value)
end checkboxClicked:

This is working really well. Not sure how to set it up so the box is checked when the box is displayed.

use AppleScript version "2.4"
use framework "Foundation"
use framework "AppKit"
use script "Myriad Tables Lib" version "1.0.7"
use scripting additions
property defaultRows : {1, 2}
property theCheckbox : missing value
property thePopup : missing value
property theAccessoryView : missing value
property emailList : {
	{"Features Copy Desk", "1address@domain.com"}, ¬
	{"Features Design Desk", "2address@domain.com"}, ¬
	{"First Last", "3address@domain.com"}, ¬
	{"First Last", "4address@domain.com"}, ¬
	{"First Last", "5address@domain.com"}}


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"
repeat
	-- Manipulation of views should be done on the main thread
	if current application's NSThread's isMainThread() as boolean then
		my createCheckBoxMainThread:{"Page has other editorial", "checkboxClicked:"}
		my createPopupMainThread:{popupList, defaultDate}
		my buildAccessoryViewMainThread:{theCheckbox, thePopup}
	else
		my performSelectorOnMainThread:"createCheckBoxMainThread:" withObject:{"Page has other editorial", "checkboxClicked:"} waitUntilDone:true
		my performSelectorOnMainThread:"createPopupMainThread:" withObject:{popupList, defaultDate} waitUntilDone:true
		my performSelectorOnMainThread:"buildAccessoryViewMainThread:" withObject:{theCheckbox, thePopup} waitUntilDone:true
	end if
	
	-- make a table and add the accessory view
	--set theTable to make new table with data emailList
	
	
	
	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 {1, 2} ¬
		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
	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
		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 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} 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
	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:

-- this is called when the checkbox is clicked
on checkboxClicked:sender
	-- make an alert and show it as a sheet over the table window
	--set theWindow to sender's |window|()
	--set theAlert to current application's NSAlert's alloc()'s init()
	--	theAlert's setMessageText:"You clicked the checkbox"
	--theAlert's setInformativeText:"Now close this sheet"
	--theAlert's beginSheetModalForWindow:theWindow completionHandler:(missing value)
end checkboxClicked:

Thanks, Shane.

Is there a way to allow deleting rows but not adding rows? I know about the can ad and delete parameter.

In its handler, add:

	its setState:1

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:



1 Like

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.