package bs.bs2d.gui.views;
import bs.bs2d.fea.BoundaryCondition;
import bs.bs2d.gui.plot.ColorMap;
import bs.bs2d.fea.FEAResults;
import bs.bs2d.gui.plot.ScalarPlot;
import bs.bs2d.fea.TriMesh2D;
import bs.bs2d.gui.BSConstants;
import bs.bs2d.gui.BusyStateListener;
import bs.bs2d.gui.MainGUI;
import bs.bs2d.gui.UserMessage;
import bs.bs2d.gui.plot.PlotPanel;
import bs.bs2d.io.CalculixIO;
import bs.bs2d.io.MeshReader;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.util.List;
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JRadioButtonMenuItem;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
/**
*
* @author Djen
*/
public class ResultView implements BSGUIView{
private static final String NAME = "View Results";
// gui
private final PlotPanel content;
private final ResultViewControls controls;
private final JMenu[] menus;
private JCheckBoxMenuItem chkWire;
ButtonGroup legendPosition;
// data
private FEAResults results;
private ScalarPlot scalarPlot;
private ScalarPlot defScalarPlot;
private TriMesh2D defMesh;
BusyStateListener bsl;
public ResultView(){
content = new PlotPanel();
ActionListener exUpdatePlot = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
updatePlot();
}
};
ActionListener exUpdateColorMap = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
ColorMap.Style style = controls.getColorMapStyle();
if(scalarPlot != null)
scalarPlot.setColorMapStyle(style);
if(defScalarPlot != null)
defScalarPlot.setColorMapStyle(style);
content.repaint();
}
};
ActionListener exToggleDeformed = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
setShowDeformed(controls.showDeformed());
}
};
ActionListener exSave = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(BSConstants.workFile);
fc.setFileFilter(FEAResults.getFileFilter());
int result = fc.showSaveDialog(null);
if(result == JFileChooser.APPROVE_OPTION){
System.out.println(fc.getSelectedFile());
saveResults(fc.getSelectedFile());
}
}
};
ActionListener exLoad = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JFileChooser fc = new JFileChooser(BSConstants.workFile);
fc.setFileFilter(FEAResults.getFileFilter());
int result = fc.showOpenDialog(null);
if(result == JFileChooser.APPROVE_OPTION)
loadResults(fc.getSelectedFile());
}
};
controls = new ResultViewControls(exUpdatePlot, exUpdateColorMap, exToggleDeformed, exSave, exLoad);
menus = buildMenus();
}
private void saveResults(File dat){
File tmpdat = BSConstants.getTempFile("dat");
File tmpmsh = BSConstants.getTempFile("msh");
if(!FilenameUtils.getExtension(dat.getParent()).equals("dat"))
dat = new File(dat.getPath() + ".dat");
File msh = new File(FilenameUtils.removeExtension(dat.getPath()) + ".msh");
try{
FileUtils.copyFile(tmpdat, dat);
FileUtils.copyFile(tmpmsh, msh);
} catch (IOException ex) {
UserMessage.showError("Unable to save file!", "The result file could not be saved.");
ex.printStackTrace();
}
}
private void loadResults(File dat) {
try {
init(FEAResults.getResultsFromFile(dat));
} catch (Exception ex) {
UserMessage.showError("Unable to load results!", "The result file could not be loaded.");
ex.printStackTrace();
}
}
private JMenu[] buildMenus(){
JMenu[] ms = new JMenu[1];
JMenu m = new JMenu("View");
chkWire = new JCheckBoxMenuItem("Wireframe");
chkWire.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if(scalarPlot != null)
scalarPlot.setShowWireframe(chkWire.isSelected());
if(defScalarPlot != null)
defScalarPlot.setShowWireframe(chkWire.isSelected());
}
});
chkWire.setSelected(false);
m.add(chkWire);
JMenu menuLegend = new JMenu("Legend Position");
JRadioButtonMenuItem[] mitLegendPos = new JRadioButtonMenuItem[4];
mitLegendPos[0] = new JRadioButtonMenuItem("Upper Left");
mitLegendPos[1] = new JRadioButtonMenuItem("Upper Right");
mitLegendPos[2] = new JRadioButtonMenuItem("Lower Left");
mitLegendPos[3] = new JRadioButtonMenuItem("Lower Right");
mitLegendPos[0].setSelected(true);
legendPosition = new ButtonGroup();
ActionListener al = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
AbstractButton btn = (AbstractButton)e.getSource();
switch (btn.getText()) {
case "Upper Left":
content.setLegendPosition(PlotPanel.UPPER_LEFT);
break;
case "Upper Right":
content.setLegendPosition(PlotPanel.UPPER_RIGHT);
break;
case "Lower Left":
content.setLegendPosition(PlotPanel.LOWER_LEFT);
break;
case "Lower Right":
content.setLegendPosition(PlotPanel.LOWER_RIGHT);
break;
}
}
};
for (JRadioButtonMenuItem item : mitLegendPos){
item.addActionListener(al);
legendPosition.add(item);
menuLegend.add(item);
}
m.add(menuLegend);
m.addSeparator();
JMenuItem mitResetView = new JMenuItem("Reset View");
mitResetView.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
content.resetView();
}
});
m.add(mitResetView);
ms[0] = m;
return ms;
}
@Override
public JComponent getContent() {
return content;
}
@Override
public JComponent getControls() {
return controls;
}
@Override
public JMenu[] getMenus() {
return menus;
}
@Override
public void init(Object data) {
if(data instanceof Object[]){
Object[] o = (Object[]) data;
TriMesh2D mesh = (TriMesh2D) o[0];
if(mesh != null){
List<BoundaryCondition> bcs = (List<BoundaryCondition>)o[1];
runAnalysis(mesh, bcs);
return;
}
}else if(data instanceof FEAResults){
init((FEAResults)data);
return;
}
// no valid data
if(MainGUI.DEBUG_RESULTS){
try {
File msh = BSConstants.getTempFile("msh");
TriMesh2D mesh = MeshReader.readMesh(msh);
File out = BSConstants.getTempFile("dat");
init(FEAResults.getResultsFromFile(mesh, out));
} catch (Exception ex) {
System.err.println("Couldn't load temp files from previous session.");
ex.printStackTrace();
}
} else {
results = null;
updatePlot();
}
}
private void init(FEAResults results){
this.results = results;
float scale = results.getMeshDeformationScale(0.1f);
controls.init(scale);
defMesh = results.getDeformedMesh(scale);
updatePlot();
content.resetView();
}
private void runAnalysis(final TriMesh2D mesh,
final List<BoundaryCondition> bcs){
bsl.setBusy(true);
new Thread(new Runnable() {
@Override
public void run() {
File in = BSConstants.getTempFile("inp");
CalculixIO.writeCCXInputFile(mesh, bcs, 5000, 0.3, in);
File out = CalculixIO.runCCX(in);
init(FEAResults.getResultsFromFile(mesh, out));
bsl.setBusy(false);
}
}).start();
}
public ScalarPlot createScalarPlot(boolean deformed){
if(results == null)
return null;
// colleact params
float[] scalar = results.getScalar(controls.getScalar());
ColorMap.Style styleID = controls.getColorMapStyle();
int res = controls.getResolution();
TriMesh2D msh;
if(deformed)
msh = defMesh;
else
msh = results.getMesh();
ScalarPlot sp;
sp = ScalarPlot.createLinearScalePlot(msh, scalar, res, styleID);
applyViewSettings(sp);
return sp;
}
private void updatePlot(){
boolean deformed = controls.showDeformed();
scalarPlot = null;
defScalarPlot = null;
setShowDeformed(deformed);
}
/**
* Switches between original and deformed view and updates the plots and
* plot panel as necessary
* @param deformed true to show the deforemed mesh
*/
private void setShowDeformed(boolean deformed){
if(deformed){
if(defScalarPlot == null)
defScalarPlot = createScalarPlot(deformed);
content.setPlotObject(defScalarPlot, false);
} else {
if(scalarPlot == null)
scalarPlot = createScalarPlot(deformed);
content.setPlotObject(scalarPlot, false);
}
}
private void applyViewSettings(ScalarPlot sp){
sp.setShowWireframe(chkWire.isSelected());
}
@Override
public Object getData() {
return new Object[]{results, controls.getColorMapStyle(), controls.getScalar()};
}
@Override
public String getName() {
return NAME;
}
@Override
public void setBusyStateListener(BusyStateListener bsl) {
this.bsl = bsl;
}
}