workcraft/workcraft

View on GitHub
workcraft/CpogPlugin/src/org/workcraft/plugins/cpog/VisualArc.java

Summary

Maintainability
A
30 mins
Test Coverage
package org.workcraft.plugins.cpog;

import org.workcraft.dom.visual.BoundingBoxHelper;
import org.workcraft.dom.visual.DrawRequest;
import org.workcraft.dom.visual.connections.ConnectionGraphic;
import org.workcraft.dom.visual.connections.VisualConnection;
import org.workcraft.formula.BooleanFormula;
import org.workcraft.formula.One;
import org.workcraft.formula.Zero;
import org.workcraft.formula.visitors.FormulaRenderingResult;
import org.workcraft.formula.visitors.FormulaToGraphics;
import org.workcraft.formula.workers.BooleanWorker;
import org.workcraft.plugins.cpog.formula.MemoryConservingBooleanWorker;
import org.workcraft.plugins.cpog.formula.PrettifyBooleanWorker;
import org.workcraft.plugins.cpog.formula.CpogBooleanReplacer;
import org.workcraft.serialisation.NoAutoSerialisation;
import org.workcraft.utils.ColorUtils;
import org.workcraft.utils.Geometry;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;

public class VisualArc extends VisualConnection {

    public static final String PROPERTY_CONDITION = "condition";

    private static final BooleanWorker WORKER = new PrettifyBooleanWorker(new MemoryConservingBooleanWorker());

    private static Font labelFont;
    private Rectangle2D labelBB = null;
    private final Arc mathConnection;

    static {
        try {
            labelFont = Font.createFont(Font.TYPE1_FONT, ClassLoader.getSystemResourceAsStream("fonts/default.pfb")).deriveFont(0.5f);
        } catch (FontFormatException | IOException e) {
            e.printStackTrace();
        }
    }

    public VisualArc(Arc mathConnection) {
        super();
        this.mathConnection = mathConnection;
    }

    public VisualArc(Arc mathConnection, VisualVertex first, VisualVertex second) {
        super(mathConnection, first, second);
        this.mathConnection = mathConnection;
    }

    @NoAutoSerialisation
    public BooleanFormula getCondition() {
        return mathConnection.getCondition();
    }

    @NoAutoSerialisation
    public void setCondition(BooleanFormula condition) {
        mathConnection.setCondition(condition);
    }

    @Override
    public Stroke getStroke() {
        BooleanFormula value = evaluate();

        if (value == Zero.getInstance()) {
            return new BasicStroke((float) super.getLineWidth(), BasicStroke.CAP_BUTT,
                BasicStroke.JOIN_MITER, 1.0f, new float[] {0.18f, 0.18f}, 0.00f);
        }

        return super.getStroke();
    }

// FIXME: Gray colour of arcs with undecided conditions is confusing.
//    @Override
//    public Color getDrawColor() {
//        BooleanFormula value = evaluate();
//        if ((value != Zero.instance() && (value != One.instance())) {
//            return Color.LIGHT_GRAY;
//        }
//        return super.getDrawColor();
//    }

    private BooleanFormula evaluate() {
        BooleanFormula condition = getCondition();

        condition = WORKER.and(condition, ((VisualVertex) getFirst()).evaluate());
        condition = WORKER.and(condition, ((VisualVertex) getSecond()).evaluate());

        return condition.accept(new CpogBooleanReplacer());
    }

    @Override
    public void draw(DrawRequest r) {
        labelBB = null;

        if (getCondition() == One.getInstance()) return;

        Graphics2D g = r.getGraphics();

        FormulaRenderingResult result = FormulaToGraphics.render(getCondition(), g.getFontRenderContext(), labelFont);

        labelBB = result.boundingBox;

        ConnectionGraphic graphic = getGraphic();

        Point2D p = graphic.getPointOnCurve(0.5);
        Point2D d = graphic.getDerivativeAt(0.5);
        Point2D dd = graphic.getSecondDerivativeAt(0.5);

        if (d.getX() < 0) {
            d = Geometry.multiply(d, -1);
            //dd = Geometry.multiply(dd, -1);
        }

        Point2D labelPosition = new Point2D.Double(labelBB.getCenterX(), labelBB.getMaxY());
        if (Geometry.crossProduct(d, dd) < 0) labelPosition.setLocation(labelPosition.getX(), labelBB.getMinY());

        AffineTransform oldTransform = g.getTransform();
        AffineTransform transform = AffineTransform.getTranslateInstance(p.getX() - labelPosition.getX(), p.getY() - labelPosition.getY());
        transform.concatenate(AffineTransform.getRotateInstance(d.getX(), d.getY(), labelPosition.getX(), labelPosition.getY()));

        g.transform(transform);
        g.setColor(ColorUtils.colorise(Color.BLACK, r.getDecoration().getColorisation()));
        result.draw(g);
        g.setTransform(oldTransform);

        labelBB = BoundingBoxHelper.transform(labelBB, transform);
    }

    @Override
    public Rectangle2D getBoundingBox() {
        return BoundingBoxHelper.union(super.getBoundingBox(), labelBB);
    }

    public Rectangle2D getLabelBoundingBox() {
        return labelBB;
    }

    @Override
    public boolean hitTest(Point2D pointInParentSpace) {
        if (labelBB != null && labelBB.contains(pointInParentSpace)) return true;

        return super.hitTest(pointInParentSpace);
    }

}