views:

406

answers:

3

I'm trying to follow the MVP (specifically Passive-View) pattern in a java swing ui application.

The basic design of the application reminds a wizard control. The screen is divided to two main parts:

  • an active view.
  • a static navigation bar, with navigation buttons.

The user can use buttons to change the active view, but the bar is always displayed.

Modeling this scenario, I have a bunch of diffirent screers, each with it's own presenter, view interface and view implementation (using JPanel). Then I have a Shell presenter, view intefrace and view implementation, using a JFrame. The idea is that the shell will load first and always by displayed, showing the bottom navigation bar and leaving a space for the active view. The shell presenter will allow setting the current active screen, somewhat like this:

interface View {
}

class Presenter {
    View view;

    public Presenter(View view) {
        this.view = view;
    }

    public View getView() {
        return view;
    }

}

interface ShellView extends View {
    void setActiveView(View activeView);
}

class ShellPresenter extends Presenter {
    private ShellView shellView;

    public void setActivePresenter(Presenter activePresenter) { 
        shellView.setActiveView(activePresenter.getView());
    }
}

class ShellFrame implements ShellView {
    private JFrame frame;
    private JPanel activePanel;
    private JPanel navigationBar;

    public ShellFrame() {
        Container c = frame.getContentPane();
        c.add(activePanel);
        c.add(navigationBar);
    }

    public setActiveView(View activeView) {
        ???
    }
}

The problem is in the setActiveView method: I'm not sure how to set the activeView to the activePanel, when the View interface is general and as such doens't know anything about JPanels. Obviously I wouldn't want my presenters to know about JPanels as well.

+1  A: 

Could you modify the definition of View to:

interface View {
    JComponent getContainer();
}

So that each view can easily get the view contents? The shell needn't know what implementation of JComponent is being returned.

David Grant
+1  A: 

Your View interface needs to provide some way to obtain something displayable in a JPanel:

interface View {
    Component getComponent();
}

Then in ShellFrame (assuming you use BorderLayout, as I would) you can set the view in the following way:

public setActiveView(View activeView) {
   activePanel.add(activeView.getComponent(), BorderLayout.CENTER);     
}
Jirka-x1
+2  A: 

May be http://bradwilson.typepad.com/blog/2008/06/composite-views.html is helpful for you.

McPudding