This topic describes progress notification, or messaging, in the ENVI API. See the following sections:
Background
ENVI uses a broadcast channel to manage messages in the API. Anyone can subscribe to the broadcast channel to listen for specific messages, or to broadcast a message that will transmit to all of the subscribers. The subscribers can decide whether or not to act on a message they receive.
The ENVI user interface subscribes to the broadcast channel and listens for the following messages:
It only acts on these messages if the first one sent is ENVIStartMessage, in which case it displays a progress dialog showing the status of data processing. The ENVI user interface must be initialized. As it receives messages about processing status, it updates the progress dialog accordingly. It dismisses the progress dialog once it receives an ENVIFinishMessage. The user interface ignores any other messages that are sent to the broadcast channel.
To allow end users to cancel (abort) processes, the code should include an ENVIAbortable object. This adds a Cancel button to the progress bar that displays during a running process. If the user clicks the Cancel button, the ABORT_REQUESTED property of ENVIAbortable is set to 1 (true). The code that sent the ENVIStartMessage checks the status of the ABORT_REQUESTED property. When it sees that the property is set to 1, it dismisses the progress dialog.
Example: Check if an Abort was Requested
The following code example sends a start message to the ENVI broadcast channel, performs 73 arbitrary "steps", and checks for messages that the end user cancelled the process. Copy this code into a new window in the IDL Editor, then save it to a file named ProgressBarAbortExample.pro. Compile and run the program. If you click the Cancel button in the progress dialog, note the number of steps that complete.
This example demonstrates how all of the ENVI API messaging components work together. It simulates an analytic operation and updates its progress in a progress bar and in the IDL console.
PRO ProgressBarAbortExample
COMPILE_OPT idl2
e = ENVI()
Channel = e.GetBroadcastChannel()
Abort = ENVIAbortable()
Start = ENVIStartMessage('Progress Bar Title', Abort)
Channel.Broadcast, Start
nSteps = 73
Progress = ENVIProgressMessage('Executing Progress Message', $
0, Abort)
FOR stepIndex=0, nSteps DO BEGIN
percentProgress = Round(stepIndex* 100.0/nSteps)
Progress.Percent = percentProgress
Channel.Broadcast, Progress
IF (Abort.Abort_Requested) THEN BREAK
dataProcess = dist(1000)
PRINT, stepIndex
ENDFOR
Finish = ENVIFinishMessage(Abort)
Channel.Broadcast, Finish
END
Custom Tasks with Messaging
If you are writing a custom task and want to include a progress bar with an option to abort the process, reference the ENVIAbortableTaskFromProcedure base class in your task. In the IDL routine that contains the data processing code, set the ABORTABLE keyword to ENVIStartMessage. When ENVITask::Execute is called on the custom task, an ENVIAbortable object is automatically created that sends an abort message to the user interface if the end user clicks the Cancel button on the progress dialog.
If ENVI is running in batch mode, it ignores these messages because the user interface is not initialized. Progress dialogs should not be invoked in a headless environment.
Example: Subscribe to Messages
To write a script that listens to broadcast messages, use the ENVIMessageHandler and ENVIMessageHandler::OnMessage method. When the script runs, it subscribes to the system's broadcast channel. Anything that sends a message using the ENVIBroadcastChannel Broadcast method is automatically sent to the OnMessage method for further action.
The following example uses the OnMessage method to listen for ENVIStartMessage, ENVIProgressMessage, and ENVIFinishMessage. When it receives these messages, it prints updates to the IDL Console. Follow these steps:
- Copy the following code and paste it into a new file named ConsoleMonitorExample__Define.pro. Save the file in the custom_code folder of your ENVI installation path. If you do not have write permission for this path, see Toolbox Extensions for other options on deploying custom code.
FUNCTION ConsoleMonitorExample::Init
COMPILE_OPT IDL2, hidden
IF (~self.ENVIMessageHandler::Init()) THEN BEGIN
RETURN, 0
ENDIF
e = ENVI(/CURRENT)
oChannel = e.GetBroadcastChannel()
oChannel.Subscribe, self
RETURN, 1
END
PRO ConsoleMonitorExample::Cleanup
COMPILE_OPT IDL2, hidden
self.ENVIMessageHandler::Cleanup
e = ENVI(/CURRENT)
oChannel = e.GetBroadcastChannel()
IF (Obj_Valid(oChannel)) THEN BEGIN
oChannel.Unsubscribe, self
ENDIF
END
PRO ConsoleMonitorExample::OnMessage, oMsg
COMPILE_OPT IDL2, hidden
CASE (1) OF
Isa(oMsg,'ENVISTARTMESSAGE'): BEGIN
PRINT, 'Start ', oMsg.message
END
Isa(oMsg,'ENVIPROGRESSMESSAGE'): BEGIN
PRINT, ' ', 'Percent Complete:', oMsg.percent, '%'
END
Isa(oMsg,'ENVIFINISHMESSAGE'): BEGIN
PRINT, 'Finish'
END
ELSE: BEGIN
RETURN
END
ENDCASE
END
PRO ConsoleMonitorExample__define
COMPILE_OPT IDL2
!NULL = {ConsoleMonitorExample, $
inherits ENVIMessageHandler}
END
- Copy and paste the following code into a new file named BroadcastSubscribeExample.pro. This program sends messages for the console monitor to listen. Save the file in the custom_code folder of the ENVI installation path.
PRO broadcastSubscribeExample_Broadcaster
COMPILE_OPT IDL2
e = ENVI(/CURRENT)
oChannel = e.GetBroadcastChannel()
oAbort = ENVIAbortable()
oStart = ENVIStartMessage('MyTask', oAbort)
oChannel.Broadcast, oStart
nSteps = 10
oProgress = ENVIProgressMessage('Executing Progress Message', $
0, oAbort)
oChannel.Broadcast, oProgress
FOR stepIndex=0, nSteps DO BEGIN
percentProgress = stepIndex* 100.0/nSteps
oProgress.Percent = percentProgress
oChannel.Broadcast, oProgress
IF (oAbort.Abort_Requested) THEN BREAK
dataProcess = dist(1000)
ENDFOR
oFinish = ENVIFinishMessage(oAbort)
oChannel.Broadcast, oFinish
END
- Copy the following code into the IDL command line to run the example:
e = ENVI(/HEADLESS)
oConsoleMonitor = ConsoleMonitorExample()
broadcastSubscribeExample_Broadcaster