Previous Next

Bean Works Tutorial

Step 3: Enabling undo and redo

Hello3 expands on Hello2 by giving your end user the ability to undo and redo changes made to the component, in this case, changing the string contained by the component's model. You enable undo and redo by using the command processing mechanism to effect any changes to the component. Hello3 implements a new class, StringCommand, that is used to reset the model's string field. The view creates a command and submits it to the component's command processor to be executed. The command processor is constructed and maintained by the component's controller. You don't need to do any work to build or activate the command processor--just use the framework defaults.

Using the command processing mechanism automatically causes the controller to enable the Undo and Redo functions in the component toolbar and Edit menu. The Undo function is enabled as soon as the user has issued at least one undoable command. The Redo function is enabled when the user has undone that command. The controller also creates customized menu items for Undo and Redo, based on the label you provide when you create each command:

Generating Hello3 code with the wizard

Hello3 source code

StringCommand.java
Hello3View.java
Hello3Model.java
Hello3.java
Hello3Resources.java
Hello3BeanInfo.java

You build and run Hello3 using wizard-generated batch files, as described in Step 1.


Generating code with the wizard

To generate the code for Hello3, use the wizard to create a new project named Hello3. Follow the instructions in Step 2 to set up the model and view.

You also need to generate the basic code for StringCommand. To do this:

  1. Select the Commands tab.
  2. Type "String" in the Command Name field
  3. Press the Add Command button to add the command to the project.

The wizard appends "Command" to the string you typed in the name field. For example, if you type in "String," it generates a command named "StringCommand".

You're ready now to generate the code from the code generation screen. The wizard generates StringCommand, Hello3Model, Hello3View, Hello3, and Hello3Resources, plus the WizGen.java and batch files. Press the Generate All Files button to generate the files.


Hello3 source code

The source code shown here differentiates between code generated by the wizard, and code you add or modify. Wizard-generated code is shown in green.

See WebRunner\BeanTools\samples\hello3 for full source code files for each class. The source code shown here does not show the comments generated by the wizard. Do NOT remove these comments from the source code files or you won't be able to reopen the project with the wizard.

StringCommand.java

To implement a command, you need to:

By default commands are serially undoable. This means that the user can both undo and redo commands in the order in which they were originally executed. You can also create commands that specifically cannot be undone, or that are not maintained within the command log (for example, commands that do not cause a change in model data). Pass one of the variables kCantUndo or kNoChange to create one of these types of commands.

Extend the default command class
public class StringCommand extends Command implements WizGen {
Build a command with the new string for the specified model, getting the command label from the resource file
public StringCommand(Hello3Model model, String string) {
    ResourceBundle resources = ResourceBundle.getBundle("hello3.Hello3Resources");
    setLabel(resources.getString("String Change"));
    this.model = model;
    this.string = string;
}
Saves the current string and performs the change
protected void handleDo() {
    oldString = model.getString();
    handleRedo();
}
Sets the string back to the data saved by handleDo
protected void handleUndo() {
    model.setString(oldString);
}
Redoes the command
protected void handleRedo() {
    model.setString(string);
}
Data used for undo and redo
private Hello3Model model;
private String string;
private String oldString;
}

(Top of page)

Hello3View.java

The only difference between Hello2View and Hello3View is in the keyReleased method. In Hello3View, the keyReleased method creates a StringCommand to encapsulate the correct change to the model. To create the command object, it passes in:

To add the command to the command processor for execution, call the component controller's addAndDo method.

View methods for initialization, notification and event handling
public class Hello3View extends ModelView implements WizGen, KeyListener {
public Hello3View() {
    textField = new TextField(30);
    add(textField);
    textField.addKeyListener(this);
}
public void handleModelChange(ModelChangeEvent event) {
    super.handleModelChange(event);
    repaint();
}
public void handleModelSelectionChange(ModelChangeEvent event) {
    repaint();
}
public void paint(Graphics g) {
    Hello3Model model = (Hello3Model)getModel();
    g.drawString(model.getString(), 10, 50);
}
public Dimension getPreferredSize() {
    return new Dimension(400, 300);
}
public void keyTyped(KeyEvent evt) {
}
public void keyPressed(KeyEvent evt) {
}
When the user presses the enter (return) key, create a StringCommand with the input string, and send it to the command processor
public void keyReleased(KeyEvent evt) {
    if (evt.getKeyChar() == '\n') {
        getComponentController().addAndDo(new StringCommand
            ((Hello3Model)getModel(), textField.getText()));
    }
}
Data field used in the UI
private  TextField textField; 
}

(Top of page)

Hello3Model.java

Hello3Model is essentially identical to Hello2Model, providing methods for accessing and persisting the model's string data field.

Hello3Model
public class Hello3Model extends Model implements WizGen {
public Hello3Model() {
    string = "Hello World!";
}
public String getFileExtension() {
    return "hl3";
}
public String getString() {
    return string;
}
public void setString(String string) {
    this.string = string;
    setModelChanged(true);
    notifyOfModelChange(null);
}
private  String string;
}

(Top of page)

Hello3.java

The controller for Hello3 components is the same as the Hello2 controller, creating Hello3Model and Hello3View objects, and reading in the resources specified by Hello3Resources.

Set up a Hello3 component
public class Hello3 extends ComponentController implements WizGen, KeyListener {
public Hello3() {
	try	{
		setResourceBundle(ResourceBundle.getBundle("hello3.Hello3Resources"));
	}
	catch (MissingResourceException e) {
		new ExceptionDialog(null, "Can't find resource file", e);
	}
    setModel(new Hello3Model());
    setView(new Hello3View());
}
public static void main(String args[]) {
    setApplicationMain(true);
    new Hello3();
}
public void keyTyped(KeyEvent evt) {
    ((KeyListener)getView()).keyTyped(evt);
}
public void keyPressed(KeyEvent evt) {
    ((KeyListener)getView()).keyPressed(evt);
}
public void keyReleased(KeyEvent evt) {
    ((KeyListener)getView()).keyReleased(evt);
}
public String getString() {
    return ((Hello3Model)getModel()).getString();
}
public void setString(String string) {
    ((Hello3Model)getModel()).setString(string);
}
}

(Top of page)

Hello3Resources.java

Hello3Resources is almost identical to the resources file for Hello2, but uses the component name "Hello3" and the file extension "hl3".

Component name and command label for Hello3 components
public class Hello3Resources extends ListResourceBundle {
public Object[][] getContents() {
    return contents;
}
static final Object[][] contents =
{
    {"Application", "Hello3"},
    {"String Change", "String Change"},    
};
};

(Top of page)

Hello3BeanInfo.java

This file is generated to allow user to change the property, method, and event descriptors which are displayed in a visual builder. By default, everything is displayed to the developer inside a builder or a tester like the Bean Tester.


Previous Next

Copyright © Taligent, Inc. 1996 - 1997.
Copyright
© IBM Corporation 1996 - 1997.
All Rights Reserved.