Allow the origin of co-ordinates on boards to be specified (#428)

* Added support to specific co-ordinate origin.

Added the Coordinate origin property to the AbstractBoard class,
this allows the user to specify the corner (TopLeft, TopRight,
BottomLeft, BottomRight) cordinates should increment from.

Updated rendering to reflect this change.

* Use the coordinate origin setter method

To safely handle the case when a project produced with an earlier
verison of the application is loaded and the coordinate origin attribute
is set to NULL.
This commit is contained in:
Tim Savage
2019-02-10 01:53:11 +11:00
committed by bancika
parent 661e5e2403
commit 51a12d61e1
@@ -19,8 +19,8 @@
along with DIYLC. If not, see <http://www.gnu.org/licenses/>. along with DIYLC. If not, see <http://www.gnu.org/licenses/>.
*/ */
package org.diylc.components.boards; package org.diylc.components.boards;
import java.awt.AlphaComposite; import java.awt.AlphaComposite;
import java.awt.Color; import java.awt.Color;
import java.awt.Composite; import java.awt.Composite;
@@ -38,132 +38,167 @@ import org.diylc.core.VisibilityPolicy;
import org.diylc.core.annotations.EditableProperty; import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.measures.Size; import org.diylc.core.measures.Size;
import org.diylc.core.measures.SizeUnit; import org.diylc.core.measures.SizeUnit;
public abstract class AbstractBoard extends AbstractTransparentComponent<String> { public abstract class AbstractBoard extends AbstractTransparentComponent<String> {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static Color BOARD_COLOR = Color.decode("#F8EBB3"); public static Color BOARD_COLOR = Color.decode("#F8EBB3");
public static Color BORDER_COLOR = BOARD_COLOR.darker(); public static Color BORDER_COLOR = BOARD_COLOR.darker();
public static Color COORDINATE_COLOR = Color.gray.brighter(); public static Color COORDINATE_COLOR = Color.gray.brighter();
public static float COORDINATE_FONT_SIZE = 9f; public static float COORDINATE_FONT_SIZE = 9f;
public static Size DEFAULT_WIDTH = new Size(1.5d, SizeUnit.in); public static Size DEFAULT_WIDTH = new Size(1.5d, SizeUnit.in);
public static Size DEFAULT_HEIGHT = new Size(1.2d, SizeUnit.in); public static Size DEFAULT_HEIGHT = new Size(1.2d, SizeUnit.in);
protected String value = ""; protected String value = "";
protected Point[] controlPoints = new Point[] {new Point(0, 0), protected Point[] controlPoints = new Point[] {new Point(0, 0),
new Point((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels())}; new Point((int) DEFAULT_WIDTH.convertToPixels(), (int) DEFAULT_HEIGHT.convertToPixels())};
protected Point firstPoint = new Point(); protected Point firstPoint = new Point();
protected Point secondPoint = new Point(); protected Point secondPoint = new Point();
protected Color boardColor = BOARD_COLOR; protected Color boardColor = BOARD_COLOR;
protected Color borderColor = BORDER_COLOR; protected Color borderColor = BORDER_COLOR;
protected Color coordinateColor = COORDINATE_COLOR; protected Color coordinateColor = COORDINATE_COLOR;
protected Boolean drawCoordinates = null; protected Boolean drawCoordinates = null;
protected CoordinateType xType = CoordinateType.Numbers; protected CoordinateType xType = CoordinateType.Numbers;
protected CoordinateOrigin coordinateOrigin = CoordinateOrigin.Top_Left;
protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side; protected CoordinateDisplay coordinateDisplay = CoordinateDisplay.One_Side;
protected CoordinateType yType = CoordinateType.Letters; protected CoordinateType yType = CoordinateType.Letters;
@Override @Override
public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project, public void draw(Graphics2D g2d, ComponentState componentState, boolean outlineMode, Project project,
IDrawingObserver drawingObserver) { IDrawingObserver drawingObserver) {
g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1)); g2d.setStroke(ObjectCache.getInstance().fetchBasicStroke(1));
Composite oldComposite = g2d.getComposite(); Composite oldComposite = g2d.getComposite();
// render as transparent when dragging // render as transparent when dragging
int alpha = componentState == ComponentState.DRAGGING ? 0 : this.alpha; int alpha = componentState == ComponentState.DRAGGING ? 0 : this.alpha;
if (alpha < MAX_ALPHA) { if (alpha < MAX_ALPHA) {
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA)); g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 1f * alpha / MAX_ALPHA));
} }
g2d.setColor(boardColor); g2d.setColor(boardColor);
g2d.fillRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); g2d.fillRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y);
g2d.setComposite(oldComposite); g2d.setComposite(oldComposite);
// Do not track any changes that follow because the whole board has been // Do not track any changes that follow because the whole board has been
// tracked so far. // tracked so far.
drawingObserver.stopTracking(); drawingObserver.stopTracking();
g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR g2d.setColor(componentState == ComponentState.SELECTED || componentState == ComponentState.DRAGGING ? SELECTION_COLOR
: borderColor); : borderColor);
g2d.drawRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y); g2d.drawRect(firstPoint.x, firstPoint.y, secondPoint.x - firstPoint.x, secondPoint.y - firstPoint.y);
} }
protected void drawCoordinates(Graphics2D g2d, int spacing, Project project) { protected void drawCoordinates(Graphics2D g2d, int spacing, Project project) {
g2d.setColor(coordinateColor); g2d.setColor(coordinateColor);
g2d.setFont(project.getFont().deriveFont(COORDINATE_FONT_SIZE)); g2d.setFont(project.getFont().deriveFont(COORDINATE_FONT_SIZE));
// The half space is used to do rounding when calculating the range.
int halfSpace = spacing / 2;
CoordinateOrigin origin = getCoordinateOrigin();
if (getCoordinateDisplay() != CoordinateDisplay.None) {
int range;
int yOffset;
CoordinateType yType = getyType();
Point drawPoint = new Point(firstPoint);
if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Top_Right) {
range = (int) ((secondPoint.y - firstPoint.y + halfSpace) / spacing);
yOffset = spacing;
} else {
range = (int) ((secondPoint.y - firstPoint.y + halfSpace) / spacing);
yOffset = -spacing;
drawPoint.y = secondPoint.y;
}
for (int c = 1; c < range; c++) {
int xOffset = (yType == CoordinateType.Numbers && c >= 10) || (yType == CoordinateType.Letters && c >= 27) ? 0 : 2;
String label = yType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
drawPoint.y += yOffset;
drawCenteredText(g2d, label,
firstPoint.x + xOffset, drawPoint.y,
HorizontalAlignment.LEFT, VerticalAlignment.CENTER);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
drawCenteredText(g2d, label,
secondPoint.x - xOffset, drawPoint.y,
HorizontalAlignment.RIGHT, VerticalAlignment.CENTER);
}
}
}
if (getCoordinateDisplay() != CoordinateDisplay.None) { if (getCoordinateDisplay() != CoordinateDisplay.None) {
Point p = new Point(firstPoint); int range;
int t = 1; int xOffset;
while (p.y < secondPoint.y - spacing) { CoordinateType xType = getxType();
p.y += spacing; Point drawPoint = new Point(firstPoint);
int offset = (getyType() == CoordinateType.Numbers && t >= 10) || (getyType() == CoordinateType.Letters && t >= 27) ? 0 : 2;
drawCenteredText(g2d, getyType() == CoordinateType.Letters ? getCoordinateLabel(t) : Integer.toString(t), p.x + offset, p.y, HorizontalAlignment.LEFT, if (origin == CoordinateOrigin.Top_Left || origin == CoordinateOrigin.Bottom_Left) {
VerticalAlignment.CENTER); range = (int) ((secondPoint.x - firstPoint.x + halfSpace) / spacing);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) { xOffset = spacing;
drawCenteredText(g2d, getyType() == CoordinateType.Letters ? getCoordinateLabel(t) : Integer.toString(t), secondPoint.x - offset, p.y, HorizontalAlignment.RIGHT, } else {
VerticalAlignment.CENTER); range = (int) ((secondPoint.x - firstPoint.x + halfSpace) / spacing);
} xOffset = -spacing;
t++; drawPoint.x = secondPoint.x;
} }
}
for (int c = 1; c < range; c++) {
String label = xType == CoordinateType.Letters ? getCoordinateLabel(c) : Integer.toString(c);
drawPoint.x += xOffset;
drawCenteredText(g2d, label,
drawPoint.x, firstPoint.y - 2,
HorizontalAlignment.CENTER, VerticalAlignment.TOP);
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) {
drawCenteredText(g2d, label,
drawPoint.x, (int) (secondPoint.y - COORDINATE_FONT_SIZE),
HorizontalAlignment.CENTER, VerticalAlignment.BOTTOM);
}
}
}
}
if (getCoordinateDisplay() != CoordinateDisplay.None) { private String getCoordinateLabel(int coordinate) {
Point p = new Point(firstPoint); String result = "";
int t = 1; while (coordinate > 0) {
while (p.x < secondPoint.x - spacing) { int digit = coordinate % 26;
p.x += spacing; coordinate /= 26;
drawCenteredText(g2d, getxType() == CoordinateType.Letters ? getCoordinateLabel(t) : Integer.toString(t), p.x, p.y - 2, HorizontalAlignment.CENTER, if (digit == 0) {
VerticalAlignment.TOP); result = 'Z' + result;
if (getCoordinateDisplay() == CoordinateDisplay.Both_Sides) { coordinate--;
drawCenteredText(g2d, getxType() == CoordinateType.Letters ? getCoordinateLabel(t) : Integer.toString(t), p.x, (int) (secondPoint.y - COORDINATE_FONT_SIZE), HorizontalAlignment.CENTER, } else {
VerticalAlignment.BOTTOM); result = (char) ((int) 'A' + digit - 1) + result;
}
t++;
} }
} }
} return result;
}
private String getCoordinateLabel(int coordinate) {
String result = ""; @EditableProperty(name = "Color")
while (coordinate > 0) { public Color getBoardColor() {
int digit = coordinate % 26; return boardColor;
coordinate /= 26; }
if (digit == 0) {
result = 'Z' + result; public void setBoardColor(Color boardColor) {
coordinate--; this.boardColor = boardColor;
} else { }
result = (char) ((int) 'A' + digit - 1) + result;
} @EditableProperty(name = "Coordinate Color")
} public Color getCoordinateColor() {
return result; // Null protection for older files
} return coordinateColor == null ? COORDINATE_COLOR : coordinateColor;
}
@EditableProperty(name = "Color")
public Color getBoardColor() { public void setCoordinateColor(Color coordinateColor) {
return boardColor; this.coordinateColor = coordinateColor;
} }
public void setBoardColor(Color boardColor) { @EditableProperty(name = "Border")
this.boardColor = boardColor; public Color getBorderColor() {
} return borderColor;
}
@EditableProperty(name = "Coordinate Color")
public Color getCoordinateColor() { public void setBorderColor(Color borderColor) {
// Null protection for older files this.borderColor = borderColor;
return coordinateColor == null ? COORDINATE_COLOR : coordinateColor;
}
public void setCoordinateColor(Color coordinateColor) {
this.coordinateColor = coordinateColor;
}
@EditableProperty(name = "Border")
public Color getBorderColor() {
return borderColor;
}
public void setBorderColor(Color borderColor) {
this.borderColor = borderColor;
} }
@EditableProperty(name = "X") @EditableProperty(name = "X")
@@ -188,6 +223,17 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
this.coordinateDisplay = coordinateDisplay; this.coordinateDisplay = coordinateDisplay;
} }
@EditableProperty(name = "Coordinate Origin")
public CoordinateOrigin getCoordinateOrigin() {
if (coordinateOrigin == null)
coordinateOrigin = CoordinateOrigin.Top_Left;
return coordinateOrigin;
}
public void setCoordinateOrigin(CoordinateOrigin coordinateOrigin) {
this.coordinateOrigin = coordinateOrigin;
}
@EditableProperty(name = "Y") @EditableProperty(name = "Y")
public CoordinateType getyType() { public CoordinateType getyType() {
if (yType == null) if (yType == null)
@@ -197,46 +243,46 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
public void setyType(CoordinateType yType) { public void setyType(CoordinateType yType) {
this.yType = yType; this.yType = yType;
} }
@Override @Override
public int getControlPointCount() { public int getControlPointCount() {
return controlPoints.length; return controlPoints.length;
} }
@Override @Override
public Point getControlPoint(int index) { public Point getControlPoint(int index) {
return controlPoints[index]; return controlPoints[index];
} }
@Override @Override
public boolean isControlPointSticky(int index) { public boolean isControlPointSticky(int index) {
return false; return false;
} }
@Override @Override
public VisibilityPolicy getControlPointVisibilityPolicy(int index) { public VisibilityPolicy getControlPointVisibilityPolicy(int index) {
return VisibilityPolicy.WHEN_SELECTED; return VisibilityPolicy.WHEN_SELECTED;
} }
@Override @Override
public void setControlPoint(Point point, int index) { public void setControlPoint(Point point, int index) {
controlPoints[index].setLocation(point); controlPoints[index].setLocation(point);
firstPoint.setLocation(Math.min(controlPoints[0].x, controlPoints[1].x), firstPoint.setLocation(Math.min(controlPoints[0].x, controlPoints[1].x),
Math.min(controlPoints[0].y, controlPoints[1].y)); Math.min(controlPoints[0].y, controlPoints[1].y));
secondPoint.setLocation(Math.max(controlPoints[0].x, controlPoints[1].x), secondPoint.setLocation(Math.max(controlPoints[0].x, controlPoints[1].x),
Math.max(controlPoints[0].y, controlPoints[1].y)); Math.max(controlPoints[0].y, controlPoints[1].y));
} }
@EditableProperty @EditableProperty
@Override @Override
public String getValue() { public String getValue() {
return value; return value;
} }
@Override @Override
public void setValue(String value) { public void setValue(String value) {
this.value = value; this.value = value;
} }
public static enum CoordinateType { public static enum CoordinateType {
@@ -250,5 +296,14 @@ public abstract class AbstractBoard extends AbstractTransparentComponent<String>
public String toString() { public String toString() {
return super.toString().replace('_', ' '); return super.toString().replace('_', ' ');
}; };
} }
}
public static enum CoordinateOrigin {
Top_Left, Top_Right, Bottom_Right, Bottom_Left;
@Override
public String toString() {
return super.toString().replace('_', ' ');
};
}
}