Modes are typically activated by a button in the GUI. Once a mode is activated, it is responsible for gathering user input, processing the input, sending a command, and performing any error handling associated with the mode or the commands it sends. This section describes how modes are processed. The following topics are covered:
During the input gathering process, the mode allows you to perform some intermediate error checking. For example, if the user is supposed to enter a value between zero and one but enters a value outside this range, you can flag the error before continuing to collect more input. After all the inputs are collected from the user, the mode verifies the input, constructs the command, and sends the command to the kernel. If there is an exception thrown by the kernel, the mode will handle the exception. The mode processing sequence is shown in Figure 7–1.
To provide custom processing in your mode, you can overwrite many of the methods shown in Figure 7–1. If you overwrite a method, you should use the exact same prototype for your method, including the same default values that the method may have. Refer to the Abaqus GUI Toolkit Reference Guide to determine the prototype of a method.
A mode is usually activated by sending it a message with its ID set to ID_ACTIVATE and a type of SEL_COMMAND. This message causes the activate method of the mode to be called. For more information, see “Targets and messages,” Section 6.5.4.
If you need to do any processing before a mode begins to collect input from the user, you can redefine the activate method. For example, you can check that the current viewport contains a part before beginning a mode that requires the user to pick something on a part, as shown in the following method:
def activate(self): if getDisplayedObjectType() == PART: AFXForm.activate(self) else: showAFXErrorDialog(getAFXApp().getAFXMainWindow(), 'A part must be displayed in the \ current viewport.')
If you write your own activate (or deactivate) method, you must call the base class version of that method if no error conditions are encountered. The base class methods perform additional processing necessary to make the mode function properly.
After a mode is activated, it cycles through a sequence of events collecting inputs from the user and verifying the inputs. After the user commits each step or dialog box, the mode calls the following methods:
verifyCurrentKeywordValues
The verifyCurrentKeywordValues method calls the verify method for each keyword associated with the current step or dialog box, and the method posts an error dialog box if necessary. The verifyCurrentKeywordValues method returns True if no errors were encountered; otherwise, it returns False and terminates further processing.
doCustomChecks
The doCustomChecks method has an empty implementation in the base class. You can redefine this method to perform any additional checking of keyword values, typically to perform range checking or to check some interdependency between values. The doCustomChecks method should return True if no errors were encountered; otherwise, it should return False so that further command processing will be terminated. The doCustomChecks method is called by the mode during step and dialog box processing and during command processing.
When the mode finishes collecting inputs from the user, it calls a series of methods. If needed, you can redefine some of the methods to customize the behavior of the mode. The following list describes each of the methods called by the mode:
verifyKeywordValues
The verifyKeywordValues method calls the verify method for each keyword of each command associated with the mode and posts an error dialog box if necessary. The verifyKeywordValues method returns True if no errors were encountered; otherwise, it returns False and terminates further command processing.
doCustomChecks
The doCustomChecks method has an empty implementation in the base class. You can redefine this method to perform any additional checking of keyword values, typically to perform range checking or to check some interdependency between values. The doCustomChecks method should return True if no errors were encountered; otherwise, it should return False so that further command processing will be terminated. The doCustomChecks method is called by the mode during step and dialog box processing and during command processing.
The following example shows how you can use the doCustomChecks method to find an invalid value and, in response, to post an error dialog box and put the cursor into the appropriate widget. If the keyword is connected to a text field in the dialog, the onKeywordError method finds the text field widget, select its contents, and places the focus on the widget.
def doCustomChecks(self): if self.lengthKw.getValue() >= 1000: showAFXErrorDialog(self.getCurrentDialog(), 'Length must be less than 1000.') self.getCurrentDialog().onKeywordError(self.lengthKw) return False
issueCommands
The issueCommands method is responsible for constructing the command string, issuing it to the kernel, handling any exceptions from the command, and deactivating the mode if necessary. The issueCommands method calls the following methods:
getCommandString: This method returns a string that represents the commands collected from each command associated with the mode. Required keywords are always sent with the command, but optional keywords are sent only if their value has changed. The commands are issued to the kernel in the same order as the commands were constructed in the mode. If your command does not fit the standard style of the command generated by the mode, you can redefine this method to generate your own command string.
sendCommandString: This method takes the command string returned from the getCommandString method and sends it to the kernel for processing. You should not overwrite this method or your mode may not perform properly.
doCustomTasks: This method has an empty implementation in the base class. You can redefine this method to perform any additional tasks required after a command is processed by the kernel.
The issueCommands method also controls the writing of the command to the replay and journal files. The GUI infrastructure always calls issueCommands with writeToReplay=True and writeToJournal=False. If you want to change the behavior, you can overwrite this method and specify different values for the arguments. If you overwrite the issueCommands method you must specify both arguments, and you should always call the base class method from your method or your mode may not perform properly. For example:
def issueCommands(self, writeToReplay, writeToJournal): AFXForm.issueCommands(self, writeToReplay=True, writeToJournal=True)
In most cases, you do not need to call issueCommands since the infrastructure will call it automatically; however, if you interrupt the normal flow of mode processing, you must call issueCommands to complete the processing. For example, if before issuing a command you want to ask the user for permission to execute the command, you can post a warning dialog box from the doCustomChecks method. In this example you must return False from the doCustomChecks method to stop the command processing. The application will then wait for the user to make a selection from the warning dialog box. When the user clicks a button in the warning dialog box, you must catch the message sent by the dialog box to your form. If the user clicks Yes, you should continue the command processing as shown in the following example:
class MyForm(AFXForm): ID_OVERWRITE = AFXForm.ID_LAST def __init__(self, owner): AFXForm.__init__(self, owner) FXMAPFUNC(self, SEL_COMMAND, self.ID_OVERWRITE, MyForm.onCmdOverwrite) ... def doCustomChecks(self): import os if os.path.exists(self.fileNameKw.getValue()): db = self.getCurrentDialog() showAFXWarningDialog(db, 'File already exists.\n\nOK to overwrite?', AFXDialog.YES|AFXDialog.NO, self, self.ID_OVERWRITE) return False return True def onCmdOverwrite(self, sender, sel, ptr): if sender.getPressedButtonId() == \ AFXDialog.ID_CLICKED_YES: self.issueCommands(writeToReplay=True, writeToJournal=True) return 1
Normally the GUI infrastructure takes care of sending commands to the kernel automatically when the mode is committed. If you need to issue a command before the mode is committed, you can call issueCommands yourself. In other cases you may want to send a command without using the form's infrastructure. You can send a command string directly to the kernel using the sendCommand(cmd) method. For more information, see “Executing commands,” Section 6.3.
deactivate
After the mode has issued its commands successfully, it will call the deactivate method to perform various cleanup tasks, unless the mode loops or an “Apply” button was pressed, in which case the mode returns to wait for further input from the user. If you need to perform your own cleanup tasks for your mode, you can overwrite this method; but you should be sure to call the base class method as well to ensure that the mode is terminated properly as shown in the following example.
def deactivate(self): # Do your processing here # Call the base class method AFXForm.deactivate(self)
cancel
If you need to cancel a mode programmatically, as opposed to the user clicking on a Cancel button, you can call the mode's cancel method, taking the default values for its arguments. The cancel method will call the deactivate method, so the mode's cleanup tasks will still be performed.
If you want to give the user a chance to confirm whether a mode should be cancelled, you can have a bailout dialog invoked. If you are writing a form mode, you can specify the bailout flag in the constructor of your dialog box. If you are writing a procedure mode, you should write the checkCancel method. The return value of the checkCancel method determines if the user will be prompted for confirmation when the procedure is cancelled. For example:
def checkCancel(self): if self.getCurrentStep() == self.step1: # If cancelled in the first step, do not # ask the user for confirmation to cancel. return AFXProcedure.BAILOUT_OK else: # After the first step, ask the user for # confirmation before cancelling. return AFXProcedure.BAILOUT_NOTOK
By default when the context changes in Abaqus/CAE, all forms are cancelled; for example, when the user opens a new database or changes the current model. If you have a form mode that you do not want to be cancelled, you can overwrite the base class implementation in your form code as follows:
def okToCancel(self): return False
If the command sent to the kernel takes more than a certain amount of time (approximately one second), the GUI will lock and the busy cursor will be displayed. If you want to provide additional feedback about the progress of your command, you can add work-in-progress commands to your kernel code. For more information, see “Status commands,” Section 53.6 of the Abaqus Scripting Reference Guide.
The following statements illustrate how you can use the milestone command to provide feedback on the progress of a volume computation:
numObjects = 4 for i in range(numObjects+1): milestone('Computing total volume', 'parts', i, numObjects) ... compute volume here ...
If the command sent to the kernel raises an exception, the mode infrastructure calls the handleException method. The handleException posts an error dialog with the message contained in the exception. Alternatively, if you want to perform your own error handling, you can redefine the handleException method, as shown in the following example:
def handleException(self, exception): exceptionType = exception[0] exceptionValue = exception[1] # Do some special error handling here # Post an error dialog # db = self.getCurrentDialog() showAFXErrorDialog(db, str(exceptionValue))