package com.baselet.element.relation; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import com.baselet.control.basics.geom.Point; import com.baselet.control.basics.geom.Rectangle; import com.baselet.control.config.SharedConfig; import com.baselet.control.constants.SharedConstants; import com.baselet.control.enums.Direction; import com.baselet.control.enums.ElementId; import com.baselet.diagram.draw.DrawHandler; import com.baselet.diagram.draw.helper.ColorOwn; import com.baselet.diagram.draw.helper.ColorOwn.Transparency; import com.baselet.element.NewGridElement; import com.baselet.element.UndoInformation; import com.baselet.element.facet.PropertiesParserState; import com.baselet.element.facet.Settings; import com.baselet.element.facet.common.LayerFacet; import com.baselet.element.interfaces.CursorOwn; import com.baselet.element.relation.facet.RelationLineTypeFacet; import com.baselet.element.relation.facet.SettingsRelation; import com.baselet.element.relation.helper.RelationPointHandler; import com.baselet.element.relation.helper.RelationPointHolder; import com.baselet.element.relation.helper.RelationPointList; import com.baselet.element.relation.helper.RelationSelection; import com.baselet.element.sticking.PointChange; import com.baselet.element.sticking.PointDoubleIndexed; import com.baselet.element.sticking.Stickable; import com.baselet.element.sticking.StickableMap; import com.baselet.element.sticking.polygon.NoStickingPolygonGenerator; public class Relation extends NewGridElement implements Stickable, RelationPointHolder { private RelationPointHandler relationPoints; @Override public ElementId getId() { return ElementId.Relation; } @Override protected void drawCommonContent(PropertiesParserState state) { state.setStickingPolygonGenerator(NoStickingPolygonGenerator.INSTANCE); } @Override protected void resetAndDrawMetaDrawerContent(DrawHandler drawer) { drawer.clearCache(); drawer.setBackgroundColor(ColorOwn.SELECTION_BG); // draw rectangle around whole element (basically a helper for developers to make sure the (invisible) size of the element is correct) if (SharedConfig.getInstance().isDev_mode()) { drawer.setForegroundColor(ColorOwn.TRANSPARENT); drawer.drawRectangle(0, 0, getRealSize().getWidth(), getRealSize().getHeight()); drawer.setBackgroundColor(ColorOwn.GREEN.transparency(Transparency.BACKGROUND)); relationPoints.drawSelectionSpace(drawer); } drawer.setForegroundColor(ColorOwn.SELECTION_FG); relationPoints.drawCirclesAndDragBox(drawer); } @Override public void setAdditionalAttributes(String additionalAttributes) { super.setAdditionalAttributes(additionalAttributes); RelationPointList pointList = new RelationPointList(); String[] split = additionalAttributes.split(";"); for (int i = 0; i < split.length; i += 2) { pointList.add(Double.valueOf(split[i]), Double.valueOf(split[i + 1])); } relationPoints = new RelationPointHandler(this, pointList); if (getHandler().isInitialized()) { relationPoints.resizeRectAndReposPoints(); } } @Override public String getAdditionalAttributes() { return relationPoints.toAdditionalAttributesString(); } @Override public void drag(Collection<Direction> resizeDirection, int diffX, int diffY, Point mousePosBeforeDragRelative, boolean isShiftKeyDown, boolean firstDrag, StickableMap stickables, boolean undoable) { String oldAddAttr = getAdditionalAttributes(); Rectangle oldRect = getRectangle(); RelationSelection returnSelection = relationPoints.getSelectionAndMovePointsIfNecessary(pointAtDefaultZoom(mousePosBeforeDragRelative), toDefaultZoom(diffX), toDefaultZoom(diffY), firstDrag); if (returnSelection == RelationSelection.DRAG_BOX) { setLocationDifference(diffX, diffY); } if (returnSelection != RelationSelection.NOTHING) { updateModelFromText(); } if (undoable) { undoStack.add(new UndoInformation(getRectangle(), oldRect, new HashMap<Stickable, List<PointChange>>(), getGridSize(), oldAddAttr, getAdditionalAttributes())); } } /** * Calculate the point for DEFAULT_ZOOM to allow ignoring zoom-level from now on */ private Point pointAtDefaultZoom(Point p) { return new Point(toDefaultZoom(p.getX()), toDefaultZoom(p.getY())); } private int toDefaultZoom(int input) { return input * SharedConstants.DEFAULT_GRID_SIZE / getGridSize(); } @Override public void dragEnd() { boolean updateNecessary = relationPoints.removeRelationPointIfOnLineBetweenNeighbourPoints(); if (updateNecessary) { updateModelFromText(); } } @Override public Set<Direction> getResizeArea(int x, int y) { return new HashSet<Direction>(); } @Override public boolean isSelectableOn(Point point) { Point relativePoint = toRelative(point); boolean isSelectableOn = relationPoints.getSelection(pointAtDefaultZoom(relativePoint)) != RelationSelection.NOTHING; return isSelectableOn; } @Override public Collection<PointDoubleIndexed> getStickablePoints() { return relationPoints.getStickablePoints(); } @Override public List<PointDoubleIndexed> movePoints(List<PointChange> changedStickPoints) { List<PointDoubleIndexed> updatedChangedList = relationPoints.movePointAndResizeRectangle(changedStickPoints); updateModelFromText(); return updatedChangedList; } @Override public Integer getLayer() { return state.getFacetResponse(LayerFacet.class, LayerFacet.DEFAULT_VALUE_RELATION); } @Override protected Settings createSettings() { return new SettingsRelation() { @Override public RelationPointHandler getRelationPoints() { return relationPoints; } }; } @Override protected void drawError(DrawHandler drawer, String errorText) { super.drawError(drawer, errorText.replace(">>", "\\>>").replace("<<", "\\<<")); RelationLineTypeFacet.drawDefaultLineAndArrows(drawer, relationPoints); } protected Point toRelative(Point point) { return new Point(point.getX() - getRectangle().getX(), point.getY() - getRectangle().getY()); } @Override public CursorOwn getCursor(Point point, Set<Direction> resizeDirections) { RelationSelection selection = relationPoints.getSelection(pointAtDefaultZoom(toRelative(point))); switch (selection) { case DRAG_BOX: return CursorOwn.MOVE; case LINE: return CursorOwn.CROSS; case RELATION_POINT: return CursorOwn.HAND; default: return super.getCursor(point, resizeDirections); } } }