/* 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 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) { } /** *

Method is called when display is in mode PvDisplayIf.MODE_PICK * or if temporarily the p-key is pressed, and a vertex dragged.

*

Drag a picked vertex of a geometry and put its coordinates into * the MsgQueue. If the queue is empty sent PolymakeFrame.ANSWER * to sink.

* * @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 ------------------------ }