diff --git a/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTComponentRenderer.java b/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTComponentRenderer.java index c32908b9..829c66ac 100644 --- a/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTComponentRenderer.java +++ b/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTComponentRenderer.java @@ -19,14 +19,17 @@ import com.io7m.jfunctional.Unit; import com.io7m.jnull.NullCheck; import com.io7m.jorchard.core.JOTreeNodeReadableType; +import com.io7m.jsycamore.core.SySpaceComponentRelativeType; import com.io7m.jsycamore.core.SySpaceParentRelativeType; import com.io7m.jsycamore.core.SyTextMeasurementType; +import com.io7m.jsycamore.core.boxes.SyBox; import com.io7m.jsycamore.core.boxes.SyBoxType; import com.io7m.jsycamore.core.boxes.SyBoxes; import com.io7m.jsycamore.core.components.SyButtonReadableType; import com.io7m.jsycamore.core.components.SyComponentReadableType; import com.io7m.jsycamore.core.components.SyImageReadableType; import com.io7m.jsycamore.core.components.SyLabelReadableType; +import com.io7m.jsycamore.core.components.SyMeterReadableType; import com.io7m.jsycamore.core.components.SyPanelReadableType; import com.io7m.jsycamore.core.components.SyWindowViewportAccumulatorType; import com.io7m.jsycamore.core.images.SyImageCacheType; @@ -36,6 +39,7 @@ import com.io7m.jsycamore.core.themes.SyThemeEmbossType; import com.io7m.jsycamore.core.themes.SyThemeImageType; import com.io7m.jsycamore.core.themes.SyThemeLabelType; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; import com.io7m.jsycamore.core.themes.SyThemeOutlineType; import com.io7m.jsycamore.core.themes.SyThemePanelType; import com.io7m.jtensors.VectorReadable3FType; @@ -49,6 +53,7 @@ import java.awt.image.BufferedImage; import java.util.Collection; import java.util.Optional; +import java.util.function.Supplier; /** * An AWT-based component renderer. @@ -182,6 +187,9 @@ private void renderActual( }, (r, image) -> { this.renderImage(graphics, image); return Unit.unit(); + }, (r, meter) -> { + this.renderMeter(graphics, meter); + return Unit.unit(); }); final JOTreeNodeReadableType node = @@ -203,6 +211,69 @@ private void renderActual( } } + private void renderMeter( + final Graphics2D graphics, + final SyMeterReadableType meter) + { + final Optional theme_opt = meter.theme(); + if (!theme_opt.isPresent()) { + throw SyAWTComponentRenderer.notAttached(meter); + } + + final SyThemeMeterType theme = theme_opt.get(); + final Optional outline = theme.outline(); + final SyBoxType box = meter.box(); + final SyBoxType box_origin = + SyBoxes.cast(SyBoxes.moveToOrigin(box)); + + if (box.width() > 0) { + this.renderThemedBox( + graphics, + outline, + () -> meter.isActive() ? theme.colorContainerActive() : theme.colorContainerInactive(), + () -> meter.isActive() ? theme.embossContainerActive() : theme.embossContainerInactive(), + box_origin); + } + + switch (meter.orientation()) { + case ORIENTATION_HORIZONTAL: { + final int width = (int) (meter.value() * (double) box.width()); + final SyBoxType box_fill = + SyBoxes.create(0, 0, width, box.height()); + + if (width > 0 && box.height() > 0) { + this.renderThemedBox( + graphics, + outline, + () -> meter.isActive() ? theme.colorFillActive() : theme.colorFillInactive(), + () -> meter.isActive() ? theme.embossFillActive() : theme.embossFillInactive(), + box_fill); + } + break; + } + case ORIENTATION_VERTICAL: { + final int height = (int) (meter.value() * (double) box.height()); + final SyBoxType box_fill = + SyBoxes.create(0, box.height() - height, box.width(), height); + + if (height > 0 && box.width() > 0) { + this.renderThemedBox( + graphics, + outline, + () -> meter.isActive() ? theme.colorFillActive() : theme.colorFillInactive(), + () -> meter.isActive() ? theme.embossFillActive() : theme.embossFillInactive(), + box_fill); + } + break; + } + } + + if (outline.isPresent()) { + SyAWTDrawing.drawOutline( + graphics, outline.get(), box_origin, meter.isActive()); + } + } + private void renderImage( final Graphics2D graphics, final SyImageReadableType image) @@ -212,7 +283,6 @@ private void renderImage( throw SyAWTComponentRenderer.notAttached(image); } - final SyThemeImageType theme = theme_opt.get(); final SyBoxType box = image.box(); final SyImageReferenceType ref = @@ -302,7 +372,31 @@ private void renderPanel( final SyThemePanelType theme = theme_opt.get(); final SyBoxType box = panel.box(); + final SyBoxType box_origin = + SyBoxes.cast(SyBoxes.moveToOrigin(box)); + final Optional outline = theme.outline(); + this.renderThemedBox( + graphics, + outline, + () -> panel.isActive() ? theme.colorActive() : theme.colorInactive(), + () -> panel.isActive() ? theme.embossActive() : theme.embossInactive(), + box_origin + ); + + if (outline.isPresent()) { + SyAWTDrawing.drawOutline( + graphics, outline.get(), SyBoxes.moveToOrigin(box), panel.isActive()); + } + } + + private void renderThemedBox( + final Graphics2D graphics, + final Optional outline, + final Supplier color, + final Supplier> emboss, + final SyBoxType box) + { final int width = box.width(); final int height = box.height(); final int fill_width; @@ -310,42 +404,26 @@ private void renderPanel( final int fill_x; final int fill_y; - final Optional outline = theme.outline(); if (outline.isPresent()) { - fill_x = 1; - fill_y = 1; + fill_x = box.minimumX() + 1; + fill_y = box.minimumY() + 1; fill_width = width - 2; fill_height = height - 2; } else { - fill_x = 0; - fill_y = 0; + fill_x = box.minimumX(); + fill_y = box.minimumY(); fill_width = width; fill_height = height; } - final Optional emboss; - final VectorReadable3FType color; - if (panel.isActive()) { - emboss = theme.embossActive(); - color = theme.colorActive(); - } else { - emboss = theme.embossInactive(); - color = theme.colorInactive(); - } - this.renderOptionallyEmbossedFill( graphics, fill_width, fill_height, fill_x, fill_y, - emboss, - color); - - if (outline.isPresent()) { - SyAWTDrawing.drawOutline( - graphics, outline.get(), SyBoxes.moveToOrigin(box), panel.isActive()); - } + emboss.get(), + color.get()); } private void renderButton( diff --git a/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTDrawing.java b/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTDrawing.java index 22569ecf..918f7ea2 100644 --- a/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTDrawing.java +++ b/io7m-jsycamore-awt/src/main/java/com/io7m/jsycamore/awt/SyAWTDrawing.java @@ -69,7 +69,7 @@ public static Color toColor( public static void drawOutline( final Graphics2D graphics, final SyThemeOutlineType outline, - final SyBoxType box, + final SyBoxType box, final boolean active) { NullCheck.notNull(graphics, "graphics"); diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SyOrientation.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SyOrientation.java new file mode 100644 index 00000000..a5c99d34 --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SyOrientation.java @@ -0,0 +1,36 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core; + +/** + * Orientation. + */ + +public enum SyOrientation +{ + /** + * Horizontal orientation. + */ + + ORIENTATION_HORIZONTAL, + + /** + * Vertical orientation. + */ + + ORIENTATION_VERTICAL +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SySpaceComponentRelativeType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SySpaceComponentRelativeType.java new file mode 100644 index 00000000..93eb5379 --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/SySpaceComponentRelativeType.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core; + +/** + * The component-relative coordinate space. + */ + +public interface SySpaceComponentRelativeType extends SySpaceType +{ + // No value-level representation. +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonCheckboxAbstract.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonCheckboxAbstract.java index 7ae20676..7101ec7b 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonCheckboxAbstract.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonCheckboxAbstract.java @@ -161,7 +161,6 @@ public final boolean mousePressed( switch (button) { case MOUSE_BUTTON_LEFT: { this.pressed = true; - this.over = true; return true; } case MOUSE_BUTTON_MIDDLE: diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonReadableType.java index b9597700..42bb6b8d 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonReadableType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonReadableType.java @@ -48,7 +48,8 @@ default B matchComponentReadable( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_button).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonRepeatingAbstract.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonRepeatingAbstract.java index cdf32516..c7372f30 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonRepeatingAbstract.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonRepeatingAbstract.java @@ -151,7 +151,6 @@ public final boolean mousePressed( switch (button) { case MOUSE_BUTTON_LEFT: { this.pressed = true; - this.over = true; return true; } case MOUSE_BUTTON_MIDDLE: diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonType.java index cb6fd48b..dc78eacc 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyButtonType.java @@ -50,7 +50,8 @@ default B matchComponent( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_button).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentAbstract.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentAbstract.java index fda894da..aa3be9b5 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentAbstract.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentAbstract.java @@ -22,6 +22,7 @@ import com.io7m.jorchard.core.JOTreeNodeType; import com.io7m.jsycamore.core.SyMouseButton; import com.io7m.jsycamore.core.SyParentResizeBehavior; +import com.io7m.jsycamore.core.SySpaceComponentRelativeType; import com.io7m.jsycamore.core.SySpaceParentRelativeType; import com.io7m.jsycamore.core.SySpaceViewportType; import com.io7m.jsycamore.core.SySpaceWindowRelativeType; @@ -31,12 +32,16 @@ import com.io7m.jsycamore.core.boxes.SyBoxType; import com.io7m.jsycamore.core.boxes.SyBoxes; import com.io7m.jsycamore.core.themes.SyThemeType; +import com.io7m.jtensors.parameterized.PVectorI2I; +import com.io7m.jtensors.parameterized.PVectorM2I; import com.io7m.jtensors.parameterized.PVectorReadable2IType; +import com.io7m.jtensors.parameterized.PVectorWritable2IType; import com.io7m.junreachable.UnreachableCodeException; import net.jcip.annotations.NotThreadSafe; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.ArrayDeque; import java.util.ArrayList; import java.util.Collection; import java.util.Optional; @@ -254,6 +259,56 @@ public final SyBoxType box() return this.box; } + @Override + public final void transformWindowRelative( + final PVectorReadable2IType w_position, + final PVectorWritable2IType c_position) + { + NullCheck.notNull(w_position, "Viewport position"); + NullCheck.notNull(c_position, "Component-relative position"); + + final PVectorI2I pos_component = + this.positionWindowRelative(); + + c_position.set2I( + Math.subtractExact(w_position.getXI(), pos_component.getXI()), + Math.subtractExact(w_position.getYI(), pos_component.getYI())); + } + + @Override + public final PVectorI2I positionWindowRelative() + { + final ArrayDeque ancestors = + new ArrayDeque<>(); + + JOTreeNodeType n = this.node; + while (true) { + final Optional> parent_opt = n.parent(); + if (parent_opt.isPresent()) { + final JOTreeNodeType parent = parent_opt.get(); + ancestors.push(parent.value()); + n = parent; + } else { + break; + } + } + + final PVectorM2I position = + new PVectorM2I<>(0, 0); + + while (!ancestors.isEmpty()) { + final SyComponentReadableType ancestor = ancestors.pop(); + position.set2I( + Math.addExact(position.getXI(), ancestor.box().minimumX()), + Math.addExact(position.getYI(), ancestor.box().minimumY())); + } + + position.set2I( + Math.addExact(position.getXI(), this.box().minimumX()), + Math.addExact(position.getYI(), this.box().minimumY())); + return new PVectorI2I<>(position); + } + @Override public final Optional componentForWindowRelative( final PVectorReadable2IType w_position, diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentReadableType.java index 9e0414f9..43b5454c 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentReadableType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentReadableType.java @@ -18,11 +18,16 @@ import com.io7m.jorchard.core.JOTreeNodeReadableType; import com.io7m.jsycamore.core.SyParentResizeBehavior; +import com.io7m.jsycamore.core.SySpaceComponentRelativeType; import com.io7m.jsycamore.core.SySpaceParentRelativeType; +import com.io7m.jsycamore.core.SySpaceViewportType; import com.io7m.jsycamore.core.SySpaceWindowRelativeType; import com.io7m.jsycamore.core.SyWindowReadableType; import com.io7m.jsycamore.core.boxes.SyBoxType; +import com.io7m.jtensors.VectorWritable2IType; +import com.io7m.jtensors.parameterized.PVectorI2I; import com.io7m.jtensors.parameterized.PVectorReadable2IType; +import com.io7m.jtensors.parameterized.PVectorWritable2IType; import java.util.Optional; import java.util.function.BiFunction; @@ -86,6 +91,23 @@ public interface SyComponentReadableType SyBoxType box(); + /** + * @return The window-relative position of the component + */ + + PVectorI2I positionWindowRelative(); + + /** + * Transform a window-relative position to component-relative form. + * + * @param w_position A window-relative position + * @param c_position The output vector + */ + + void transformWindowRelative( + PVectorReadable2IType w_position, + PVectorWritable2IType c_position); + /** * @return The window to which this component belongs */ @@ -100,6 +122,7 @@ public interface SyComponentReadableType * @param on_panel A function evaluated if this component is a panel * @param on_label A function evaluated if this component is a label * @param on_image A function evaluated if this component is an image + * @param on_meter A function evaluated if this component is a meter * @param The type of opaque context values * @param The type of returned values * @@ -112,7 +135,8 @@ B matchComponentReadable( BiFunction on_button, BiFunction on_panel, BiFunction on_label, - BiFunction on_image); + BiFunction on_image, + BiFunction on_meter); /** * Determine the topmost component at the given window-relative position. diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentType.java index 7aa5b0b4..46e5c080 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyComponentType.java @@ -101,6 +101,7 @@ Optional componentForWindowRelative( * @param on_panel A function evaluated if this component is a panel * @param on_label A function evaluated if this component is a label * @param on_image A function evaluated if this component is an image + * @param on_meter A function evaluated if this component is a meter * @param The type of opaque context values * @param The type of returned values * @@ -113,7 +114,8 @@ B matchComponent( BiFunction on_button, BiFunction on_panel, BiFunction on_label, - BiFunction on_image); + BiFunction on_image, + BiFunction on_meter); /** * Set this component as active/inactive. diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageReadableType.java index 48c3572a..543d9f68 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageReadableType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageReadableType.java @@ -68,7 +68,8 @@ default B matchComponentReadable( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_image).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageType.java index 5841f9e4..ff64b235 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyImageType.java @@ -63,7 +63,8 @@ default B matchComponent( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_image).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelReadableType.java index 69e51f11..fca3885a 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelReadableType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelReadableType.java @@ -67,7 +67,8 @@ default B matchComponentReadable( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_label).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelType.java index 3dffa8ba..5a1b2dff 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyLabelType.java @@ -62,7 +62,8 @@ default B matchComponent( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_label).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeter.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeter.java new file mode 100644 index 00000000..3e2a387e --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeter.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core.components; + +import com.io7m.jsycamore.core.themes.SyThemeMeterType; +import com.io7m.jsycamore.core.themes.SyThemeType; + +import java.util.Optional; + +/** + * The default implementation of the {@link SyMeterType} interface. + */ + +public final class SyMeter extends SyMeterAbstract +{ + private SyMeter() + { + super(() -> true); + } + + /** + * @return A new meter + */ + + public static SyMeterType create() + { + return new SyMeter(); + } + + @Override + public String toString() + { + final StringBuilder sb = new StringBuilder(128); + sb.append("[SyMeter 0x"); + sb.append(Integer.toHexString(this.hashCode())); + sb.append(" "); + sb.append(this.value()); + sb.append(" "); + sb.append(this.box().width()); + sb.append("x"); + sb.append(this.box().height()); + sb.append(" "); + sb.append(this.box().minimumX()); + sb.append("+"); + sb.append(this.box().minimumY()); + sb.append("]"); + return sb.toString(); + } + + @Override + public Optional theme() + { + return this.windowTheme().map(SyThemeType::meterTheme); + } +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterAbstract.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterAbstract.java new file mode 100644 index 00000000..d48ee6fb --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterAbstract.java @@ -0,0 +1,177 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core.components; + +import com.io7m.jnull.NullCheck; +import com.io7m.jsycamore.core.SyMouseButton; +import com.io7m.jsycamore.core.SyOrientation; +import com.io7m.jsycamore.core.SySpaceComponentRelativeType; +import com.io7m.jsycamore.core.SySpaceViewportType; +import com.io7m.jsycamore.core.SySpaceWindowRelativeType; +import com.io7m.jtensors.parameterized.PVectorM2I; +import com.io7m.jtensors.parameterized.PVectorReadable2IType; +import com.io7m.junreachable.UnreachableCodeException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.function.BooleanSupplier; + +/** + * An abstract implementation of the {@link SyMeterType} interface. + */ + +public abstract class SyMeterAbstract extends SyComponentAbstract implements + SyMeterType +{ + private static final Logger LOG; + + static { + LOG = LoggerFactory.getLogger(SyMeterAbstract.class); + } + + private double value; + private SyOrientation orientation; + + protected SyMeterAbstract( + final BooleanSupplier in_detach_check) + { + super(in_detach_check); + this.value = 0.0; + this.orientation = SyOrientation.ORIENTATION_HORIZONTAL; + } + + @Override + public final SyOrientation orientation() + { + return this.orientation; + } + + @Override + public final void setOrientation(final SyOrientation o) + { + this.orientation = NullCheck.notNull(o, "Orientation"); + } + + @Override + public final void setValue(final double x) + { + this.value = Math.max(Math.min(1.0, x), 0.0); + } + + @Override + public final double value() + { + return this.value; + } + + @Override + public final boolean mouseHeld( + final PVectorReadable2IType mouse_position_first, + final PVectorReadable2IType mouse_position_now, + final SyMouseButton button, + final SyComponentType actual) + { + NullCheck.notNull(mouse_position_first); + NullCheck.notNull(mouse_position_now); + NullCheck.notNull(button); + NullCheck.notNull(actual); + + if (SyMeterAbstract.LOG.isTraceEnabled()) { + SyMeterAbstract.LOG.trace( + "mouseHeld: {} {} {} {}", + mouse_position_first, + mouse_position_now, + button, + actual); + } + + switch (button) { + case MOUSE_BUTTON_LEFT: { + this.updateValueForMouse(mouse_position_now); + return true; + } + case MOUSE_BUTTON_MIDDLE: + case MOUSE_BUTTON_RIGHT: { + return false; + } + } + + throw new UnreachableCodeException(); + } + + @Override + public final boolean mousePressed( + final PVectorReadable2IType mouse_position, + final SyMouseButton button, + final SyComponentType actual) + { + NullCheck.notNull(mouse_position); + NullCheck.notNull(button); + NullCheck.notNull(actual); + + if (SyMeterAbstract.LOG.isTraceEnabled()) { + SyMeterAbstract.LOG.trace( + "mousePressed: {} {} {}", mouse_position, button, actual); + } + + switch (button) { + case MOUSE_BUTTON_LEFT: { + this.updateValueForMouse(mouse_position); + return true; + } + case MOUSE_BUTTON_MIDDLE: + case MOUSE_BUTTON_RIGHT: { + return false; + } + } + + throw new UnreachableCodeException(); + } + + private void updateValueForMouse( + final PVectorReadable2IType mouse_position) + { + this.window().ifPresent(window -> { + final PVectorM2I mouse_pos_window = + new PVectorM2I<>(); + final PVectorM2I mouse_pos_component = + new PVectorM2I<>(); + + window.transformViewportRelative(mouse_position, mouse_pos_window); + this.transformWindowRelative(mouse_pos_window, mouse_pos_component); + + switch (this.orientation) { + case ORIENTATION_HORIZONTAL: { + final double w = (double) this.box().width(); + final double x = (double) mouse_pos_component.getXI(); + this.setValue(x / w); + break; + } + case ORIENTATION_VERTICAL: { + final double h = (double) this.box().height(); + final double y = h - (double) mouse_pos_component.getYI(); + this.setValue(y / h); + break; + } + } + + if (SyMeterAbstract.LOG.isTraceEnabled()) { + SyMeterAbstract.LOG.trace("value: {}", Double.valueOf(this.value())); + } + }); + } +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterReadableType.java new file mode 100644 index 00000000..3330ce67 --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterReadableType.java @@ -0,0 +1,61 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core.components; + +import com.io7m.jnull.NullCheck; +import com.io7m.jsycamore.core.SyOrientation; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; + +import java.util.Optional; +import java.util.function.BiFunction; + +/** + * The type of readable meters. + */ + +public interface SyMeterReadableType extends SyComponentReadableType +{ + /** + * @return The meter's orientation + */ + + SyOrientation orientation(); + + /** + * @return The theme for the meter + */ + + Optional theme(); + + /** + * @return The current meter value, in the range `[0.0, 1.0]` + */ + + double value(); + + @Override + default B matchComponentReadable( + final A context, + final BiFunction on_button, + final BiFunction on_panel, + final BiFunction on_label, + final BiFunction on_image, + final BiFunction on_meter) + { + return NullCheck.notNull(on_meter).apply(context, this); + } +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterType.java new file mode 100644 index 00000000..c5e336e6 --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyMeterType.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core.components; + +import com.io7m.jnull.NullCheck; +import com.io7m.jsycamore.core.SyOrientation; + +import java.util.function.BiFunction; + +/** + * The type of meters. + */ + +public interface SyMeterType extends SyComponentType, SyMeterReadableType +{ + /** + * Set the meter's orientation. + * + * @param o The orientation + */ + + void setOrientation(SyOrientation o); + + /** + * Set the meter value. + * + * @param x A value in the range `[0.0, 1.0]` + */ + + void setValue(double x); + + @Override + default B matchComponent( + final A context, + final BiFunction on_button, + final BiFunction on_panel, + final BiFunction on_label, + final BiFunction on_image, + final BiFunction on_meter) + { + return NullCheck.notNull(on_meter).apply(context, this); + } +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelReadableType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelReadableType.java index bb99ff19..56ec0e41 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelReadableType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelReadableType.java @@ -51,7 +51,8 @@ default B matchComponentReadable( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_panel).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelType.java index 33866365..3279c576 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/components/SyPanelType.java @@ -43,7 +43,8 @@ default B matchComponent( final BiFunction on_button, final BiFunction on_panel, final BiFunction on_label, - final BiFunction on_image) + final BiFunction on_image, + final BiFunction on_meter) { return NullCheck.notNull(on_panel).apply(context, this); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeMeterType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeMeterType.java new file mode 100644 index 00000000..49d8d190 --- /dev/null +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeMeterType.java @@ -0,0 +1,95 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.core.themes; + +import com.io7m.jsycamore.core.SyImmutableStyleType; +import com.io7m.jtensors.VectorI3F; +import org.immutables.value.Value; + +import java.util.Optional; + +/** + * A meter theme specification. + */ + +@SyImmutableStyleType +@Value.Immutable +public interface SyThemeMeterType +{ + /** + * @return The base color used for the containers of active meters + */ + + @Value.Parameter + VectorI3F colorContainerActive(); + + /** + * @return The base color used for containers of inactive meters + */ + + @Value.Parameter + VectorI3F colorContainerInactive(); + + /** + * @return The embossing used for containers of active meters + */ + + @Value.Parameter + Optional embossContainerActive(); + + /** + * @return The embossing used for containers of inactive meters + */ + + @Value.Parameter + Optional embossContainerInactive(); + + /** + * @return The base color used for the fills of active meters + */ + + @Value.Parameter + VectorI3F colorFillActive(); + + /** + * @return The base color used for fills of inactive meters + */ + + @Value.Parameter + VectorI3F colorFillInactive(); + + /** + * @return The embossing used for fills of active meters + */ + + @Value.Parameter + Optional embossFillActive(); + + /** + * @return The embossing used for fills of inactive meters + */ + + @Value.Parameter + Optional embossFillInactive(); + + /** + * @return The outline used for panels + */ + + @Value.Parameter + Optional outline(); +} diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeType.java index 488355e9..5cc9eb92 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/SyThemeType.java @@ -49,6 +49,13 @@ public interface SyThemeType @Value.Parameter SyThemeButtonCheckboxType buttonCheckboxTheme(); + /** + * @return The theme used for meters + */ + + @Value.Parameter + SyThemeMeterType meterTheme(); + /** * @return The theme used for panels */ diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBee.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBee.java index 3b8ad2cd..9e6551db 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBee.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBee.java @@ -38,6 +38,8 @@ import com.io7m.jsycamore.core.themes.SyThemeImage; import com.io7m.jsycamore.core.themes.SyThemeLabel; import com.io7m.jsycamore.core.themes.SyThemeLabelType; +import com.io7m.jsycamore.core.themes.SyThemeMeter; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; import com.io7m.jsycamore.core.themes.SyThemeOutline; import com.io7m.jsycamore.core.themes.SyThemePadding; import com.io7m.jsycamore.core.themes.SyThemePanel; @@ -257,7 +259,7 @@ public static SyTheme.Builder builderFrom( theme_frame_b.setBottomLeftStyle( SyThemeWindowFrameCorner.FRAME_CORNER_NONE); theme_frame_b.setBottomRightStyle( - SyThemeWindowFrameCorner.FRAME_CORNER_NONE); + SyThemeWindowFrameCorner.FRAME_CORNER_L_PIECE); theme_frame_b.setEmbossActive(theme_frame_emboss_active_b.build()); theme_frame_b.setEmbossInactive(theme_frame_emboss_inactive_b.build()); @@ -286,14 +288,60 @@ public static SyTheme.Builder builderFrom( background_lighter_lighter, background_darker)); + theme.setMeterTheme(SyThemeBee.createThemeMeter(spec)); + theme.setPanelTheme(SyThemeBee.createThemePanel(background)); theme.setLabelTheme(SyThemeBee.createThemeLabel( spec.foregroundColorActive(), - spec.foregroundColorDisabled())); + spec.foregroundColorInactive())); theme.setImageTheme(SyThemeImage.builder().build()); return theme; } + private static SyThemeMeterType createThemeMeter( + final SyThemeBeeSpecificationType spec) + { + final SyThemeMeter.Builder b = SyThemeMeter.builder(); + + b.setColorContainerActive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerActive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorContainerInactive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerInactive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorFillActive(new VectorI3F(0.15f, 0.46f, 0.79f)); + b.setEmbossFillActive(SyThemeEmboss.of( + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + 1 + )); + + b.setColorFillInactive(new VectorI3F(0.15f, 0.46f, 0.79f)); + b.setEmbossFillInactive(SyThemeEmboss.of( + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + 1 + )); + + return b.build(); + } + private static int elementOrder( final SyThemeTitleBarElement e0, final SyThemeTitleBarElement e1) diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBeeSpecificationType.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBeeSpecificationType.java index 839e0c5a..3d6b8159 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBeeSpecificationType.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeBeeSpecificationType.java @@ -47,7 +47,7 @@ default VectorI3F titlebarColorActive() @Value.Default default VectorI3F titlebarColorInactive() { - return new VectorI3F(0.8f, 0.8f, 0.8f); + return new VectorI3F(0.85f, 0.85f, 0.85f); } /** @@ -80,7 +80,7 @@ default VectorI3F titlebarTextColorInactive() @Value.Default default VectorI3F frameColor() { - return new VectorI3F(0.8f, 0.8f, 0.8f); + return new VectorI3F(0.85f, 0.85f, 0.85f); } /** @@ -135,11 +135,12 @@ default float colorDarkFactor() @Value.Default default VectorI3F backgroundColor() { - return new VectorI3F(0.8f, 0.8f, 0.8f); + return new VectorI3F(0.85f, 0.85f, 0.85f); } /** - * @return The general foreground color used for text on components, etc + * @return The general foreground color used for text on active components, + * etc */ @Value.Parameter @@ -150,13 +151,13 @@ default VectorI3F foregroundColorActive() } /** - * @return The general foreground color used for text on disabled components, + * @return The general foreground color used for text on inactive components, * etc */ @Value.Parameter @Value.Default - default VectorI3F foregroundColorDisabled() + default VectorI3F foregroundColorInactive() { return new VectorI3F(0.4f, 0.4f, 0.4f); } diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeFenestra.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeFenestra.java index f9e3baf8..b391ab70 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeFenestra.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeFenestra.java @@ -37,6 +37,8 @@ import com.io7m.jsycamore.core.themes.SyThemeImage; import com.io7m.jsycamore.core.themes.SyThemeLabel; import com.io7m.jsycamore.core.themes.SyThemeLabelType; +import com.io7m.jsycamore.core.themes.SyThemeMeter; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; import com.io7m.jsycamore.core.themes.SyThemeOutline; import com.io7m.jsycamore.core.themes.SyThemePadding; import com.io7m.jsycamore.core.themes.SyThemePanel; @@ -234,7 +236,6 @@ public static SyTheme.Builder builderFrom( 1, true)); - theme.setButtonCheckboxTheme(SyThemeFenestra.createThemeButtonCheckbox( spec, background, @@ -244,6 +245,8 @@ public static SyTheme.Builder builderFrom( 1, true)); + theme.setMeterTheme(SyThemeFenestra.createThemeMeter(spec)); + theme.setPanelTheme( SyThemeFenestra.createThemePanel(background, background_darker)); theme.setLabelTheme( @@ -254,6 +257,50 @@ public static SyTheme.Builder builderFrom( return theme; } + private static SyThemeMeterType createThemeMeter( + final SyThemeFenestraSpecificationType spec) + { + final SyThemeMeter.Builder b = SyThemeMeter.builder(); + + b.setColorContainerActive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerActive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorContainerInactive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerInactive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorFillActive(spec.titlebarColorActive()); + b.setEmbossFillActive(SyThemeEmboss.of( + VectorI3F.scale(spec.titlebarColorActive(), 1.5f), + VectorI3F.scale(spec.titlebarColorActive(), 0.5f), + VectorI3F.scale(spec.titlebarColorActive(), 1.5f), + VectorI3F.scale(spec.titlebarColorActive(), 0.5f), + 1 + )); + + b.setColorFillInactive(spec.titlebarColorInactive()); + b.setEmbossFillInactive(SyThemeEmboss.of( + VectorI3F.scale(spec.titlebarColorInactive(), 1.5f), + VectorI3F.scale(spec.titlebarColorInactive(), 0.5f), + VectorI3F.scale(spec.titlebarColorInactive(), 1.5f), + VectorI3F.scale(spec.titlebarColorInactive(), 0.5f), + 1 + )); + + return b.build(); + } + private static SyThemeButtonCheckboxType createThemeButtonCheckbox( final SyThemeFenestraSpecificationType spec, final VectorI3F background, diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeMotive.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeMotive.java index b4f0003c..bd4ef6d9 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeMotive.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeMotive.java @@ -37,6 +37,8 @@ import com.io7m.jsycamore.core.themes.SyThemeImage; import com.io7m.jsycamore.core.themes.SyThemeLabel; import com.io7m.jsycamore.core.themes.SyThemeLabelType; +import com.io7m.jsycamore.core.themes.SyThemeMeter; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; import com.io7m.jsycamore.core.themes.SyThemeOutline; import com.io7m.jsycamore.core.themes.SyThemeOutlines; import com.io7m.jsycamore.core.themes.SyThemePadding; @@ -92,6 +94,8 @@ public static SyTheme.Builder builderFrom( VectorI3F.scale(background_lighter, spec.colorLightFactor()); final VectorI3F background_darker = VectorI3F.scale(background, spec.colorDarkFactor()); + final VectorI3F background_darker_darker = + VectorI3F.scale(background_darker, spec.colorDarkFactor()); final VectorI3F color_active_base = spec.colorActive(); final VectorI3F color_active_lighter = @@ -258,6 +262,15 @@ public static SyTheme.Builder builderFrom( 2, true)); + theme.setMeterTheme(SyThemeMotive.createThemeMeter( + spec, + background, + background_lighter, + background_lighter_lighter, + background_darker, + background_darker_darker + )); + theme.setLabelTheme(SyThemeMotive.createThemeLabel( spec.foregroundColorActive(), spec.foregroundColorInactive())); @@ -266,6 +279,55 @@ public static SyTheme.Builder builderFrom( return theme; } + private static SyThemeMeterType createThemeMeter( + final SyThemeMotiveSpecificationType spec, + final VectorI3F background, + final VectorI3F background_lighter, + final VectorI3F background_lighter_lighter, + final VectorI3F background_darker, + final VectorI3F background_darker_darker) + { + final SyThemeMeter.Builder b = SyThemeMeter.builder(); + + b.setColorContainerActive(background_darker_darker); + b.setEmbossContainerActive(SyThemeEmboss.of( + background_darker, + background_lighter, + background_darker, + background_lighter, + 1 + )); + + b.setColorContainerInactive(background_darker_darker); + b.setEmbossContainerInactive(SyThemeEmboss.of( + background_darker, + background_lighter, + background_darker, + background_lighter, + 1 + )); + + b.setColorFillActive(spec.foregroundColorActive()); + b.setEmbossFillActive(SyThemeEmboss.of( + background_lighter, + background_darker, + background_lighter, + background_darker, + 1 + )); + + b.setColorFillInactive(spec.foregroundColorInactive()); + b.setEmbossFillInactive(SyThemeEmboss.of( + background_lighter, + background_darker, + background_lighter, + background_darker, + 1 + )); + + return b.build(); + } + /** * Arrange components in a manner suitable for this theme. * diff --git a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeStride.java b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeStride.java index 21ed0cf8..f738c2da 100644 --- a/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeStride.java +++ b/io7m-jsycamore-core/src/main/java/com/io7m/jsycamore/core/themes/provided/SyThemeStride.java @@ -37,6 +37,8 @@ import com.io7m.jsycamore.core.themes.SyThemeImage; import com.io7m.jsycamore.core.themes.SyThemeLabel; import com.io7m.jsycamore.core.themes.SyThemeLabelType; +import com.io7m.jsycamore.core.themes.SyThemeMeter; +import com.io7m.jsycamore.core.themes.SyThemeMeterType; import com.io7m.jsycamore.core.themes.SyThemeOutline; import com.io7m.jsycamore.core.themes.SyThemePadding; import com.io7m.jsycamore.core.themes.SyThemePanel; @@ -256,6 +258,8 @@ public static SyTheme.Builder builderFrom( 1, true)); + theme.setMeterTheme(SyThemeStride.createThemeMeter(spec)); + theme.setPanelTheme( SyThemeStride.createThemePanel(background, background_darker)); theme.setLabelTheme( @@ -266,6 +270,50 @@ public static SyTheme.Builder builderFrom( return theme; } + private static SyThemeMeterType createThemeMeter( + final SyThemeStrideSpecificationType spec) + { + final SyThemeMeter.Builder b = SyThemeMeter.builder(); + + b.setColorContainerActive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerActive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorContainerInactive(new VectorI3F(1.0f, 1.0f, 1.0f)); + b.setEmbossContainerInactive(SyThemeEmboss.of( + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + VectorI3F.scale(spec.frameColor(), 0.8f), + VectorI3F.scale(spec.frameColor(), 1.8f), + 1 + )); + + b.setColorFillActive(new VectorI3F(0.15f, 0.46f, 0.79f)); + b.setEmbossFillActive(SyThemeEmboss.of( + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + 1 + )); + + b.setColorFillInactive(new VectorI3F(0.15f, 0.46f, 0.79f)); + b.setEmbossFillInactive(SyThemeEmboss.of( + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 1.5f), + VectorI3F.scale(new VectorI3F(0.15f, 0.46f, 0.79f), 0.5f), + 1 + )); + + return b.build(); + } + private static int elementOrder( final SyThemeTitleBarElement e0, final SyThemeTitleBarElement e1) diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/WindowDemo.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/WindowDemo.java index 985d0f19..e635848c 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/WindowDemo.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/WindowDemo.java @@ -24,6 +24,7 @@ import com.io7m.jsycamore.core.SyGUI; import com.io7m.jsycamore.core.SyGUIType; import com.io7m.jsycamore.core.SyMouseButton; +import com.io7m.jsycamore.core.SyOrientation; import com.io7m.jsycamore.core.SyParentResizeBehavior; import com.io7m.jsycamore.core.SySpaceParentRelativeType; import com.io7m.jsycamore.core.SySpaceViewportType; @@ -38,6 +39,8 @@ import com.io7m.jsycamore.core.components.SyButtonType; import com.io7m.jsycamore.core.components.SyLabel; import com.io7m.jsycamore.core.components.SyLabelType; +import com.io7m.jsycamore.core.components.SyMeter; +import com.io7m.jsycamore.core.components.SyMeterType; import com.io7m.jsycamore.core.components.SyPanel; import com.io7m.jsycamore.core.components.SyPanelType; import com.io7m.jsycamore.core.images.SyImageCacheLoaderType; @@ -322,6 +325,40 @@ private SyWindowType createWindow( ++y_index; } } + + { + final SyMeterType meter = SyMeter.create(); + meter.setBox(SyBoxes.create(224 + 8, 8, 16, 128)); + meter.setOrientation(SyOrientation.ORIENTATION_VERTICAL); + meter.setActive(SyActive.ACTIVE); + meter.setValue(0.75); + panel.node().childAdd(meter.node()); + } + + { + final SyMeterType meter = SyMeter.create(); + meter.setBox(SyBoxes.create(224 + 8 + 16 + 8, 8, 16, 128)); + meter.setOrientation(SyOrientation.ORIENTATION_VERTICAL); + meter.setActive(SyActive.INACTIVE); + meter.setValue(0.4); + panel.node().childAdd(meter.node()); + } + + { + final SyMeterType meter = SyMeter.create(); + meter.setBox(SyBoxes.create(8, 80 + 16, 128, 16)); + meter.setActive(SyActive.ACTIVE); + meter.setValue(0.75); + panel.node().childAdd(meter.node()); + } + + { + final SyMeterType meter = SyMeter.create(); + meter.setBox(SyBoxes.create(8, 80 + 16 + 8 + 16, 128, 16)); + meter.setActive(SyActive.INACTIVE); + meter.setValue(0.4); + panel.node().childAdd(meter.node()); + } } return window; diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonCheckboxContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonCheckboxContract.java index ac260a7c..62d13e9f 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonCheckboxContract.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonCheckboxContract.java @@ -71,6 +71,9 @@ public final void testMatch() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); @@ -96,6 +99,9 @@ public final void testMatchReadable() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonRepeatingContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonRepeatingContract.java index 81570ffa..598e2b7d 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonRepeatingContract.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyButtonRepeatingContract.java @@ -66,8 +66,12 @@ public final void testMatch() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); + Assert.assertTrue(called.get()); } @@ -91,6 +95,9 @@ public final void testMatchReadable() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyImageContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyImageContract.java index 70539352..262af607 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyImageContract.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyImageContract.java @@ -70,6 +70,9 @@ public final void testMatch() (x, b_image) -> { called.set(true); return Unit.unit(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); @@ -95,7 +98,9 @@ public final void testMatchReadable() (x, b_image) -> { called.set(true); return Unit.unit(); - + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyLabelContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyLabelContract.java index c29759f1..13aec92b 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyLabelContract.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyLabelContract.java @@ -60,6 +60,9 @@ public final void testMatch() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); @@ -85,6 +88,9 @@ public final void testMatchReadable() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterContract.java new file mode 100644 index 00000000..a0af6d41 --- /dev/null +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterContract.java @@ -0,0 +1,377 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.tests.core.components; + +import com.io7m.jfunctional.Unit; +import com.io7m.jsycamore.core.SyAlignmentHorizontal; +import com.io7m.jsycamore.core.SyAlignmentVertical; +import com.io7m.jsycamore.core.SyGUIType; +import com.io7m.jsycamore.core.SyMouseButton; +import com.io7m.jsycamore.core.SyOrientation; +import com.io7m.jsycamore.core.SyWindowType; +import com.io7m.jsycamore.core.boxes.SyBoxes; +import com.io7m.jsycamore.core.components.SyButtonCheckboxType; +import com.io7m.jsycamore.core.components.SyButtonState; +import com.io7m.jsycamore.core.components.SyLabelType; +import com.io7m.jsycamore.core.components.SyMeterType; +import com.io7m.jtensors.parameterized.PVectorI2I; +import com.io7m.junreachable.UnreachableCodeException; +import net.java.quickcheck.QuickCheck; +import net.java.quickcheck.characteristic.AbstractCharacteristic; +import net.java.quickcheck.generator.support.DoubleGenerator; +import org.junit.Assert; +import org.junit.Test; + +import java.util.concurrent.atomic.AtomicBoolean; + +public abstract class SyMeterContract extends SyComponentContract +{ + @Override + protected abstract SyMeterType create(); + + @Test + public void testWindowlessTheme() + { + final SyMeterType c = this.create(); + Assert.assertFalse(c.window().isPresent()); + Assert.assertFalse(c.theme().isPresent()); + } + + @Test + public final void testMatch() + { + final SyMeterType meter = this.create(); + final AtomicBoolean called = new AtomicBoolean(false); + + meter.matchComponent( + this, + (x, button) -> { + throw new UnreachableCodeException(); + }, + (x, panel) -> { + throw new UnreachableCodeException(); + }, + (x, label) -> { + throw new UnreachableCodeException(); + }, + (x, image) -> { + throw new UnreachableCodeException(); + }, + (x, b_meter) -> { + called.set(true); + return Unit.unit(); + }); + + Assert.assertTrue(called.get()); + } + + @Test + public final void testMatchReadable() + { + final SyMeterType meter = this.create(); + final AtomicBoolean called = new AtomicBoolean(false); + + meter.matchComponentReadable( + this, + (x, button) -> { + throw new UnreachableCodeException(); + }, + (x, panel) -> { + throw new UnreachableCodeException(); + }, + (x, label) -> { + throw new UnreachableCodeException(); + }, + (x, image) -> { + throw new UnreachableCodeException(); + }, + (x, b_meter) -> { + called.set(true); + return Unit.unit(); + }); + + Assert.assertTrue(called.get()); + } + + @Test + public final void testIdentities() + { + final SyMeterType meter = this.create(); + + Assert.assertEquals(0.0, meter.value(), 0.0); + Assert.assertEquals( + SyOrientation.ORIENTATION_HORIZONTAL, meter.orientation()); + } + + @Test public final void testPressLeftAttachedHorizontal() + { + final SyGUIType gui = this.gui(); + final SyWindowType window = gui.windowCreate(320, 240, "Window 0"); + + final SyMeterType meter = this.create(); + meter.setBox(SyBoxes.create(0, 0, 64, 32)); + window.contentPane().node().childAdd(meter.node()); + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(0, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.0, meter.value(), 0.0); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(32, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.406, meter.value(), 0.001); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(64, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.906, meter.value(), 0.001); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(3000, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + } + + @Test public final void testHeldLeftAttachedHorizontal() + { + final SyGUIType gui = this.gui(); + final SyWindowType window = gui.windowCreate(320, 240, "Window 0"); + + final SyMeterType meter = this.create(); + meter.setBox(SyBoxes.create(0, 0, 64, 32)); + window.contentPane().node().childAdd(meter.node()); + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(0, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.0, meter.value(), 0.0); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(32, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.406, meter.value(), 0.001); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(64, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.906, meter.value(), 0.001); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(3000, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + } + + @Test public final void testPressLeftAttachedVertical() + { + final SyGUIType gui = this.gui(); + final SyWindowType window = gui.windowCreate(320, 240, "Window 0"); + + final SyMeterType meter = this.create(); + meter.setBox(SyBoxes.create(0, 0, 32, 64)); + meter.setOrientation(SyOrientation.ORIENTATION_VERTICAL); + window.contentPane().node().childAdd(meter.node()); + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(-3000, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(0, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(0, 32), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.843, meter.value(), 0.001); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(0, 64), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.343, meter.value(), 0.001); + } + + { + final boolean pressed_event = meter.mousePressed( + new PVectorI2I<>(0, 3000), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(pressed_event); + Assert.assertEquals(0.0, meter.value(), 0.0); + } + } + + @Test public final void testPressLeftHeldVertical() + { + final SyGUIType gui = this.gui(); + final SyWindowType window = gui.windowCreate(320, 240, "Window 0"); + + final SyMeterType meter = this.create(); + meter.setBox(SyBoxes.create(0, 0, 32, 64)); + meter.setOrientation(SyOrientation.ORIENTATION_VERTICAL); + window.contentPane().node().childAdd(meter.node()); + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(-3000, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(0, 0), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(1.0, meter.value(), 0.0); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(0, 32), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.843, meter.value(), 0.001); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(0, 64), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.343, meter.value(), 0.001); + } + + { + final boolean held_event = meter.mouseHeld( + new PVectorI2I<>(0, 0), + new PVectorI2I<>(0, 3000), + SyMouseButton.MOUSE_BUTTON_LEFT, + meter); + Assert.assertTrue(held_event); + Assert.assertEquals(0.0, meter.value(), 0.0); + } + } + + @Test + public final void testValue() + { + final SyMeterType meter = this.create(); + + QuickCheck.forAllVerbose( + new DoubleGenerator(0.0, 1.0), + new AbstractCharacteristic() + { + @Override + protected void doSpecify(final Double any) + throws Throwable + { + meter.setValue(any.doubleValue()); + Assert.assertEquals(any.doubleValue(), meter.value(), 0.0); + } + }); + } + + @Test + public final void testValueRange() + { + final SyMeterType meter = this.create(); + + QuickCheck.forAllVerbose( + new DoubleGenerator(-100.0, 100.0), + new AbstractCharacteristic() + { + @Override + protected void doSpecify(final Double any) + throws Throwable + { + meter.setValue(any.doubleValue()); + + if (any.doubleValue() >= 1.0) { + Assert.assertEquals(1.0, meter.value(), 0.0); + } else if (any.doubleValue() <= 0.0) { + Assert.assertEquals(0.0, meter.value(), 0.0); + } else { + Assert.assertEquals(any.doubleValue(), meter.value(), 0.0); + } + } + }); + } +} diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterTest.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterTest.java new file mode 100644 index 00000000..252c17e8 --- /dev/null +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyMeterTest.java @@ -0,0 +1,40 @@ +/* + * Copyright © 2016 http://io7m.com + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR + * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +package com.io7m.jsycamore.tests.core.components; + +import com.io7m.jsycamore.awt.SyAWTTextMeasurement; +import com.io7m.jsycamore.core.SyGUI; +import com.io7m.jsycamore.core.SyGUIType; +import com.io7m.jsycamore.core.components.SyLabel; +import com.io7m.jsycamore.core.components.SyLabelType; +import com.io7m.jsycamore.core.components.SyMeter; +import com.io7m.jsycamore.core.components.SyMeterType; + +public final class SyMeterTest extends SyMeterContract +{ + @Override + protected SyGUIType gui() + { + return SyGUI.create(SyAWTTextMeasurement.create(), "GUI"); + } + + @Override + protected SyMeterType create() + { + return SyMeter.create(); + } +} diff --git a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyPanelContract.java b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyPanelContract.java index 95776ead..9e54d468 100644 --- a/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyPanelContract.java +++ b/io7m-jsycamore-tests/src/test/java/com/io7m/jsycamore/tests/core/components/SyPanelContract.java @@ -73,6 +73,9 @@ public final void testMatch() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get()); @@ -98,6 +101,9 @@ public final void testMatchReadable() }, (x, image) -> { throw new UnreachableCodeException(); + }, + (x, meter) -> { + throw new UnreachableCodeException(); }); Assert.assertTrue(called.get());