You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2019 lines
65 KiB

//==============================================================================
//
// Copyright (c) 2002-
// Authors:
// * Andrew Hinton <ug60axh@cs.bham.ac.uk> (University of Birmingham)
// * Dave Parker <david.parker@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
// * Mark Kattenbelt <mark.kattenbelt@comlab.ox.ac.uk> (University of Oxford, formerly University of Birmingham)
// * Vincent Nimal <vincent.nimal@comlab.ox.ac.uk> (University of Oxford)
//
//------------------------------------------------------------------------------
//
// This file is part of PRISM.
//
// PRISM is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// PRISM is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with PRISM; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//==============================================================================
package userinterface.properties;
import java.io.*;
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.datatransfer.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import userinterface.*;
import userinterface.model.*;
import userinterface.properties.computation.*;
import userinterface.util.*;
import userinterface.simulator.*;
import userinterface.simulator.networking.*;
import prism.*;
import parser.*;
import parser.ast.*;
import parser.type.*;
/**
* Properties tab of the PRISM GUI.
*/
public class GUIMultiProperties extends GUIPlugin implements MouseListener, ListSelectionListener, PrismSettingsListener, ContainerListener
{
//CONSTANTS
public static final int CONTINUE = 0;
public static final int CANCEL = 1;
public static final int WARN_INVALID_PROPS = 1;
public static final int NEVER_INVALID_PROPS = 2;
// ATTRIBUTES
// Current model (gets updated only by event listening to GUIModel)
private ModulesFile parsedModel;
private Model builtModel;
// Constants for model (updated by events or locally)
private Values mfConstants;
// State
private boolean modified;
private boolean modifiedSinceBuild;
private boolean computing;
private boolean verifyAfterReceiveParseNotification, verifyAfterReceiveBuildNotification, experimentAfterReceiveParseNotification,
simulateAfterReceiveParseNotification;
private PropertiesFile parsedProperties;
private ArrayList<GUIProperty> propertiesToBeVerified;
private File activeFile;
private Values pfConstants;
// GUI
private GUIPrismFileFilter propsFilter[];
private GUIPrismFileFilter resultsFilter[];
private JMenu propMenu;
private JPopupMenu propertiesPopup, constantsPopup, labelsPopup, experimentPopup;
private GUIExperimentTable experiments;
private GUIGraphHandler graphHandler;
private JScrollPane expScroller;
private JLabel fileLabel;
private Vector clipboardVector;
private Action newProps, openProps, saveProps, savePropsAs, insertProps, verifySelected, newProperty, editProperty, newConstant, removeConstant, newLabel,
removeLabel, newExperiment, deleteExperiment, stopExperiment, viewResults, plotResults,
exportResultsListText, exportResultsListCSV, exportResultsMatrixText, exportResultsMatrixCSV, simulate, details;
// Current properties
private GUIPropertiesList propList;
private GUIPropConstantList consTable;
private GUIPropLabelList labTable;
// Cached copies of settings
private Font displayFontFast;
private Color backgroundFast, warningFast;
// CONSTRUCTORS
/** Creates a new instance of GUIMultiProperties */
public GUIMultiProperties(GUIPrism pr, GUISimulator simulator)
{
super(pr);
simulator.setGUIProb(this); // link required
initComponents();
a_newList();
setBuiltModel(null);
setParsedModel(null);
//options = new GUIPropertiesOptions(this);
}
public void takeCLArgs(String args[])
{
// disabled for now - need to sort out so this doesn't happen until model is fully parsed
// if (args.length > 1) {
// Thread t = new LoadPropertiesThread(this, parsedModel, new File(args[1]));
// t.setPriority(Thread.NORM_PRIORITY);
// t.start();
// }
}
//ACCESS METHODS
public ModulesFile getParsedModel()
{
return parsedModel;
}
public String getConstantsString()
{
return consTable.getValidConstantsString();
}
public String getLabelsString()
{
return labTable.getValidLabelsString();
}
public int getNumConstants()
{
return consTable.getRowCount();
}
public int getNumLabels()
{
return labTable.getRowCount();
}
public Font getListFont()
{
return displayFontFast;
}
public Color getWarningColor()
{
return warningFast;
}
public Color getSelectionColor()
{
return backgroundFast;
}
public int getInvalidPropertyStrategy()
{
return getPrism().getSettings().getInteger(PrismSettings.PROPERTIES_ADDITION_STRATEGY) + 1; //note the correction
}
/* UPDATE METHODS */
public void repaintList()
{
propList.repaint();
}
protected void verifyAfterBuild()
{
verifyAfterReceiveBuildNotification = false;
// Start model check process
if (builtModel != null && parsedProperties != null && propertiesToBeVerified != null) {
Thread t = new ModelCheckThread(this, builtModel, parsedProperties, propertiesToBeVerified, mfConstants, pfConstants);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
}
protected void verifyAfterParse()
{
ArrayList<GUIProperty> validGUIProperties;
UndefinedConstants uCon;
verifyAfterReceiveParseNotification = false;
try {
// Get valid/selected properties
String propertiesString = getLabelsString() + "\n" + getConstantsString() + "\n" + propList.getValidSelectedAndReferencedString();
// Get PropertiesFile for valid/selected properties
parsedProperties = getPrism().parsePropertiesString(parsedModel, propertiesString);
// And get list of corresponding GUIProperty objects
validGUIProperties = propList.getValidSelectedProperties();
// Query user for undefined constant values (if required)
int n = parsedProperties.getNumProperties();
ArrayList<Property> validProperties = new ArrayList<Property>(n);
for (int i = 0; i < n; i++)
validProperties.add(parsedProperties.getPropertyObject(i));
uCon = new UndefinedConstants(parsedModel, parsedProperties, validProperties);
if (uCon.getMFNumUndefined() + uCon.getPFNumUndefined() > 0) {
// Use previous constant values as defaults in dialog
int result = GUIConstantsPicker.defineConstantsWithDialog(this.getGUI(), uCon, mfConstants, pfConstants);
if (result != GUIConstantsPicker.VALUES_DONE)
return;
}
// Store model constants (even though will be stored again after build)
// Don't set in model: this will be done during build process
mfConstants = uCon.getMFConstantValues();
// Store property constants and set in file
pfConstants = uCon.getPFConstantValues();
parsedProperties.setSomeUndefinedConstants(pfConstants);
// Store properties to be verified
propertiesToBeVerified = validGUIProperties;
// If required, trigger build then verify
if (parsedModel.getModelType() != ModelType.PTA) {
verifyAfterReceiveBuildNotification = true;
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.REQUEST_MODEL_BUILD, mfConstants));
}
// If no build required (e.g. for PTAs), just do model checking now
else {
// Start model check process
parsedModel.setUndefinedConstants(mfConstants);
if (parsedProperties != null && propertiesToBeVerified != null) {
Thread t = new ModelCheckThread(this, parsedModel, parsedProperties, propertiesToBeVerified, mfConstants, pfConstants);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
}
} catch (PrismException e) {
error(e.getMessage());
return;
}
}
public void simulateAfterParse()
{
simulateAfterReceiveParseNotification = false;
ArrayList<GUIProperty> validGUIProperties, simulatableGUIProperties;
ArrayList<Expression> simulatableExprs;
UndefinedConstants uCon;
try {
parsedProperties = getPrism().parsePropertiesString(parsedModel,
getLabelsString() + "\n" + getConstantsString() + "\n" + propList.getValidSelectedAndReferencedString());
validGUIProperties = propList.getValidSelectedProperties();
if (validGUIProperties.size() == 0) {
error("None of the selected properties are suitable for simulation");
return;
}
} catch (PrismException e) {
error(e.getMessage());
return;
}
// See which of the (valid) selected properties are ok for simulation
// Also store a list of the expression themselves
simulatableGUIProperties = new ArrayList<GUIProperty>();
ArrayList<Property> simulatableProperties = new ArrayList<Property>();
simulatableExprs = new ArrayList<Expression>();
for (int i = 0; i < validGUIProperties.size(); i++) {
GUIProperty guiP = validGUIProperties.get(i);
try {
getPrism().checkPropertyForSimulation(guiP.getProperty());
simulatableGUIProperties.add(guiP);
simulatableProperties.add(parsedProperties.getPropertyObject(i));
simulatableExprs.add(guiP.getProperty());
} catch (PrismException e) {
// do nothing
}
}
if (simulatableGUIProperties.size() == 0) {
error("None of the selected properties are suitable for simulation");
return;
}
if (simulatableGUIProperties.size() < validGUIProperties.size()) {
int q = questionYesNo("Warning", "Warning: Some of the selected properties are not suitable for simulation. Continue?");
if (q != 0)
return;
}
//find out any undefined constants
try {
uCon = new UndefinedConstants(parsedModel, parsedProperties, simulatableProperties);
if (uCon.getMFNumUndefined() + uCon.getPFNumUndefined() > 0) {
// Use previous constant values as defaults in dialog
int result = GUIConstantsPicker.defineConstantsWithDialog(this.getGUI(), uCon, mfConstants, pfConstants);
if (result != GUIConstantsPicker.VALUES_DONE)
return;
}
// Store model/property constants and set in files
mfConstants = uCon.getMFConstantValues();
pfConstants = uCon.getPFConstantValues();
parsedModel.setUndefinedConstants(mfConstants);
parsedProperties.setSomeUndefinedConstants(pfConstants);
// Get simulation info with dialog
SimulationInformation info = GUISimulationPicker.defineSimulationWithDialog(this.getGUI(), simulatableExprs, parsedModel, null);
// If user cancelled simulation, quit
if (info == null)
return;
if (parsedModel != null && parsedProperties != null) {
if (info.isDistributed()) {
new GUISimulatorDistributionDialog(getGUI(), getPrism().getSimulator(), true).show(this, parsedModel, parsedProperties, simulatableGUIProperties,
info);
} else {
Thread t = new SimulateModelCheckThread(this, parsedModel, parsedProperties, simulatableGUIProperties, mfConstants, pfConstants, info);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
}
} catch (PrismException e) {
error(e.getMessage());
return;
}
}
public void experimentAfterParse()
{
experimentAfterReceiveParseNotification = false;
GUIProperty gp = propList.getProperty(propList.getSelectedIndex());
Type type;
try {
//get referenced named properties
String namedString = "";
//Add named properties
for (GUIProperty namedProp : this.propList.getAllNamedProperties()) {
if (gp.getReferencedNames().contains(namedProp.getName())) {
namedString += "\"" + namedProp.getName() + "\" : " + namedProp.getPropString() + "\n";
}
}
// parse property to be used for experiment
parsedProperties = getPrism().parsePropertiesString(parsedModel, getLabelsString() + "\n" + getConstantsString() + "\n" + namedString + gp.getPropString());
if (parsedProperties.getNumProperties() <= 0) {
error("There are no properties selected");
return;
}
if (propList.getNumSelectedProperties() > 1) {
error("Experiments can only be created for a single property");
return;
}
// check the type of the property
int index = parsedProperties.getNumProperties() - 1;
type = parsedProperties.getProperty(index).getType();
} catch (PrismException e) {
error(e.getMessage());
return;
}
//get Property objects for sorting out undefined constants
ArrayList<Property> props = new ArrayList<Property>();
for (int i = 0; i < parsedProperties.getNumProperties(); i++) {
props.add(parsedProperties.getPropertyObject(i));
}
// sort out undefined constants
UndefinedConstants uCon = new UndefinedConstants(parsedModel, parsedProperties, props);
boolean showGraphDialog = false;
boolean useSimulation = false;
if (uCon.getMFNumUndefined() + uCon.getPFNumUndefined() == 0) {
error("Cannot create an experiment because there are no constants with undefined values");
return;
}
boolean offerGraph = type instanceof TypeInt || type instanceof TypeDouble || type instanceof TypeInterval;
int result = GUIExperimentPicker.defineConstantsWithDialog(this.getGUI(), uCon, offerGraph, gp
.isValidForSimulation());
if (result == GUIExperimentPicker.VALUES_DONE_SHOW_GRAPH || result == GUIExperimentPicker.VALUES_DONE_SHOW_GRAPH_AND_SIMULATE) {
showGraphDialog = true;
} else if (result == GUIExperimentPicker.CANCELLED)
return;
if (result == GUIExperimentPicker.VALUES_DONE_SIMULATE || result == GUIExperimentPicker.VALUES_DONE_SHOW_GRAPH_AND_SIMULATE) {
useSimulation = true;
}
//if we are using simulation, make sure the property is ok
if (useSimulation) {
try {
getPrism().checkPropertyForSimulation(gp.getProperty());
} catch (PrismException e) {
error("Property is not suitable for simulation: " + e.getMessage());
return;
}
}
// make sure we can actually create a graph, i.e. that there is >1 result
if (showGraphDialog)
if (uCon.getRangingConstants().size() == 0) {
message("Cannot create a graph since there is only a single result.");
showGraphDialog = false;
}
// Use these values to create a new experiment
int i = experiments.newExperiment(parsedProperties, uCon, parsedModel, useSimulation);
boolean notCancelled = true;
// start the experiment, via the graph dialog if appropriate
if (showGraphDialog) {
GUIGraphPicker ggp = new GUIGraphPicker(getGUI(), this, experiments.getExperiment(i), graphHandler, false);
if (ggp.isGraphCancelled()) {
if (questionYesNo("Do you want to cancel the experiment completely?", 0) == 0)
notCancelled = false;
}
}
if (notCancelled)
experiments.startExperiment(i);
//else
// experiments.removeExperiment(i);
}
public void propertyLoadSuccessful(PropertiesFile pf, File f)
{
// note: add constants/labels first to stop property parse errors
consTable.newList();
consTable.addPropertiesFile(pf);
labTable.newList();
labTable.addPropertiesFile(pf);
propList.deleteAll();
propList.addPropertiesFile(pf);
tabToFront();
setModified(false);
setActiveFile(f);
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.PROPERTIES_LIST_CHANGED));
}
public void propertyInsertSuccessful(PropertiesFile pf)
{
propList.addPropertiesFile(pf);
consTable.addPropertiesFile(pf);
labTable.addPropertiesFile(pf);
tabToFront();
setModified(true);
}
public void propertySaveSuccessful(File f)
{
setActiveFile(f);
setModified(false);
}
public void changeProperty(String pctl, String comment, String id)
{
int index = propList.getIndexOf(id);
if (index < 0) {
if (pctl != null) {
propList.addProperty(pctl, comment);
setModified(true);
}
} else {
GUIProperty gp = propList.getProperty(index);
gp.setBeingEdited(false);
if (pctl != null) {
if (pctl.matches("\"[^\"]*\"[ ]*:.*")) {
//the string contains property name
int start = pctl.indexOf('"') + 1;
int end = pctl.indexOf('"', start);
String name = pctl.substring(start,end);
int colon = pctl.indexOf(':') + 1;
pctl = pctl.substring(colon).trim();
gp.setPropStringAndName(pctl, name, parsedModel, getConstantsString(), getLabelsString());
} else {
gp.setPropStringAndName(pctl, null, parsedModel, getConstantsString(), getLabelsString());
}
gp.setComment(comment);
setModified(true);
}
// Force repaint because we modified the GUIProperty directly
repaintList();
}
selectionChangeHandler.notifyListeners(new GUIEvent(1));
updateCommentLabel();
}
public void cancelProperty(String id)
{
int index = propList.getIndexOf(id);
if (index >= 0) {
GUIProperty gp = propList.getProperty(index);
gp.setBeingEdited(false);
// Force repaint because we modified the GUIProperty directly
repaintList();
}
}
/** Called by the constant list to let us know something changed there */
public void constantListChanged()
{
labTable.validateLabels();
propList.validateProperties();
setModified(true);
}
/** Called by the label list to let us know something changed there */
public void labelListChanged()
{
propList.validateProperties();
setModified(true);
}
protected void setModified(boolean mod)
{
modified = mod;
setActiveFileLabel();
if (modified) {
doEnables();
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.PROPERTIES_LIST_CHANGED));
}
}
protected void setComputing(boolean com)
{
computing = com;
doEnables();
selectionChangeHandler.notifyListeners(new GUIEvent(1));
}
protected void setActiveFile(File f)
{
activeFile = f;
setActiveFileLabel();
}
protected void setActiveFileLabel()
{
fileLabel.setText("Properties list: " + ((activeFile == null) ? "<Untitled>" : activeFile.getPath()) + (modified ? "*" : ""));
}
protected void setParsedModel(ModulesFile m)
{
parsedModel = m;
consTable.validateConstants();
propList.validateProperties();
doEnables();
}
protected void setBuiltModel(Model m)
{
builtModel = m;
doEnables();
}
protected void doEnables()
{
// properties panel
setEnabled(true);
setTabEnabled(true);
// properties menu
newProps.setEnabled(!computing);
openProps.setEnabled(!computing);
insertProps.setEnabled(!computing);
saveProps.setEnabled(!computing);
savePropsAs.setEnabled(!computing);
simulate.setEnabled(!computing && parsedModel != null && propList.existsValidSimulatableSelectedProperties());
verifySelected.setEnabled(!computing && parsedModel != null && propList.existsValidSelectedProperties());
details.setEnabled(!computing && parsedModel != null && propList.existsValidSelectedProperties());
// properties list
propList.setEnabled(!computing);
newProperty.setEnabled(!computing);
editProperty.setEnabled(!computing && propList.getSelectedProperties().size() > 0);
// constants list
consTable.setEnabled(!computing);
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
// label list
labTable.setEnabled(!computing);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
// newExperiment: enabled if there is exactly one prop selected and it is valid
newExperiment.setEnabled(propList.getNumSelectedProperties() == 1 && propList.getValidSelectedProperties().size() == 1);
// deleteExperiments: enabled if one or more experiments selected
deleteExperiment.setEnabled(experiments.getSelectedRowCount() > 0);
// viewResults: enabled if at least one experiment is selected
viewResults.setEnabled(experiments.getSelectedRowCount() > 0);
// plotResults: enabled if exactly one experiment is selected and its type is int/double
if (experiments.getSelectedRowCount() == 1) {
GUIExperiment exp = experiments.getExperiment(experiments.getSelectedRow());
Type type = exp.getPropertyType();
plotResults.setEnabled(type instanceof TypeInt || type instanceof TypeDouble || type instanceof TypeInterval);
} else {
plotResults.setEnabled(false);
}
// exportResults: enabled if at least one experiment is selected
exportResultsListText.setEnabled(experiments.getSelectedRowCount() > 0);
exportResultsListCSV.setEnabled(experiments.getSelectedRowCount() > 0);
exportResultsMatrixText.setEnabled(experiments.getSelectedRowCount() > 0);
exportResultsMatrixCSV.setEnabled(experiments.getSelectedRowCount() > 0);
}
public int doModificationCheck()
{
if (modified) {
if (activeFile == null) {
String[] selection = { "Yes", "No", "Cancel" };
int selectionNo = -1;
selectionNo = optionPane("Properties list has been modified.\nDo you wish to save it?", "Question", JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, selection, selection[0]);
switch (selectionNo) {
case 0:
return a_save();
case 1:
return CONTINUE;
case 2:
return CANCEL;
default:
return CANCEL;
}
} else {
String[] selection = { "Yes", "No", "Save As...", "Cancel" };
int selectionNo = -1;
selectionNo = optionPane("Properties list has been modified.\nDo you wish to save it?", "Question", JOptionPane.OK_CANCEL_OPTION,
JOptionPane.QUESTION_MESSAGE, selection, selection[0]);
switch (selectionNo) {
case 0:
return a_save();
case 1:
return CONTINUE;
case 2:
return a_saveAs();
case 3:
return CANCEL;
default:
return CANCEL;
}
}
}
return CONTINUE;
}
private void updateCommentLabel()
{
ArrayList selectedProps = propList.getSelectedProperties();
if (selectedProps.size() == 1) {
GUIProperty p = (GUIProperty) selectedProps.get(0);
comLabel.setText(p.getComment());
} else {
comLabel.setText("");
}
}
//ACTION METHODS
public void a_newList()
{
if (doModificationCheck() != CONTINUE)
return;
propList.deleteAll();
consTable.newList();
labTable.newList();
setModified(false);
modifiedSinceBuild = true;
setActiveFile(null);
doEnables();
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.PROPERTIES_LIST_CHANGED));
}
public void a_open()
{
if (doModificationCheck() != CONTINUE)
return;
if (showOpenFileDialog(propsFilter, propsFilter[0]) == JFileChooser.APPROVE_OPTION) {
File file = getChooserFile();
if (file == null) {
error("No file selected");
return;
}
Thread t = new LoadPropertiesThread(this, parsedModel, file);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
}
// Save properties
// NB: This used to be in a thread but I have taken it out because:
// (a) We sometimes need to know whether save was successful before continuing
// (b) When saving before clearing, clear can occur too early
public int a_save()
{
if (activeFile == null) {
return a_saveAs();
} else {
// only allow save if all props valid (can't reopen file otherwise)
if (!propList.allPropertiesAreValid()) {
message("Cannot save properties list: some properties are invalid");
return CANCEL;
} else {
// do save
try {
setTaskBarText("Saving properties...");
PrintWriter out = new PrintWriter(new FileWriter(activeFile));
out.print(propList.toFileString(activeFile, consTable, labTable));
out.flush();
out.close();
} catch (IOException e) {
setTaskBarText("Saving properties... error.");
error("Could not save to file \"" + activeFile + "\"");
return CANCEL;
}
setTaskBarText("Saving properties... done.");
propertySaveSuccessful(activeFile);
return CONTINUE;
}
}
}
// Save properties as
// NB: This used to be in a thread but I have taken it out because:
// (a) We sometimes need to know whether save was successful before continuing
// (b) When saving before clearing, clear can occur too early
public int a_saveAs()
{
// only allow save if all props valid (can't reopen file otherwise)
if (!propList.allPropertiesAreValid()) {
message("Cannot save properties list: some properties are invalid");
return CANCEL;
}
if (!consTable.isConstantListValid()) {
message("Cannot save properties list: some constants are invalid");
return CANCEL;
}
if (showSaveFileDialog(propsFilter, propsFilter[0]) == JFileChooser.APPROVE_OPTION) {
File file = getChooserFile();
// do save
try {
setTaskBarText("Saving properties...");
PrintWriter out = new PrintWriter(new FileWriter(file));
out.print(propList.toFileString(file, consTable, labTable));
out.flush();
out.close();
} catch (IOException e) {
setTaskBarText("Saving properties... error.");
error("Could not save to file \"" + file + "\"");
return CANCEL;
}
setTaskBarText("Saving properties... done.");
propertySaveSuccessful(file);
return CONTINUE;
}
return CANCEL;
}
public void a_insert()
{
if (showOpenFileDialog(propsFilter, propsFilter[0]) == JFileChooser.APPROVE_OPTION) {
File file = getChooserFile();
if (file == null) {
error("No file selected");
return;
}
Thread t = new LoadPropertiesThread(this, parsedModel, file, true);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
} else {
return;
}
}
public void a_simulateSelected()
{
consTable.correctEditors();
labTable.correctEditors();
// Bail out if there are no valid properties to simulate
// (probably never occurs - action is disabled in this case)
if (!propList.existsValidSimulatableSelectedProperties()) {
error("None of the selected properties are suitable for simulation");
return;
}
// Reset warnings counter
getPrism().getMainLog().resetNumberOfWarnings();
// Request a parse
simulateAfterReceiveParseNotification = true;
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.REQUEST_MODEL_PARSE));
}
public void a_detailSelected()
{
int[] selected = propList.getSelectedIndices();
for (int i = 0; i < selected.length; i++) {
GUIProperty gp = propList.getProperty(selected[i]);
if (!gp.isBeingEdited()) {
gp.setBeingEdited(true);
// Force repaint because we modified the GUIProperty directly
repaintList();
new GUIPropertyResultDialog(getGUI(), this, gp).display();
}
}
}
public void a_verifySelected()
{
consTable.correctEditors();
labTable.correctEditors();
// Bail out if there are no valid properties to verify
// (probably never occurs - action is disabled in this case)
if (!propList.existsValidSelectedProperties()) {
error("None of the selected properties are suitable for verification. The model was not built");
return;
}
// Reset warnings counter
getPrism().getMainLog().resetNumberOfWarnings();
// Request a parse
verifyAfterReceiveParseNotification = true;
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.REQUEST_MODEL_PARSE));
}
public void a_cut()
{
java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//java.awt.datatransfer.StringSelection selection = new java.awt.datatransfer.StringSelection(propList.getClipboardString());
//clipboard.setContents(selection, null);
clipboard.setContents(new GUIClipboardProperties(propList.getSelectedProperties()), null);
a_delete();
}
public void a_copy()
{
java.awt.datatransfer.Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
//java.awt.datatransfer.StringSelection selection = new java.awt.datatransfer.StringSelection(propList.getClipboardString());
//clipboard.setContents(selection, null);
clipboard.setContents(new GUIClipboardProperties(propList.getSelectedProperties()), null);
}
public void a_paste()
{
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = clipboard.getContents(null);
if (contents != null) {
if (contents.isDataFlavorSupported(getGUIClipboardPropertiesDataFlavor())) {
try {
GUIClipboardProperties gcp = (GUIClipboardProperties) contents.getTransferData(getGUIClipboardPropertiesDataFlavor());
ArrayList listOfProperties = gcp.getProperties();
for (int i = 0; i < listOfProperties.size(); i++) {
GUIProperty property = (GUIProperty) listOfProperties.get(i);
propList.addProperty(property.getName(), property.getPropString(), property.getComment());
setModified(true);
}
} catch (UnsupportedFlavorException e) {
} catch (IOException e) {
}
} else {
try {
String text = (String) contents.getTransferData(java.awt.datatransfer.DataFlavor.stringFlavor);
propList.pastePropertiesString(text);
setModified(true);
} catch (UnsupportedFlavorException e) {
} catch (IOException e) {
}
}
}
}
public void a_delete()
{
propList.deleteSelected();
setModified(true);
}
public void a_deleteAll()
{
propList.deleteAll();
setModified(true);
}
public void a_newProperty()
{
GUIPropertyEditor ed = new GUIPropertyEditor(this, parsedModel, getInvalidPropertyStrategy());
ed.show();
}
public void a_editProperty()
{
int[] selected = propList.getSelectedIndices();
for (int i = 0; i < selected.length; i++) {
GUIProperty gp = propList.getProperty(selected[i]);
if (!gp.isBeingEdited()) {
gp.setBeingEdited(true);
// Force repaint because we modified the GUIProperty directly
repaintList();
GUIPropertyEditor ed = new GUIPropertyEditor(this, parsedModel, gp, getInvalidPropertyStrategy());
ed.show();
}
}
selectionChangeHandler.notifyListeners(new GUIEvent(1));
}
public void a_selectAll()
{
propList.selectAll();
}
public void a_addConstant()
{
consTable.addNewConstant();
}
public void a_removeSelectedConstants()
{
// Note: Unlike for prop list, this is safe because constants can always be deleted
// (not the case properties - e.g. if they are being edited)
while (consTable.getSelectedRowCount() > 0) {
consTable.removeConstant(consTable.getSelectedRow());//for now
}
}
public void a_addLabel()
{
labTable.addNewLabel();
}
public void a_removeSelectedLabels()
{
// Note: Unlike for prop list, this is safe because constants can always be deleted
// (not the case properties - e.g. if they are being edited)
while (labTable.getSelectedRowCount() > 0) {
labTable.removeLabel(labTable.getSelectedRow());
}
}
public void a_newExperiment()
{
experimentAfterReceiveParseNotification = true;
notifyEventListeners(new GUIPropertiesEvent(GUIPropertiesEvent.REQUEST_MODEL_PARSE));
}
public void a_stopExperiment()
{
experiments.stop();
}
public void a_deleteExperiment()
{
experiments.deleteSelected();
}
public void a_viewResults()
{
GUIExperiment exp;
int i, n, inds[];
// get selected experiments
n = experiments.getSelectedRowCount();
if (n < 1)
return;
inds = experiments.getSelectedRows();
// show results dialog for reach one
for (i = 0; i < n; i++) {
exp = experiments.getExperiment(inds[i]);
new GUIResultsTable(this.getGUI(), this, exp).show();
}
}
public void a_plotResults()
{
GUIExperiment exp;
Type type;
// get experiment
if (experiments.getSelectedRowCount() != 1)
return;
exp = experiments.getExperiment(experiments.getSelectedRow());
// check its type
type = exp.getPropertyType();
if (!(type instanceof TypeInt || type instanceof TypeDouble || type instanceof TypeInterval)) {
message("Can only plot results if the property is of type int or double");
return;
}
// make sure we can actually create a graph, i.e. that there is >1 result
if (exp.getRangingConstants().size() == 0) {
message("Cannot create a graph since there is only a single result.");
return;
}
// launch dialog, plot series (modal)
GUIGraphPicker ggp = new GUIGraphPicker(getGUI(), this, exp, graphHandler, true);
}
public void a_exportResults(boolean exportMatrix, String sep)
{
GUIExperiment exps[];
int i, n, inds[];
// get selected experiments
n = experiments.getSelectedRowCount();
if (n < 1)
return;
exps = new GUIExperiment[n];
inds = experiments.getSelectedRows();
for (i = 0; i < n; i++)
exps[i] = experiments.getExperiment(inds[i]);
// get filename to save
if (showSaveFileDialog(resultsFilter, sep.equals(", ") ? resultsFilter[1] : resultsFilter[0]) == JFileChooser.APPROVE_OPTION) {
File file = getChooserFile();
Thread t = new ExportResultsThread(this, exps, file, exportMatrix, sep);
t.setPriority(Thread.NORM_PRIORITY);
t.start();
}
}
//METHODS TO IMPLEMENT GUIPlugin INTERFACE
public boolean displaysTab()
{
return true;
}
public JMenu getMenu()
{
return propMenu;
}
public OptionsPanel getOptions()
{
return null;
}
public String getTabText()
{
return "Properties";
}
public JToolBar getToolBar()
{
return null;
}
public String getXMLIDTag()
{
return "";
}
public Object getXMLSaveTree()
{
return null;
}
public void loadXML(Object c)
{
}
// if return value is true, event should not be passed on to any more listeners
public boolean processGUIEvent(GUIEvent e)
{
if (e instanceof GUIModelEvent) {
GUIModelEvent me = (GUIModelEvent) e;
if (me.getID() == me.NEW_MODEL) {
//New Model
setBuiltModel(null);
setParsedModel(null);
//newList();
} else if (me.getID() == GUIModelEvent.MODEL_BUILT) {
setBuiltModel(me.getModel());
if (me.getBuildValues() != null)
mfConstants = me.getBuildValues();
modifiedSinceBuild = false;
if (verifyAfterReceiveBuildNotification)
verifyAfterBuild();
} else if (me.getID() == GUIModelEvent.MODEL_PARSED) {
setParsedModel(me.getModulesFile());
if (verifyAfterReceiveParseNotification)
verifyAfterParse();
if (experimentAfterReceiveParseNotification)
experimentAfterParse();
if (simulateAfterReceiveParseNotification)
simulateAfterParse();
} else if (me.getID() == GUIModelEvent.MODEL_PARSE_FAILED) {
verifyAfterReceiveParseNotification = false;
experimentAfterReceiveParseNotification = false;
simulateAfterReceiveParseNotification = false;
} else if (me.getID() == GUIModelEvent.MODEL_BUILD_FAILED) {
verifyAfterReceiveBuildNotification = false;
} else if (me.getID() == GUIModelEvent.MODIFIED_SINCE_SAVE) {
//setBuiltModel(null);
modifiedSinceBuild = true;
} else if (me.getID() == GUIModelEvent.NEW_LOAD_NOT_RELOAD_MODEL) {
if (getPrism().getSettings().getBoolean(PrismSettings.PROPERTIES_CLEAR_LIST_ON_LOAD)) {
a_newList();
}
}
} else if (e instanceof GUIComputationEvent) {
if (e.getID() == GUIComputationEvent.COMPUTATION_START) {
setComputing(true);
} else if (e.getID() == GUIComputationEvent.COMPUTATION_DONE) {
setComputing(false);
} else if (e.getID() == GUIComputationEvent.COMPUTATION_ERROR) {
setComputing(false);
}
} else if (e instanceof GUIClipboardEvent && super.getGUI().getFocussedPlugin() == this) {
GUIClipboardEvent ce = (GUIClipboardEvent) e;
if (ce.getComponent() == this || ce.getComponent() == propList) {
if (!computing) {
if (ce.getID() == ce.CUT) {
a_cut();
} else if (ce.getID() == ce.COPY) {
a_copy();
} else if (ce.getID() == ce.PASTE) {
a_paste();
} else if (ce.getID() == ce.DELETE) {
a_delete();
} else if (ce.getID() == ce.SELECT_ALL) {
a_selectAll();
}
}
} else {
}
} else if (e instanceof GUIPropertiesEvent) {
GUIPropertiesEvent pr = (GUIPropertiesEvent) e;
if (pr.getID() == GUIPropertiesEvent.EXPERIMENT_START) {
stopExperiment.setEnabled(true);
} else if (pr.getID() == GUIPropertiesEvent.EXPERIMENT_END) {
stopExperiment.setEnabled(false);
} else if (pr.getID() == GUIPropertiesEvent.VERIFY_END) {
a_detailSelected();
}
} else if (e instanceof GUIExitEvent) {
if (e.getID() == GUIExitEvent.REQUEST_EXIT) {
if (doModificationCheck() != CONTINUE) {
notifyEventListeners(new GUIExitEvent(GUIExitEvent.CANCEL_EXIT));
return true;
}
}
}
return false;
}
//METHODS TO IMPLEMENT MouseListner INTERFACE
public void mouseClicked(MouseEvent e)
{
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
if (!computing) {
if (e.getClickCount() >= 2) {
if (e.getSource() == propList) {
int index = propList.locationToIndex(e.getPoint());
if (index != -1) {
propList.setSelectedIndex(index);
}
a_editProperty();
}
}
}
}
public void mouseEntered(MouseEvent e)
{
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
}
public void mouseExited(MouseEvent e)
{
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
}
public void mousePressed(MouseEvent e)
{
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
if (!computing) {
if (e.isPopupTrigger() && e.getSource() == propList) {
int index = propList.locationToIndex(e.getPoint());
// if there are no properties selected, select the one under the popup
if (propList.isSelectionEmpty()) {
if (index != -1) {
propList.setSelectedIndex(index);
}
} else {
// if the property under the popup is not already selected, select just that one
int[] sel = propList.getSelectedIndices();
boolean valid = false;
for (int i = 0; i < sel.length; i++) {
if (sel[i] == index) {
valid = true;
break;
}
}
if (!valid) {
propList.setSelectedIndex(index);
}
}
// disable certain actions if any of the selected propeties are currently being edited
int[] sel = propList.getSelectedIndices();
boolean showDeleters = true;
for (int i = 0; i < sel.length; i++) {
if (propList.getProperty(sel[i]).isBeingEdited()) {
showDeleters = false;
break;
}
}
verifySelected.setEnabled(propList.existsValidSelectedProperties());
simulate.setEnabled(propList.existsValidSimulatableSelectedProperties());
details.setEnabled(propList.existsValidSelectedProperties());
editProperty.setEnabled(propList.getSelectedProperties().size() > 0);
newExperiment.setEnabled(propList.getNumSelectedProperties() == 1 && propList.getValidSelectedProperties().size() == 1);
if (showDeleters == false) {
simulate.setEnabled(false);
verifySelected.setEnabled(false);
details.setEnabled(false);
editProperty.setEnabled(false);
newExperiment.setEnabled(false);
}
propertiesPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == consTable || e.getSource() == constantsScroll)) {
constantsPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == labTable || e.getSource() == labelsScroll)) {
labelsPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == experiments || e.getSource() == expScroller)) {
doEnables();
this.experimentPopup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
@Override
public boolean canDoClipBoardAction(Action action)
{
if (computing)
return false;
// disable certain actions if any of the selected propeties are currently being edited
int[] sel = propList.getSelectedIndices();
boolean showDeleters = true;
for (int i = 0; i < sel.length; i++) {
if (propList.getProperty(sel[i]).isBeingEdited()) {
showDeleters = false;
break;
}
}
if (action == GUIPrism.getClipboardPlugin().getPasteAction()) {
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
return (clipboard.getContents(null) != null);
} else if (action == GUIPrism.getClipboardPlugin().getCutAction() || action == GUIPrism.getClipboardPlugin().getDeleteAction()) {
if (!showDeleters)
return false;
return (propList.getSelectedProperties().size() > 0);
} else if (action == GUIPrism.getClipboardPlugin().getCopyAction()) {
return (propList.getSelectedProperties().size() > 0);
} else if (action == GUIPrism.getClipboardPlugin().getSelectAllAction()) {
return true;
}
return false;
}
public void mouseReleased(MouseEvent e)
{
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
if (!computing) {
if (e.isPopupTrigger() && e.getSource() == propList) {
int index = propList.locationToIndex(e.getPoint());
// if there are no properties selected, select the one under the popup
if (propList.isSelectionEmpty()) {
if (index != -1) {
propList.setSelectedIndex(index);
}
} else {
// if the property under the popup is not already selected, select just that one
int[] sel = propList.getSelectedIndices();
boolean valid = false;
for (int i = 0; i < sel.length; i++) {
if (sel[i] == index) {
valid = true;
break;
}
}
if (!valid) {
propList.setSelectedIndex(index);
}
}
// disable certain actions if any of the selected propeties are currently being edited
int[] sel = propList.getSelectedIndices();
boolean showDeleters = true;
for (int i = 0; i < sel.length; i++) {
if (propList.getProperty(sel[i]).isBeingEdited()) {
showDeleters = false;
break;
}
}
verifySelected.setEnabled(propList.existsValidSelectedProperties());
simulate.setEnabled(propList.existsValidSimulatableSelectedProperties());
details.setEnabled(propList.existsValidSelectedProperties());
editProperty.setEnabled(propList.getSelectedProperties().size() > 0);
newExperiment.setEnabled(propList.getNumSelectedProperties() == 1 && propList.getValidSelectedProperties().size() == 1);
if (showDeleters == false) {
simulate.setEnabled(false);
verifySelected.setEnabled(false);
details.setEnabled(false);
editProperty.setEnabled(false);
newExperiment.setEnabled(false);
}
propertiesPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == consTable || e.getSource() == constantsScroll)) {
constantsPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == labTable || e.getSource() == labelsScroll)) {
labelsPopup.show(e.getComponent(), e.getX(), e.getY());
} else if (e.isPopupTrigger() && (e.getSource() == experiments || e.getSource() == expScroller)) {
doEnables();
this.experimentPopup.show(e.getComponent(), e.getX(), e.getY());
}
}
}
public void componentAdded(ContainerEvent e)
{
// notify GUIClipboard
selectionChangeHandler.notifyListeners(new GUIEvent(1));
}
public void componentRemoved(ContainerEvent e)
{
// notify GUIClipboard
selectionChangeHandler.notifyListeners(new GUIEvent(1));
}
//METHODS TO IMPLEMENT ListSelectionListener INTERFACE
public void valueChanged(ListSelectionEvent e)
{
ArrayList<GUIProperty> selectedProps = propList.getSelectedProperties();
// disable certain actions if any of the selected properties are currently being edited
boolean showDeleters = true;
for (int i = 0; i < selectedProps.size(); i++) {
if (((GUIProperty) selectedProps.get(i)).isBeingEdited()) {
showDeleters = false;
break;
}
}
verifySelected.setEnabled(propList.existsValidSelectedProperties());
simulate.setEnabled(propList.existsValidSimulatableSelectedProperties());
details.setEnabled(propList.existsValidSelectedProperties());
editProperty.setEnabled(propList.getSelectedProperties().size() > 0);
if (showDeleters == false) {
simulate.setEnabled(false);
verifySelected.setEnabled(false);
details.setEnabled(false);
editProperty.setEnabled(false);
}
updateCommentLabel();
//Now do the one for the constants table
removeConstant.setEnabled(consTable.getSelectedRowCount() > 0);
removeLabel.setEnabled(labTable.getSelectedRowCount() > 0);
// notify GUIClipboard
selectionChangeHandler.notifyListeners(new GUIEvent(1));
}
//CONSTRUCTOR HELPER METHODS
JScrollPane constantsScroll, labelsScroll;
JTextArea comLabel;
private void initComponents()
{
setupActions();
//panel
JSplitPane mainSplit = new JSplitPane();
{
JPanel left = new JPanel();
{
left.setMinimumSize(new java.awt.Dimension(10, 10));
JSplitPane leftSc = new JSplitPane();
{
JPanel topLeft = new JPanel();
{
JScrollPane propScroll = new JScrollPane();
{
propList = new GUIPropertiesList(getPrism(), this);
propList.addListSelectionListener(this);
propList.addContainerListener(this);
propScroll.setViewportView(propList);
}
JScrollPane comScroll = new JScrollPane();
comLabel = new JTextArea();
{
comLabel.setRows(2);
comLabel.setEditable(false);
//comLabel.setPreferredSize(new Dimension(300, 20));
//comLabel.setMinimumSize(new Dimension(10,10));
}
comScroll.setViewportView(comLabel);
topLeft.setLayout(new BorderLayout());
topLeft.add(propScroll, BorderLayout.CENTER);
topLeft.add(comScroll, BorderLayout.SOUTH);
topLeft.setBorder(new TitledBorder("Properties"));
}
JSplitPane bottomLeft = new JSplitPane();
{
constantsScroll = new JScrollPane();
{
consTable = new GUIPropConstantList(this);
consTable.setBackground(Color.white);
consTable.addMouseListener(this);
constantsScroll.setViewportView(consTable);
constantsScroll.addMouseListener(this);
constantsScroll.setBorder(new TitledBorder("Constants"));
}
labelsScroll = new JScrollPane();
{
labTable = new GUIPropLabelList(this);
labTable.setBackground(Color.white);
labTable.addMouseListener(this);
labelsScroll.setViewportView(labTable);
labelsScroll.addMouseListener(this);
labelsScroll.setBorder(new TitledBorder("Labels"));
}
bottomLeft.setOrientation(JSplitPane.VERTICAL_SPLIT);
bottomLeft.setTopComponent(constantsScroll);
bottomLeft.setBottomComponent(labelsScroll);
bottomLeft.setDividerLocation(0.5);
bottomLeft.setDividerSize(5);
bottomLeft.setResizeWeight(0.5);
}
leftSc.setOrientation(JSplitPane.VERTICAL_SPLIT);
leftSc.setTopComponent(topLeft);
leftSc.setBottomComponent(bottomLeft);
leftSc.setDividerLocation(0.5);
leftSc.setDividerSize(5);
leftSc.setResizeWeight(0.5);
}
left.setLayout(new BorderLayout());
left.add(leftSc, BorderLayout.CENTER);
}
JPanel right = new JPanel();
{
JSplitPane rightSplit = new JSplitPane();
{
JPanel topRight = new JPanel();
{
JToolBar stopTool = new JToolBar();
{
JButton b = new JButton(stopExperiment);
b.setToolTipText("Stop Current Experiment");
stopTool.add(b);
stopTool.setFloatable(false);
}
expScroller = new JScrollPane();
{
experiments = new GUIExperimentTable(this);
experiments.addMouseListener(this);
expScroller.addMouseListener(this);
expScroller.setViewportView(experiments);
}
topRight.setLayout(new BorderLayout());
topRight.add(stopTool, BorderLayout.NORTH);
topRight.add(expScroller, BorderLayout.CENTER);
}
JPanel bottomRight = new JPanel(new GridLayout(1, 1));
{
graphHandler = new GUIGraphHandler(this.getGUI(), this, true);
bottomRight.add(graphHandler);
bottomRight.setPreferredSize(new Dimension(300, 300));
//graphHandler.addGraph();
//graphHandler.addGraph();
}
rightSplit.setOrientation(JSplitPane.VERTICAL_SPLIT);
rightSplit.setTopComponent(topRight);
rightSplit.setBottomComponent(bottomRight);
rightSplit.setDividerLocation(0.5);
rightSplit.setDividerSize(5);
rightSplit.setResizeWeight(0.5);
}
right.setLayout(new BorderLayout());
right.setBorder(new TitledBorder("Experiments"));
right.add(rightSplit, BorderLayout.CENTER);
}
mainSplit.setLeftComponent(left);
mainSplit.setRightComponent(right);
mainSplit.setDividerLocation(0.5);
mainSplit.setOneTouchExpandable(true);
mainSplit.setResizeWeight(0.5);
}
JPanel topPanel = new JPanel();
{
fileLabel = new JLabel();
{
fileLabel.setHorizontalAlignment(javax.swing.SwingConstants.LEFT);
fileLabel.setBorder(new javax.swing.border.EtchedBorder());
fileLabel.setMinimumSize(new java.awt.Dimension(40, 25));
}
//progress = new JProgressBar(0, 100);
topPanel.setLayout(new BorderLayout());
//topPanel.add(progress, BorderLayout.WEST);
topPanel.add(fileLabel, BorderLayout.CENTER);
}
setLayout(new BorderLayout());
add(mainSplit, BorderLayout.CENTER);
add(topPanel, BorderLayout.NORTH);
//menu
propMenu = new JMenu("Properties");
{
//JSplitter split = new JSeparator();
propMenu.add(newProps);
propMenu.add(new JSeparator());
propMenu.add(openProps);
propMenu.add(insertProps);
propMenu.add(new JSeparator());
propMenu.add(saveProps);
propMenu.add(savePropsAs);
propMenu.add(new JSeparator());
propMenu.add(verifySelected);
propMenu.add(simulate);
propMenu.add(newExperiment);
propMenu.setMnemonic('P');
}
createPopups();
//file filters
propsFilter = new GUIPrismFileFilter[1];
propsFilter[0] = new GUIPrismFileFilter("PRISM properties (*.pctl, *.csl)");
propsFilter[0].addExtension("pctl");
propsFilter[0].addExtension("csl");
resultsFilter = new GUIPrismFileFilter[2];
resultsFilter[0] = new GUIPrismFileFilter("Plain text files (*.txt)");
resultsFilter[0].addExtension("txt");
resultsFilter[1] = new GUIPrismFileFilter("Comma-separated values (*.csv)");
resultsFilter[1].addExtension("csv");
}
private void createPopups()
{
propertiesPopup = new JPopupMenu();
propertiesPopup.add(editProperty);
propertiesPopup.add(newProperty);
propertiesPopup.add(new JSeparator());
propertiesPopup.add(verifySelected);
propertiesPopup.add(simulate);
//experiment
propertiesPopup.add(newExperiment);
propertiesPopup.add(details);
propertiesPopup.add(new JSeparator());
propertiesPopup.add(GUIPrism.getClipboardPlugin().getCutAction());
propertiesPopup.add(GUIPrism.getClipboardPlugin().getCopyAction());
propertiesPopup.add(GUIPrism.getClipboardPlugin().getPasteAction());
propertiesPopup.add(GUIPrism.getClipboardPlugin().getDeleteAction());
propertiesPopup.add(new JSeparator());
propertiesPopup.add(GUIPrism.getClipboardPlugin().getSelectAllAction());
constantsPopup = new JPopupMenu();
constantsPopup.add(newConstant);
constantsPopup.add(removeConstant);
labelsPopup = new JPopupMenu();
labelsPopup.add(newLabel);
labelsPopup.add(removeLabel);
consTable.addMouseListener(this);
propList.addMouseListener(this);
experimentPopup = new JPopupMenu();
experimentPopup.add(newExperiment);
experimentPopup.add(deleteExperiment);
experimentPopup.add(new JSeparator());
experimentPopup.add(viewResults);
experimentPopup.add(plotResults);
JMenu exportResultsMenu = new JMenu("Export results");
exportResultsMenu.setMnemonic('E');
exportResultsMenu.setIcon(GUIPrism.getIconFromImage("smallExport.png"));
exportResultsMenu.add(exportResultsListText);
exportResultsMenu.add(exportResultsListCSV);
exportResultsMenu.add(exportResultsMatrixText);
exportResultsMenu.add(exportResultsMatrixCSV);
experimentPopup.add(exportResultsMenu);
}
private void setupActions()
{
newProps = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_newList();
}
};
newProps.putValue(Action.LONG_DESCRIPTION, "Clears the current properties list, and the current active properties list.");
//newProps.putValue(Action.SHORT_DESCRIPTION, "New properties list");
newProps.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_N));
newProps.putValue(Action.NAME, "New properties list");
newProps.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallNew.png"));
newProps.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_N, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK));
openProps = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_open();
}
};
openProps.putValue(Action.LONG_DESCRIPTION, "Opens a properties list, checking that it is valid according to the current parsed model");
//openProps.putValue(Action.SHORT_DESCRIPTION, "Open properties list");
openProps.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_O));
openProps.putValue(Action.NAME, "Open properties list...");
openProps.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallOpen.png"));
openProps.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_O, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK));
saveProps = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_save();
}
};
saveProps.putValue(Action.LONG_DESCRIPTION,
"Saves all properties to the current active properties list, if non exists the user is prompted with a dialog.");
// saveProps.putValue(Action.SHORT_DESCRIPTION, "Save properties list");
saveProps.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
saveProps.putValue(Action.NAME, "Save properties list");
saveProps.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallSave.png"));
saveProps.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_S, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | InputEvent.SHIFT_MASK));
savePropsAs = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_saveAs();
}
};
savePropsAs.putValue(Action.LONG_DESCRIPTION, "Saves all properties to a new file selected by the user from a dialog.");
//savePropsAs.putValue(Action.SHORT_DESCRIPTION, "Save properties list As...");
savePropsAs.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_A));
savePropsAs.putValue(Action.NAME, "Save properties list as...");
savePropsAs.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallSaveAs.png"));
insertProps = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_insert();
}
};
insertProps.putValue(Action.LONG_DESCRIPTION,
"Inserts properties from user selected file into the properties list. The active property file remains the same however.");
//insertProps.putValue(Action.SHORT_DESCRIPTION, "Insert properties list");
insertProps.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_I));
insertProps.putValue(Action.NAME, "Insert properties list...");
insertProps.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallAdd.png"));
simulate = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_simulateSelected();
}
};
simulate.putValue(Action.LONG_DESCRIPTION, "Calls the PRISM simulator to approximately model check the selected properties against the parsed model.");
simulate.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_S));
simulate.putValue(Action.NAME, "Simulate");
simulate.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallSimulate.png"));
simulate.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F6, 0));
details = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_detailSelected();
}
};
details.putValue(Action.LONG_DESCRIPTION, "Shows the details for the currently selected properties in a dialog box.");
details.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
details.putValue(Action.NAME, "Show details");
details.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallDetails.png"));
verifySelected = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_verifySelected();
}
};
verifySelected
.putValue(
Action.LONG_DESCRIPTION,
"Model checks the selected properties against the model that is built. If there is no built model, the parsed model is automatically built. If the parsed model has changed since the last build, the user is prompted as to whether they wish to re-build the model. If the model text has been modified since the last build, the user is asked whether they want to re-parse and re-build.");
//verifySelected.putValue(Action.SHORT_DESCRIPTION, "Verify Selected Properties");
verifySelected.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_V));
verifySelected.putValue(Action.NAME, "Verify");
verifySelected.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallTick.png"));
verifySelected.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F5, 0));
newProperty = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_newProperty();
}
};
newProperty.putValue(Action.LONG_DESCRIPTION, "Brings up a dialog to add a new property to the list.");
newProperty.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
newProperty.putValue(Action.NAME, "Add");
newProperty.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallAdd.png"));
editProperty = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_editProperty();
}
};
editProperty.putValue(Action.LONG_DESCRIPTION, "Brings up a dialog to edit a selected property.");
editProperty.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_E));
editProperty.putValue(Action.NAME, "Edit");
editProperty.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallEdit.png"));
newConstant = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_addConstant();
}
};
newConstant.putValue(Action.LONG_DESCRIPTION, "Adds a new constant to the constants list");
newConstant.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
newConstant.putValue(Action.NAME, "Add constant");
newConstant.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallAdd.png"));
removeConstant = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_removeSelectedConstants();
}
};
removeConstant.putValue(Action.LONG_DESCRIPTION, "Deletes selected constants");
removeConstant.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
removeConstant.putValue(Action.NAME, "Delete constant");
removeConstant.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallDelete.png"));
newLabel = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_addLabel();
}
};
newLabel.putValue(Action.LONG_DESCRIPTION, "Adds a new Label to the Labels list");
newLabel.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
newLabel.putValue(Action.NAME, "Add label");
newLabel.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallAdd.png"));
removeLabel = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_removeSelectedLabels();
}
};
removeLabel.putValue(Action.LONG_DESCRIPTION, "Deletes selected Labels");
removeLabel.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
removeLabel.putValue(Action.NAME, "Delete label");
removeLabel.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallDelete.png"));
newExperiment = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_newExperiment();
}
};
newExperiment.putValue(Action.LONG_DESCRIPTION, "Creates a new experiment");
newExperiment.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_N));
newExperiment.putValue(Action.NAME, "New experiment");
newExperiment.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallExperiment.png"));
newExperiment.putValue(Action.ACCELERATOR_KEY, KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0));
deleteExperiment = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_deleteExperiment();
}
};
deleteExperiment.putValue(Action.LONG_DESCRIPTION, "Deletes the selected experiment");
deleteExperiment.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_D));
deleteExperiment.putValue(Action.NAME, "Delete experiment");
deleteExperiment.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallDelete.png"));
viewResults = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_viewResults();
}
};
viewResults.putValue(Action.LONG_DESCRIPTION, "View the results of this experiment");
viewResults.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_V));
viewResults.putValue(Action.NAME, "View results");
viewResults.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallView.png"));
plotResults = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_plotResults();
}
};
plotResults.putValue(Action.LONG_DESCRIPTION, "Plot the results of this experiment in a graph series");
plotResults.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_P));
plotResults.putValue(Action.NAME, "Plot results");
plotResults.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallFileGraph.png"));
exportResultsListText = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_exportResults(false, "\t");
}
};
exportResultsListText.putValue(Action.LONG_DESCRIPTION, "Export the results of this experiment to a text file");
exportResultsListText.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_L));
exportResultsListText.putValue(Action.NAME, "List (text)");
exportResultsListText.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallFileText.png"));
exportResultsListCSV = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_exportResults(false, ", ");
}
};
exportResultsListCSV.putValue(Action.LONG_DESCRIPTION, "Export the results of this experiment to a CSV file");
exportResultsListCSV.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_L));
exportResultsListCSV.putValue(Action.NAME, "List (CSV)");
exportResultsListCSV.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallMatrix.png"));
exportResultsMatrixText = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_exportResults(true, "\t");
}
};
exportResultsMatrixText.putValue(Action.LONG_DESCRIPTION, "Export the results of this experiment to a file in matrix form");
exportResultsMatrixText.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_M));
exportResultsMatrixText.putValue(Action.NAME, "Matrix (text)");
exportResultsMatrixText.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallFileText.png"));
exportResultsMatrixCSV = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_exportResults(true, ", ");
}
};
exportResultsMatrixCSV.putValue(Action.LONG_DESCRIPTION, "Export the results of this experiment to a file in matrix form");
exportResultsMatrixCSV.putValue(Action.MNEMONIC_KEY, new Integer(KeyEvent.VK_M));
exportResultsMatrixCSV.putValue(Action.NAME, "Matrix (CSV)");
exportResultsMatrixCSV.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallMatrix.png"));
stopExperiment = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
a_stopExperiment();
}
};
stopExperiment.putValue(Action.LONG_DESCRIPTION, "Stops the Experiment that is currently running");
stopExperiment.putValue(Action.SMALL_ICON, GUIPrism.getIconFromImage("smallStop.png"));
stopExperiment.setEnabled(false);
}
/**
* Getter for property propList.
* @return Value of property propList.
*/
public userinterface.properties.GUIPropertiesList getPropList()
{
return propList;
}
/**
* Getter for property consTable.
* @return Value of property consTable.
*/
public userinterface.properties.GUIPropConstantList getConsTable()
{
return consTable;
}
/**
* Getter for property labTable.
* @return Value of property labTable.
*/
public userinterface.properties.GUIPropLabelList getLabTable()
{
return labTable;
}
public void notifySettings(PrismSettings settings)
{
displayFontFast = settings.getFontColorPair(PrismSettings.PROPERTIES_FONT).f;
setFont(displayFontFast);
backgroundFast = new Color(202, 225, 255);
warningFast = settings.getColor(PrismSettings.PROPERTIES_WARNING_COLOUR);
repaint();
}
public static DataFlavor getGUIClipboardPropertiesDataFlavor()
{
return new DataFlavor(GUIClipboardProperties.class, "PRISM Property List");
}
/**
* A class that allows sets of properties to be put on the clipboard.
*/
public class GUIClipboardProperties implements Transferable
{
private ArrayList listOfProperties;
private StringSelection stringRepresentation;
public GUIClipboardProperties(ArrayList listOfProperties)
{
this.listOfProperties = listOfProperties;
String tmpString = "";
for (int i = 0; i < listOfProperties.size(); i++) {
GUIProperty gp = (GUIProperty) listOfProperties.get(i);
if (gp.getComment().trim().length() > 0) {
tmpString += "//" + gp.getComment() + "\n";
}
tmpString += gp.getPropString();
if (i != listOfProperties.size() - 1)
tmpString += "\n";
}
stringRepresentation = new StringSelection(tmpString);
}
public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException
{
if (flavor.getRepresentationClass() == this.getClass()) {
return this;
} else {
return this.stringRepresentation.getTransferData(flavor);
}
}
public DataFlavor[] getTransferDataFlavors()
{
DataFlavor[] stringFlavors = stringRepresentation.getTransferDataFlavors();
DataFlavor[] allFlavors = new DataFlavor[stringFlavors.length + 1];
allFlavors[0] = GUIMultiProperties.getGUIClipboardPropertiesDataFlavor();
for (int i = 0; i < stringFlavors.length; i++) {
allFlavors[i + 1] = stringFlavors[i];
}
return allFlavors;
}
public boolean isDataFlavorSupported(DataFlavor flavor)
{
return (stringRepresentation.isDataFlavorSupported(flavor) || flavor.equals(GUIMultiProperties.getGUIClipboardPropertiesDataFlavor()));
}
public ArrayList getProperties()
{
return listOfProperties;
}
}
}