package opg.main; import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.awt.RenderingHints; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.geom.AffineTransform; import javax.swing.JPanel; import opg.gui.DrawableChart; import opg.other.Chart; public class View extends JPanel { private static View singleton = new View(); public static View singleton() { return singleton; } private float scale; private boolean showRuler; private boolean showGrid; private Point downPoint; private View() { this.setBackground(Const.COLOR_PAGE_BACKGROUND); this.scale = 1; this.addMouseListener(mouseAdapter); this.addMouseMotionListener(mouseAdapter); this.downPoint = null; } public void setRuler(boolean isShown) { showRuler = isShown; this.repaint(); } public void setGrid(boolean isShown) { showGrid = isShown; this.repaint(); } public void zoomIn() { scale *= 2; if (scale > Const.ZOOM_IN_MAX) scale = Const.ZOOM_IN_MAX; this.repaint(); this.revalidate(); } public void zoomOut() { scale /= 2; if (scale < Const.ZOOM_OUT_MAX) scale = Const.ZOOM_OUT_MAX; this.repaint(); this.revalidate(); } private MouseAdapter mouseAdapter = new MouseAdapter() { @Override public void mouseDragged(MouseEvent event) { downPoint = event.getPoint(); View.this.repaint(); View.this.revalidate(); } @Override public void mouseReleased(MouseEvent event) { downPoint = null; View.this.repaint(); View.this.revalidate(); } }; @Override public Dimension getPreferredSize() { Chart chart = Controller.singleton().getChart(); if (chart == null) { int w = (int) (scale * Const.DRAWING_SIZE.width); int h = (int) (scale * Const.DRAWING_SIZE.height); return new Dimension(w, h); } else { int w = (int) (scale * (chart.getWidth() + Const.MARGIN_DRAWING * 2)); int h = (int) (scale * (chart.getHeight() + Const.MARGIN_DRAWING * 2)); return new Dimension(w, h); } } @Override public void paintComponent(Graphics graphics) { super.paintComponent(graphics); Graphics2D g = (Graphics2D) graphics; Chart chart = Controller.singleton().getChart(); AffineTransform saveAt = g.getTransform(); // transformations g.scale(scale, scale); double extraSideSpace = (getWidth() - (chart.getWidth() * scale)) / scale; double xTranslate = extraSideSpace / 2; double yTranslate = Const.MARGIN_DRAWING; g.translate(xTranslate, yTranslate); g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // draw chart with new size // if (downPoint != null) { // int newHeight = (int) Math.abs(downPoint.y / scale - yTranslate); // if (newHeight > Const.DEFAULT_PAGE_HEIGHT) // chart.setHeight(newHeight); // int newWidth = (int) Math.abs(downPoint.x / scale - xTranslate); // if (newWidth > Const.DEFUALT_PAGE_WIDTH) // chart.setWidth(newWidth); // } // draw page outline // Color oldColor = g.getColor(); // g.setStroke(new BasicStroke(Const.STROKE_SIZE / scale)); // g.setColor(Const.COLOR_PAGE_OUTLINE); // g.draw((new Rectangle(0, 0, chart.getWidth(), chart.getHeight()))); // draw page inline (margins) // g.setColor(Const.COLOR_PAGE_INLINE); // g.drawRect(chart.getMarginLeft(), chart.getMarginTop(), chart.getAvaliableWidth(), chart.getAvaliableHeight()); // g.setStroke(new BasicStroke(Const.STROKE_SIZE)); // g.setColor(oldColor); // draw pedigree DrawableChart dc = Controller.singleton().getDrawableChart(); g.translate(dc.getDx(), dc.getDy()); dc.draw(g); //draw grid if (showGrid) { g.setColor(Const.COLOR_GRID); g.setStroke(new BasicStroke(Const.STROKE_SIZE / 2 / scale)); for (int i = 0; i <= chart.getWidth(); i += Const.RULER_MAX_INTERVAL/4) g.drawLine(i, 0, i, chart.getHeight()); for (int j = 0; j < chart.getHeight(); j += Const.RULER_MAX_INTERVAL/4) g.drawLine(0, j, chart.getWidth(), j); } // draw ruler if (showRuler) { int offset = -Const.RULER_OFFSET; g.setColor(Const.COLOR_RULER); g.setStroke(new BasicStroke(Const.STROKE_SIZE / 2 / scale)); drawRuler(g, offset, 0, offset, chart.getHeight()); drawRuler(g, 0, offset, chart.getWidth(), offset); } g.setTransform(saveAt); } // ///////////////////////////////////////////////////// private void drawRuler(Graphics2D g, int x1, int y1, int x2, int y2) { Font oldFont = g.getFont(); g.setFont(oldFont.deriveFont(16.0f)); g.drawLine(x1, y1, x2, y2); for (int i = y1; i <= y2; i += Const.RULER_MIN_INTERVAL) { int tickLength = getTickLength(i); g.drawLine(x1, i, x1 + tickLength, i); if (tickLength == Const.RULER_MAX_TICK_LENGTH) { FontMetrics metrics = g.getFontMetrics(); String label = (i - y1) / Const.RULER_MAX_INTERVAL + ""; g.drawString(label, x1 - metrics.stringWidth(label) - 5, i + metrics.getHeight() / 3); } } for (int i = x1; i <= x2; i += Const.RULER_MIN_INTERVAL) { int tickLength = getTickLength(i); g.drawLine(i, y1, i, y1 + tickLength); if (tickLength == Const.RULER_MAX_TICK_LENGTH) { FontMetrics metrics = g.getFontMetrics(); String label = (i - y1) / Const.RULER_MAX_INTERVAL + ""; g.drawString(label, i + metrics.getHeight() / 3, y1 - metrics.stringWidth(label) - 5); } } g.setFont(oldFont); } private int getTickLength(int i) { int length = Const.RULER_MAX_TICK_LENGTH; int interval = Const.RULER_MAX_INTERVAL; while (i % interval != 0) { interval /= 2; length /= 2; if (interval == 0) throw new IllegalArgumentException("Bad Tick Mark: " + i); } return length; } }