diff --git a/src/org/atriasoft/etk/Dimension2f.java b/src/org/atriasoft/etk/Dimension2f.java new file mode 100644 index 0000000..80e515b --- /dev/null +++ b/src/org/atriasoft/etk/Dimension2f.java @@ -0,0 +1,282 @@ +/** @file + * @author Edouard DUPIN + * @copyright 2011, Edouard DUPIN, all right reserved + * @license MPL v2.0 (see license file) + */ +package org.atriasoft.etk; + +import org.atriasoft.etk.internal.Log; +import org.atriasoft.etk.math.Vector2f; +import org.atriasoft.etk.math.Vector2i; + +/** + * in the dimension class we store the data as the more usefull unit (pixel) + * but one case need to be dynamic the %, then when requested in % the register the % value + */ +public record Dimension2f( + Vector2f size, + Distance type) { + + public static final Dimension2f ZERO = new Dimension2f(Vector2f.ZERO, Distance.PIXEL); + private static Vector2f ratio = new Vector2f(9999999, 888888); + private static Vector2f invRatio = Vector2f.ONE; + private static Dimension2f windowsSize = new Dimension2f(Vector2f.MAX_VALUE, Distance.PIXEL); + + public static final float INCH_TO_MILLIMETER = 1.0f / 25.4f; + public static final float FOOT_TO_MILLIMETER = 1.0f / 304.8f; + public static final float METER_TO_MILLIMETER = 1.0f / 1000.0f; + public static final float CENTIMETER_TO_MILLIMETER = 1.0f / 10.0f; + public static final float KILOMETER_TO_MILLIMETER = 1.0f / 1000000.0f; + public static final float MILLIMETER_TO_INCH = 25.4f; + public static final float MILLIMETER_TO_FOOT = 304.8f; + public static final float MILLIMETER_TO_METER = 1000.0f; + public static final float MILLIMETER_TO_CENTIMETER = 10.0f; + public static final float MILLIMETER_TO_KILOMETER = 1000000.0f; + /** + * basic init + */ + static { + final Dimension2f conversion = new Dimension2f(new Vector2f(72, 72), Distance.INCH); + ratio = conversion.getMillimeter(); + invRatio = new Vector2f(1.0f / ratio.x(), 1.0f / ratio.y()); + windowsSize = new Dimension2f(new Vector2f(200, 200), Distance.PIXEL); + } + + /** + * get the Windows diagonal size in the request unit + * @param type Unit type requested. + * @return the requested size + */ + public static float getWindowsDiag(final Distance type) { + final Vector2f size = getWindowsSize(type); + return size.length(); + } + + /** + * get the Windows size in the request unit + * @param type Unit type requested. + * @return the requested size + */ + public static Vector2f getWindowsSize(final Distance type) { + return windowsSize.get(type); + } + + /** + * set the Millimeter ratio for calculation + * @param ratio Millimeter ration for the screen calculation interpolation + * @param type Unit type requested. + * @note: same as @ref setPixelPerInch (internal manage convention) + */ + public static void setPixelRatio(final Vector2f ratio, final Distance type) { + Log.info("Set a new screen ratio for the screen : ratio=" + ratio + " type=" + type); + final Dimension2f conversion = new Dimension2f(ratio, type); + Log.info(" == > " + conversion); + Dimension2f.ratio = conversion.getMillimeter(); + invRatio = new Vector2f(1.0f / Dimension2f.ratio.x(), 1.0f / Dimension2f.ratio.y()); + Log.info("Set a new screen ratio for the screen : ratioMm=" + Dimension2f.ratio); + } + + /** + * set the current Windows size + * @param size size of the current windows in pixel. + */ + public static void setPixelWindowsSize(final Vector2f size) { + windowsSize = new Dimension2f(size); + Log.verbose("Set a new Windows property size " + windowsSize + "px"); + } + + /** + * Constructor (default :0,0 mode pixel) + */ + public Dimension2f() { + this(Vector2f.ZERO, Distance.PIXEL); + } + + /** + * Constructor + * @param size Requested dimension + */ + public Dimension2f(final Vector2f size) { + this(size, Distance.PIXEL); + } + + public Dimension2f(final Vector2f size, final Distance type) { + this.size = size; + this.type = type; + } + + /** + * get the current dimension in requested type + * @param type Type of unit requested. + * @return dimension requested. + */ + public Vector2f get(final Distance type) { + return switch (type) { + case POURCENT -> getPourcent(); + case PIXEL -> getPixel(); + case METER -> getMeter(); + case CENTIMETER -> getCentimeter(); + case MILLIMETER -> getMillimeter(); + case KILOMETER -> getKilometer(); + case INCH -> getInch(); + case FOOT -> getFoot(); + case ELEMENT -> throw new UnsupportedOperationException("Unimplemented case: " + type); + case EX -> throw new UnsupportedOperationException("Unimplemented case: " + type); + case PC -> { + Log.error("Does not support other than Px and % type of dimention : " + type + " automaticly convert with {72,72} pixel/inch"); + yield null; + } + case POINT -> throw new UnsupportedOperationException("Unimplemented case: " + type); + default -> throw new IllegalArgumentException("Unexpected value: " + type); + }; + } + + /** + * get the current dimension in Centimeter + * @return dimension in Centimeter + */ + public Vector2f getCentimeter() { + return getMillimeter().multiply(MILLIMETER_TO_CENTIMETER); + } + + /** + * get the current dimension in Foot + * @return dimension in Foot + */ + public Vector2f getFoot() { + return getMillimeter().multiply(MILLIMETER_TO_FOOT); + } + + /** + * get the current dimension in Inch + * @return dimension in Inch + */ + public Vector2f getInch() { + return getMillimeter().multiply(MILLIMETER_TO_INCH); + } + + /** + * get the current dimension in Kilometer + * @return dimension in Kilometer + */ + public Vector2f getKilometer() { + return getMillimeter().multiply(MILLIMETER_TO_KILOMETER); + } + + /** + * get the current dimension in Meter + * @return dimension in Meter + */ + public Vector2f getMeter() { + return getMillimeter().multiply(MILLIMETER_TO_METER); + } + + /** + * get the current dimension in Millimeter + * @return dimension in Millimeter + */ + public Vector2f getMillimeter() { + return new Vector2f(getPixel().x() * invRatio.x(), getPixel().y() * invRatio.y()); + } + + /** + * get the current dimension in pixel + * @return dimension in Pixel + */ + public Vector2f getPixel() { + if (this.type != Distance.POURCENT) { + return this.size; + } + return getPixel(windowsSize.getPixel()); + } + + public Vector2f getPixel(final Vector2f uppersize) { + if (this.type != Distance.POURCENT) { + return this.size; + } + final Vector2f res = new Vector2f(uppersize.x() * this.size.x() * 0.01f, uppersize.y() * this.size.y() * 0.01f); + //GALE_DEBUG("Get % : " + m_data + " / " + windDim + " == > " + res); + return res; + } + + public Vector2i getPixeli() { + Vector2f tmpSize = windowsSize.getPixel(); + return getPixeli(new Vector2i((int) tmpSize.x(), (int) tmpSize.y())); + } + + public Vector2i getPixeli(final Vector2i uppersize) { + if (this.type != Distance.POURCENT) { + return new Vector2i((int) this.size.x(), (int) this.size.y()); + } + final Vector2i res = new Vector2i((int) (uppersize.x() * this.size.x() * 0.01f), (int) (uppersize.y() * this.size.y() * 0.01f)); + //GALE_DEBUG("Get % : " + m_data + " / " + windDim + " == > " + res); + return res; + } + + /** + * get the current dimension in Percent + * @return dimension in Percent + */ + public Vector2f getPourcent() { + if (this.type != Distance.POURCENT) { + final Vector2f windDim = windowsSize.getPixel(); + //GALE_DEBUG(" windows dimension : " /*+ windowsSize*/ + " == > " + windDim + "px"); // ==> infinite loop ... + //printf(" windows dimension : %f,%f", windDim.x(),windDim.y()); + //printf(" data : %f,%f", m_data.x(),m_data.y()); + return new Vector2f((this.size.x() / windDim.x()) * 100.0f, (this.size.y() / windDim.y()) * 100.0f); + } + return new Vector2f(this.size.x() * 100.0f, this.size.y() * 100.0f); + } + + /** + * get the dimension type + * @return the type + */ + public Distance getType() { + return this.type; + } + + /** + * set the current dimension in requested type + * @param config dimension configuration. + */ + public static Dimension2f valueOf(String config) { + Distance type = Distance.parseEndSmallString(config); + config = type.removeEndString(config); + if (type == Distance.UNKNOW) { + Log.critical("Can not parse dimension : '" + config + "'"); + return null; + } + final Vector2f tmp = Vector2f.valueOf(config); + final Dimension2f ret = new Dimension2f(tmp, type); + Log.verbose(" config dimension : '" + config + "' == > " + ret.toString()); + return ret; + } + + /** + * string cast : + */ + @Override + public String toString() { + return get(getType()).toString() + getType().toSmallString(); + } + + public static Dimension2f valueOf(String contentX, String contentY) { + Distance typeX = Distance.parseEndSmallString(contentX); + contentX = typeX.removeEndString(contentX); + float tmpX = Float.valueOf(contentX); + + Distance typeY = Distance.parseEndSmallString(contentY); + contentX = typeY.removeEndString(contentY); + float tmpY = Float.valueOf(contentY); + + if (typeX != Distance.UNKNOW) { + return new Dimension2f(new Vector2f(tmpX, tmpY), typeX); + } + if (typeY != Distance.UNKNOW) { + return new Dimension2f(new Vector2f(tmpX, tmpY), typeY); + } + return new Dimension2f(new Vector2f(tmpX, tmpY), Distance.PIXEL); + } + +} diff --git a/src/org/atriasoft/etk/math/Vector3b.java b/src/org/atriasoft/etk/math/Vector3b.java new file mode 100644 index 0000000..b57ec66 --- /dev/null +++ b/src/org/atriasoft/etk/math/Vector3b.java @@ -0,0 +1,107 @@ +package org.atriasoft.etk.math; + +import org.atriasoft.etk.internal.Log; + +import edu.umd.cs.findbugs.annotations.CheckReturnValue; + +@SuppressWarnings("preview") +public record Vector3b( + boolean x, + boolean y, + boolean z) { + public static Vector3b valueOf(String value) { + boolean val1 = false; + boolean val2 = false; + boolean val3 = false; + // copy to permit to modify it : + while (value.length() > 0 && value.charAt(0) == '(') { + value = value.substring(1); + } + while (value.length() > 0 && value.charAt(0) == ')') { + value = value.substring(0, value.length() - 1); + } + final String[] values = value.split(",| "); + if (values.length > 3) { + Log.error("Can not parse Vector3b with more than 3 values: '" + value + "'"); + } + if (values.length == 1) { + // no coma ... + // in every case, we parse the first element : + val1 = Boolean.valueOf(values[0]); + val2 = val1; + val3 = val1; + } else if (values.length == 2) { + val1 = Boolean.valueOf(values[0]); + val2 = Boolean.valueOf(values[1]); + val3 = val2; + } else { + val1 = Boolean.valueOf(values[0]); + val2 = Boolean.valueOf(values[1]); + val3 = Boolean.valueOf(values[2]); + } + return new Vector3b(val1, val2, val3); + } + + /* + * **************************************************** Constructor + *****************************************************/ + public Vector3b() { + this(false, false, false); + } + + public Vector3b(final boolean x, final boolean y, final boolean z) { + this.x = x; + this.y = y; + this.z = z; + } + + /** + * In-Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are NOT identical + * @return false The Objects are identical + */ + @CheckReturnValue + public boolean isDifferent(final Vector3b obj) { + return (obj.x != this.x || obj.y != this.y || obj.z != this.z); + } + + /** + * Equality compare operator with an other object. + * @param obj Reference on the comparing object + * @return true The Objects are identical + * @return false The Objects are NOT identical + */ + @CheckReturnValue + public boolean isEqual(final Vector3b obj) { + return (obj.x == this.x && obj.y == this.y && obj.z == this.z); + } + + public static final Vector3b FALSE = new Vector3b(false, false, false); + public static final Vector3b TRUE = new Vector3b(true, true, true); + public static final Vector3b FALSE_FALSE_FALSE = FALSE; + public static final Vector3b TRUE_TRUE_TRUE = TRUE; + public static final Vector3b TRUE_FALSE_FALSE = new Vector3b(true, false, false); + public static final Vector3b FALSE_TRUE_FALSE = new Vector3b(false, true, false); + public static final Vector3b FALSE_FALSE_TRUE = new Vector3b(false, false, true); + + @Override + public String toString() { + return "(" + this.x + "," + this.y + ")"; + } + + @CheckReturnValue + public Vector3b withX(final boolean xxx) { + return new Vector3b(xxx, this.y, this.z); + } + + @CheckReturnValue + public Vector3b withY(final boolean yyy) { + return new Vector3b(this.x, yyy, this.z); + } + + @CheckReturnValue + public Vector3b withZ(final boolean zzz) { + return new Vector3b(this.x, this.y, zzz); + } +} diff --git a/src/org/atriasoft/etk/util/AutoUnLock.java b/src/org/atriasoft/etk/util/AutoUnLock.java new file mode 100644 index 0000000..73b87c5 --- /dev/null +++ b/src/org/atriasoft/etk/util/AutoUnLock.java @@ -0,0 +1,35 @@ +package org.atriasoft.etk.util; + +import java.util.concurrent.locks.Lock; + +/** + * simple use: + * try (AutoUnlock autoUnlock = AutoUnlock.lock(lock)) { + * + * @author heero + * + */ +public class AutoUnLock implements AutoCloseable { + public static AutoUnLock lock(final Lock lock) { + lock.lock(); + return new AutoUnLock(lock); + } + + public static AutoUnLock tryLock(final Lock lock) throws Exception { + if (!lock.tryLock()) { + throw new Exception("wxvwvc"); + } + return new AutoUnLock(lock); + } + + private final Lock lock; + + private AutoUnLock(final Lock lock) { + this.lock = lock; + } + + @Override + public void close() { + this.lock.unlock(); + } +} \ No newline at end of file