web-applicationsnavigationosgieclipse-rapeclipse-virgo

Navigation in a simple Eclipse RAP web-application


I have a feeling that I'm about to ask something obvous/basic here, but I'm a novice when it comes the technologies and have not figured out the "correct" way of doing things so here it goes.

Background

I am currently developing a web-application as sort of a hobby project. I have decided to use Eclipse RAP (RWT Standalone) for the UI. The application will be deployed on Eclipse Virgo server (Tomcat variant) as I'm planing to take advantage of the OSGI framework (makes some of the business logic easier to implement, but this is out of the scope of this question).

Problem

The application will have multiple sections and only one of these should be visible at a time. While setting up RAP was relatively easy, I am having trouble understanding how to set up navigation between the different sections of the application.

What I mean by this is for example having buttons such as "Data" and "Settings" in the application header and the content below these buttons changing depending on which button the user clicks.

Current solution

Currently the easiest solution i came up with is to

  1. Use the active Shell as a parent for the visible section
  2. Create a secondary invisible Shell as a parent for all of the inactive sections
  3. If the visible section changes then use currentlyVisibleSection.setParent(backgroundShell) to move the currently visible section to the background Shell and newVisibleSection.setParent(activeShell) to make the selected section visible

This idea is illustrated by the next stripped down example:

public class TestUI extends AbstractEntryPoint {
    private Composite visibleSection;
    private Shell backgroundShell;

    public void createContents( Composite parent ) {
        backgroundShell = new Shell();

        //Implementation comes from other OSGI bundles
        Composite dataSection = createDataSection(parent);
        Composite settingsSection = createSettingsSection(backgroundShell);
        visibleSection = dataSection;

        Button dataButton = new Button(parent, SWT.PUSH);
        dataButton.setText("Data");
        dataButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                if (visibleSection!=dataSection) {
                    visibleSection.setParent(backgroundShell);
                    dataSection.setParent(parent);
                    visibleSection=dataSection;
                    parent.layout();
                }
            }
        });

        Button settingsButton = new Button(parent, SWT.PUSH);
        settingsButton.setText("Data");
        settingsButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                if (visibleSection!=settingsSection) {
                    visibleSection.setParent(backgroundShell);
                    settingsSection.setParent(parent);
                    visibleSection=settingsSection;
                    parent.layout();
                }
            }
        });
    }
}

Obviously I have stripped away all of the layout and styling code, pluss it would still need some work to look decent for the end user. It does require me to manually keep track of all the different sections, creating them and managing them, but that is acceptable for me. So overall this pretty much does what I need it to do, however it feels a bit "hackish".

Questions

I also looked a bit into using Eclipse workspaces/perspectives (Workbench), but this seems to add a significant amount of complexity to the application (not to mention the initial learning-curve) and i would prefer to avoid it. Especially because I would not need most of that functionality.


Solution

  • The StackLayout is the recommended way to display a stack of control where only one will be visible at a time.

    The example below creates button area to show the selection buttons ("Data", "Settings", ...) at the top of the parent and the container takes the remaining space. All sections are created within the container that uses a StackLayout.

    parent.setLayout( new GridLayout( 1, false ) );
    Composite buttonArea = new Composite( parent, SWT.NONE );
    buttonArea.setLayoutData( new GridData( SWT.FILL, SWT.TOP, true, false ) );
    
    Composite container = new Composite( parent, SWT.NONE );
    container.setLayoutData( new GridData( SWT.FILL, SWT.FILL, true, true ) );
    StackLayout containerLayout = new StackLayout();
    container.setLayout( containerLayout );
    Composite dataSection = createDataSection( container );
    Composite settingsSection = createDataSection( container );
    

    The selection listener code tells the layout which section is to be shown.

    dataButton.addSelectionListener( new SelectionAdapter() {
      public void widgetSelected( SelectionEvent event ) {
        containerLayout.topControl = dataSection;
        container.layout();
      }
    });
    

    Fore more on layouts see also this article: https://www.eclipse.org/articles/article.php?file=Article-Understanding-Layouts/index.html

    You are on the right track. Don't use the workbench ("workspaces/perspectives" as you called it), it adds much more than you will probably need. Besides, certain parts of that stack can be used independantly when needed. Like JFace viewers or core commands for example.