package uk.ac.rhul.cs.cl1.ui.cytoscape;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.ArrayList;
import java.util.Collections;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import cytoscape.Cytoscape;
import cytoscape.data.CyAttributes;
import cytoscape.view.cytopanels.CytoPanel;
import uk.ac.rhul.cs.cl1.ClusterONE;
import uk.ac.rhul.cs.cl1.ClusterONEAlgorithmParameters;
import uk.ac.rhul.cs.cl1.ui.ClusterONEAlgorithmParametersPanel;
import uk.ac.rhul.cs.cl1.ui.ClusterONEAlgorithmParametersPanel.Section;
import uk.ac.rhul.cs.cl1.ui.CollapsiblePanel;
/**
* Cytoscape control panel for ClusterONE
*
* @author tamas
*/
public class ControlPanel extends JPanel implements PropertyChangeListener {
/** Algorithm parameters panel embedded inside the control panel */
protected ClusterONEAlgorithmParametersPanel algorithmParametersPanel;
/** Selection info panel embedded inside the control panel */
protected SelectionPropertiesPanel selectionInfoPanel;
/** Combobox for selecting the appropriate weight attribute */
protected JComboBox weightAttributeCombo;
/** Button for refreshing the list of weight attributes */
protected JButton weightAttributeRefreshButton;
public ControlPanel() {
super();
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
JPanel algorithmParametersPanel = constructAlgorithmParametersPanel();
Dimension d = algorithmParametersPanel.getPreferredSize();
d.width = Integer.MAX_VALUE;
algorithmParametersPanel.setMaximumSize(d);
this.add(algorithmParametersPanel);
this.add(constructSelectionInfoPanel());
this.add(constructButtonPanel());
this.add(Box.createVerticalGlue());
}
protected JPanel constructAlgorithmParametersPanel() {
/* Algorithm parameters panel */
algorithmParametersPanel = new ClusterONEAlgorithmParametersPanel();
/* Weight attribute name method */
JPanel weightPanel = new JPanel();
weightPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0));
weightAttributeCombo = new JComboBox();
updateWeightAttributeCombo();
weightAttributeRefreshButton = new JButton(
new ImageIcon(this.getClass().getResource("../../resources/refresh.png"))
);
weightAttributeRefreshButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
updateWeightAttributeCombo();
}
});
if (ClusterONE.isRunningOnMac()) {
weightAttributeRefreshButton.putClientProperty("JButton.buttonType", "square");
}
weightPanel.add(weightAttributeCombo);
weightPanel.add(Box.createHorizontalStrut(3));
weightPanel.add(weightAttributeRefreshButton);
algorithmParametersPanel.addComponent(Section.BASIC, "Edge weights:", weightPanel);
try {
algorithmParametersPanel.monitorComponent(weightAttributeCombo);
} catch (Exception ex) {
ex.printStackTrace();
}
algorithmParametersPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE));
algorithmParametersPanel.addPropertyChangeListener(
"parameters", this);
return algorithmParametersPanel;
}
protected JPanel constructSelectionInfoPanel() {
selectionInfoPanel = new SelectionPropertiesPanel(this);
return new CollapsiblePanel(selectionInfoPanel, "Selection info");
}
protected JPanel constructButtonPanel() {
/* Button panel */
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout());
JButton startButton = new JButton("Start");
startButton.addActionListener(new StartAction());
buttonPanel.add(startButton);
JButton closeButton = new JButton("Close panel");
closeButton.addActionListener(new CloseControlPanelAction());
buttonPanel.add(closeButton);
JButton helpButton = new JButton(new HelpAction("control-panel"));
if (ClusterONE.isRunningOnMac()) {
helpButton.putClientProperty("JButton.buttonType", "help");
helpButton.setText("");
}
buttonPanel.add(helpButton);
return buttonPanel;
}
/**
* Returns a {@link ClusterONEAlgorithmParameters} object from the current state
* of the panel
*/
ClusterONEAlgorithmParameters getParameters() {
return algorithmParametersPanel.getParameters();
}
/**
* Retrieves the {@link ControlPanel} instance that is shown on the Cytoscape control panel
*
* @return the {@link ControlPanel} instance or null if no control panel is open
*/
public static ControlPanel getShownInstance() {
CytoPanel panel = Cytoscape.getDesktop().getCytoPanel(SwingConstants.WEST);
for (int i = 0; i < panel.getCytoPanelComponentCount(); i++) {
Component c = panel.getComponentAt(i);
if (c instanceof ControlPanel)
return (ControlPanel)c;
}
return null;
}
/**
* Returns the selected weight attribute name
*
* @return the selected weight attribute name or null if no weights should be used
*/
public String getWeightAttributeName() {
if (weightAttributeCombo.getSelectedIndex() == 0)
return null;
if (weightAttributeCombo.getSelectedItem() == null)
return null;
return weightAttributeCombo.getSelectedItem().toString();
}
/** Updates the weight attribute combo box to contain the suitable edge attribute
* names from the current Cytoscape network
*/
public void updateWeightAttributeCombo() {
Object currentItem = weightAttributeCombo.getSelectedItem();
weightAttributeCombo.removeAllItems();
weightAttributeCombo.addItem("[unweighted]");
CyAttributes attributes = Cytoscape.getEdgeAttributes();
ArrayList<String> names = new ArrayList<String>();
for (String attributeName: attributes.getAttributeNames()) {
if (!attributes.getUserVisible(attributeName))
continue;
byte type = attributes.getType(attributeName);
if (type != CyAttributes.TYPE_FLOATING && type != CyAttributes.TYPE_INTEGER)
continue;
names.add(attributeName);
}
Collections.sort(names);
for (String name: names)
weightAttributeCombo.addItem(name);
if (currentItem != null)
weightAttributeCombo.setSelectedItem(currentItem);
}
/**
* Called when the algorithm parameters have changed.
*
* This method will update the properties of the current selection in the
* info panel accordingly.
*/
public void propertyChange(PropertyChangeEvent evt) {
if (evt.getSource() == algorithmParametersPanel) {
selectionInfoPanel.setQualityFunction(
getParameters().getQualityFunction()
);
selectionInfoPanel.updateNodeSetFromSelection();
}
}
}