All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.vectorpublish.desktop.vp.split.Split Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2016, Peter Rader. All rights reserved.
 *  ___ ___               __                 ______         __     __  __         __
 * |   |   |.-----..----.|  |_ .-----..----.|   __ \.--.--.|  |--.|  ||__|.-----.|  |--.
 * |   |   ||  -__||  __||   _||  _  ||   _||    __/|  |  ||  _  ||  ||  ||__ --||     |
 *  \_____/ |_____||____||____||_____||__|  |___|   |_____||_____||__||__||_____||__|__|
 *
 * http://www.gnu.org/licenses/gpl-3.0.html
 */
package net.vectorpublish.desktop.vp.split;

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.geom.Rectangle2D.Float;
import java.util.Objects;
import java.util.Set;

import net.vectorpublish.desktop.vp.api.DrawParticipant;
import net.vectorpublish.desktop.vp.api.Moment;
import net.vectorpublish.desktop.vp.api.layer.IllegalParentException;
import net.vectorpublish.desktop.vp.api.ui.kf.Keyframe;
import net.vectorpublish.desktop.vp.api.ui.kf.Keyframer;
import net.vectorpublish.desktop.vp.api.vpd.DocumentNode;
import net.vectorpublish.desktop.vp.api.vpd.ModificationContext.LayerNodeImpl;
import net.vectorpublish.desktop.vp.api.vpd.VectorPublishNode;
import net.vectorpublish.desktop.vp.pd.official.RelativeKeyframeRecalculator;
import net.vectorpublish.desktop.vp.pd.official.TechnicalMouseDrag;
import net.vectorpublish.desktop.vp.pd.official.VectorPublishGraphics;

public class Split implements Keyframer, Spliter {
	private static final int PRECISION = 10_000;

	private float percent;
	private boolean vertical, selected;
	private DocumentNode doc;

	private int borderWidth2, borderWidth1;

	public Split(DocumentNode doc, int border, float percent, boolean vertical) {
		this.doc = Objects.requireNonNull(doc);
		this.setBorderWidth(border);
		this.percent = percent;
		this.vertical = vertical;
	}

	public int getBorderWidth() {
		return borderWidth1 + borderWidth2;
	}

	Float rect;
	boolean drawHelpLines;

	@Override
	public Cursor updateMouse(int markerX, int markerY, float docRelX, float docRelY, RelativeKeyframeRecalculator rel,
			TechnicalMouseDrag pressedLMBSince) {
		Dimension outerSize = findSize();
		Float relative = calulateChildRectangle(true);
		Float sideT = rel.toTechnical(relative);
		drawHelpLines = markerX > sideT.x && markerX < sideT.x + rel.calcTechnicalWidth(outerSize.width) && markerY > sideT.y
				&& markerY < sideT.y + sideT.height;
		int border1 = rel.calcTechnicalWidth(borderWidth1);
		int border2 = rel.calcTechnicalWidth(borderWidth2);
		if (border1 + border2 < 10) {
			border1 = 5;
			border2 = 5;
		}
		if (pressedLMBSince == null || !pressedLMBSince.hasHandler()) {
			Float borderRect = sliderRect(sideT.x, sideT.y, sideT.width, sideT.height, border1, border2);
			boolean mouseInBorder = borderRect.contains(markerX, markerY);
			if (mouseInBorder) {
				rect = borderRect;
				if (pressedLMBSince != null) {
					pressedLMBSince.setHandler(this);
				}
			}
			return mouseInBorder ? Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR) : null;
		}
		if (pressedLMBSince != null && pressedLMBSince.isHandler(this)) {
			if (vertical) {
				percent = (markerX - sideT.x) / rel.calcTechnicalWidth(outerSize.width) * 100f;
				if (percent < 0) {
					percent = 0;
				}
				if (percent > 100) {
					percent = 100;
				}
			} else {
				percent = (markerY - sideT.y) / rel.calcTechnicalHeight(outerSize.height) * 100f;
				if (percent < 0) {
					percent = 0;
				}
				if (percent > 100) {
					percent = 100;
				}
				rect = sliderRect(sideT.x, sideT.y, sideT.width, sideT.height, border1, border2);
			}
		}
		return null;
	}

	private Dimension findSize() {
		VectorPublishNode sp = findNodeHavingSpliterParent(this);
		Dimension outerSize = sp == null ? doc.getParticipant().getDimensions()
				: ((SplitNode) sp.getParent()).getParticipant().getDimensions();
		return outerSize;
	}

	private Float sliderRect(float x, float y, float w, float h, int span1, int span2) {
		Float sliderRect = null;
		if (vertical) {
			sliderRect = new Float(x + w, y, span1 + span2, h);
		} else {
			sliderRect = new Float(x - span1, y - span1 + h, w + 10, 10);
		}
		return sliderRect;
	}

	public void setSelected(boolean selected) {
		this.selected = selected;
	}

	public boolean isSelected() {
		return selected;
	}

	@Override
	public Dimension getDimensions() {
		Float r = calculateRectangle();
		return new Dimension((int) r.width, (int) r.height);
	}

	@Override
	public boolean opacity() {
		return false;
	}

	@Override
	public void paint(VectorPublishGraphics graphics, int width, int height) {
		doc.paintChildren(this, graphics, width, height);
	}

	@Override
	public void paintOutside(VectorPublishGraphics graphics, RelativeKeyframeRecalculator r, int documentWidth,
			int documentHeight) {
		Float first = calulateChildRectangle(true);
		Float second = calulateChildRectangle(false);
		if (isSelected()) {
			int xScale = r.calcTechnicalWidth(PRECISION);
			int yScale = r.calcTechnicalHeight(PRECISION);
			int x = (int) (r.calcTechnicalX(0) + xScale * first.x / PRECISION);
			int y = (int) (r.calcTechnicalY(0) + yScale * first.y / PRECISION);
			int w = (int) (xScale * first.width / PRECISION);
			int h = (int) (yScale * first.height / PRECISION);
			int x2 = (int) (r.calcTechnicalX(0) + xScale * second.x / PRECISION);
			int y2 = (int) (r.calcTechnicalY(0) + yScale * second.y / PRECISION);
			int w2 = (int) (xScale * second.width / PRECISION);
			int h2 = (int) (yScale * second.height / PRECISION);
			graphics.setColor(Color.blue);
			Float mr = rect;
			if (mr != null) {
				graphics.fillRect((int) mr.x, (int) mr.y, (int) mr.width, (int) mr.height);
			}
			if (drawHelpLines) {
				graphics.drawLine(x, y, x, y + 20);
			}
		}
		doc.paintChildrenOuter(this, graphics, r, documentWidth, documentHeight);
	}

	@Override
	public void reset(Set keyframes, Moment time) {
	}

	@Override
	public Float calulateChildRectangle(boolean first) {
		final Float self = calculateRectangle();
		return halfOfBoundary(first, self);
	}

	private Float calculateRectangle() {
		VectorPublishNode childOfParent = findNodeHavingSpliterParent(this);
		final Float self;
		if (childOfParent == null) {
			Dimension dim = doc.getParticipant().getDimensions();
			self = new Float(0f, 0f, dim.width * 1f, dim.height * 1f);
		} else {
			SplitNode parent = (SplitNode) childOfParent.getParent();
			boolean isFirst = parent.getIndex(childOfParent) == 0;
			self = parent.getParticipant().calulateChildRectangle(isFirst);
		}
		return self;
	}

	private Float halfOfBoundary(boolean first, Float self) {
		if (first) {
			if (vertical) {
				return new Float(self.x, self.y, self.width / 100f * percent - borderWidth1, self.height);
			} else {
				return new Float(self.x, self.y, self.width, self.height / 100f * percent - borderWidth1);
			}
		} else {
			if (vertical) {
				float relX = self.width / 100f * percent;
				return new Float(self.x + relX + borderWidth2, self.y, self.width - relX - borderWidth2, self.height);
			} else {
				float relY = self.height / 100f * percent;
				return new Float(self.x, self.y + relY + borderWidth2, self.width, self.height - relY - borderWidth2);
			}
		}
	}

	private VectorPublishNode findNodeHavingSpliterParent(Split split) {
		VectorPublishNode current = doc.findSelfOrChildByPaintParticipant(this);
		while (current != null) {
			if (current.getParent() instanceof SplitNode) {
				return current;
			}
			current = current.getParent();
		}
		return null;
	}

	@Override
	public String toString() {
		return vertical ? "Left " + Math.round(percent * 10) / 10f : "Top " + Math.round(percent * 10) / 10f;
	}

	public void setBorderWidth(Integer border) {
		if (border % 2 == 0) {
			borderWidth1 = borderWidth2 = border / 2;
		} else {
			borderWidth1 = (int) Math.floor(border * 1d / 2);
			borderWidth2 = (int) Math.ceil(border * 1d / 2);
		}
	}

	/**
	 * Finds the bounds of the split
	 * 
	 * @see #calulateChildRectangle(boolean)
	 * @param node
	 *            The node we need the rectangle for, never null.
	 * @return The rectangle the node is bound to, never null.
	 * @throws IllegalParentException
	 *             If the node is no the first or second child of a splitter.
	 */
	public static Float calculateRectangle(LayerNodeImpl node) throws IllegalParentException {
		while (!(node.getParent() instanceof DocumentNode)) {
			VectorPublishNode parent = node.getParent();
			if (parent instanceof SplitNode) {
				SplitNode splitParent = (SplitNode) parent;
				int index = splitParent.getIndex(node);
				if (index == 0) {
					return splitParent.getParticipant().calulateChildRectangle(true);
				} else if (index == 1) {

					return splitParent.getParticipant().calulateChildRectangle(false);
				} else {
					throw new IllegalParentException(node, "Must be first child or second child of parent.");
				}
			}
		}
		Dimension dim = node.getDocumentNode().getParticipant().getDimensions();
		return new Float(0, 0, dim.width, dim.height);
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy