Adding extra panels to Lucy

For the detailed steps to add an extra panel, see the Add extra panels with custom UI tutorial.

To add extra panels to the Lucy user interface, you can use application panes. Application panes make abstraction of the actual form of these panels: they can be tabbed panes, internal frames, panels inside a bigger whole or anything else you can come up with. In the out-of-the-box setup, the application panes are the dockable frames inside the Lucy frame.

This abstraction is useful because it allows you to change the Lucy front-end, which defines the form of the application panes, while add-ons can just work with the application panes without knowing where and how they are displayed.

Using a Lucy application pane

Each GUI element, such as a map, a layer control, a settings panel and so on, that needs to be displayed in the Lucy environment is inserted in an ILcyApplicationPane. ILcyLucyEnv provides a factory that allows you to create these panes. For more information, see Creating an application pane with an application pane factory.

An ILcyApplicationPane is a container of other GUI widgets and is empty by default. To add GUI widgets to the ILcyApplicationPane, use the method getAppContentPane() to retrieve a regular java.awt.Container. Add GUI components to this Container as you would usually do, for example by using one of the add methods. Layout is also specified as usual, by using setLayout. However, take care not to assume a specific size, minimum size, look or layout for the application pane container, to ensure that the addon works with any front-end.

Creating an application pane with an application pane factory

To add an extra GUI panel to Lucy, first create an application pane. Use an ILcyApplicationPaneFactory, returned by the ILcyLucyEnv.getApplicationPaneFactory() method, for this purpose. Such a factory can create ILcyApplicationPane instances with different position types. The default frontend (TLcyMain) provides four types:

  • ILcyApplicationPaneFactory.MAP_PANE

  • ILcyApplicationPaneFactory.HORIZONTAL_PANE

  • ILcyApplicationPaneFactory.VERTICAL_PANE

  • ILcyApplicationPaneFactory.VERTICAL_PANE2

These types are defined as constants in the ILcyApplicationPaneFactory interface. They determine the location on the Lucy application window, as shown in the figure Figure 1, “Location of ILcyApplicationPaneFactory constants in the default front-end (TLcyMain)”. Other front-ends may define other types. It is, however, recommended to support at least the pre-defined types, even though the positioning may be different. Add-ons might use these constants if they are unaware of the actually used front-end.

Use a regular number to indicate the panel position, referring the position as an index in the array of possible positions. All Lucy add-ons read the location for their application panes from their configuration file, from a property named applicationPaneLocation or appPaneType or something similar. This allows for the easy customization of all locations of all panels, to match a certain front-end.

The default front-end TLcyMain allows the user to move the panels around by dragging and dropping. Therefore, it also stores the location of the application panes in the workspace, to make sure that the workspace storing and restoring process puts the panels back where the user put them previously. So when a workspace is loaded, the location configuration settings for the panels present in the workspace are ignored.

panes
Figure 1. Location of ILcyApplicationPaneFactory constants in the default front-end (TLcyMain)

An ILcyApplicationPaneFactory provides a createApplicationPane method that can be used to create the new pane: createApplicationPane( int aApplicationPaneType, ILcyApplicationPaneOwner aOwner) creates an ILcyApplicationPane at the given location.

The ILcyApplicationPaneOwner parameter represents the owner of the ILcyApplicationPane. To notify this owner when the pane closes, its method applicationPaneDisposing is called. This allows you to specify which actions should be taken before actually closing down the application pane.

Program: Adding a user interface panel to Lucy. When the panel is closed, the owner is notified to perform the cleanup. shows an example of the creation of a vertical application pane with the ILcyApplicationPaneFactory. After the creation of the application pane, the content is set and the pane is visualized. It is put in front of the other vertical panes. When the application pane is closed, the owner is notified, so that the necessary cleanup can be performed.

Program: Adding a user interface panel to Lucy. When the panel is closed, the owner is notified to perform the cleanup. (from samples/lucy/layerpropertyeditor/LayerPropertyEditorActiveSettable)
public class LayerPropertyEditorActiveSettable extends ALcyActiveSettable {

  ILcyApplicationPane fApplicationPane;
  private LayerPropertyEditor fLayerPropertyEditor;

  @Override
  public void setActive(boolean aActive) {
    if (isActive() != aActive) {
      if (aActive) {
        MyApplicationPaneOwner owner = new MyApplicationPaneOwner();
        fApplicationPane = fLucyEnv.getApplicationPaneFactory().createApplicationPane(
            ILcyApplicationPaneFactory.VERTICAL_PANE, owner);
        fApplicationPane.setAppTitle(TLcyLang.getString("Layer properties"));
        fLayerPropertyEditor = new LayerPropertyEditor(fLucyEnv);
        fLayerPropertyEditor.setMapComponent(fMapComponent);

        fApplicationPane.getAppContentPane().setLayout(new BorderLayout());

        fApplicationPane.getAppContentPane().add(fLayerPropertyEditor, BorderLayout.CENTER);

        if (fApplicationPane.canPackApp()) {
          fApplicationPane.packApp();
        }
        fApplicationPane.setResizable(true);
        fApplicationPane.setAppVisible(true);
        fApplicationPane.bringAppToFront();
      } else {
        fApplicationPane.disposeApp();
      }
    }
  }
  private class MyApplicationPaneOwner implements ILcyApplicationPaneOwner {
    @Override
    public void applicationPaneDisposing(EventObject aEvent) {
      if (fApplicationPane != null) {
        fApplicationPane = null;
        //remove listener from mapcomponent
        fLayerPropertyEditor.setMapComponent(null);
        fLayerPropertyEditor = null;
        updateActiveState();
      }
    }
  }
}