package pikelake; import java.awt.BasicStroke; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; import java.awt.geom.Rectangle2D; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import com.thoughtworks.xstream.XStream; import com.thoughtworks.xstream.io.xml.DomDriver; import fr.cemagref.observation.gui.Configurable; import fr.cemagref.observation.gui.Drawable; import fr.cemagref.observation.kernel.ObservablesHandler; import fr.cemagref.observation.kernel.ObserverListener; import fr.cemagref.ohoui.annotations.Description; import fr.cemagref.ohoui.annotations.NoRecursive; import fr.cemagref.ohoui.filters.NoTransientField; import fr.cemagref.ohoui.swing.OhOUI; import fr.cemagref.ohoui.swing.OhOUIDialog; import fr.cemagref.simaqualife.kernel.util.TransientParameters; import fr.cemagref.simaqualife.pilot.Pilot; @SuppressWarnings("serial") @NoRecursive public class GridObserver extends ObserverListener implements Configurable, Drawable, MouseMotionListener { private transient JComponent display; private transient JLabel label; private transient Grid grid; private String title; private Color envColor = Color.GREEN; private Color preyColor = Color.BLUE; private Color pikeColor = Color.RED; @Description (name="Background color",tooltip="Background color") private Color bgColor = Color.WHITE; private transient int displayWidthBak,displayHeightBak; private transient double cellSizeX, cellSizeY; private transient int[] cellsAlpha; public String getTitle() { return title; } public JComponent getDisplay() { return display; } public void valueChanged(ObservablesHandler clObservable, Object instance, long t) { display.repaint(); } @TransientParameters.InitTransientParameters public void init(Pilot pilot) { // init display component display = new JPanel(new BorderLayout()); DisplayComponent displayComponent = new DisplayComponent(); displayComponent.addMouseMotionListener(this); displayComponent.setVisible(true); displayComponent.setDoubleBuffered(true); label = new JLabel(""); display.add(displayComponent,BorderLayout.CENTER); display.add(label,BorderLayout.PAGE_START); grid = (Grid)pilot.getAquaticWorld().getEnvironment(); // init display variables displayWidthBak = 0; displayHeightBak = 0; // compute HabitatQuality colors double cellsHabitatQualityMin = 0; double cellsHabitatQualityMax = 0; cellsAlpha = new int[grid.getCells().length]; if (grid.getCells().length > 0) { cellsHabitatQualityMin = grid.getCells()[0].getHabitatQuality(); cellsHabitatQualityMax = grid.getCells()[0].getHabitatQuality(); for (int i = 1; i < grid.getCells().length; i++) { if (grid.getCells()[i].getHabitatQuality() < cellsHabitatQualityMin) cellsHabitatQualityMin = grid.getCells()[i].getHabitatQuality(); else if (grid.getCells()[i].getHabitatQuality() > cellsHabitatQualityMax) cellsHabitatQualityMax = grid.getCells()[i].getHabitatQuality(); } } if (Double.compare(cellsHabitatQualityMax,cellsHabitatQualityMin) == 0) { for (int i = 0; i < grid.getCells().length; i++) { cellsAlpha[i] = 255; } } else { for (int i = 0; i < grid.getCells().length; i++) { cellsAlpha[i] = (int)(155 + 100*(grid.getCells()[i].getHabitatQuality() - cellsHabitatQualityMin)/(cellsHabitatQualityMax - cellsHabitatQualityMin)); } } // show the result display.repaint(); } public void disable() { display.setVisible(false); } public static interface AsShapeConvertible { public Shape getShape(); } public void configure() { OhOUIDialog dialog = OhOUI.getDialog(null,this,new NoTransientField()); dialog.setSize(new Dimension(500, 600)); dialog.setVisible(true); display.repaint(); } @Override public void addObservable(ObservablesHandler classObservable) { // nothing to do } @Override public void init() { // nothing to do } @Override public void close() { // nothing to do } private class DisplayComponent extends JComponent { @Override protected synchronized void paintComponent(Graphics g) { super.paintComponents(g); Graphics2D g2d = (Graphics2D)g; // determine if generalPath must be rescaled if ( (this.getWidth() != displayWidthBak) || (this.getHeight() != displayHeightBak) ) { // backup for comparaison in the next loop displayWidthBak = this.getWidth(); displayHeightBak = this.getHeight(); cellSizeX = displayWidthBak/grid.getGridWidth(); cellSizeY = displayHeightBak/grid.getGridHeight(); } // Draw Background g.setColor(bgColor); g2d.setStroke(new BasicStroke(3)); g.fillRect(0, 0, getWidth(), getHeight()); Rectangle2D.Double cellRect = null; Rectangle2D.Double pikeRect = null; double preyDiameterX, preyDiameterY, pikeWidth, pikeHeight; // draw each cell for (int i = 0; i < grid.getCells().length; i++) { // the bounds of a cell cellRect = new Rectangle2D.Double((int)cellSizeX*(i%grid.getGridWidth()), (int)cellSizeY*(i/grid.getGridHeight()), (int)cellSizeX, (int)cellSizeY); // filling the cell with a color corresponding to the habitat level g.setColor(new Color(envColor.getRed(),envColor.getGreen(),envColor.getBlue(),cellsAlpha[i])); g2d.fill(cellRect); // drawing preys if (grid.getCells()[i].getPreys().size() > 0) { g.setColor(preyColor); preyDiameterX = cellRect.width*(double)grid.getCells()[i].getPreys().size()/grid.getCells()[i].getPreyCarryingCapacity(); preyDiameterY = cellRect.height*(double)grid.getCells()[i].getPreys().size()/grid.getCells()[i].getPreyCarryingCapacity(); g.fillOval((int)(cellRect.x + (cellRect.width - preyDiameterX)/2), (int)(cellRect.y + (cellRect.height - preyDiameterY)/2), (int)preyDiameterX, (int)preyDiameterY); // represention as pie ... not very pretty /*g2d.fill(new Arc2D.Double(cellRect,90,-360*((double)grid.getCells()[i].getPreys().size()/grid.getCells()[i].getPreyCarryingCapacity()),Arc2D.PIE)); g2d.draw(new Arc2D.Double(cellRect,90,360,Arc2D.OPEN));*/ } // drawing pikes presence if (grid.getCells()[i].getPikes().size() > 0) { g.setColor(pikeColor); pikeWidth = cellRect.width / 3; pikeHeight = cellRect.height / 3; pikeRect = new Rectangle2D.Double(cellRect.x + (cellRect.width - pikeWidth)/2, cellRect.y + (cellRect.height - pikeHeight)/2, pikeWidth, pikeHeight); g2d.draw(pikeRect); g2d.drawString(""+grid.getCells()[i].getPikes().size(), (float)(cellRect.x + cellRect.width/2 - 5), (float)pikeRect.y+(float)pikeRect.height-1); } } } } public void mouseDragged(MouseEvent e) {} public void mouseMoved(MouseEvent e) { int y = (int)(e.getY()/cellSizeY); int x = (int)(e.getX()/cellSizeX); Cell cell = grid.getCells()[grid.getGridWidth()*Math.min(y,grid.getGridHeight()-1) + Math.min(x,grid.getGridWidth()-1)]; label.setText("( "+x+" , "+y+" ) : habitat value = "+cell.getHabitatQuality()+" / "+cell.getPreys().size() + " preys ( max = "+cell.getPreyCarryingCapacity()+") and " + cell.getPikes().size()+ " pikes."); } public static void main (String [] args){ System.out.println((new XStream(new DomDriver())).toXML(new GridObserver())); } }