HowTos - Display: FormSheet

Create a FormSheet

Description:
Although it is quite easy to initialize and display a FormSheet, it is a bit difficult to describe how to do it because of the vast opportunities to display them and the many possibilities to use the FormSheets and combine them with Components or even JComponents.
The first thing you should do before you create your own FormSheet is to consult the framework API and take a closer look at FormSheet. There you will find all methods and of course the subClasses of FormSheet, like the LogOnForm, the MsgForm or the TableForms, which are all specialized FormSheets of great use.
Talking about the elements, every FormSheet needs a caption, which is normally defined by calling the constructor and at least some JComponents to display. These can be put together either by a FormSheetContentCreator or by creating and overwriting methods within a new FormSheet instance before or using it's methods during runtime.
It is though recommended to use the ContentCreator as shown in this example, for it is able to serialize the Components and all their properities, esp. their behaviour, which will be lost if you just use FormSheet methods and serialize the Shop's status.

Used classes:

Related topics:

ToDo:

  1. Instantiate a subclass of FormSheetContentCreator.
  2. Add the constructor and call the superclass to inherit its methods.
  3. Add the protected void createFormSheetContent(FormSheet fs) method and therein add/remove your components to the FormSheet.
  4. Add the FormSheetContentCreator to your FormSheet class by calling the method addContentCreator(FormSheetContentCreator or by initializing in the constructor.

Example Source Code:

FormSheetContentCreator class:

1
public class DisplayFormSheetContentCreator extends FormSheetContentCreator
{
			
    2
    public DisplayFormSheetContentCreator()
    {
        super();
    }
			
    3
    protected void createFormSheetContent(FormSheet fs)
    {
        // add/remove your components here
        fs.removeAllButtons();
        fs.addButton("TutorialButton", 1, new ArchitectureCustomAction());
    }
}
		

Class that uses a FormSheet:

4
// adding the FormSheetContentCreator in FormSheet constructor
        FormSheet fs = new FormSheet("DisplayFormSheet",
                new DisplayFormSheetContentCreator(),
                false);
			
// adding the FormSheetContentCreator by using the addContentCreator method
        SingleTableFormSheet fs = SingleTableFormSheet.create(
                "DisplayFormSheet",
                catalog,
                uigate);
        fs.addContentCreator(new DisplayFormSheetContentCreator());
		

Back to:


Define a FormSheet for a SalesPoint

Description:
The recommended way to define a FormSheet for a SalesPoint is to redefine the method getDefaultFormSheet() of your Salespoint instance, which is used by the Framework to resolve the FormSheet which shall be displayed at that SalesPoint. You may also add a FormSheet during runtime by using the method setFormSheet(SaleProcess sp, FormSheet fs). As you can see, this method is also used to add a SalesProcess to the SalesPoint, which itself is able to display FormSheets.
This example describes how to add a FormSheet to the SalesPoint, while the FormSheet itself should be assembled in a FormSheetContentCreator.

Used classes:

Related topics:

ToDo:

  1. Redefine the method getDefaultFormSheet() in the SalesPoint class.
  2. Return the FormSheet you want to use.

Example Source Code:

public class DisplaySalesPoint extends SalesPoint
{
    public DisplaySalesPoint(String sName)
    {
        super(sName);
    }
			
    1
    protected FormSheet getDefaultFormSheet()
    {
        2
        return new FormSheet("DefaultFormSheet",
                new DisplayFormSheetContentCreator(), false);
    }
}
		

Back to:


Define a StatusFormSheet for a SalesPoint

Description:
SalesPoints are being displayed in a separate window but also have a StatusDisplay at the Shop, which is the TabbedPane in the Shop's Frame, labled the name of the SalesPoint. By bringing it on top, it shows what is defined as the StatusDisplay in your SalesPoint instance and also adds the Menu defined as StatusMenuSheet in the SalesPoint instance to the Shop's MenuSheet. By default, both, the StatusFormSheet and the StatusMenuSheet are empty.
Feel free to use the StatusDisplay and MenuSheet, which are equally handled to the DefaultFormSheet and the DefaultMenuSheet except that due to the strong division of the Shop and it's SalesPoints it is not possible to have processes running on it. You may trigger a Processes on it, but they will always be displayed by the SalesPoint's window. Therefor a more suitable name would be "Statical Display". For further information on Processes refer to the section "Processes".
This example describes how to define a FormSheet as the SalesPoint's StatusFormSheet, while the FormSheet itself should be assembled in a FormSheetContentCreator.

Used classes:

Related topics:

ToDo:

  1. Redefine the method getDefaultStatusFormSheet() in the SalesPoint class.
  2. Return the FormSheet you want to use.

Example Source Code:

public class DisplaySalesPoint extends SalesPoint
{
    public DisplaySalesPoint(String sName)
    {
        super(sName);
    }
			
    1
    protected FormSheet getDefaultStatusFormSheet()
    {
        2
        return new FormSheet("StatusFormSheet",
                new DisplayFormSheetContentCreator(), false);
    }
}
		

Back to:


Change the standard OK or CANCEL button behaviour

Description:
A FormSheet initially has two buttons, one labeled "ok" and one with "cancel" on it. But they don't do anything by default, so you have to define their behaviour. There are mainly three ways to define the behaviour of the buttons. One is to create your own FormSheet and implement the methods ok() and cancel() and the other one is to remove the buttons and add your own ones with a FormSheetContentCreator. The second one is more commonly used, because it is less effort to add two buttons instead of creating lots of new FormSheets just to define the behaviour of a single click on a button.
The third one is almost as common but due to the lack of influence on the button's look and feel less used. It's because here you only set an action to the standard button by resolving it with getButton(int id) and using setAction(Action action) on it. The button's ids are stored as static int in the FormSheet, where BTNID_CANCEL stands for the cancel button and BTNID_OK for the ok button.
In order to make the behaviour serializable you have to define it within a FormSheetContentCreator. Otherwise the information will be lost after loading. It is also possible to alter the buttons design and caption when adding new ones.

Used classes:

Related topics:

ToDo:

  1. Initialize a new FormSheet.
  2. Create a new FormSheetContentCreator for the FormSheet and add it.
  3. In the protected void createFormSheetContent(FormSheet fs) method of the FormSheetContentCreator remove the OK-Button by calling removeButton(int id).
  4. Add a new FormButton using the addButton method. Like here you can shortly add an sale.Action to the button.
    (See also: ).
  5. Set a new sale.Action to the CANCEL-Button by fetching it with the getButton(int id) method and setting the action with setAction(Action).
    (See also: ).

Example Source Code:

class where FormSheet is set:

 
        1
        FormSheet sheet = new FormSheet("DisplaySheet", null);
			
	2
        sheet.addContentCreator(new DisplayFormSheetContentCreator());
		

FormSheetContentCreator class:

 
2
public class DisplayFormSheetContentCreator extends FormSheetContentCreator
{
			
    3
    protected void createFormSheetContent(FormSheet fs)
    {
        fs.removeButton(FormSheet.BTNID_OK);
			
        4
        fs.addButton("Ok", 102, new DisplayCustomAction());
			
        5
        fs.getButton(FormSheet.BTNID_CANCEL).setAction(new DisplayCustomAction());
			
    }
}
		

Back to:


Define an Action for a FormSheet Button

Description:
The reason for adding buttons to your application is of course to let the user interact with it.
By default, buttons don't have any functions, so you have to add a sale.Action to the button either by the method setAction(Action aAction) provided by the button or by already initializing the button with an action.
Remember to put all this into a FormSheetContentCreator in order to have the Actions serialized as you save the Shop's status. Otherwise all the information will be lost after loading and the buttons will be useless.

Used classes:

Related topics:

ToDo:

  1. There are two ways of defining an Action:
    1. Create a class implementing the interface Action and add the public void doAction(SaleProcess process, SalesPoint point) throws Throwable method to it. Therein define what to do if the action was called.
    2. Create an anonymous implementation of Action and define what to do if triggered.

Example Source Code:

 
1 a
public class DisplayCustomAction implements Action
{
			
    public void doAction(SaleProcess process, SalesPoint point) throws Throwable
    {
    // define what shall be done when triggering the action
        point.runProcess(new DisplaySaleProcess("SampleProcess"));
    }
}
			
1 b
public class DisplaySalesPoint extends SalesPoint
{
			
    protected FormSheet getDefaultFormSheet()
    {
			
        FormSheet fs = new FormSheet("FormSheet", null);
        fs.getButton(FormSheet.BTNID_OK).setAction(
                new Action()
                {
                    public void doAction(SaleProcess process, SalesPoint point) throws Throwable
                    {
                        // define what shall be done when triggering the action
                        point.runProcess(new DisplaySaleProcess("SampleProcess"));
                    }
                });
    }
}
        

Back to:


Define an Action for a Button in a Component

Description:
Sometimes you will need to add Buttons in the component part of a FormSheet, since the Button bar at the bottom may be not sufficient (e.g. too small). This has to be done within a FormSheetContentCreator when serialization is needed.

Used classes:

Related topics:

ToDo:

  1. Create a new FormSheetContentCreator with the standard constructor and add the createFormSheetContent() method.
  2. Create the JButton according to your needs.
  3. Associate the Action that should be executed when clicking with the Button. This is done with the ActionActionListener, that takes the Action itself aswell as the FormSheet that contains the button.
  4. Add the button to the FormSheet component. In this case this is done by creating a container for the button and setting it as FormSheet component. You could also use the getComponent() method of the FormSheet and manipulate the component directly (e.g. if it is already a special FormSheet).

Example Source Code:

1
public class DisplayFormSheetContentCreator extends FormSheetContentCreator
{
    public DisplayFormSheetContentCreator()
    {
        super();
    }
    protected void createFormSheetContent(FormSheet fs)
    {
        2
        JButton button = new JButton("TutorialButton");
        3
        button.addActionListener(new ActionActionListener(fs, new DisplayCustomAction()));
        4
        JPanel container = new JPanel();
        container.add(button);
        fs.setComponent(container);
    }
}
        

Back to:


Set error handling for a FormSheet

Description:
According to the type of FormSheet you use (and the purpose you use them for), it could be useful to react on errors occurring in different ways. So it is, for example, not always senseful to stop the currently running process, whenever an error occurs if you are able to correct it programatically.

Most of the FormSheets use their own strategies for handling their tasks. Here you can setup the error handlers.

Used classes:

Related topics:

ToDo:

  1. Create a new FormSheetContentCreator with the standard constructor and add the createFormSheetContent() method.
  2. Get the FormSheet of the type you need. In our case we assume, we've been given a TwoTableFormSheet and therefore can use it's strategy.
  3. Set the error handler you need. Basically, there are three possibilities:
    1. If the process has to be aborted immediately and an error message has to be displayed for the user, you can use the FormSheetStrategy.DEFAULT_ERROR_HANDLER. This is also set by default, so normally you don't have to do anything in this case.
    2. If the process can be continued, but a popup dialog shall be used displaying the error message for the user, you can use the FormSheetStrategy.MSG_POPUP_ERROR_HANDLER.
    3. In any other case, you will have to implement your own ErrorHandler.

Example Source Code:

1
public class DisplayFormSheetContentCreator extends FormSheetContentCreator
{
    public DisplayFormSheetContentCreator()
    {
        super();
    }
    protected void createFormSheetContent(FormSheet fs)
    {
        2
        TwoTableFormSheet ttfs = (TwoTableFormSheet) fs;
        3 a
        ttfs.getStrategy().setErrorHandler(FormSheetStrategy.DEFAULT_ERROR_HANDLER);
        3 b
        ttfs.getStrategy().setErrorHandler(FormSheetStrategy.MSG_POPUP_ERROR_HANDLER);
        3 c
        ttfs.getStrategy().setErrorHandler(new FormSheetStrategy.ErrorHandler() {
            public void error(SaleProcess p, int nErrorCode) {
                System.out.println(p.getErrorMsg(nErrorCode));
            }
        });
    }
}
        

Back to:


Standard FormSheet tasks

Description:
As described in "Create a FormSheet", SalesPoint provides you with a vast collection of standard FormSheets that are able to take care of most of the tasks that will occur in your application. We will now have a closer look at some tasks and how to solve them.

Related topics:

Display contents of containers:
Containers are all kinds of Catalogs, Stocks, user lists and DataBastkets that are registered in your Shop. In order to display them, you can use a SingleTableFormSheet:

        SingleTableFormSheet fs = SingleTableFormSheet.create(
                "DisplayFormSheet",
                catalog,
                uigate);
        fs.addContentCreator(new DisplayFormSheetContentCreator());
		

You can use any of the container types mentioned above by using the appropriate static create(...) method of the SingleTableFormSheet.

Add items to or remove items from containers:
Adding or removing items is a bit more complicated than simply displaying them. In this example, we will concentrate on adding and removing items in a catalog.

  1. Create a SingleTableFormSheet as needed. Make sure to give the FormSheet exactly the same DataBasket that is currently used. If you are in process, you can simply use it's getBasket() method. If you don't, there will be no valid display update when changes on the container are performed.
  2. Add a new FormSheetContentCreator.
  3. If adding items is needed:
    1. Create an appropriate EditButtonStrategy:
      • If you wish to add items to a catalog, you can use the AbstractAddCatalogItemStrategy class. Then you simply have to override it's createCatalogItem() method according to your needs and the type of CatalogItem you need.
      • If you wish to add items to another container, you will have to create your own EditButtonStrategy. You can have a look at the AbstractAddCatalogItemStrategy as an example.
    2. Add the button to the FormSheet. Therefore we have to cast the FormSheet given to a SingleTableFormSheet.
  4. If deleting items is needed:
    1. Create an appropriate EditButtonStrategy:
      • If you wish to remove items from a catalog, you can simply use the DefaultRemoveCatalogItemStrategy class. No additional implementations are needed.
      • If you wish to remove items from another container, you will have to create your own EditButtonStrategy. You can have a look at the DefaultRemoveCatalogItemStrategy as an example.
    2. Add the button to the FormSheet. Therefore we have to cast the FormSheet given to a SingleTableFormSheet.
// The catalog item needed
public class DisplayCatalogItem extends CatalogItemImpl {
    public DisplayCatalogItem(String sName) {
        super(sName);
        setValue(new DoubleValue(100.0d));
    }

    protected CatalogItemImpl getShallowClone() {
        return null;
    }
}
		
 		
        1
        SingleTableFormSheet fs = SingleTableFormSheet.create(
                "DisplayFormSheet",
                catalog,
                uigate);
        2
        fs.addContentCreator(new FormSheetContentCreator() {
            protected void createFormSheetContent(FormSheet fs) {
                3 a
                EditButtonStrategy ebs = new AbstractAddCatalogItemStrategy(catalog) {
                    protected CatalogItem createCatalogItem(String sKey) {
                        return new DisplayCatalogItem(sKey);
                    }
                };
                3 b
                ((SingleTableFormSheet) fs).addAddButton(ebs);
                4 a
                ebs = new DefaultRemoveCatalogItemStrategy(catalog);
                4 b
                ((SingleTableFormSheet) fs).addRemoveButton(ebs);
            }
        });
		


Move items between containers:
In order to move items between containers, you can use the TwoTableFormSheet, that has been designed especially for this kind of task. Therefore you choose a source and a destination container. The FormSheet can move items between them in both directions, depending on how you wish to use it. There are exactly eleven possible combinations of source and destination containers:

Source Destination Default MoveStrategy
CountingStock CountingStock CSCSStrategy
StoringStock StoringStock SSSSStrategy
CountingStock DataBasket CSDBStrategy
DataBasket CountingStock DBCSStrategy
StoringStock DataBasket SSDBStrategy
DataBasket StoringStock DBSSStrategy
Catalog Catalog CCStrategy
Catalog DataBasket CDBStrategy
DataBasket Catalog DBCStrategy
Catalog StoringStock CSSStrategy
Attention: You need to override the createStockItem() method, as it is application dependent.
Catalog CountingStock CCSStrategy

You can refer to the individual documentations on how they exactly work. When creating the TwoTableFormSheet, simply use the create() that you need (giving null as DataBasket means the FormSheet will work outside any transitional context, causing all data manipulations to be executed immediately, without any rollback possibilities).

    private FormSheet getMoveContentFormSheet(UIGate uigate, Catalog cSource, Catalog cDest)
    {
        TwoTableFormSheet ttfs = TwoTableFormSheet.create("Title", 
                    cSource, cDest, (DataBasket)null, uigate, TwoTableFormSheet.RIGHT);
        return ttfs;
    }
		

Back to:


Update a formsheet display

Description:
A common problem is notifying FormSheets that the data, or at least a part of it, has been changed by some process. Now it shall display the new data.
The solution for this task is to use DataBaskets in the right way. You do not tell the formsheet that it shall update itself, rather you tell the modified data element to notify all it's listeners to update all their necessary parts (e.g. table cells).

Used classes:

Related topics:

ToDo:

  1. Create a new DataBasket.
  2. Retrieve the CatalogItem relative to the DataBasket and tell the get method to prepare the item for editing. After that you can manipulate it in any way you want.
  3. Call the DataBasket's commit method. This will put the updated item back in the container appropriately and tells all listeners such as visual display components to update themselves.

Example Source Code:

	
1
        DataBasket db = new DataBasketImpl();
	2
        CatalogItem ci = catalog.get("TheItemsKey", db, true);
	3
        db.commit();
		

Back to:


previous Data Management: CommonDisplay: MenuSheet next



by Thomas Ryssel