/* Copyright (c) 1997-2006
Ewgenij Gawrilow, Michael Joswig (Technische Universitaet Berlin, Germany)
http://www.math.tu-berlin.de/polymake, mailto:polymake@math.tu-berlin.de
This program 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, or (at your option) any
later version: http://www.gnu.org/licenses/gpl.txt.
This program 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.
$Project: polymake $$Id: JavaviewSpringEmbedderFrame.java 7529 2006-12-20 16:57:12Z thilosch $
*/
package de.tuberlin.polymake.graph;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Checkbox;
import java.awt.CheckboxGroup;
import java.awt.Component;
import java.awt.Frame;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;
import javax.swing.JPanel;
import javax.swing.JSplitPane;
import jv.number.PuDouble;
import jv.object.PsDebug;
import jv.object.PsObject;
import jv.object.PsPanel;
import jv.project.PgGeometryIf;
import jv.project.PvPickEvent;
import jv.project.PvPickListenerIf;
import jv.vecmath.PdVector;
import de.tuberlin.polymake.common.EmbeddedGeometries;
import de.tuberlin.polymake.common.JavaviewUtils;
import de.tuberlin.polymake.common.JavaviewControl;
import de.tuberlin.polymake.common.PointSet;
import de.tuberlin.polymake.common.JavaviewFrame;
import de.tuberlin.polymake.common.SimpleGeometryParser;
/**
* Frame used to display a Schlegel Diagram which can be interactively
* modified by dragging vertices, changing the zoomFactor and selecting
* new projection facets. The data which is sent will be filtered using the
* MsgQueue.
*
* @author Thilo Schröder
*
*/
public class JavaviewSpringEmbedderFrame extends JavaviewFrame implements PvPickListenerIf {
/** Help frame belonging to the Schlegelframe */
protected static JavaviewSpringEmbedderHelpFrame helpFrame = null;
protected CheckboxGroup stepCheckboxGroup = new CheckboxGroup();
protected TextField stepField = new TextField();
protected Button helpButton = new Button("Help");
protected Button sendButton = new Button("Recompute");
protected Button stopButton = new Button("Stop");
protected Button restartButton = new Button("Reset");
protected boolean autoRecompute = false;
protected boolean startup = true;
/**
* Create a frame displaying the given geometry with given zoom parameter.
* The output of any event is written into a pipe.
*
* @param i_geom geometry to be displayed
* @param params non Javaview jvx parameters
* @param sink
*/
public JavaviewSpringEmbedderFrame(EmbeddedGeometries geoms,
Properties params, Properties iparams,
JavaviewControl parent) {
super(geoms,params,iparams,parent);
setUpGUI();
for(Iterator it = iparameters.keySet().iterator(); it.hasNext();) {
String prop = (String)it.next();
if (!params.getProperty(prop).equals("null")) {
parameters.setProperty(prop,params.getProperty(prop));
PuDouble slider = (PuDouble)sliderMap.get(prop);
slider.setValue(Double.parseDouble(parameters.getProperty(prop)));
}
}
parameters.setProperty("continue",params.getProperty("continue"));
disp.addPickListener(this);
disp.fit();
pack();
}
/** update the frame with new values for the vertices and the zoom Factor */
public void update(PointSet ps, Properties params) {
if(!getTitle().equals(ps.getName())) {
title = ps.getName();
setTitle(title);
}
stopButton.setEnabled(autoRecompute);
for(Iterator it = iparameters.keySet().iterator(); it.hasNext();) {
String param = (String)(it.next());
if (!params.getProperty(param).equals("null")) {
parameters.setProperty(param,params.getProperty(param));
PuDouble slider = (PuDouble)(sliderMap.get(param));
slider.setValue(Double.parseDouble(parameters.getProperty(param)));
}
}
if (!params.getProperty("continue").equals("null")) {
parameters.setProperty("continue",params.getProperty("continue"));
stopButton.setEnabled(!(parameters.getProperty("continue").equals("0")));
}
geom.update(ps);
if(startup) { startup = false; disp.fit(); }
}
public boolean autoRecompute() {
return autoRecompute;
}
/* ---------------------GUI------------------------*/
public JPanel getParamPanel() {
JPanel paramPanel = new JPanel(new GridLayout(iparameters.size()+1,1));
paramPanel.add(getAnimationPanel());
for(Iterator it = iparameters.keySet().iterator(); it.hasNext();) {
String param = (String)it.next();
String value = (String)(iparameters.get(param));
PuDouble slider;
if(value.equals("1")) {
slider = new PuDouble(param,new directSlider(param));
} else {
slider = new PuDouble(param,null);
}
slider.setDefBounds(0.5, 100.0, 0.01, 1);
slider.init();
paramPanel.add(slider.assureInspector(PsPanel.INFO, PsPanel.INFO_EXT));
sliderMap.put(param,slider);
}
return paramPanel;
}
public JPanel getAnimationPanel() {
JPanel stepPanel = new JPanel(new GridLayout(1,6));
stepPanel.add(new Label("AnimationSteps"));
stepPanel.add(new Checkbox("none",stepCheckboxGroup,true));
stepPanel.add(new Checkbox("5",stepCheckboxGroup,false));
stepPanel.add(new Checkbox("10",stepCheckboxGroup,false));
stepPanel.add(new Checkbox("50",stepCheckboxGroup,false));
stepPanel.add(new Checkbox("100",stepCheckboxGroup,false));
stopButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(getStepValue().equals("0")) {
statusBar.setText("No animation to stop.");
} else {
autoRecompute = false;
}
}
});
stepPanel.add(stopButton);
return stepPanel;
}
public JPanel getComputationPanel() {
JPanel computationPanel = new JPanel(new BorderLayout());
JPanel buttonPanel = new JPanel(new GridLayout(1,2));
restartButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
for(Iterator it = sliderMap.keySet().iterator(); it.hasNext();) {
String param = (String)it.next();
PuDouble slider = (PuDouble)sliderMap.get(param);
parameters.setProperty(param,Double.toString(slider.getValue()));
}
parameters.setProperty("step",getStepValue());
parameters.setProperty("continue",(!getStepValue().equals("0"))?"1":"0");
parameters.setProperty("restart","1");
parent.putMessage(SimpleGeometryParser.write(geom.getName(),parameters),true);
parameters.remove("restart");
statusBar.setText("Press <Recompute> to start embedding.");
} catch (IOException ex) {
System.err.println("SchlegelFrame: error writing to client");
ex.printStackTrace(System.err);
}
}
});
sendButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
for(Iterator it = sliderMap.keySet().iterator(); it.hasNext();) {
String param = (String)it.next();
PuDouble slider = (PuDouble)sliderMap.get(param);
parameters.setProperty(param,Double.toString(slider.getValue()));
}
parameters.setProperty("step",getStepValue());
parameters.setProperty("continue",(!getStepValue().equals("0"))?"1":"0");
Vector markedVertices = geom.getMarkedVertices();
parent.putMessage(SimpleGeometryParser.write(JavaviewUtils.toPointSet(geom.getEmbedding()),markedVertices,parameters),true);
statusBar.setText("");
} catch (IOException ex) {
System.err.println("SchlegelFrame: error writing to client");
ex.printStackTrace(System.err);
}
}
});
buttonPanel.add(restartButton);
buttonPanel.add(sendButton);
computationPanel.add(buttonPanel,BorderLayout.CENTER);
computationPanel.add(statusBar,BorderLayout.SOUTH);
return computationPanel;
}
public JPanel getSouthPanel() {
JPanel southPanel = new JPanel(new BorderLayout());
JPanel computationPanel = getComputationPanel();
southPanel.add(computationPanel, BorderLayout.SOUTH);
return southPanel;
}
protected String getStepValue() {
Checkbox selectedCheckbox = stepCheckboxGroup.getSelectedCheckbox();
if(selectedCheckbox.getLabel().equals("none")) {
autoRecompute = false;
return "0";
} else {
autoRecompute = true;
return selectedCheckbox.getLabel();
}
}
protected void setUpGUI() {
setLayout(new BorderLayout());
helpButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (helpFrame == null)
helpFrame = new JavaviewSpringEmbedderHelpFrame();
if (!helpFrame.isVisible()
|| helpFrame.getState() == Frame.ICONIFIED)
helpFrame.setLocation(getX() + 20, getY() + 20);
helpFrame.setState(Frame.NORMAL);
helpFrame.setVisible(true);
}
});
JPanel southPanel = getComputationPanel();
JPanel topPanel = new JPanel();
topPanel.setLayout(new BorderLayout());
topPanel.add(helpButton, BorderLayout.EAST);
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
(Component)disp, getParamPanel());
splitPane.setContinuousLayout(true);
splitPane.setOneTouchExpandable(true);
splitPane.setResizeWeight(1.);
add(topPanel, BorderLayout.NORTH);
add(splitPane, BorderLayout.CENTER);
add(southPanel, BorderLayout.SOUTH);
}
/**
* @author Thilo Schröder
*
* This class implements the update behaviour of the zoom factor slider.
*/
protected class directSlider extends PsObject {
protected String paramName;
public directSlider(String paramName) {
this.paramName = paramName;
}
public boolean update(java.lang.Object event) {
if (Double.parseDouble((String)(parameters.get(paramName))) == ((PuDouble) event).getValue())
return true;
parameters.setProperty(paramName, Double.toString(((PuDouble) event).getValue()));
try {
for(Iterator it = sliderMap.keySet().iterator(); it.hasNext();) {
String param = (String)it.next();
PuDouble slider = (PuDouble)(sliderMap.get(param));
parameters.setProperty(param,Double.toString(slider.getValue()));
}
parameters.setProperty("step",getStepValue());
parameters.setProperty("continue",(!getStepValue().equals("0"))?"1":"0");
parent.putMessage(SimpleGeometryParser.write(geom.getName(),parameters),true);
statusBar.setText("");
} catch (IOException ex) {
System.err.println("SpringEmbedderFrame: communication error");
ex.printStackTrace();
return false;
}
return true;
}
}
// ---------------- Begin of PvPickListenerIf ------------------------
/** The name of a listeners allows the display to issue verbal debug messages. */
public String getName() {
return "SpringEmbedderFramePicker";
}
/** Currently not supported by display yet. */
public void selectGeometry(PgGeometryIf geom) {
}
/**
* Get a location in the display with 2d display and 3d world coordinates.
* Method is called when display is in mode PvDisplayIf.MODE_DISPLAY_PICK.
* @see jv.project.PvPickListenerIf
* @param pos Pick event issued by the display
*/
public void pickDisplay(PvPickEvent pos) {
PsDebug.message("pickDisplay entered.");
}
/**
* Drag a location in the display with 2d display and 3d world coordinates.
* Method is called when display is in mode PvDisplayIf.MODE_DISPLAY_PICK.
* @see jv.project.PvPickListenerIf
* @param pos Pick event issued by the display
*/
public void dragDisplay(PvPickEvent pos) {
PsDebug.message("pickDisplay entered.");
}
/**
* Pick an arbitrary point on a geometry, point may lie inside an element.
* Method is called when display is in mode PvDisplayIf.MODE_INITIAL_PICK
* or if temporarily the i-key is pressed, and any pixel in the display is picked.
* @see jv.project.PvPickListenerIf
* @param pos Pick event issued by the display
*/
public void pickInitial(PvPickEvent pos) {
// PsDebug.message("pickInitial entered.");
}
/**
* Drag an arbitrary point along a geometry, point may lie inside an element.
* Method is called when display is in mode PvDisplayIf.MODE_INITIAL_PICK
* or if temporarily the i-key is pressed, and any pixel in the display is dragged.
* @see jv.project.PvPickListenerIf
* @param pos Pick event issued by the display
*/
public void dragInitial(PvPickEvent pos) {
// PsDebug.message("dragInitial entered = "+pos.getLocation());
}
/**
* Get a picked vertex of a geometry.
* Method is called when display is in mode PvDisplayIf.MODE_PICK
* or if temporarily the p-key is pressed, and a vertex picked.
* @see jv.project.PvPickListenerIf
* @param geom Picked geometry on which vertex lies
* @param index Index of vertex in vertex array of geometry
* @param vertex 3d coordinates of vertex position
*/
public void pickVertex(PgGeometryIf geom, int index, PdVector vertex) {
}
/**
* <p>Method is called when display is in mode PvDisplayIf.MODE_PICK
* or if temporarily the p-key is pressed, and a vertex dragged.</p>
* <p>Drag a picked vertex of a geometry and put its coordinates into
* the MsgQueue. If the queue is empty sent PolymakeFrame.ANSWER
* to sink.</p>
*
* @param geom Picked geometry on which vertex lies
* @param index Index of vertex in vertex array of geometry
* @param vertex 3d coordinates of vertex position
*/
public void dragVertex(PgGeometryIf a_geom, int index, PdVector vertex) {
geom.moveVertex(a_geom.getName(),index,vertex);
}
/**
* Mark a set of vertices of a geometry within a given bounding box.
* Method is called when display is in mode PvDisplayIf.MODE_MARK
* or if temporarily the m-key is pressed, and a rectangle is drawn.
* @param markBox contains four coplanar points on the bounding prism,
* and direction of prism.
*/
public void markVertices(PvPickEvent markBox) {
}
/**
* Unmark a set of vertices of a geometry within a given bounding box.
* Method is called when display is in mode PvDisplayIf.MODE_UNMARK
* or if temporarily the u-key is pressed, and a rectangle is drawn.
* @param markBox contains four coplanar points on the bounding prism, and direction of prism.
*/
public void unmarkVertices(PvPickEvent markBox) {
// PsDebug.message("unmarkVertices entered. Unmarked Vertex: " + pos.getVertexInd());
}
// ---------------- End of PvPickListenerIf ------------------------
}
syntax highlighted by Code2HTML, v. 0.9.1