/*
* Copyright 2014-2016 Cel Skeggs
*
* This file is part of the CCRE, the Common Chicken Runtime Engine.
*
* The CCRE is free software: you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the CCRE. If not, see <http://www.gnu.org/licenses/>.
*/
package ccre.frc.components;
import java.awt.Color;
import java.awt.FontMetrics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import ccre.channel.FloatCell;
import ccre.channel.FloatInput;
import ccre.channel.FloatOutput;
import ccre.frc.DeviceComponent;
/**
* A bar that can be dragged around to modify a floating-point value
*
* @author skeggsc
*/
public class ControlBarComponent extends DeviceComponent implements FloatOutput {
private boolean dragging = false;
private int maxWidth = 0; // zero means no maximum
private final FloatCell value;
private final float min, max, originValue;
/**
* Create a ControlBarComponent with a certain minimum and maximum.
*
* @param min the value at the far left.
* @param max the value at the far right.
* @param defaultValue the default value.
* @param originValue the origin value.
*/
public ControlBarComponent(float min, float max, float defaultValue, float originValue) {
this.max = max;
this.min = min;
this.value = new FloatCell(defaultValue);
this.originValue = originValue;
}
@Override
public int render(Graphics2D g, int width, int height, FontMetrics fontMetrics, int mouseX, int mouseY, int lastShift) {
int startX = lastShift + 5;
int startY = 5;
int endX = width - 5;
int endY = height - 5;
int barWidth = endX - startX;
if (maxWidth != 0 && barWidth > maxWidth) {
barWidth = maxWidth;
endX = startX + maxWidth;
}
int barHeight = endY - startY;
int originX = Math.round(startX + barWidth * (originValue - min) / (max - min));
g.setColor(Color.WHITE);
g.drawRect(startX - 1, startY - 1, barWidth + 1, barHeight + 1);
g.setColor(Color.RED);
int actualLimitX = Math.round(startX + barWidth * (value.get() - min) / (max - min)) - originX;
if (actualLimitX < 0) {
g.fillRect(originX + actualLimitX, startY, -actualLimitX, barHeight);
} else {
g.fillRect(originX, startY, actualLimitX, barHeight);
}
hitzone = new Rectangle(startX, startY, endX - startX, endY - startY);
return endX + 5;
}
/**
* Set the maximum width for this component to take up, in pixels. Zero
* means no maximum, which is the default.
*
* @param width the new maximum width.
* @return this ControlBarComponent, for method chaining.
*/
public ControlBarComponent setMaxWidth(int width) {
this.maxWidth = width;
return this;
}
@Override
public void onPress(int x, int y) {
dragging = true;
onMouseMove(x, y);
}
@Override
public void onMouseMove(int x, int y) {
if (dragging) {
Rectangle rect = hitzone.getBounds();
value.safeSet(Math.min(1, Math.max(0, ((x - rect.x) / (float) rect.width))) * (max - min) + min);
repaint();
}
}
@Override
public void onMouseExit(int x, int y) {
dragging = false;
}
@Override
public void onRelease(int x, int y) {
dragging = false;
}
/**
* Gets the current value set on this slider.
*
* @return the current value.
*/
public float get() {
return value.get();
}
/**
* Provides a FloatInput representing the current value set on this slider.
*
* @return the FloatInput.
*/
public FloatInput asInput() {
return value;
}
@Override
public void set(float value) {
this.value.safeSet(value);
repaint();
}
}