--- /dev/null
+package net.mograsim.logic.model.model.components;
+
+/**
+ * For components that can have different orientations. The meaning is not clearly defined, however it is common that the orientation
+ * denotes the direction the output is facing or the general flow of signals. <code>_ALT</code> represents an alternative, which is normally
+ * a mirrored version. A component can choose to not support some variants.
+ * <p>
+ * In terms of calculation, {@link #RIGHT} is considered the default.
+ * <p>
+ * Note that this needs to be interpreted using the GUI coordinate system, meaning that UP and DOWN are swapped.
+ *
+ * @author Christian Femers
+ */
+public enum Orientation
+{
+ /**
+ * The orientation <code>RIGHT</code> is the default orientation, all others are defined relative to it.
+ */
+ RIGHT(1, 0, 0, 1), LEFT(-1, 0, 0, -1), UP(0, 1, -1, 0), DOWN(0, -1, 1, 0), RIGHT_ALT(1, 0, 0, -1), LEFT_ALT(-1, 0, 0, 1),
+ UP_ALT(0, -1, -1, 0), DOWN_ALT(0, 1, 1, 0);
+
+ // simple 2D transformation matrix
+ final double trans11;
+ final double trans12;
+ final double trans21;
+ final double trans22;
+
+ private Orientation(double trans11, double trans12, double trans21, double trans22)
+ {
+ this.trans11 = trans11;
+ this.trans12 = trans12;
+ this.trans21 = trans21;
+ this.trans22 = trans22;
+ }
+
+ /**
+ * Performs a simple rotation around the origin. This does not work for the display coordinate system.
+ *
+ * @return the point's new X coordinate
+ */
+ public double getNewX(double rightX, double rightY)
+ {
+ return rightX * trans11 + rightY * trans12;
+ }
+
+ /**
+ * Performs a simple rotation around the origin. This does not work for the display coordinate system.
+ *
+ * @return the point's new Y coordinate
+ */
+ public double getNewY(double rightX, double rightY)
+ {
+ return rightX * trans21 + rightY * trans22;
+ }
+
+ public boolean doesMirror()
+ {
+ return ordinal() > 3;
+ }
+
+ public boolean swapsWidthAndHeight()
+ {
+ return trans11 == 0;
+ }
+}
\ No newline at end of file
--- /dev/null
+package net.mograsim.logic.model.model.components;
+
+/**
+ * This class simplifies the calculation of coordinates, especially for GUI components.
+ * <p>
+ * Supply it with the original width and height and an orientation, and use the methods {@link #newX(double, double)} and
+ * {@link #newY(double, double)} to retrieve the new coordinates, relative to the upper left corner of {@link Orientation#RIGHT}. The
+ * {@link #height()} and {@link #width()} methods return the width and height in the new orientation.
+ * <p>
+ * This is meant to be used in the context of a a classic display coordinate system, as done in the {@link GUIComponent}s.
+ *
+ * @see Orientation
+ * @author Christian Femers
+ */
+public class OrientationCalculator
+{
+ final Orientation o;
+ final double oldWHalf;
+ final double oldHHalf;
+ final double w;
+ final double h;
+ final double wHalf;
+ final double hHalf;
+
+ public OrientationCalculator(Orientation o, double width, double height)
+ {
+ this.o = o;
+ this.oldWHalf = width / 2;
+ this.oldHHalf = height / 2;
+
+ if (o.swapsWidthAndHeight())
+ {
+ w = height;
+ h = width;
+ wHalf = oldHHalf;
+ hHalf = oldWHalf;
+ } else
+ {
+ w = width;
+ h = height;
+ wHalf = oldWHalf;
+ hHalf = oldHHalf;
+ }
+ }
+
+ /**
+ * Returns the new height (that equals the old width if {@link Orientation#swapsWidthAndHeight()} is true)
+ */
+ public double height()
+ {
+ return h;
+ }
+
+ /**
+ * Returns the new width (that equals the old height if {@link Orientation#swapsWidthAndHeight()} is true)
+ */
+ public double width()
+ {
+ return w;
+ }
+
+ public double newX(double x, double y)
+ {
+ return (x - oldWHalf) * o.trans11 + (y - oldHHalf) * o.trans12 + wHalf;
+ }
+
+ public double newY(double x, double y)
+ {
+ return (x - oldWHalf) * o.trans21 + (y - oldHHalf) * o.trans22 + hHalf;
+ }
+
+ public final Orientation getOrientation()
+ {
+ return o;
+ }
+}
import net.haspamelodica.swt.helper.swtobjectwrappers.Rectangle;
import net.mograsim.logic.model.model.ViewModelModifiable;
import net.mograsim.logic.model.model.components.GUIComponent;
+import net.mograsim.logic.model.model.components.Orientation;
+import net.mograsim.logic.model.model.components.OrientationCalculator;
import net.mograsim.logic.model.model.wires.Pin;
import net.mograsim.logic.model.model.wires.PinUsage;
import net.mograsim.logic.model.modeladapter.ViewLogicModelAdapter;
private double[] path;
private GUITriStateBufferParams params;
+ private OrientationCalculator oc;
public GUITriStateBuffer(ViewModelModifiable model, GUITriStateBufferParams params)
{
super(model, name);
this.params = params;
+ oc = new OrientationCalculator(params.orientation, width, height);
+
double wHalf = width / 2;
double hHalf = height / 2;
- double wQuar = width / 4;
double hQuar = height / 4;
- int ordi = params.orientation.ordinal();
- int isVerti = (ordi % 4) / 2;
- int isHori = 1 ^ isVerti;
- int isAlt = ordi / 4;
- int isInv = ordi % 2;
- int isStd = 1 ^ isInv;
-
- this.input = new Pin(this, "IN", params.logicWidth, PinUsage.INPUT, width * isInv * isHori + wHalf * isVerti,
- height * isVerti * isStd + hHalf * isHori);
- this.output = new Pin(this, "OUT", params.logicWidth, PinUsage.OUTPUT, width * isStd * isHori + wHalf * isVerti,
- height * isVerti * isInv + hHalf * isHori);
- this.enable = new Pin(this, "EN", 1, PinUsage.INPUT, wQuar * isVerti + wHalf * (isAlt | isHori),
- hQuar * isHori + hHalf * (isAlt | isVerti));
- this.path = new double[] { width * (isStd ^ isHori), height * (isStd ^ isHori), width * isInv, height * isStd,
- width * isStd * isHori + wHalf * isVerti, height * isVerti * isInv + hHalf * isHori };
-
- setSize(width, height);
+
+ this.input = new Pin(this, "IN", params.logicWidth, PinUsage.INPUT, oc.newX(0, hHalf), oc.newY(0, hHalf));
+ this.output = new Pin(this, "OUT", params.logicWidth, PinUsage.OUTPUT, oc.newX(width, hHalf), oc.newY(width, hHalf));
+ this.enable = new Pin(this, "EN", 1, PinUsage.INPUT, oc.newX(wHalf, hQuar), oc.newY(wHalf, hQuar));
+ this.path = new double[] { oc.newX(0, 0), oc.newY(0, 0), oc.newX(width, hHalf), oc.newY(width, hHalf), oc.newX(0, height),
+ oc.newY(0, height) };
+
+ setSize(oc.width(), oc.height());
addPin(input);
addPin(output);
addPin(enable);
double x = getPosX();
double y = getPosY();
gc.drawPolygon(new double[] { x + path[0], y + path[1], x + path[2], y + path[3], x + path[4], y + path[5] });
-// Font oldFont = gc.getFont();
-// Font labelFont = new Font(oldFont.getName(), fontHeight, oldFont.getStyle());
-// gc.setFont(labelFont);
-// Point textExtent = gc.textExtent(label);
-// Color textColor = Preferences.current().getColor("net.mograsim.logic.model.color.text");
-// if (textColor != null)
-// gc.setForeground(textColor);
-// gc.drawText(label, getPosX() + (rectWidth - textExtent.x) / 2, getPosY() + (height - textExtent.y) / 2, true);
-// gc.setFont(oldFont);
}
@Override
});
}
- private static class GUITriStateBufferParams
+ public static class GUITriStateBufferParams
{
int logicWidth;
Orientation orientation;
- }
- public enum Orientation
- {
- RIGHT, LEFT, UP, DOWN, RIGHT_ALT, LEFT_ALT, UP_ALT, DOWN_ALT;
+ public GUITriStateBufferParams(int logicWidth, Orientation orientation)
+ {
+ this.logicWidth = logicWidth;
+ this.orientation = orientation;
+ }
}
}