/*
* CCVisu is a tool for visual graph clustering
* and general force-directed graph layout.
* This file is part of CCVisu.
*
* Copyright (C) 2005-2012 Dirk Beyer
*
* CCVisu is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* CCVisu 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with CCVisu; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Please find the GNU Lesser General Public License in file
* license_lgpl.txt or http://www.gnu.org/licenses/lgpl.txt
*
* Dirk Beyer (firstname.lastname@uni-passau.de)
* University of Passau, Bavaria, Germany
*/
package org.sosy_lab.ccvisu.ui.controlpanel;
import java.awt.BorderLayout;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.DecimalFormat;
import java.util.EventObject;
import javax.swing.AbstractAction;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JFormattedTextField;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import org.sosy_lab.ccvisu.Options;
import org.sosy_lab.ccvisu.Options.InFormat;
import org.sosy_lab.ccvisu.Options.OptionsEnum;
import org.sosy_lab.ccvisu.layout.MinimizerBarnesHut;
import org.sosy_lab.ccvisu.layout.TwoPhaseMinimizer;
import org.sosy_lab.ccvisu.readers.ReaderData;
import org.sosy_lab.ccvisu.ui.StopTaskButton;
import org.sosy_lab.util.interfaces.WorkerManager;
@SuppressWarnings("serial")
public class ToolPanelLayouter extends ControlPanel {
private JCheckBox weightedCheckbox = new JCheckBox();
private JFormattedTextField gravitationTextField = new JFormattedTextField(DecimalFormat.getInstance());
private JComboBox<String> repulsionTypeTextField = new JComboBox<>();
private JFormattedTextField repulsionExponentTextField = new JFormattedTextField();
private JCheckBox animationCheckBox = new JCheckBox();
private JFormattedTextField attractionExponentTextField = new JFormattedTextField();
private JSpinner numOfIterationsSpinner = new JSpinner();
private JCheckBox autoStopIteratingCheckBox = new JCheckBox("Yes");
private JSpinner dimensionsSpinner = new JSpinner();
private JFormattedTextField scaleTextField = new JFormattedTextField();
private JButton chooseInitialLayoutButton = new JButton();
private JTextField initialLayoutTextField = new JTextField();
private JButton startMinimizerButton = new JButton("Run layouter");
private JButton randomLayoutButton = new JButton("Random layout");
private StopTaskButton stopTaskButton;
private final Options options;
private final WorkerManager workerManager;
public ToolPanelLayouter(Options options, WorkerManager workerManager) {
this.options = options;
this.workerManager = workerManager;
initComponents();
}
@Override
public void applyOptions() {
options.getOption(OptionsEnum.dim).set(((Integer) dimensionsSpinner.getValue()).intValue());
options.getOption(OptionsEnum.iter).set(Integer.parseInt(this.numOfIterationsSpinner.getValue().toString()));
options.getOption(OptionsEnum.autoStopIterating).set(autoStopIteratingCheckBox.isSelected());
options.getOption(OptionsEnum.initLayout).set(initialLayoutTextField.getText());
options.attrExponent = (Float) attractionExponentTextField.getValue();
options.repuExponent = (Float) repulsionExponentTextField.getValue();
options.gravitation = ((Number) gravitationTextField.getValue()).floatValue();
options.vertRepu = (repulsionTypeTextField.getSelectedIndex() == 1);
options.noWeight = !weightedCheckbox.isSelected();
options.getOption(OptionsEnum.scalePos).set((Float) scaleTextField.getValue());
options.getOption(OptionsEnum.anim).set(animationCheckBox.isSelected());
}
@Override
public void loadOptions() {
scaleTextField.setValue(new Float(options.getOption(OptionsEnum.scalePos).getFloat()));
dimensionsSpinner.setValue(options.getOption(OptionsEnum.dim).getInt());
numOfIterationsSpinner.setValue(options.getOption(OptionsEnum.iter).getInt());
autoStopIteratingCheckBox.setSelected(options.getOption(OptionsEnum.autoStopIterating).getBool());
initialLayoutTextField.setText(options.getOption(OptionsEnum.initLayout).getString());
attractionExponentTextField.setValue(new Float(options.attrExponent));
gravitationTextField.setValue(new Float(options.gravitation));
repulsionExponentTextField.setValue(new Float(options.repuExponent));
weightedCheckbox.setSelected(!options.noWeight);
animationCheckBox.setSelected(options.getOption(OptionsEnum.anim).getBool());
if (options.vertRepu) {
repulsionTypeTextField.setSelectedIndex(1);
} else {
repulsionTypeTextField.setSelectedIndex(0);
}
}
public void initComponents() {
stopTaskButton = new StopTaskButton(workerManager);
JPanel initLayoutPanel = new JPanel(new BorderLayout());
initLayoutPanel.add(initialLayoutTextField, BorderLayout.CENTER);
initLayoutPanel.add(chooseInitialLayoutButton, BorderLayout.EAST);
JPanel controlPanel = new JPanel();
controlPanel.add(randomLayoutButton);
controlPanel.add(startMinimizerButton);
controlPanel.add(stopTaskButton);
JPanel paramsPanel = new JPanel();
paramsPanel.setLayout(new GridBagLayout());
addOptionControls(paramsPanel, "Weighted edges?", weightedCheckbox);
addOptionControls(paramsPanel, "Animation during layouting?", animationCheckBox);
addOptionControls(paramsPanel, "Attraction exponent:", attractionExponentTextField);
addOptionControls(paramsPanel, "Repulsion exponent:", repulsionExponentTextField);
addOptionControls(paramsPanel, "Repulsion type:", repulsionTypeTextField);
addOptionControls(paramsPanel, "Gravitation:", gravitationTextField);
addOptionControls(paramsPanel, "Initial layout:", initLayoutPanel);
addOptionControls(paramsPanel, "Dimensions:", dimensionsSpinner);
addOptionControls(paramsPanel, "Scale factor:", scaleTextField);
addOptionControls(paramsPanel, "Number of iterations:", numOfIterationsSpinner);
addOptionControls(paramsPanel, "Stop iterating on energy minimum?", autoStopIteratingCheckBox);
this.setLayout(new BorderLayout());
this.add(paramsPanel, BorderLayout.CENTER);
this.add(controlPanel, BorderLayout.SOUTH);
animationCheckBox.setText("Yes");
repulsionTypeTextField.setModel(
new DefaultComboBoxModel<String>(new String[] { "Edge repulsion", "Vertex repulsion" }));
chooseInitialLayoutButton.setText("Choose...");
weightedCheckbox.setText("Yes");
setActionOnEnter(attractionExponentTextField);
setActionOnEnter(repulsionExponentTextField);
setActionOnEnter(gravitationTextField);
setActionOnEnter(scaleTextField);
setActionOnEnter(initialLayoutTextField);
setActionOnEnter(dimensionsSpinner);
setActionOnEnter(numOfIterationsSpinner);
setMnemonics();
registerListeners();
}
private void registerListeners() {
startMinimizerButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
applyAndMinimize();
}
});
randomLayoutButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent pE) {
options.graph.setNodesToRandomPositions(options.graph.getVertices(), options.getOption(OptionsEnum.dim).getInt());
options.graph.notifyAboutLayoutChange(new EventObject(this));
}
});
chooseInitialLayoutButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
JFileChooser fileDialog = new JFileChooser(".");
fileDialog.setFileFilter(ReaderData.mkExtensionFileFilter(InFormat.LAY));
int outcome = fileDialog.showOpenDialog(null);
if (outcome == JFileChooser.APPROVE_OPTION) {
assert (fileDialog.getCurrentDirectory() != null);
assert (fileDialog.getSelectedFile() != null);
String fileName =
fileDialog.getCurrentDirectory().toString() + File.separator
+ fileDialog.getSelectedFile().getName();
initialLayoutTextField.setText(fileName);
}
}
});
}
private void applyAndMinimize() {
applyOptions();
MinimizerBarnesHut minimizer = new TwoPhaseMinimizer(options);
workerManager.addAndRunTask(minimizer, "Minimizer");
}
private void setActionOnEnter(JComponent component) {
component.getInputMap().put(KeyStroke.getKeyStroke('\n'), "runMinimizer");
component.getActionMap().put("runMinimizer", new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
applyAndMinimize();
}
});
}
private void setMnemonics() {
chooseInitialLayoutButton.setMnemonic('C');
startMinimizerButton.setMnemonic('R');
stopTaskButton.setMnemonic('S');
}
}