123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505 |
- package ui.view;
- import classes.*;
- import classes.comparator.UnitGraphPointComperator;
- import interfaces.GraphEditable;
- import interfaces.GraphEditable.Graphtype;
- import interfaces.IGraphedElement;
- import sun.reflect.generics.reflectiveObjects.NotImplementedException;
- import ui.controller.Control;
- import ui.controller.SingletonControl;
- import ui.model.Model;
- import javax.swing.*;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.geom.Path2D;
- import java.awt.geom.Point2D;
- import java.util.ArrayList;
- import java.util.LinkedList;
- import java.util.ListIterator;
- /**
- * This Class represents a Graph where the User can model the behavior of
- * elements and switches over time.
- *
- * @author Tom Troppmann
- */
- public class UnitGraph extends JPanel implements MouseListener, MouseMotionListener, ComponentListener {
- private static final long serialVersionUID = 1L;
-
-
- // Normal Settings
- private int border = 4;
- private int clickThreshholdSquared = 25;
-
- // Display Settings
- /**
- * The size of a dot in the graph.
- * It should be at least 1.
- * */
- int dotSize = 8;
- /** The Color of a dot in the graph. */
- Color dotColor = Color.blue;
- Color editDotColor = new Color(255, 119, 0);
-
- //Intern Variables
- //TODO: JavaDoc
- private LinkedList<UnitGraphPoint> actualGraphPoints = new LinkedList<UnitGraphPoint>();
- private Graphtype actualGraphType;
- private GraphEditable actualElement;
- Position editPosition;
- boolean editMode = false;
- private enum pointType {Normal, StartPoint, EndPoint};
- pointType editPoint = pointType.Normal;
-
- //Maybe Needed
- private Model model;
- private Control controller;
-
-
- private int widthWithBorder, heightWithBorder;
-
-
-
-
-
-
- /**
- * Constructor.
- *
- * @param model the Model
- * @param control the Controller
- */
- public UnitGraph(final Model model, Control control) {
- setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
- this.controller = control;
- this.model = model;
- this.setBackground(Color.WHITE);
- this.addMouseListener(this);
- this.addMouseMotionListener(this);
- this.addComponentListener(this);
- }
- /**
- * Paints all Components on the Canvas.
- *
- * @param g Graphics
- */
- public void paintComponent(Graphics g) {
- super.paintComponent(g);
-
- //System.out.println("paint");
- Graphics2D g2D = (Graphics2D) g;
- g2D.setColor(Color.BLACK);
- g2D.setRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
- g2D.setStroke(new BasicStroke(2));
- drawUnitGraph(g2D);
- g2D.setColor(dotColor);
- if(editMode)
- {
- drawUnitGraphPointsReleased(g2D);
- }else
- {
- drawUnitGraphPoints(g2D);
- }
- g2D.setStroke(new BasicStroke(1));
- drawCurrentIterartionLine(g2D);
- }
- //TODO -> New Section
-
- private void drawCurrentIterartionLine(Graphics2D g)
- {
- int cur = model.getCurIteration();
- int max = model.getIterations();
- double where = ((double) cur)/((double) max);
- Position oben = new Position(border + (int)(where * widthWithBorder), 0);
- Position unten = new Position(border + (int)(where * widthWithBorder), 2 * border + heightWithBorder);
- drawLine(g,oben,unten);
- }
-
- private void drawLine(Graphics2D g, Position start, Position end)
- {
- Path2D.Double path = new Path2D.Double();
- path.moveTo(start.x, start.y);
- path.lineTo(end.x, end.y);
- g.draw(path);
- }
-
- private Path2D.Double initBezier(Position start) {
- //Good Source for basic understanding for Bezier Curves
- //http://www.theappguruz.com/blog/bezier-curve-in-games
-
- Path2D.Double path = new Path2D.Double();
- path.moveTo(start.x, start.y);
- return path;
- }
- private void curveTo(Path2D.Double path, Position actual, Position target) {
- double mitte = (actual.x + target.x)* 0.5;
- path.curveTo(mitte, actual.y, mitte, target.y, target.x, target.y);
- }
- private void drawDot(Graphics2D g, Position p)
- {
- g.fillOval(p.x -dotSize/2, p.y-dotSize/2, dotSize, dotSize);
- }
- private void drawUnitGraph(Graphics2D g) {
- switch(actualGraphType) {
- case boolGraph:
- drawBoolGraph(g);
- break;
- case doubleGraph:
- if(editMode)
- drawDoubleGraphWithEditPosition(g);
- else
- drawDoubleGraph(g);
- break;
- default:
- throw new UnsupportedOperationException();
- }
- }
- private void drawUnitGraphPoints(Graphics2D g) {
- g.setColor(dotColor);
- for(UnitGraphPoint p : actualGraphPoints){
- drawDot(g, p.displayedPosition);
- }
- }
-
- private void saveGraph() {
- LinkedList<Point2D.Double> actual = actualElement.getStateGraph();
- actual.clear();
- for(UnitGraphPoint p: actualGraphPoints)
- {
- actual.add(p.getPoint());
- }
- actualElement.sampleGraph();
- }
- private void drawUnitGraphPointsReleased(Graphics2D g) {
- drawUnitGraphPoints(g);
- g.setColor(editDotColor);
- drawDot(g, editPosition);
- }
-
- private void drawBoolGraph(Graphics2D g) {
- throw new NotImplementedException();
- }
-
- private void drawDoubleGraph(Graphics2D g) {
- if(actualGraphPoints.isEmpty()) throw new IndexOutOfBoundsException("A Graph Without Points is not supportet jet");
- ListIterator<UnitGraphPoint> iter = actualGraphPoints.listIterator();
- Position actual = iter.next().displayedPosition;
- Path2D.Double path = this.initBezier(actual);
- while (iter.hasNext())
- {
- Position target = iter.next().displayedPosition;
- this.curveTo(path, actual, target);
- actual = target;
- }
- g.draw(path);
-
- }
- private void drawDoubleGraphWithEditPosition(Graphics2D g) {
- LinkedList<Position> before = new LinkedList<Position>();
- LinkedList<Position> after = new LinkedList<Position>();
- for(UnitGraphPoint p: actualGraphPoints)
- {
- if(p.displayedPosition.x < editPosition.x)
- before.add(p.displayedPosition);
- else
- after.add(p.displayedPosition);
- }
- drawUnitGraphFromList(g, before);
- drawUnitGraphFromList(g, after);
- //EditGraph
- LinkedList<Position> middle = new LinkedList<Position>();
- if(!before.isEmpty()) middle.add(before.getLast());
- middle.add(editPosition);
- if(!after.isEmpty()) middle.add(after.getFirst());
-
- g.setColor(editDotColor);
- drawUnitGraphFromList(g, middle);
- }
- private void drawUnitGraphFromList(Graphics2D g, LinkedList<Position> list) {
- if(list.size() <= 1) return;
- ListIterator<Position> iter = list.listIterator();
- Position actual = list.getFirst();
- Path2D.Double path = this.initBezier(actual);
- while (iter.hasNext())
- {
- Position target = iter.next();
- curveTo(path, actual, target);
- actual = target;
- }
- g.draw(path);
- }
-
-
-
- private void updateRepresentativePositions()
- {
- for(UnitGraphPoint p : actualGraphPoints) {
- p.calcDisplayedPosition(border, widthWithBorder, heightWithBorder);
- }
- }
-
- private void overrideUnitGraph(LinkedList<Point2D.Double> stateCurve) {
- actualGraphPoints.clear();
- for(Point2D.Double p: stateCurve){
- actualGraphPoints.add(new UnitGraphPoint(p));
- }
- updateRepresentativePositions();
- }
- private void calculateWidthHeight()
- {
- widthWithBorder = this.getWidth() - 2 * border;
- heightWithBorder = this.getHeight() - 2 * border;
- }
-
- public void initNewElement(GraphEditable element)
- {
- overrideUnitGraph(element.getStateGraph());
- actualGraphType = element.getGraphType();
- actualElement = element;
- repaint();
- }
-
-
- private void removePointNearPosition(Position mPosition) {
- ListIterator<UnitGraphPoint> iter = actualGraphPoints.listIterator();
- while (iter.hasNext())
- {
- if(mPosition.squareDistance(iter.next().displayedPosition) < clickThreshholdSquared)
- {
- iter.remove();
- break;
- }
- }
- }
-
- private void detectStartEndPoint(Position mPosition)
- {
- UnitGraphPoint first = actualGraphPoints.getFirst();
- UnitGraphPoint last = actualGraphPoints.getLast();
- if((mPosition.squareDistance(first.displayedPosition) < clickThreshholdSquared)) editPoint = pointType.StartPoint;
- else if(mPosition.squareDistance(last.displayedPosition) < clickThreshholdSquared) editPoint = pointType.EndPoint;
- else editPoint = pointType.Normal;
- }
-
- private void updateEditPointPosition(Position newPosition) {
- //make it in the bounds of the UnitGraph no Point out of the Border
- Position currentPosition = setInBounds(newPosition);
- if(editPoint != pointType.Normal) attachToBorder(currentPosition);
- this.editPosition = currentPosition;
- }
-
- private Position setInBounds(Position p) {
- p.clampX(border, border + widthWithBorder);
- p.clampY(border, border + heightWithBorder);
- return p;
- }
-
- private Point.Double getBezierPoint(double t, Point.Double p0, Point.Double p1,Point.Double p2,Point.Double p3) {
- /*
- * Calculate Beziér:
- * B(t) = (1-t)^3 * P0 + 3*(1-t)^2 * t * P1 + 3*(1-t)*t^2 * P2 + t^3 * P3 , 0 < t < 1
- *
- * Source: //http://www.theappguruz.com/blog/bezier-curve-in-games
- */
- Point.Double bezier = new Point.Double();
- double OneSubT = 1-t;
- double OneSubT2 = Math.pow(OneSubT, 2);
- double OneSubT3 = Math.pow(OneSubT, 3);
- double t2 = Math.pow(t , 2);
- double t3 = Math.pow(t , 3);
-
- bezier.x = OneSubT3 * p0.x + 3 * OneSubT2 * t * p1.x + 3 * OneSubT * t2 * p2.x + t3 * p3.x;
- bezier.y = OneSubT3 * p0.y + 3 * OneSubT2 * t * p1.y + 3 * OneSubT * t2 * p2.y + t3 * p3.y;
- return bezier;
-
- }
- private double getYBetweenTwoPoints(double t, Point.Double start, Point.Double end) {
-
- double mitte = (start.x + end.x)* 0.5;
- Point.Double bezier = getBezierPoint(t, start, new Point.Double(mitte, start.y), new Point.Double(mitte, end.y), end);
- return bezier.y;
- }
-
- private float[] sampleGraph(int sampleLength)
- {
- ListIterator<UnitGraphPoint> iter = actualGraphPoints.listIterator();
- Point.Double before = iter.next().getPoint();
- Point.Double after = iter.next().getPoint();
- float [] sampleCurve = new float[sampleLength];
- for(int i = 0; i<sampleLength ; i++)
- {
- double graphX = (double)i / (double) (sampleLength - 1); //from 0.0 to 1.0
- if(graphX > after.x)
- {
- before = after;
- after = iter.next().getPoint();
- }
- //inverseLerp(valueBetween, min, max) (valueBetween - min) / (max - min)
- // e.g. old.x = 0.4, actual.x = 0.8 and graphX = 0.6 then t is 0.5
- double t = (after.x -before.x > 0)? (graphX - before.x) / (after.x -before.x) : 0.0;
- sampleCurve[i] = (float) getYBetweenTwoPoints(t, before, after);
- }
- return sampleCurve;
- }
-
-
- private Position attachToBorder(Position p)
- {
- switch(editPoint)
- {
- case StartPoint:
- p.x = border;
- break;
- case EndPoint:
- p.x = border + widthWithBorder;
- break;
- default:
- break;
- }
- return p;
- }
-
- private void insertNewGraphPoint(Position pos)
- {
- System.out.println("insertNewGraphPoint");
- setInBounds(pos);
- ListIterator<UnitGraphPoint> iter2 = actualGraphPoints.listIterator();
- while (iter2.hasNext())
- {
- Position tempPosition = iter2.next().displayedPosition;
- if(pos.x <= tempPosition.x)
- {
- //previous to go back a position to make the new point before the the Position with greater X
- iter2.previous();
- iter2.add(generateUnitGraphPoint(pos));
- break;
- }
- }
- if(!iter2.hasNext()) //if behind last point
- {
- iter2.add(generateUnitGraphPoint(pos));
- }
- }
- private UnitGraphPoint generateUnitGraphPoint(Position pos) {
- UnitGraphPoint temp = new UnitGraphPoint((double) (pos.x - border) / (double) widthWithBorder,
- 1 - (double) (pos.y - border) / (double) heightWithBorder, true);
- temp.displayedPosition = pos;
- return temp;
- }
-
- @Override
- public void mouseDragged(MouseEvent e) {
- System.out.println("MouseDragged");
- updateEditPointPosition(new Position(e.getPoint()));
- repaint();
- }
- @Override
- public void mouseMoved(MouseEvent e) {
- }
- @Override
- public void mouseClicked(MouseEvent e) {
- }
- @Override
- public void mouseEntered(MouseEvent e) {
- }
- @Override
- public void mouseExited(MouseEvent e) {
- }
- @Override
- public void mousePressed(MouseEvent e) {
- System.out.println("mousePressed");
- Position mPosition = new Position(e.getPoint());
- if (e.getButton() == MouseEvent.BUTTON3) {
- // RightMouseButtonEvent
- detectStartEndPoint(mPosition);
- if (editPoint == pointType.Normal) {
- removePointNearPosition(mPosition);
- repaint();
- }
- editMode = false;
- } else if (e.getButton() == MouseEvent.BUTTON1) {
- // LeftMouseButtonEvent
- detectStartEndPoint(mPosition);
- removePointNearPosition(mPosition);
- updateEditPointPosition(mPosition);
- editMode = true;
- repaint();
- }
- }
- @Override
- public void mouseReleased(MouseEvent e) {
- System.out.println("mouseReleased");
- if(editMode)
- {
- this.insertNewGraphPoint(editPosition);
- editMode = false;
- repaint();
- }
- saveGraph();
- }
- /**
- * When the Component is Resized.
- *
- * @param e ComponentEvent
- */
- public void componentResized(ComponentEvent e) {
- System.out.println("componentResized");
- calculateWidthHeight();
- updateRepresentativePositions();
- repaint();
- }
- @Override
- public void componentHidden(ComponentEvent e) {
- }
- @Override
- public void componentMoved(ComponentEvent e) {
- }
- @Override
- public void componentShown(ComponentEvent e) {
- }
- public void reset() {
- System.out.println("reset");
- }
- public void update(ArrayList<AbstractCpsObject> obj) {
- System.out.println("update");
- }
- public void setStretching(boolean selected) {
- System.out.println("setStretching");
- }
- public void setLocalPeriod(int localLength) {
- System.out.println("setLocalPeriod");
- }
- public void repaintGraph(AbstractCpsObject cps) {
- // TODO Auto-generated method stub
- System.out.println("repaintGraph");
- }
-
-
- }
|