Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Model View Presenter and Composite Views

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.

like image 353
Asaf David Avatar asked Feb 10 '10 21:02

Asaf David


2 Answers

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.

like image 162
David Grant Avatar answered Nov 11 '22 04:11

David Grant


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);     
}
like image 33
Jirka Avatar answered Nov 11 '22 06:11

Jirka