Skip to content

Commit

Permalink
Implement basic meters
Browse files Browse the repository at this point in the history
The meter component is expected to assume the roles of progress
bars (#21) and sliders (#22). It does not yet support indeterminate
progress (which is simply a rendering flag), and rendering of
meters is currently very limited.

Fix #21
Fix #22
  • Loading branch information
io7m committed Jul 24, 2016
1 parent ab60436 commit 6be71fb
Show file tree
Hide file tree
Showing 36 changed files with 1,429 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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.
Expand Down Expand Up @@ -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<SyComponentReadableType> node =
Expand All @@ -203,6 +211,69 @@ private void renderActual(
}
}

private void renderMeter(
final Graphics2D graphics,
final SyMeterReadableType meter)
{
final Optional<SyThemeMeterType> theme_opt = meter.theme();
if (!theme_opt.isPresent()) {
throw SyAWTComponentRenderer.notAttached(meter);
}

final SyThemeMeterType theme = theme_opt.get();
final Optional<SyThemeOutlineType> outline = theme.outline();
final SyBoxType<SySpaceParentRelativeType> box = meter.box();
final SyBoxType<SySpaceComponentRelativeType> 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<SySpaceComponentRelativeType> 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<SySpaceComponentRelativeType> 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)
Expand All @@ -212,7 +283,6 @@ private void renderImage(
throw SyAWTComponentRenderer.notAttached(image);
}

final SyThemeImageType theme = theme_opt.get();
final SyBoxType<SySpaceParentRelativeType> box = image.box();

final SyImageReferenceType<BufferedImage> ref =
Expand Down Expand Up @@ -302,50 +372,58 @@ private void renderPanel(

final SyThemePanelType theme = theme_opt.get();
final SyBoxType<SySpaceParentRelativeType> box = panel.box();
final SyBoxType<SySpaceComponentRelativeType> box_origin =
SyBoxes.cast(SyBoxes.moveToOrigin(box));
final Optional<SyThemeOutlineType> 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<SyThemeOutlineType> outline,
final Supplier<VectorReadable3FType> color,
final Supplier<Optional<SyThemeEmbossType>> emboss,
final SyBoxType<SySpaceComponentRelativeType> box)
{
final int width = box.width();
final int height = box.height();
final int fill_width;
final int fill_height;
final int fill_x;
final int fill_y;

final Optional<SyThemeOutlineType> 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<SyThemeEmbossType> 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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public static Color toColor(
public static void drawOutline(
final Graphics2D graphics,
final SyThemeOutlineType outline,
final SyBoxType<SySpaceParentRelativeType> box,
final SyBoxType<?> box,
final boolean active)
{
NullCheck.notNull(graphics, "graphics");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* Copyright © 2016 <code@io7m.com> 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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright © 2016 <code@io7m.com> 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.
}
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ default <A, B> B matchComponentReadable(
final BiFunction<A, SyButtonReadableType, B> on_button,
final BiFunction<A, SyPanelReadableType, B> on_panel,
final BiFunction<A, SyLabelReadableType, B> on_label,
final BiFunction<A, SyImageReadableType, B> on_image)
final BiFunction<A, SyImageReadableType, B> on_image,
final BiFunction<A, SyMeterReadableType, B> on_meter)
{
return NullCheck.notNull(on_button).apply(context, this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ default <A, B> B matchComponent(
final BiFunction<A, SyButtonType, B> on_button,
final BiFunction<A, SyPanelType, B> on_panel,
final BiFunction<A, SyLabelType, B> on_label,
final BiFunction<A, SyImageType, B> on_image)
final BiFunction<A, SyImageType, B> on_image,
final BiFunction<A, SyMeterType, B> on_meter)
{
return NullCheck.notNull(on_button).apply(context, this);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -254,6 +259,56 @@ public final SyBoxType<SySpaceParentRelativeType> box()
return this.box;
}

@Override
public final void transformWindowRelative(
final PVectorReadable2IType<SySpaceWindowRelativeType> w_position,
final PVectorWritable2IType<SySpaceComponentRelativeType> c_position)
{
NullCheck.notNull(w_position, "Viewport position");
NullCheck.notNull(c_position, "Component-relative position");

final PVectorI2I<SySpaceWindowRelativeType> 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<SySpaceWindowRelativeType> positionWindowRelative()
{
final ArrayDeque<SyComponentReadableType> ancestors =
new ArrayDeque<>();

JOTreeNodeType<SyComponentType> n = this.node;
while (true) {
final Optional<JOTreeNodeType<SyComponentType>> parent_opt = n.parent();
if (parent_opt.isPresent()) {
final JOTreeNodeType<SyComponentType> parent = parent_opt.get();
ancestors.push(parent.value());
n = parent;
} else {
break;
}
}

final PVectorM2I<SySpaceWindowRelativeType> 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<SyComponentType> componentForWindowRelative(
final PVectorReadable2IType<SySpaceWindowRelativeType> w_position,
Expand Down
Loading

0 comments on commit 6be71fb

Please sign in to comment.