In the org.decisiondeck.mytest.view package, the file SampleMenuItem.java describe the main view associated to our plug-in.
Let us modify the createComponent function, so that it create a JTabbedPane with two panels, one for the weights (i.e. the parameters of the method) and the other for the scores (i.e. the "results" of the method).
protected Component createComponent(UserType userType) { JPanel panel = new JPanel(); panel.setLayout(new GridBagLayout()); panel.setBackground(Color.WHITE); JTabbedPane pane = new JTabbedPane(); MyBeanPanel myBeanPanel = new MyBeanPanel(userType); WsResultPanel wsResultPanel = new WsResultPanel(userType); pane.addTab("Weights", myBeanPanel); pane.addTab("Scores", wsResultPanel); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.weightx = 1.0; c.weighty = 1.0; panel.add(pane, c); return panel; }
It is necessary to add the following imports
import javax.swing.JTabbedPane; import org.decisiondeck.mytest.view.MyBeanPanel; import org.decisiondeck.mytest.view.WsResultPanel;
You may also want to modify the getLabel function that determines the interface label for our plug-in. It is a good idea to use the Messages system, that allows you to gather the strings in a config file: src/main/resources/org.decisiondeck.mytest/messages.properties. Therefore, you may redefine the getLabel function as follows, and then modify the appropriate string in the messages.properties file.
public String getLabel() { return MytestMessages.getString("label.text"); }
Now, Eclipse should warn you that both MyBeanPanel and WsResultPanel are not defined! These are our following tasks...
Each view, either for the parameters or for the results, will build a table. Each of these tables will be modeled by a table model. Therefore, for the parameters and for the results, we will have 3 files
Let's start with the parameters.
In the org.decisiondeck.mytest.view package, create a new class, named MyBeanPanel and extending MultiDeciderTabPanel. The latter abstract class is designed to cope with several DM and to allows either the automatic selection of relevant DM or the browsing among them. Its behavior depends on your log-in status, either DM or coordinator.
You need then to implement a constructor: this constructor needs to add itself as a listener to any change in the list of criteria. The getTabComponent function is responsible for creating the content of the panel; here a MyBeanTable still to define.
package org.decisiondeck.mytest.view; import org.decisiondeck.computation.view.MultiDeciderTabPanel; import org.decisiondeck.model.User; import org.decisiondeck.view.common.table.AbstractEvalTable; import java.beans.PropertyChangeEvent; import org.decisiondeck.model.UserType; import org.decisiondeck.service.CriteriaService; import org.decisiondeck.mytest.view.MyBeanTable; public class MyBeanPanel extends MultiDeciderTabPanel { private static final long serialVersionUID = 1; public MyBeanPanel(UserType userType) { super(userType); CriteriaService.getAllCriterias().addCriteriaListChangedListener(this); } @Override protected String canShowPanel() { if (CriteriaService.getAllCriterias().size()==0) { return "No criterion defined yet"; } return null; } @Override protected AbstractEvalTable getTabComponent(User u) { final AbstractEvalTable table = new MyBeanTable(u); return table; } @Override protected String getTableTitle() { return "Parameters"; } public void propertyChange(PropertyChangeEvent evt) { super.propertyChange(evt); reloadCurrentComponent(); } }
In the same package, create a new class, named MyBeanTable, extending AbstractEvalTable and implementing IReloadable.
The definition of the table is rather simple: declare the selected table model, set some table properties (as sorting capability), and link the reload function of the table to the reload function of the table model. That's it !
package org.decisiondeck.mytest.view; import org.decisiondeck.computation.view.IReloadable; import org.decisiondeck.view.common.table.AbstractEvalTable; import org.decisiondeck.model.User; import org.decisiondeck.util.Messages; import org.decisiondeck.mytest.view.MyBeanTableModel; public class MyBeanTable extends AbstractEvalTable implements IReloadable { private static final long serialVersionUID = 1L; public static final String TABLE_NAME = Messages.getInstance(Messages.DEFAULT_BUNDLE_NAME, MyBeanTable.class).getString("EvalUI.EvaluatorTable.evaluators"); public MyBeanTable(User user) { super(new MyBeanTableModel(user)); setSortingCapability(); setBlankLineVisible(false); setColumnHeader(); } @Override protected void createPopupMenu() { } public void reloadData() { ((MyBeanTableModel) getModel()).reloadData(); } }
In the same package, create a new class, named MyBeanTableModel, extending AbstractEvalTableModel.
This task is little bit longer, since we have to define
We have also to add change listener, that will reload the table is some relevant information changes.
package org.decisiondeck.mytest.view; import org.decisiondeck.view.common.table.AbstractEvalTableModel; import org.decisiondeck.model.User; import org.decisiondeck.model.UserType; import java.util.ArrayList; import java.util.List; import org.decisiondeck.service.CriteriaService; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import org.decisiondeck.mytest.service.MyBeanService; import org.decisiondeck.util.ObjectUtils; import org.decisiondeck.view.kernel.Workbench; import org.decisiondeck.model.evaluation.ICriteria; import org.decisiondeck.mytest.model.MyBean; public class MyBeanTableModel extends AbstractEvalTableModel { private static final long serialVersionUID = 1L; private boolean loading; private boolean needReload; private User user; private List entities = new ArrayList(); public MyBeanTableModel(User user) { this.user = user; needReload = true; reloadData(); CriteriaService.getAllCriterias().addCriteriaListChangedListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { needReload=true; } }); } public void reloadData() { if (needReload && !loading) { loading = true; CriteriaService.reload(); entities = MyBeanService.getInstance().getAll(user); fireTableDataChanged(); loading = false; needReload = false; } } @Override public void addRow(int col, Object value) { // nothing } @Override public void copyRow(int row) { // nothing } @Override public void deleteRow(int row) { // nothing } @Override public String getColumnName(int col) { switch(col) { case 0: return ""; case 1: return "Weight"; } return null; } @Override public boolean isCellEditable(int row, int col) { if (col!=0 && !ObjectUtils.areEqual(UserType.COORDINATOR,Workbench.getKernel().getUserType())) { return true; } return false; } public int getColumnCount() { return 2; } public int getRowCount() { return CriteriaService.getAllCriterias().size(); } public Object getValueAt(int rowIndex, int colIndex) { ICriteria criterion = getCriteriaAt(rowIndex); MyBean bean = getMyBean(criterion); switch (colIndex) { case 0: return criterion.getName(); case 1: return bean==null ? null : bean.getWeight(); } return null; } @SuppressWarnings("unchecked") public void setValueAt(Object aValue, int rowIndex, int colIndex) { ICriteria criterion = getCriteriaAt(rowIndex); MyBean bean = getMyBean(criterion); if (bean==null) { bean = MyBeanService.getInstance().createEntity(user, false); bean.setCriterion(criterion); entities.add(bean); } switch (colIndex) { case 1: bean.setWeight((Float) aValue); break; } MyBeanService.getInstance().update(bean); fireTableDataChanged(); } private ICriteria getCriteriaAt(int rowIndex) { return (CriteriaService.getAllCriterias().get(rowIndex)); } private MyBean getMyBean(ICriteria criterion) { for (Object o: entities) { MyBean bean = (MyBean) o; if (ObjectUtils.areEqual(criterion, bean.getCriterion())) { return bean; } } return null; } @Override public Class<?> getColumnClass(int colIndex) { if (colIndex==0) { return String.class; } return Float.class; } }
Creating the results view is very similar to creating the parameters one... Create a new class, named WsResultPanel and extending MultiDeciderTabPanel.
package org.decisiondeck.mytest.view; import org.decisiondeck.computation.view.MultiDeciderTabPanel; import org.decisiondeck.model.User; import org.decisiondeck.view.common.table.AbstractEvalTable; import org.decisiondeck.model.UserType; import org.decisiondeck.service.CriteriaService; import org.decisiondeck.service.AlternativeService; import org.decisiondeck.service.EvaluatorService; import org.decisiondeck.mytest.view.WsResultTable; import java.beans.PropertyChangeEvent; public class WsResultPanel extends MultiDeciderTabPanel { private static final long serialVersionUID = 1L; public WsResultPanel(UserType userType) { super(userType); CriteriaService.getAllCriterias().addCriteriaListChangedListener(this); AlternativeService.getAllMultiCritObjects().addMCObjectListChangedListener(this); } @Override protected String canShowPanel() { if (CriteriaService.getAllCriterias().size()==0) { return "No criterion defined yet"; } if (EvaluatorService.getEvaluators().size()==0) { return "No evaluator defined yet"; } if (AlternativeService.getAlternatives().size()==0) { return "No alternative defined yet"; } return null; } @Override protected AbstractEvalTable getTabComponent(User u) { final AbstractEvalTable table = new WsResultTable(u); return table; } @Override protected String getTableTitle() { return "Weighted Sum Results"; } public void propertyChange(PropertyChangeEvent evt) { super.propertyChange(evt); reloadCurrentComponent(); } }
Create a new class, named WsResultTable, extending AbstractEvalTable and implementing IReloadable.
package org.decisiondeck.mytest.view; import org.decisiondeck.computation.view.IReloadable; import org.decisiondeck.view.common.table.AbstractEvalTable; import org.decisiondeck.model.User; import org.decisiondeck.mytest.view.WsResultTableModel; public class WsResultTable extends AbstractEvalTable implements IReloadable { private static final long serialVersionUID = 1L; public WsResultTable(User user) { super (new WsResultTableModel(user)); setSortingCapability(); setBlankLineVisible(false); setColumnHeader(); } @Override protected void createPopupMenu() { } public void reloadData() { ((WsResultTableModel) getModel()).recomputeAll(); } }
Create a new class, named WsResultTableModel and extending AbstractEvalTableModel.
package org.decisiondeck.mytest.view; import org.decisiondeck.view.common.table.AbstractEvalTableModel; import org.decisiondeck.model.User; import org.decisiondeck.model.AbstractEntity; import org.decisiondeck.service.CriteriaService; import org.decisiondeck.service.AlternativeService; import org.decisiondeck.mytest.service.MyBeanService; import org.decisiondeck.mytest.computation.WeightedSum; import org.decisiondeck.computation.service.IEntityChangeListener; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; public class WsResultTableModel extends AbstractEvalTableModel { private static final long serialVersionUID = 1L; private User user; public WsResultTableModel(User user) { this.user = user; CriteriaService.loadIfNecessary(); recomputeAll(); CriteriaService.getAllCriterias().addCriteriaListChangedListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { recomputeAll(); } }); AlternativeService.getAllMultiCritObjects().addMCObjectListChangedListener(new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { recomputeAll(); } }); MyBeanService.getInstance().addEntityListener(new IEntityChangeListener() { public void entityChanged(AbstractEntity cat) { fireTableDataChanged(); } }); } @Override public void addRow(int col, Object value) { // nothing } @Override public void copyRow(int row) { // nothing } @Override public void deleteRow(int row) { // nothing } @Override public String getColumnName(int col) { switch (col) { case 0: return ""; case 1: return "Score"; } return null; } @Override public boolean isCellEditable(int row, int col) { return false; } public int getColumnCount() { return 2; } public int getRowCount() { return AlternativeService.getAlternatives().size(); } public Object getValueAt(int row, int col) { switch(col) { case 0: return AlternativeService.getAlternatives().get(row).getAbbreviation(); case 1: WeightedSum computer = new WeightedSum(); computer.setAlternative1(AlternativeService.getAlternatives().get(row)); return computer.compute(user); } return null; } public void recomputeAll() { for (int row=0; row<getRowCount(); row++) { for (int col=0; col<getColumnCount(); col++) { setValueAt(getValueAt(row,col),row,col); } } } @Override public Class<?> getColumnClass(int col) { if (col==0) { return String.class; } return Float.class; } }
Congratulations !!! Now, you may run your new plug-in !