001 package nl.cwi.sen1.gui.plugin; 002 003 import java.awt.Color; 004 import java.awt.Dimension; 005 import java.awt.event.MouseAdapter; 006 import java.awt.event.MouseEvent; 007 008 import javax.swing.BorderFactory; 009 import javax.swing.Box; 010 import javax.swing.BoxLayout; 011 import javax.swing.JLabel; 012 import javax.swing.JPanel; 013 import javax.swing.JSlider; 014 import javax.swing.event.ChangeEvent; 015 import javax.swing.event.ChangeListener; 016 017 import nl.cwi.sen1.util.Preferences; 018 import prefuse.util.force.Force; 019 import prefuse.util.force.ForceSimulator; 020 021 /* A panel with sliders to configure a ForceSimulator. Adapted from 022 * the prefuse implementation. 023 * 024 */ 025 public class GraphForcePanel extends JPanel { 026 private ForceSimulator fsim; 027 028 public GraphForcePanel(ForceSimulator fsim, Preferences prefs) { 029 this.fsim = fsim; 030 this.setBackground(Color.WHITE); 031 initUI(prefs); 032 } 033 034 private void initUI(Preferences prefs) { 035 this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS)); 036 Force[] forces = fsim.getForces(); 037 // create a bordered box for every force, containing a 038 // configurator for every parameter of that force 039 for (int i = 0; i < forces.length; i++) { 040 Force f = forces[i]; 041 Box box = new Box(BoxLayout.Y_AXIS); 042 043 // We use the class name and the parameter name to get 044 // properties from the preferences 045 String name = f.getClass().getName(); 046 name = name.substring(name.lastIndexOf(".") + 1); 047 048 String label = prefs.getString("force." + name + ".label"); 049 box.setBorder(BorderFactory.createTitledBorder(label)); 050 051 for (int j = 0; j < f.getParameterCount(); j++) { 052 String parName = f.getParameterName(j); 053 final float min = prefs.getFloat("force." + name + "." 054 + parName + ".min"); 055 final float max = prefs.getFloat("force." + name + "." 056 + parName + ".max"); 057 final float def = prefs.getFloat("force." + name + "." 058 + parName + ".default"); 059 060 final JSlider slider = createSlider(f, j, min, max, def); 061 062 final String parLabel = prefs.getString("force." + name + "." 063 + parName + ".label"); 064 JLabel tag = new JLabel(parLabel); 065 tag.setPreferredSize(new Dimension(100, 20)); 066 tag.setMaximumSize(new Dimension(100, 20)); 067 tag.setToolTipText("click to return to default"); 068 tag.addMouseListener(new MouseAdapter() { 069 public void mouseClicked(MouseEvent e) { 070 slider.setValue(percentage(def, min, max)); 071 } 072 }); 073 074 Box paramBox = new Box(BoxLayout.X_AXIS); 075 paramBox.add(tag); 076 paramBox.add(Box.createHorizontalStrut(10)); 077 paramBox.add(Box.createHorizontalGlue()); 078 paramBox.add(slider); 079 box.add(paramBox); 080 } 081 this.add(box); 082 } 083 this.add(Box.createVerticalGlue()); 084 } 085 086 private static int percentage(float value, float min, float max) { 087 // first normalize the range to start at zero 088 max = max - min; 089 090 // then compute the percentage 091 value = value - min; 092 return (int) ((value / max) * 100); 093 } 094 095 private static float value(int percentage, float min, float max) { 096 float value; 097 // first normalize the range to start at zero 098 max = max - min; 099 100 // compute the value 101 value = (((float) percentage) / 100) * max; 102 103 // shift range back 104 value += min; 105 106 return value; 107 } 108 109 private JSlider createSlider(Force f, int param, final float min, 110 final float max, final float def) { 111 final JSlider slider = new JSlider(0, 100); 112 slider.setBackground(Color.WHITE); 113 114 // We store both a reference to the force and the index of the property 115 // in the widget 116 slider.putClientProperty("force", f); 117 slider.putClientProperty("param", new Integer(param)); 118 slider.setToolTipText("" + def); 119 slider.setValue(percentage(def, min, max)); 120 121 slider.addChangeListener(new ChangeListener() { 122 public void stateChanged(ChangeEvent event) { 123 JSlider s = (JSlider) event.getSource(); 124 125 // retrieve the force object, and the index of the property we 126 // want 127 Force f = (Force) s.getClientProperty("force"); 128 Integer param = (Integer) s.getClientProperty("param"); 129 130 // forward the new value to the force, and update the tooltip 131 float val = value(s.getValue(), min, max); 132 f.setParameter(param.intValue(), val); 133 s.setToolTipText("" + val); 134 } 135 }); 136 137 return slider; 138 } 139 }