Retired Document
Important: This document may not represent best practices for current development. Links to downloads and other resources may no longer be valid.
Mail Search Tutorial: Write the Code
In this chapter you’ll write the scripts and handlers for Mail Search, an AppleScript Studio application that searches for specified text in messages in the Mac OS X Mail application. You’ll also build and test the completed application. To do this, you’ll perform the steps described in the following sections:
This chapter assumes you have completed previous Mail Search tutorial chapters.
Obtaining the Code for the Mail Search Tutorial
The Mail Search tutorial chapters in this document contain listings for most of the handlers and script objects the application uses, and you can find a complete listing in Chapter 10. However, both for convenience and completeness, it is recommended that you obtain script statements by copying them from the Mail Search sample application distributed with AppleScript Studio.
Look for the file Mail Search.applescript
in the Mail Search project folder. See AppleScript Studio Sample Applications for information on where to find the sample applications.
You should also read the section Switching Between AppleScript Studio and Script Editor before beginning this tutorial.
Define Global Variables and Properties
In Plan the Code, you identified a handful of global variables and properties Mail Search makes available to all its scripts and handlers. The one global variable is a global list to keep track of instances of the controller script. Each controller script handles search operations for one search window. You define this global variable as shown in Listing 9-1 and place it at the top of the script file Mail Search.applescript
.
Listing 9-1 Global list variable to store instances of controller script
(*==== Globals ====*) |
global controllers |
Mail Search uses two global properties, a counter to keep track of the number of open windows and a boolean to keep track of whether the status panel nib file has been opened. You define these properties as shown in Listing 9-2 and place them at the top of the script file Mail Search.applescript
, below the global variable you just defined.
Listing 9-2 Properties used in Mail Search
(*==== Properties ====*) |
property windowCount: 0 |
property statusPanelNibLoaded: false |
Write Event Handlers for the Interface
In Plan the Code, you identified event handlers for objects in Mail Search’s interface that must respond to user actions or changes in application state (pending or completed). For example, the search window has three handlers: became main
, called when the window becomes active; will open
, called as the window is about to open, and will close
, called when the window is about to close. The find button has one handler, clicked
, called when a user clicks the button.
In Connect the Interface, you hooked up objects in the interface to the required handlers. As part of that step, Interface Builder inserted event handler declarations in the file Mail Search.applescript
. In this section, you’ll write script statements for those handlers.
When planning the code, you also specified additional scripts and handlers to carry out operations such as searching, displaying results, and displaying status. You’ll write those scripts and handlers in Write Scripts and Additional Handlers. The handlers you’ll write in this section don’t do much except call other handlers, so you won’t be able to build and run the application until you’ve completed both sections (though you can compile Mail Search.applescript
to check syntax).
While this approach may be suitable for simple applications—or for a tutorial, where the end result is already known—it’s not recommended for complex, real-world applications. For those applications, you will most likely work incrementally, adding parts of the interface, connecting them to event handlers, and testing individual scripts and handlers as you create them.
As a workaround to allow you to continue to build the application, you can add empty versions of the handlers you haven’t implemented yet to the script file. And as always, you can put display dialog
statements in the stubbed out handlers to show when they are called.
Position each of the event handlers described here at the beginning of the script file Mail Search.applescript
, just after the global variables and properties defined earlier.
Before working on this section, be sure you’ve read the section Obtaining the Code for the Mail Search Tutorial.
Application Object Handler
You previously connected a will finish launching
handler for the application object. That handler is called after the application’s user interface has been unarchived from its nib files and just before the application enters its main event loop. In that handler, Mail Search can do any additional initialization it requires before a user performs any actions.
The only initialization Mail Search requires is to set the global controllers
variable to an empty list, as shown in Listing 9-3.
Listing 9-3 The will finish launching
handler for the application object
on will finish launching theObject |
set controllers to {} |
end will finish launching |
Search Window Handlers
You previously connected three handlers for the application.search window: will open
, became main
, and will close
.
The will open
handler is called after a window has been created from a nib file and before the window opens. At this point, Mail Search can do any additional initialization for the window. The handler is shown in Listing 9-4.
Listing 9-4 will open
handler for search window
on will open theObject |
set theController to makeController(theObject) |
if theController is not equal to null then |
addController(theController) |
tell theController to initialize() |
end if |
end will open |
The will open
handler performs these operations:
It calls
makeController
to create a controller for the window. The controller is a script that responds to user actions in the window.If
makeController
successfully returns a controller, thewill open
handler adds the controller to the global list of controllers, then tells the controller to initialize itself.
The became main
handler is called when a window becomes the current window. It’s similar to what you might be familiar with as an activate event—an event a window receives when it needs to present itself as the active window. The handler is shown in Listing 9-5.
Listing 9-5 The became main
handler for the search window
on became main theObject |
set theController to controllerForWindow(theObject) |
if theController is not equal to null then |
tell theController to loadMailboxes() |
end if |
end became main |
The became main
handler performs these operations:
It calls
controllerForWindow
to get the controller for the window. The controller should have been created during a previous call towill open
.If
controllerForWindow
successfully returns a controller, thebecame main
handler calls the controller’sloadMailboxes
handler (shown in Listing 9-12) to search the Mail application for all available mailboxes and display them in the Mailboxes outline view.
The will close
handler is called before a window closes. At this point, Mail Search can do any cleanup for the window. The only cleanup Mail Search requires is to remove window’s controller from the global list of controllers, as shown in Listing 9-6.
Listing 9-6 The will close
handler for the search window
on will close theObject |
removeController(theObject) |
end will close |
Text Field Handler
You previously connected an action
handler for the search text field object. That handler is called when a user presses the Return key. The handler is shown in Listing 9-7.
Listing 9-7 The action
handler for the search text field
on action theObject |
set theController to controllerForWindow(window of theObject) |
if theController is not equal to null then |
tell theController to find() |
end if |
end action |
The action
handler performs these operations:
It calls
controllerForWindow
to get the controller for the window.If
controllerForWindow
successfully returns a controller, theaction
handler calls the controller’sfind
handler (shown in Listing 9-16) to search for the specified text in messages in the selected mailboxes (and display any matching messages in the Messages table view).
Find Button Handler
You previously connected a clicked
handler for the find button object. That handler is called when a user clicks the find button. The handler is shown in Listing 9-8.
Listing 9-8 The clicked
handler for the find button
on clicked theObject |
set theController to controllerForWindow(window of theObject) |
if theController is not equal to null then |
tell theController to find() |
end if |
end clicked |
The clicked
handler is virtually identical to the action
handler described in Text Field Handler:
It calls
controllerForWindow
to get the controller for the window.If
controllerForWindow
successfully returns a controller, theclicked
handler calls the controller’sfind
handler (shown in Listing 9-16) to search for the specified text in messages in the selected mailboxes (and display any matching messages in the Messages table view).
Search Results Table View Handler
You previously connected a double clicked
handler for the Messages table view object. That handler is called when a user double-clicks a selected message in the table. The handler is shown in Listing 9-9.
Listing 9-9 The double clicked
handler for the search results table view
on double clicked theObject |
set theController to controllerForWindow(window of theObject) |
if theController is not equal to null then |
tell theController to openMessages() |
end if |
end double clicked |
The double clicked
handler performs these operations:
It calls
controllerForWindow
to get the controller for the window.If
controllerForWindow
successfully returns a controller, thedouble clicked
handler calls the controller’sopenMessages
handler (shown in Listing 9-18) to open the selected message (or messages) in a separate window.
Write Scripts and Additional Handlers
In Plan the Code, you identified handlers for objects in Mail Search’s interface that must respond to user actions or changes in application state (pending or completed). In Connect the Interface, you hooked up objects in the interface to the required handlers. Then you wrote the event handlers, in Write Event Handlers for the Interface.
When planning the code, you also specified additional scripts and handlers to carry out operations such as searching, displaying results, and displaying status. In this section, you’ll write those scripts and handlers. As mentioned previously, you won’t be able to build and run the application until you’ve completed this section, though you can compile Mail Search.applescript
to check syntax.
Before working on this section, be sure you’ve read the section Obtaining the Code for the Mail Search Tutorial.
Write the Controller Script
Mail Search defines a controller script to perform tasks associated with the search window, including finding and displaying mailboxes, and finding and displaying messages that match the current search criteria. You specified the properties and handlers for this script in The Controller Script. In this section, you’ll look at the actual script and the handlers it contains. The controller script is defined in the makeController
handler. All of the controller’s properties and handlers shown here are defined in that handler, which is listed in full in Chapter 10.
Controller Script Properties and Initialization
The controller script is defined in the makeController
handler, which is described in Write Handlers for Working With Controllers. The script defines and initializes properties for several things it needs to keep track of:
theWindow:
a reference to its windowtheStatusPanel:
a reference to a status panelfoundMessages:
a list of found messagesmailboxesLoaded:
a boolean for whether it has created a list of available mailboxes
Listing 9-10 shows the definitions for these properties.
Listing 9-10 Properties of the controller script
property theWindow : forWindow |
property theStatusPanel : null |
property foundMessages : {} |
property mailboxesLoaded : false |
The value for the theWindow
property, forWindow
, is passed to the makeController
handler.
The controller script initialization handler sets up columns in the data handlers that provide data for the mailboxes and messages views in the search window. This handler is shown in Listing 9-11.
Listing 9-11 The controller script’s initialize
handler
on initialize() |
-- Add a column to the mailboxes data source |
tell scroll view "mailboxes" of split view 1 of theWindow |
make new data column at the end of the data columns of data source ¬ |
of outline view "mailboxes" with properties {name:"mailboxes"} |
end tell |
-- Add the columns to the messages data source |
tell scroll view "messages" of split view 1 of theWindow |
make new data column at the end of the data columns of data source ¬ |
of table view "messages" with properties {name:"from"} |
make new data column at the end of the data columns of data source ¬ |
of table view "messages" with properties {name:"subject"} |
make new data column at the end of the data columns of data source ¬ |
of table view "messages" with properties {name:"mailbox"} |
end tell |
set windowCount to windowCount + 1 |
end initialize |
The initialize
handler performs the following steps:
It adds a mailboxes column with the name “mailboxes” to the data source of the Mailboxes outline view. The data source supplies the outline view with the data to display (account and mailbox names).
Similarly, it adds columns for “from”, “subject”, and “mailbox” to the data source of the Messages table view. The data source supplies the table view with the data to display (from names, subject lines, and mailbox names).
Finding and Displaying Accounts and Mailboxes
This section describes the handlers in the controller script Mail Search uses to find and display mailboxes in the search window. The jumping off point for displaying mailboxes is the loadMailboxes
handler, shown in Listing 9-12. It is called from the became main
handler, shown in Listing 9-5, to ensure that whenever a window is activated it displays the available mailboxes. The loadMailboxes
handler is responsible for loading all available mailboxes from all available accounts, if they have not already been loaded, and for showing the status dialog while loading.
The logic for the process of loading mailboxes is as follows:
loadMailboxes
kicks off the process by callingaddMailBoxes
.Mailboxes can reside in any account, so for each account,
addMailBoxes
callsaddAccount
.For each mailbox the account contains,
addAccount
callsaddMailbox
.addAccount
adds the mailbox to the outline view of mailboxes available to search.
Listing 9-12 The controller script’s loadMailboxes
handler
on loadMailboxes() |
if not mailboxesLoaded then |
-- Open the status panel |
set theStatusPanel to makeStatusPanel(theWindow) |
tell theStatusPanel to openPanel("Looking for Mailboxes...") |
-- Add the mailboxes |
addMailboxes() |
-- Close the status panel |
tell theStatusPanel to closePanel() |
set mailboxesLoaded to true |
end if |
end loadMailboxes |
The loadMailboxes
handler performs the following steps:
If the mailboxes have already been loaded, it does nothing. Otherwise it performs the following steps.
It calls the
makeStatusPanel
handler to create a status dialog script object, and stores a reference to it in thetheStatusPanel
property. ThemakeStatusPanel
handler is described in Write Handlers for Working With the Status Dialog.It calls the
openPanel
handler of the status dialog script object to start displaying the dialog, with the message “Looking for Mailboxes...” TheopenPanel
handler is described in The Status Dialog Script.It calls the controller handler
addMailboxes
to get all available mailboxes in all available accounts.On completion of the previous step, it closes the status dialog.
It sets the controller property
mailboxesLoaded
totrue
(so it won’t load the mailboxes if they’ve already been loaded).
The addMailboxes
handler is shown in Listing 9-13. It is called from the loadMailboxes
handler, shown in Listing 9-12. The addMailboxes
handler is responsible for iterating over all available accounts to obtain their mailboxes.
Listing 9-13 The controller script’s addMailboxes
handler
on addMailboxes() |
tell application "Mail" |
set accountIndex to 0 |
repeat with a in (get accounts) |
try |
set accountIndex to accountIndex + 1 |
my addAccount(a, accountIndex, account name of a) |
end try |
end repeat |
end tell |
end addMailboxes |
The addMailboxes
handler performs the following steps:
It targets the Mail application.
It gets a list of all accounts from the application.
It uses a repeat statement to iterate over the accounts.
For each account, it calls the controller handler
addAccount
(shown in Listing 9-14), passing among other things the name of the account.Within the
tell application "Mail"
statement block, theaddMailboxes
handler uses the termmy addAccount
to specify that it is calling another handler in the controller script.
The addAccount
handler (shown in Listing 9-14) is called from the addMailboxes
handler (shown in Listing 9-13). The addAccount
handler is responsible for getting all available mailboxes in the passed account and adding them to the data source for the mailboxes view in the search window.
Listing 9-14 The controller script’s addAccounts
handler
on addAccount(a, accountIndex, accountName) |
-- Add a new item |
set accountItem to make new data item at the end of the data items ¬ |
of data source of outline view "mailboxes" ¬ |
of scroll view "mailboxes" of split view 1 of theWindow |
set name of data cell 1 of accountItem to "mailboxes" |
set contents of data cell 1 of accountItem to accountName |
set associated object of accountItem to accountIndex |
-- Add the mail boxes |
tell application "Mail" |
set mailboxIndex to 0 |
repeat with m in (get mailboxes of a) |
try |
set mailboxIndex to mailboxIndex + 1 |
my addMailbox(accountItem, accountName, mailboxIndex, ¬ |
mailbox name of m) |
end try |
end repeat |
end tell |
end addAccount |
The addAccount
handler performs the following steps:
It adds an account item to the data source for the mailboxes view in the search window. It also sets various information for the item, including its name (the name of the account).
It targets the Mail application.
It gets a list of all mailboxes in the account from the application.
It uses a repeat statement to iterate over the mailboxes.
For each mailbox, it calls the controller handler
addMailbox
(shown in Listing 9-15), passing among other things the name of the mailbox, to add the mailbox to the data source for the mailboxes view in the search window.
The addMailbox
handler is called from the addAccount
handler, shown in Listing 9-14, to add a single mailbox to the data source for the mailboxes view in the search window. The addMailbox
handler is shown in Listing 9-15.
Listing 9-15 The controller script’s addMailbox
handler
on addMailbox(accountItem, accountName, mailboxIndex, mailboxName) |
-- Add a new item |
set mailboxItem to make new data item at the end of the data items ¬ |
of accountItem |
set name of data cell 1 of mailboxItem to "mailboxes" |
set contents of data cell 1 of mailboxItem to mailboxName |
set associated object of mailboxItem to mailboxIndex |
end addMailbox |
The addMailboxes
handler performs the following step:
It adds a mailbox item to the data source for the mailboxes view in the search window. It also sets various information for the item, including its name (the name of the mailbox).
Finding and Displaying Messages
This section describes the handlers in the controller script Mail Search uses to find and display messages in the search window. Only messages in the specified mailboxes that contain the specified text in the specified part of the message are displayed.
The jumping off point for finding messages is the find
handler. It is called from the clicked
handler for the find button, shown in Listing 9-8 and the action
handler for the search text field, shown in Listing 9-7. The find
handler is responsible for gathering the search criteria, searching the selected mailboxes for matching messages, and displaying any such messages that are found. It also displays various status messages during the search. The find
handler is shown in Listing 9-16
Listing 9-16 The controller script’s find
handler
on find() |
-- Get what and where to find |
set whatToFind to contents of text field "what" of theWindow |
set whereToFind to title of current menu item of popup button "where" ¬ |
of theWindow |
-- Make sure that we have something to find |
if (count of whatToFind) is greater than 0 then |
-- Clear any previously found messages |
clearMessages() |
-- Setup a status panel |
set theStatusPanel to makeStatusPanel(theWindow) |
tell theStatusPanel to ¬ |
openPanel("Determining the number of messages...") |
try |
-- Determine the mailboxes to search |
set mailboxesToSearch to selectedMailboxes() |
-- Determine the total number of messages to search |
set totalCount of theStatusPanel to ¬ |
countMessages(mailboxesToSearch) |
-- Adjust the status panel |
tell theStatusPanel to adjustPanel() |
-- Find the messages |
set foundMessages to findMessages(mailboxesToSearch, ¬ |
whereToFind, whatToFind) |
-- Change the status panel |
tell theStatusPanel to changePanel("Adding found messages...") |
-- Add the found messages to the result table |
addMessages(foundMessages) |
-- Close the status panel |
tell theStatusPanel to closePanel() |
on error errorText |
tell theStatusPanel to closePanel() |
display alert "AppleScript Error" as critical ¬ |
attached to theWindow message errorText |
end try |
else |
display alert "Missing Value" as critical attached to theWindow ¬ |
message "You need to enter a value to search for." |
end if |
end find |
The find
handler performs the following steps:
It gets the search criteria: the contents of the search text field (the “what” field) and the title of the location pop-up (the “where” menu).
If there is no search text, it displays an error message “Missing Value”. Otherwise it performs the following steps.
It calls the controller handler
clearMessages
to clear any previous found messages in the Messages table view.It calls the
makeStatusPanel
handler to create a status dialog script object, and stores a reference to it in thetheStatusPanel
property. ThemakeStatusPanel
handler is described in Write Handlers for Working With the Status Dialog.It calls the
openPanel
handler of the status dialog script object to start displaying the panel, with the message “Determining the number of messages...” TheopenPanel
handler is described in The Status Dialog Script.It sets up an error handler (a
try…on error…end try
statement) around the statements that search for and display messages. If an error occurs, theon error
clause closes the status dialog and displays an error message. Within the handler, it performs these steps:It calls the controller handler
selectedMailboxes
to get the selected mailboxes.It calls the controller handler
countMessages
to set the total count property of the status dialog to the total number of messages to search.It calls the
adjustPanel
handler of the status dialog script object to display the number of the messages to be searched. TheadjustPanel
handler is described in The Status Dialog Script.It calls the controller handler
findMessages
(shown in Listing 9-17), passing the mailboxes to search, the search location, and the text to find.It calls the
changePanel
handler of the status dialog script object to display the message “Adding found messages...” ThechangePanel
handler is described in The Status Dialog Script.It calls the controller handler
addMessages
, to display the found messages in the search window’s message view.It closes the status dialog.
The findMessages
handler is shown in Listing 9-17. It is called from the find
handler, shown in Listing 9-16. The findMessages
handler is responsible for iterating over the specified mailboxes and finding any messages that contain the specified text in the specified location (From, To, or Contents of the message).
Listing 9-17 The controller script’s findMessages
handler
on findMessages(mailboxesToSearch, whereToFind, whatToFind) |
-- Initialize the result |
set messagesFound to {} |
tell application "Mail" |
-- Search through each of the mail boxes |
repeat with b in (get mailboxesToSearch) |
try |
-- Search through each of the messages of the mail box |
repeat with m in (get messages of b) |
try |
if whereToFind is equal to "Subject" then |
if whatToFind is in the subject of m then |
copy m to end of messagesFound |
end if |
else if whereToFind is equal to "From" then |
if whatToFind is in sender of m then |
copy m to end of messagesFound |
end if |
else if whereToFind is equal to "To" then |
set foundRecipient to false |
-- Recipients |
repeat with r in (get recipients of m) |
if whatToFind is in address of r or whatToFind ¬ |
is in display name of r then |
set foundRecipient to true |
end if |
end repeat |
-- To Recipients |
if not foundRecipient then |
repeat with r in (get to recipients of m) |
if whatToFind is in address of r or whatToFind ¬ |
is in display name of r then |
set foundRecipient to true |
end if |
end repeat |
end if |
-- cc Recipients |
if not foundRicipient then |
repeat with r in (get cc recipients of m) |
if whatToFind is in address of r or whatToFind ¬ |
is in display name of r then |
set foundRecipient to true |
end if |
end repeat |
end if |
-- bcc Recipients |
if not foundRicipient then |
repeat with r in (get bcc recipients of m) |
if whatToFind is in address of r or whatToFind ¬ |
is in display name of r then |
set foundRecipient to true |
end if |
end repeat |
end if |
if foundRecipient then |
copy m to end of messagesFound |
end if |
else if whereToFind is equal to "Contents" then |
if whatToFind is in the content of m then |
copy m to end of messagesFound |
end if |
end if |
-- Update the status panel |
tell theStatusPanel to incrementPanel() |
end try |
end repeat |
end try |
end repeat |
end tell |
-- Return the result |
return messagesFound |
end findMessages |
The findMessages
handler is similar in many ways to the find
handler. It performs the following steps:
It gets the location criteria: the title of the current choice of the search location pop-up (the “where” menu).
It targets the Mail application.
It sets up a Repeat loop for each selected mailbox. The repeat loop contains a
try…end try
error handler so that if any error occurs, the script doesn’t halt. Any error is displayed by the error handler in the calling routine (find
).It sets up a Repeat loop for each message in the mailbox. This repeat loop also contains an error handler.
Within the inner repeat loop it does the following:
It calls on the Mail application to search for the specified text in the specified location.
If a message contains the specified text, it adds it to a list of found messages.
At the end of the loop, it calls the
incrementPanel
handler of the status dialog script object to increment the count of the messages to be searched. TheincrementPanel
handler is described in Write Handlers for Working With Message Windows.
It returns the list of found messages. The list may be empty.
The find
handler (shown in Listing 9-16) also calls the following handlers. These handlers, which perform simple operations, aren’t shown in individual listings, but you can examine them in Chapter 10 or in the Mail Search sample application.
clearMessages
: Tells the data source of the Messages table view of the controller script object’s search window to delete every row, thus clearing the messages.countMessages
: Communicates with the Mail application to count the messages in each mailbox in the passed list of mailboxes. Returns the total count.addMessages
: Turns off updating in the Message table view. For each message in the passed list of messages, callsaddMessage
. Turns updating back on, so that the Messages table view displays the added messages.addMessage
: (Not called directly by thefind
handler, but called byaddMessages
.) For the passed message, adds a row to the data source for the Messages table view, then adds a cell for each column in the row, so that the row displays the From, Subject, and Mailbox information for the message.selectedMailboxes
: Gets the currently selected mailboxes from the Mailboxes outline view. If any accounts are selected, calls themailboxesForIndex
handler to get all corresponding mailboxes (both from accounts and from individual selected mailboxes) from the Mail application. If only mailboxes are selected, gets the mailboxes itself from the Mail Application. Returns the list of selected mailboxes (which may be empty).mailboxesForIndex
: (Not called directly by thefind
handler, but called byselectedMailboxes
.) Communicates with the Mail application to obtain the actual mailboxes corresponding to the currently selected mailboxes. Returns the list of selected mailboxes (which may be empty).
Opening Message Windows
Because the Mail application’s scripting support doesn’t currently allow you to open a message in a separate window, Mail Search gets the message text and displays it in its own window. This section describes the controller handlers Mail Search uses to do this.
The jumping off point for displaying messages is the openMessages
handler. It is called from the double clicked
handler for the Messages view in the Search window (the handler is shown in Listing 9-9). The Messages view currently supports only selection of single messages, so the openMessages
handler merely calls the openMessageWindow
handler to open the selected message. You could, however, modify the Messages table view in Interface Builder to allow multiple selection (see the Attributes pane in the Info window), then modify openMessages
to iterate over the current selections, calling openMessageWindow
for each selection.
The openMessageWindow
handler is shown in Listing 9-18
Listing 9-18 The controller script’s openMessageWindow
handler
on openMessageWindow() |
set clickedRow to clicked row of table view "messages" ¬ |
of scroll view "messages" of split view 1 of theWindow |
if clickedRow is greater than or equal to 0 then |
set theAccount to "" |
set theMailbox to "" |
set theSubject to "" |
set theDateReceived to "" |
set theContents to "" |
set theSender to "" |
set theRecipients to "" |
set theCCRecipients to "" |
set theReplyTo to "" |
tell application "Mail" |
set theMessage to Abstract object clickedRow of foundMessages |
set theAccount to account name of account of container of theMessage |
set theMailbox to mailbox name of container of theMessage |
set theSubject to subject of theMessage |
-- set theDateReceived to date received of theMessage |
set theContents to content of theMessage |
set theSender to sender of theMessage |
set theRecipients to address of every recipient of theMessage |
set theCCRecipients to address of every cc recipient of theMessage |
set theReplyTo to reply to of theMessage |
end tell |
set messageWindow to makeMessageWindow() |
tell messageWindow |
set messageContents to "Account: " & theAccount & return |
set messageContents to messageContents & "Mailbox: " & theMailbox & return |
if length of theSender > 0 then |
set messageContents to messageContents & "From: " & theSender & return |
end if |
if length of theDateReceived as string > 0 then |
set messageContents to messageContents & "Date: " ¬ |
& (theDateReceived as string) & return |
end if |
if length of theRecipients > 0 then |
set messageContents to messageContents & "To: " ¬ |
& theRecipients & return |
end if |
if length of theCCRecipients > 0 then |
set messageContents to messageContents & "Cc: " ¬ |
& theCCRecipients & return |
end if |
if length of theSubject > 0 then |
set messageContents to messageContents & "Subject: " ¬ |
& theSubject & return |
end if |
if length of theReplyTo > 0 then |
set messageContents to messageContents & "Reply-To: " ¬ |
& theReplyTo & return & return |
end if |
set messageContents to messageContents & theContents |
set contents of text view "message" of scroll view "message" ¬ |
to messageContents |
set title to theSubject |
set visible to true |
end tell |
end if |
end openMessageWindow |
The openMessageWindow
handler performs the following steps:
It gets the row number for the currently selected message from the Messages table view.
If there is no currently selected row (the row number is less than zero), it does nothing. Otherwise it performs the following steps.
It initializes some local variables to store message information, such as the account, mailbox, subject, and so on.
It calls on the Mail application to obtain an object representing the message at the selected row. The term
Abstract object
is a Cocoa scripting term specifying an object that is the parent for all script objects that have no other parent class.Continuing to use the Mail application, it sets local variables to message information from the message object returned in the previous step.
It calls the
makeMessageWindow
handler to create a new message window for displaying the message. ThemakeMessageWindow
handler is described in Write Handlers for Working With Message Windows.It sets another local variable to the message contents of the found message by concatenating the message information previously stored in local variables, then sets the text contents of the new message window.
It sets the title of the new window to the subject of the found message.
It sets the visible property of the new window to display it to the user.
Write Handlers for Working With Controllers
Mail Search needs several handlers for working with controllers. These handlers are not part of the controller script itself. They aren’t shown in individual listings, but you can examine them in Chapter 10 or in the Mail Search sample application.
makeController
: This handler contains the entire controller script. You’ve examined most of the handlers in this script in previous sections. ThemakeController
handler is called by thewill open
handler, shown in Listing 9-4, to create a controller script object for a search window. Since the script is the only content of themakeController
handler, calling the handler effectively returns the script object as a return result.addController
: This handler is also called by thewill open
handler, shown in Listing 9-4. It simply adds a controller to the global list of controllers.removeController
: This handler is also called by thewill close
handler, shown in Listing 9-6. It simply removes a controller from the global list of controllers by calling the utility handlerdeleteItemInList
.controllerForWindow
: This handler is called whenever a handler needs to obtain the controller for the current window. It returns the controller for the passed window from the global list of controllers.
Write Handlers for Working With the Status Dialog
Mail Search only needs one handler to work with the status dialog script, the makeStatusPanel
handler, which creates the status dialog script object. This handler is shown in full in Chapter 10. The handlers and properties it contains are described in The Status Dialog Script. Since the script is the only content of the makeStatusPanel
handler, calling the handler effectively returns the script object as a return result.
Write Handlers for Working With Message Windows
Mail Search only needs one handler to work with the message window, the makeMessageWindow
handler. This handler, shown in Listing 9-19, is called from the openMessageWindow
handler (shown in Listing 9-18.
Listing 9-19 The makeMessageWindow
handler
on makeMessageWindow() |
load nib "Message" |
set windowCount to windowCount + 1 |
set windowName to "message " & windowCount |
set name of window "message" to windowName |
return window windowName |
end makeMessageWindow |
The makeMessageWindow
performs the following steps:
It loads an instance of the Message window from the Message nib.
It increments Mail Search’s global window count property.
It constructs a name for the window.
It returns the window name.
Write Utility Handlers
Mail Search needs one utility handler, deleteItemInList
, to remove an item from a list. This handler is called by removeController
, which in turn is called by the window’s will close
handler to remove a controller before the window closes. AppleScript doesn’t currently support deleting items from lists directly, so scripters rely on a utility handler such as deleteItemInList
, shown in Listing 9-20.
Listing 9-20 Utility function to delete an item from a list
on deleteItemInList(x, theList) |
(* To Be Provided *) |
end deleteItemInList |
Copyright © 2001, 2011 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2011-01-07