package genegui; import java.awt.*; import java.awt.event.*; import java.awt.geom.*; import java.io.*; import java.util.*; import javax.swing.*; import javax.swing.event.*; import main.*; /** CellViewer.java This is a re-write of the CellViewer class to make it more efficient and possibly less silly.

The viewer is composed on a series verticaly arrayed panels. The first panel will always be used to display time step and other information. Each additional panel is a CellViewerPanel which can be configured to display the color information collected from one or more nodes. @author WJS */ public class CellSurfaceViewer extends JInternalFrame implements ModelStateChangeListener,GuiInterface { public static final int GRAPH_CELL = 0; public static final int GRAPH_BAR = 1; public static final int GRAPH_FUNCTION_LINEAR=0; public static final int GRAPH_FUNCTION_LOG=1; public static final int GRAPH_FUNCTION_EXP=2; public static final int GRAPH_FUNCTION_THRESH=3; public static final int GRAPH_FUNCTION_PSUEDO=4; /** A pointer to the attached NodeStateViewer if there is one */ private NodeStateViewer AttachedNodeStateViewer; /** Stores the cell shapes including scale and translation - speeds up painting */ private Polygon[] CellShapeArray; /** Stores the base cell shapes and locations */ private Polygon[] CellShapeArrayBase; /** Multiplier used for exp color maping*/ private float ExpMultiplier = 1f; /** Sets the type of graph being displayed */ private int GraphMode = GRAPH_CELL; /** Specifies what transformation function should be applied to the graph color */ private int GraphFunction = GRAPH_FUNCTION_LINEAR; /** Multiplier used for log color maping*/ private float LogMultiplier = 1f; /** The Main JMenuBar */ private JMenuBar MainMenu; /** The main panel */ private JPanel MainPanel; /** The unique instance of the optionspanel */ private CellViewOptionsPanel OptionsPanel; /** An array list of all the SingleNodeNodeViewerPaintPaenls */ private ArrayList PaintPanels = new ArrayList(); /** Controls the rate at which the display refreshes by rejecting changes in size below the RefreshReject */ private float RefreshReject = .03125f; /** Self Reference */ private CellSurfaceViewer SaveThis = this; /** The scale at which to draw the cell shape objects */ private double Scale = 5.0; /** If set to true, simple display mode is used which just shows values */ private boolean SimpleDisplay = false; /** Preferred dimension for the SingleNodeViewerPanels */ private Dimension SingleNodeViewerPanelDimension; /** The MainGui object that this belongs to */ private MainGui TheMainGui; /** A pointer to the Model being displayed */ private Model TheModel = null; /** A pointer to the ModelState used to pass information to the CellViewer */ private ModelState TheModelState = null; /** A pointer to the network found in each cell */ private Network TheNetwork = null; /** The threshold value used by the threshold colormap */ private float ThresholdValue = 0.5f; /** Translation for drawing of cells */ private Point Translation = new Point(5,5); /** Simple constructor. @author WJS */ public CellSurfaceViewer(Model model, MainGui theMainGUI, String title, boolean simpleDisplay) { super(title,false,true,true,true); TheMainGui = theMainGUI; SimpleDisplay = simpleDisplay; MainPanel = new JPanel(); setContentPane(MainPanel); MainPanel.setLayout(new BoxLayout(MainPanel,BoxLayout.Y_AXIS)); setModel(model); setNetwork(model.net); // Build the unique copy of the options panel OptionsPanel = new CellViewOptionsPanel(); OptionsPanel.setLocation(getLocation()); OptionsPanel.setVisible(false); // Build the JMenuBar for the CellViewer MainMenu = new JMenuBar(); MainMenu.setBackground(Color.lightGray); JMenuItem item; // Displays JMenu displays = new JMenu("Displays"); displays.setBackground(Color.lightGray); item = new JMenuItem("Add New Node"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { addNewNode(); } }); displays.add(item); item = new JMenuItem("Remove All Nodes"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { removeAllNodes(); } }); displays.add(item); displays.addSeparator(); item = new JMenuItem("Options"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { OptionsPanel.toFront(); OptionsPanel.setLocation(getLocation()); OptionsPanel.setVisible(true); OptionsPanel.pack(); } }); displays.add(item); displays.addSeparator(); item = new JMenuItem("Close"); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { close(); } }); displays.add(item); MainMenu.add(displays); final JMenu graphs = new JMenu("Graphs"); graphs.setBackground(Color.lightGray); item = new JMenuItem("Cell Graph",new ImageIcon("icons/CSVChecked.gif")); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(graphs,GraphFunction); GraphMode = GRAPH_CELL; checkMenuItem(graphs,GraphFunction); repaint(); } }); graphs.add(item); item = new JMenuItem("Bar Graph"); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { // TODO Implement bar graph deal // unCheckJMenuItem(graphs,GraphFunction); // GraphMode = GRAPH_BAR; // checkMenuItem(graphs,GraphFunction); // repaint(); } }); graphs.add(item); MainMenu.add(graphs); // Color maps menu final JMenu colorMaps = new JMenu("ColorMaps"); colorMaps.setBackground(Color.lightGray); item = new JMenuItem("Linear",new ImageIcon("icons/CSVChecked.gif")); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(colorMaps,GraphFunction); GraphFunction = GRAPH_FUNCTION_LINEAR; checkMenuItem(colorMaps,GraphFunction); paintAll(); repaint(); } }); colorMaps.add(item); item = new JMenuItem("Logarithmic"); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(colorMaps,GraphFunction); GraphFunction = GRAPH_FUNCTION_LOG; checkMenuItem(colorMaps,GraphFunction); CellViewerLogControl viewer = new CellViewerLogControl(); Point p = SaveThis.getLocation(); // TODO - Autoposition viewer.setLocation(p); paintAll(); repaint(); } }); colorMaps.add(item); item = new JMenuItem("Exponential"); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(colorMaps,GraphFunction); GraphFunction = GRAPH_FUNCTION_EXP; checkMenuItem(colorMaps,GraphFunction); CellViewerExpControl viewer = new CellViewerExpControl(); Point p = SaveThis.getLocation(); // TODO - Autoposition viewer.setLocation(p); paintAll(); repaint(); } }); colorMaps.add(item); item = new JMenuItem("Linear Threshold"); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(colorMaps,GraphFunction); GraphFunction = GRAPH_FUNCTION_THRESH; checkMenuItem(colorMaps,GraphFunction); CellViewerThresholdControl viewer = new CellViewerThresholdControl(); Point p = SaveThis.getLocation(); // TODO - Autoposition viewer.setLocation(p); paintAll(); repaint(); } }); colorMaps.add(item); item = new JMenuItem("PseudoColor"); item.setHorizontalTextPosition(SwingConstants.LEFT); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { unCheckJMenuItem(colorMaps,GraphFunction); GraphFunction = GRAPH_FUNCTION_PSUEDO; checkMenuItem(colorMaps,GraphFunction); paintAll(); repaint(); } }); colorMaps.add(item); MainMenu.add(colorMaps); setJMenuBar(MainMenu); // Add an internal frame listener for capturing frame closing events addInternalFrameListener(new InternalFrameAdapter() { public void internalFrameClosing(InternalFrameEvent ife) { close(); } }); pack(); setVisible(true); setIconifiable(true); } /** Adds a new node display panel to the viewer. The new panel is put at the top of the display and its value is set to that of the first node in the list ofall nodes. @author WJS */ private void addNewNode() { // At the node panel NodeTemplate node = TheNetwork.getNode(0); SingleNodeViewerPanel p = new SingleNodeViewerPanel(node); MainPanel.add(p,0); // Keep track of the node pamel's paint panel for fast paint operations SingleNodeViewerPanel.SingleNodeViewerPaintPanel pp = p.getPaintPanel(); PaintPanels.add(pp); pp.paintOffScreen(true); pp.repaint(); pack(); } /** Checks the selected menu item. @param JMenu menu @param int index @author WJS */ private void checkMenuItem(JMenu menu, int index) { menu.getItem(index).setIcon(new ImageIcon("icons/CSVChecked.gif")); } /** Close up the JFrame properly, and disconnect fromlistener lists. @author WJS */ private void close() { TheModelState.removeModelStateChangeListener(this); dispose(); GeneNet.TheMainGui.removeInternalFrame(this); GeneNet.TheMainGui.removeGUIListener(this); OptionsPanel.dispose(); } /** Find the cell which contains point p. This is implemented in a slower but more general way to allow for different/multiple cells shapes and cell positions. It searche through the list of cell shapes and uses the contains method to identify the cell. @param Point p - A point in the ModelStateViewPane. @return int - The index of the cell or -1 if the point is not in a cell. @author WJS */ private int findCellAt(Point p) { for (int i=0;imaxX) maxX = rect.getX()+rect.getWidth(); if ((rect.getY()+rect.getHeight())>maxY) maxY = rect.getY()+rect.getHeight(); } SingleNodeViewerPanelDimension = new Dimension((int)maxX+20,(int)maxY+4); } /** Reinitializes all the SingleNodeViewerPanels @author WJS */ private void reinitPanels() { Component c[] = MainPanel.getComponents(); for (int i=0;i This was designed largely for backward compatibility to the original CellView. @author WJS */ private class SingleNodeViewerPanel extends JPanel { /** A pointer to the panel used to paint the cells */ private SingleNodeViewerPaintPanel PaintPanel; /** Selection box that allows the user to choose which node they are viewing */ private JComboBox NodeSelectionBox; /** Self reference */ private SingleNodeViewerPanel SaveThis = this; /** The Node Template this is attached to */ private NodeTemplate TheNodeTemplate; public SingleNodeViewerPanel(NodeTemplate theNodeTemplate) { super(); TheNodeTemplate = theNodeTemplate; // Set up panel for holding label and paint panel setBorder(BorderFactory.createLineBorder(Color.black,1)); setLayout(new BoxLayout(this,BoxLayout.X_AXIS)); setBackground(Color.lightGray); // Create the panel that the cell images will be painted into PaintPanel = new SingleNodeViewerPaintPanel(); // Create a mouse listener for detecting user mouse clicks on cells PaintPanel.addMouseListener(new MouseAdapter() { public void mouseClicked(MouseEvent me) { int cell = findCellAt(me.getPoint()); if ((AttachedNodeStateViewer==null)||(AttachedNodeStateViewer.isClosed())) { AttachedNodeStateViewer = new NodeStateViewer(TheModelState,TheMainGui,"Node Viewer"); TheModelState.addModelStateChangeListener(AttachedNodeStateViewer); GeneNet.TheMainGui.addInternalFrame(AttachedNodeStateViewer); } GeneNet.TheMainGui.showInternalFrame(AttachedNodeStateViewer); AttachedNodeStateViewer.setCell(cell); } }); init(); } private void init() { Dimension d; if (!SimpleDisplay) { // Build the JComboBox that shows which node is being displayed and // allows the user to change it. d = new Dimension(80,20); NodeSelectionBox = new JComboBox(); NodeSelectionBox.setPreferredSize(d); NodeSelectionBox.setMaximumSize(d); NodeSelectionBox.setMinimumSize(d); NodeSelectionBox.setBackground(Color.lightGray); NodeTemplate node; for (int i=0;i1.0) v=1; switch (GraphFunction) { case GRAPH_FUNCTION_LOG: try { v = (float)((Math.log(v*LogMultiplier)+1.0)/(Math.log(LogMultiplier)+1)); if (v>1) v = 1f; else if (v<0) v = 0f; } catch (Exception ex) { v = 0; } break; case GRAPH_FUNCTION_EXP: v = (float)(Math.exp(ExpMultiplier*v)/Math.exp(ExpMultiplier)); break; case GRAPH_FUNCTION_THRESH: if (v>ThresholdValue) v = 1; else v = 0; break; } if ((Math.abs(v-LastPaintedValues[i])>RefreshReject)||paintAll) { dirty = true; LastPaintedValues[i] = v; if (GraphFunction==GRAPH_FUNCTION_PSUEDO) { // TODO Math not quite right. Find proper LUT functions. red = (int)((1-v)*255); if (v<0.5) green = (int)(v*511); else green = (int)((1-v)*511); blue = (int)(v*255); } else { c = TheNodeTemplate.getColor(); red = (int)(v*c.getRed()); green = (int)(v*c.getGreen()); blue = (int)(v*c.getBlue()); } g.setColor(new Color(red,green,blue)); g.fillPolygon(CellShapeArray[i]); } } Redrawing = false; g.dispose(); } return(dirty); } } } /** CellViewerExpControl.java @author WJS */ private class CellViewerExpControl extends JFrame { private ExpGraphPanel TheGraph; public CellViewerExpControl() { super("Exponential Multiplier: "+ExpMultiplier); setIconifiable(false); setResizable(false); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS)); setContentPane(mainPanel); // Make panel for size slider and its label JPanel thresholdSliderPanel = new JPanel(); thresholdSliderPanel.setLayout(new BoxLayout(thresholdSliderPanel,BoxLayout.X_AXIS)); // Make slider for controling size of the display final JSlider thresholdSlider = new JSlider(JSlider.HORIZONTAL,1,10,(int)ExpMultiplier); thresholdSlider.setMinorTickSpacing(1); thresholdSlider.setMajorTickSpacing(1); thresholdSlider.setPaintTicks(true); thresholdSlider.setPaintLabels(true); thresholdSlider.setSnapToTicks(true); thresholdSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent ce) { ExpMultiplier = thresholdSlider.getValue(); setTitle("Exponential Multiplier: "+ExpMultiplier); TheGraph.repaint(); SaveThis.paintAll(); } }); thresholdSliderPanel.add(thresholdSlider); mainPanel.add(thresholdSliderPanel); // Make JPanel for drawing ColorMap graph TheGraph = new ExpGraphPanel(); TheGraph.setSize(300,300); mainPanel.add(TheGraph); // Add a WindowListener that will close down the control window if it // is de-activtaed or loses focus addWindowListener(new WindowAdapter() { public void windowLostFocus(WindowEvent we) { setVisible(false); } public void windowDeactivated(WindowEvent we) { if (!System.getProperty("os.name").startsWith("Mac")) setVisible(false); } }); setSize(300,370); setVisible(true); } /** ExpGraphPanel.java Extends JPanel to draw an exp graph @author WJS */ public class ExpGraphPanel extends JPanel { public ExpGraphPanel() { super(); setBorder(BorderFactory.createLineBorder(Color.black,1)); } /** Over-ride paint operation to draw the graph @author WJS */ public void paint(Graphics g) { super.paint(g); float v =.05f; int x1 = (int)(v*getWidth()); int y1 = getHeight()-(int)(Math.exp(v*ExpMultiplier)/Math.exp(ExpMultiplier)*getHeight()); int x2 = 0; int y2 = 0; for (int i=1;i<20;i++) { v += .05f; x2 = (int)(v*getWidth()); y2 = getHeight()-(int)(Math.exp(v*ExpMultiplier)/Math.exp(ExpMultiplier)*getHeight()); g.drawLine(x1,y1,x2,y2); x1 = x2; y1 = y2; } } } } /** CellViewerLogControl.java @author WJS */ private class CellViewerLogControl extends JFrame { private LogGraphPanel TheGraph; public CellViewerLogControl() { super("Log Multiplier: "+LogMultiplier); setIconifiable(false); setResizable(false); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS)); setContentPane(mainPanel); // Make panel for size slider and its label JPanel thresholdSliderPanel = new JPanel(); thresholdSliderPanel.setLayout(new BoxLayout(thresholdSliderPanel,BoxLayout.X_AXIS)); // Make slider for controling size of the display final JSlider thresholdSlider = new JSlider(JSlider.HORIZONTAL,1,10,(int)LogMultiplier); thresholdSlider.setMinorTickSpacing(1); thresholdSlider.setMajorTickSpacing(1); thresholdSlider.setPaintTicks(true); thresholdSlider.setPaintLabels(true); thresholdSlider.setSnapToTicks(true); thresholdSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent ce) { LogMultiplier = thresholdSlider.getValue(); setTitle("Log Multiplier: "+LogMultiplier); TheGraph.repaint(); SaveThis.paintAll(); } }); thresholdSliderPanel.add(thresholdSlider); mainPanel.add(thresholdSliderPanel); // Make JPanel for drawing ColorMap graph TheGraph = new LogGraphPanel(); TheGraph.setSize(300,300); mainPanel.add(TheGraph); // Add a WindowListener that will close down the control window if it // is de-activtaed or loses focus addWindowListener(new WindowAdapter() { public void windowLostFocus(WindowEvent we) { setVisible(false); } public void windowDeactivated(WindowEvent we) { if (!System.getProperty("os.name").startsWith("Mac")) setVisible(false); } }); setSize(300,370); setVisible(true); } /** LogGraphPanel.java Extends JPanel to draw a log graph @author WJS */ public class LogGraphPanel extends JPanel { public LogGraphPanel() { super(); setBorder(BorderFactory.createLineBorder(Color.black,1)); } /** Over-ride paint operation to draw the graph @author WJS */ public void paint(Graphics g) { super.paint(g); float temp = (float)(Math.log(LogMultiplier)+1); float v =.05f; int x1 = (int)(v*getWidth()); int y1 = getHeight()-(int)(((Math.log(v*LogMultiplier)+1)/temp)*getHeight()); int x2 = 0; int y2 = 0; for (int i=1;i<20;i++) { v += .05f; x2 = (int)(v*getWidth()); y2 = getHeight()-(int)(((Math.log(v*LogMultiplier)+1)/temp)*getHeight()); g.drawLine(x1,y1,x2,y2); x1 = x2; y1 = y2; } } } } /** CellViewerLinearControl.java @author WJS */ private class CellViewerThresholdControl extends JFrame { public CellViewerThresholdControl() { super("Threshhold Level: "+(int)(ThresholdValue*100f)); setIconifiable(false); setResizable(false); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS)); setContentPane(mainPanel); // Make panel for size slider and its label JPanel thresholdSliderPanel = new JPanel(); thresholdSliderPanel.setLayout(new BoxLayout(thresholdSliderPanel,BoxLayout.X_AXIS)); // Make slider for controling size of the display final JSlider thresholdSlider = new JSlider(JSlider.HORIZONTAL,0,100,(int)(ThresholdValue*100f)); thresholdSlider.setMinorTickSpacing(5); thresholdSlider.setMajorTickSpacing(25); thresholdSlider.setPaintTicks(true); thresholdSlider.setPaintLabels(true); thresholdSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent ce) { ThresholdValue = (float)thresholdSlider.getValue()/100f; setTitle("Threshhold Level: "+(int)(ThresholdValue*100f)); SaveThis.paintAll(); } }); thresholdSliderPanel.add(thresholdSlider); mainPanel.add(thresholdSliderPanel); // Add a WindowListener that will close down the control window if it // is de-activtaed or loses focus addWindowListener(new WindowAdapter() { public void windowLostFocus(WindowEvent we) { setVisible(false); } public void windowDeactivated(WindowEvent we) { if (!System.getProperty("os.name").startsWith("Mac")) setVisible(false); } }); setSize(350,70); setVisible(true); } } /** CellViewOptionsPanel.java @author WJS */ private class CellViewOptionsPanel extends JFrame { public CellViewOptionsPanel() { super("Cell View Options"); setIconifiable(false); setResizable(false); JPanel mainPanel = new JPanel(); mainPanel.setLayout(new BoxLayout(mainPanel,BoxLayout.Y_AXIS)); setContentPane(mainPanel); // Make panel for size slider and its label JPanel sizeSliderPanel = new JPanel(); sizeSliderPanel.setLayout(new BoxLayout(sizeSliderPanel,BoxLayout.X_AXIS)); // Make a label JLabel scaleLabel = new JLabel("Scale"); sizeSliderPanel.add(scaleLabel); // Make slider for controling size of the display final JSlider sizeSlider = new JSlider(JSlider.HORIZONTAL,0,25,(int)Scale); sizeSlider.setMinorTickSpacing(1); sizeSlider.setMajorTickSpacing(5); sizeSlider.setPaintTicks(true); sizeSlider.setPaintLabels(true); sizeSlider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent ce) { setScaleAndTranslation(sizeSlider.getValue(),Translation); Component[] c = MainPanel.getComponents(); for (int i=0;i