package org.singinst.uf.view; import java.awt.BasicStroke; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; import java.awt.font.FontRenderContext; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.Stack; import javax.swing.JPanel; import org.singinst.uf.math.SimplePoint; import org.singinst.uf.presenter.CanvasString; import org.singinst.uf.presenter.GraphCanvas; import org.singinst.uf.presenter.MouseClickListener; import org.singinst.uf.presenter.MouseDragListener; import org.singinst.uf.presenter.PlaneBounds; import org.singinst.uf.presenter.SimpleLine; import org.singinst.uf.presenter.SimpleStyle; public class SwingGraphCanvas implements GraphCanvas, MouseListener, MouseMotionListener { private Graphics2D g2; private Stack styleStack; private Dimension size; private PlaneBounds bounds; private final Set dragListeners = new HashSet(); private final Set clickListeners = new HashSet(); private JPanel panel; private MouseDragListener selectedDragListener; public SwingGraphCanvas() { // MainWindow.pane.addChangeListener(new ChangeListener() { // // public void stateChanged(ChangeEvent e) { //// dragListeners.clear(); //// clickListeners.clear(); // } // // }); } public void setPanel(JPanel panel) { this.panel = panel; } public void setGraphics(Graphics2D g2) { this.g2 = g2; this.styleStack = new Stack(); styleStack.push(new SwingStyle(g2)); } public void setSize(Dimension size) { this.size = size; this.bounds = new PlaneBounds(0, size.width, size.height, 0); } public void clear() { g2.clearRect(0,0,size.width,size.height); } public void drawLine(SimpleLine line) { g2.draw(new Line2D.Double(point(line.p1), point(line.p2))); } private Point2D point(SimplePoint p) { return new Point2D.Double(p.x, p.y); } public void drawDecorationPoint(SimplePoint point) { double dotDiameter = size.width / 200; double dotRadius = dotDiameter / 2; g2.draw(new Ellipse2D.Double(point.x - dotRadius, point.y - dotRadius, dotDiameter, dotDiameter)); } public PlaneBounds getPlaneBounds() { return bounds; } public void drawCurve(List points) { if (points.isEmpty()) { return; } GeneralPath curve = new GeneralPath(); Iterator iterator = points.iterator(); curveMoveTo(curve, iterator.next()); while (iterator.hasNext()) { curveLineTo(curve, iterator.next()); } g2.draw(curve); } private void curveLineTo(GeneralPath curve, SimplePoint point) { curve.lineTo((float) point.x, (float) point.y); } private void curveMoveTo(GeneralPath curve, SimplePoint point) { curve.moveTo((float) point.x, (float) point.y); } public void addMouseClickListener(MouseClickListener listener) { clickListeners.add(listener); if (dragListeners.size() + dragListeners.size() > 1) { throw new UnsupportedOperationException(); } panel.addMouseListener(this); } public void addMouseDragListener(MouseDragListener listener) { dragListeners.add(listener); if (dragListeners.size() + clickListeners.size() > 1) { throw new UnsupportedOperationException(); } panel.addMouseListener(this); panel.addMouseMotionListener(this); } public void mouseClicked(MouseEvent e) { } public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { selectedDragListener = null; } public void mousePressed(MouseEvent e) { for (MouseClickListener listener : clickListeners) { listener.mouseClick(simplePoint(e.getPoint())); } if (dragListeners.size() > 0) { MouseDragListener dragListener = dragListeners.iterator().next(); int priority = dragListener.mouseDown(simplePoint(e.getPoint())); if (priority > 0) { selectedDragListener = dragListener; } } } public void mouseReleased(MouseEvent e) { if (selectedDragListener != null) { selectedDragListener.dragTo(simplePoint(e.getPoint())); selectedDragListener = null; } } public void mouseDragged(MouseEvent e) { if (selectedDragListener != null) { selectedDragListener.dragTo(simplePoint(e.getPoint())); } } private SimplePoint simplePoint(Point point) { return new SimplePoint(point.getX(), point.getY()); } public void mouseMoved(MouseEvent e) { } public void invalidate() { if (panel != null) { panel.repaint(); } } public void popStyle() { styleStack.pop(); setStyle(styleStack.peek()); } private void setStyle(SwingStyle style) { g2.setColor(style.getColor()); if (style.isDottedLine()) { g2.setStroke(new BasicStroke(1, BasicStroke.CAP_SQUARE, BasicStroke.JOIN_MITER, 10, new float[] {2}, 0)); } else { g2.setStroke(new BasicStroke()); } } public void pushStyle(SimpleStyle style) { SwingStyle swingStyle; if (style == null) { swingStyle = styleStack.peek(); } else { swingStyle = new SwingStyle(style); } styleStack.push(swingStyle); setStyle(swingStyle); } public void write(SimplePoint point, CanvasString canvasString) { FontRenderContext frc = g2.getFontRenderContext(); TextLayout textLayout = new TextLayout(getAttributedCharacterIterator(canvasString), frc); textLayout.draw(g2, (float) point.x, (float) point.y); } private AttributedCharacterIterator getAttributedCharacterIterator( CanvasString canvasString) { String main = canvasString.getMain(); String optionalPower = canvasString.getOptionalPower(); AttributedString string; if (optionalPower == null) { string = new AttributedString(main); } else { if (ViewUtil.renderExponentsAsSuperscript()) { String plainText = main + optionalPower; string = new AttributedString(plainText); string.addAttribute(TextAttribute.SUPERSCRIPT, TextAttribute.SUPERSCRIPT_SUPER, main.length(), plainText.length()); } else { string = new AttributedString(main + "^" + optionalPower); } } string.addAttribute(TextAttribute.SIZE, 18f); return string.getIterator(); } }