aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--make/scripts/tests.sh8
-rw-r--r--src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java158
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java12
-rw-r--r--src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java420
4 files changed, 416 insertions, 182 deletions
diff --git a/make/scripts/tests.sh b/make/scripts/tests.sh
index e143d6e42..22a6b2e31 100644
--- a/make/scripts/tests.sh
+++ b/make/scripts/tests.sh
@@ -45,8 +45,8 @@ if [ $MOSX -eq 1 ] ; then
fi
# We use TempJarCache and JAR files per default now!
-export USE_BUILDDIR=0
-#export USE_BUILDDIR=1
+#export USE_BUILDDIR=0
+export USE_BUILDDIR=1
if [ $USE_BUILDDIR -eq 1 ] ; then
export LD_LIBRARY_PATH=$JOGAMP_LD_LIBRARY_PATH
@@ -1022,8 +1022,8 @@ function testawtswt() {
#testnoawt com.jogamp.opengl.demos.av.MovieSimple $*
#testnoawt com.jogamp.opengl.demos.av.MovieCube $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UIMediaGrid00 $*
-testnoawt com.jogamp.opengl.demos.graph.ui.UIMediaGrid01 $*
-#testnoawt com.jogamp.opengl.demos.graph.ui.FontView01 $*
+#testnoawt com.jogamp.opengl.demos.graph.ui.UIMediaGrid01 $*
+testnoawt com.jogamp.opengl.demos.graph.ui.FontView01 $*
#testawt com.jogamp.opengl.demos.graph.ui.UISceneDemo20 $*
#testawt com.jogamp.opengl.demos.es2.GearsES2 $*
#testnoawt com.jogamp.opengl.demos.graph.ui.UIGraphDemoU01a $*
diff --git a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
index 0e7590995..dd416e58d 100644
--- a/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
+++ b/src/demos/com/jogamp/opengl/demos/graph/ui/FontView01.java
@@ -52,11 +52,13 @@ import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.GlyphShape;
import com.jogamp.graph.ui.shapes.Label;
import com.jogamp.graph.ui.shapes.Rectangle;
+import com.jogamp.graph.ui.widgets.RangeSlider;
+import com.jogamp.graph.ui.widgets.RangeSlider.SliderListener;
+import com.jogamp.math.Vec2f;
import com.jogamp.math.Vec2i;
import com.jogamp.math.geom.AABBox;
import com.jogamp.newt.event.KeyAdapter;
import com.jogamp.newt.event.KeyEvent;
-import com.jogamp.newt.event.MouseAdapter;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.WindowAdapter;
import com.jogamp.newt.event.WindowEvent;
@@ -273,7 +275,7 @@ public class FontView01 {
final float infoCellWidth = 1f - GlyphGridWidth;
final float infoCellHeight = glyphGrid.getBounds().getHeight() / 2f;
final Group infoGrid = new Group( new GridLayout(1, infoCellWidth, infoCellHeight * 0.98f, Alignment.FillCenter, new Gap(infoCellHeight*0.02f, 0)) );
- infoGrid.setPaddding( new Padding(0, 0, 0, 0.02f) );
+ infoGrid.setPaddding( new Padding(0, 0, 0, 0.01f) );
infoGrid.addShape(glyphShapeBox.setBorder(0.005f).setBorderColor(0, 0, 0, 1));
infoGrid.addShape(glyphInfoBox.setBorder(0.005f).setBorderColor(0, 0, 0, 1));
if( VERBOSE_UI ) {
@@ -282,8 +284,50 @@ public class FontView01 {
System.err.println("InfoGrid "+infoGrid.getLayout());
}
- final Group glyphInfoGrid = new Group(new GridLayout(2, 0f, 0f, Alignment.None));
+ final Group glyphInfoGrid = new Group(new GridLayout(4, 0f, 0f, Alignment.None));
glyphInfoGrid.addShape(glyphGrid);
+ final boolean sliderInverted = true;
+ final RangeSlider rs1 = new RangeSlider(options.renderModes,
+ new Vec2f((GlyphGridWidth/gridDim.rawSize.x())/5f, glyphGrid.getBounds().getHeight()),
+ new Vec2f(0, gridDim.contourChars.size()/gridDim.columns), gridDim.rows, 0).setInverted(sliderInverted);
+ final RangeSlider rs2 = new RangeSlider(options.renderModes,
+ new Vec2f((GlyphGridWidth/gridDim.rawSize.x())/5f, glyphGrid.getBounds().getHeight()), 2,
+ new Vec2f(0, gridDim.contourChars.size()/gridDim.columns), 0).setInverted(sliderInverted);
+ final SliderListener sliderListener = new SliderListener() {
+ @Override
+ public void clicked(final RangeSlider w, final MouseEvent e) { }
+ @Override
+ public void pressed(final RangeSlider w, final MouseEvent e) { }
+ @Override
+ public void released(final RangeSlider w, final MouseEvent e) { }
+ @Override
+ public void dragged(final RangeSlider w, final float old_val, final float val, final float old_val_pct, final float val_pct) {
+ final int totalRows = gridDim.contourChars.size() / gridDim.columns;
+ if( w == rs1 ) {
+ System.err.println("XXX range "+w.getMinMax()+", v "+w.getValue()+"/"+totalRows+" -> "+(w.getValue()*gridDim.columns)+"/"+gridDim.contourChars.size()+", "+(100f*w.getValuePct())+"%");
+ rs2.setValue(w.getValue());
+ } else {
+ System.err.println("YYY range "+w.getMinMax()+", v "+w.getValue()+"/"+totalRows+" -> "+(w.getValue()*gridDim.columns)+"/"+gridDim.contourChars.size()+", "+(100f*w.getValuePct())+"%");
+ rs1.setValue(w.getValue());
+ }
+ gridDim.setStartRow( (int)w.getValue() );
+ window.invoke(false, new GLRunnable() {
+ @Override
+ public boolean run(final GLAutoDrawable drawable) {
+ glyphGrid.removeAllShapes(drawable.getGL().getGL2ES2(), scene.getRenderer());
+ addGlyphs(reqGLP, font, glyphGrid, gridDim, showUnderline[0], showLabel[0], fontStatus, fontInfo, glyphMouseListener);
+ if( VERBOSE_UI ) {
+ System.err.println("Slider: "+gridDim);
+ }
+ return true;
+ }
+ });
+ }
+ };
+ rs1.onSlider( sliderListener );
+ rs2.onSlider( sliderListener );
+ glyphInfoGrid.addShape(rs1);
+ glyphInfoGrid.addShape(rs2);
glyphInfoGrid.addShape(infoGrid);
if( VERBOSE_UI ) {
glyphInfoGrid.validate(reqGLP);
@@ -293,7 +337,7 @@ public class FontView01 {
mainGrid = new Group(new GridLayout(1, 0f, 0f, Alignment.None));
mainGrid.addShape(glyphInfoGrid);
- final Label infoText = new Label(options.renderModes, fontInfo, "Key-Up/Down or Mouse-Scroll to move through glyph symbols. Page-Up/Down or Control + Mouse-Scroll to page through glyph symbols fast.");
+ final Label infoText = new Label(options.renderModes, fontInfo, "Slider: Key-Up/Down or Mouse-Scroll to move through glyphs. Page-Up/Down or Control + Mouse-Scroll to page through glyph symbols fast.");
infoText.setColor(0.1f, 0.1f, 0.1f, 1f);
{
final float h = glyphGrid.getBounds().getHeight() / gridDim.rawSize.y() * 0.6f;
@@ -310,85 +354,13 @@ public class FontView01 {
}
scene.addShape(mainGrid);
- window.addMouseListener( new MouseAdapter() {
- @Override
- public void mouseWheelMoved(final MouseEvent e) {
- if( VERBOSE_UI ) {
- System.err.println("Scroll.0: "+gridDim);
- }
- if( e.getRotation()[1] < 0f ) {
- // scroll down
- if( e.isControlDown() ) {
- gridDim.pageDown();
- } else {
- gridDim.lineDown();
- }
- } else {
- // scroll up
- if( e.isControlDown() ) {
- gridDim.pageUp();
- } else {
- gridDim.lineUp();
- }
- }
- window.invoke(false, new GLRunnable() {
- @Override
- public boolean run(final GLAutoDrawable drawable) {
- glyphGrid.removeAllShapes(drawable.getGL().getGL2ES2(), scene.getRenderer());
- addGlyphs(reqGLP, font, glyphGrid, gridDim, showUnderline[0], showLabel[0], fontStatus, fontInfo, glyphMouseListener);
- if( VERBOSE_UI ) {
- System.err.println("Scroll.X: "+gridDim);
- }
- return true;
- }
- });
- }
- });
window.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(final KeyEvent e) {
final short keySym = e.getKeySymbol();
- boolean gridScroll = false;
- if( keySym == KeyEvent.VK_DOWN ) {
- if( VERBOSE_UI ) {
- System.err.println("Scroll.0: "+gridDim);
- }
- gridScroll = true;
- gridDim.lineDown();
- } else if( keySym == KeyEvent.VK_PAGE_DOWN ) {
- if( VERBOSE_UI ) {
- System.err.println("Scroll.0: "+gridDim);
- }
- gridScroll = true;
- gridDim.pageDown();
- } else if( keySym == KeyEvent.VK_UP ) {
- if( VERBOSE_UI ) {
- System.err.println("Scroll.0: "+gridDim);
- }
- gridScroll = true;
- gridDim.lineUp();
- } else if( keySym == KeyEvent.VK_PAGE_UP ) {
- if( VERBOSE_UI ) {
- System.err.println("Scroll.0: "+gridDim);
- }
- gridScroll = true;
- gridDim.pageUp();
- } else if( keySym == KeyEvent.VK_F4 || keySym == KeyEvent.VK_ESCAPE || keySym == KeyEvent.VK_Q ) {
+ if( keySym == KeyEvent.VK_F4 || keySym == KeyEvent.VK_ESCAPE || keySym == KeyEvent.VK_Q ) {
MiscUtils.destroyWindow(window);
}
- if( gridScroll ) {
- window.invoke(false, new GLRunnable() {
- @Override
- public boolean run(final GLAutoDrawable drawable) {
- glyphGrid.removeAllShapes(drawable.getGL().getGL2ES2(), scene.getRenderer());
- addGlyphs(reqGLP, font, glyphGrid, gridDim, showUnderline[0], showLabel[0], fontStatus, fontInfo, glyphMouseListener);
- if( VERBOSE_UI ) {
- System.err.println("Scroll.X: "+gridDim);
- }
- return true;
- }
- });
- }
}
});
@@ -447,33 +419,13 @@ public class FontView01 {
return contourChars.size();
}
- void pageDown() {
- if( nextPage < contourChars.size() - elemCount ) {
- start = nextPage;
- } else {
- start = 0;
- }
- }
- void pageUp() {
- if( start >= elemCount ) {
- start -= elemCount;
- } else {
- start = contourChars.size() - 1 - elemCount;
- }
- }
- void lineDown() {
- if( nextLine < contourChars.size() - columns ) {
- start = nextLine;
- } else {
- start = 0;
- }
- }
- void lineUp() {
- if( start >= columns ) {
- start -= columns;
- } else {
- start = contourChars.size() - 1 - columns;
+ void setStartRow(final int row) {
+ final int old = start;
+ final int np = row * columns;
+ if( np < contourChars.size() - columns ) {
+ start = np;
}
+ // System.err.println("XXX "+columns+"x"+rows+" @ "+old+"/"+contourChars.size()+": r "+row+" -> s "+start);
}
@Override
diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java
index 3fc48306a..799a9e8ad 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/MediaPlayer.java
@@ -128,10 +128,14 @@ public class MediaPlayer extends Widget {
mButton.setName("mp.mButton").setInteractive(false);
mButton.setPerp().setPressedColorMod(1f, 1f, 1f, 0.85f);
- final RangeSlider ctrlSlider = new RangeSlider(renderModes, aratio, ctrlSliderHeight, 4.0f, 0, 100, 0);
+ final RangeSlider ctrlSlider;
{
- final float dy = ( ctrlSlider.getKnobSize() - ctrlSliderHeight ) * 0.5f;
- ctrlSlider.setPaddding(new Padding(0, 0, ctrlCellHeight-dy, 0));
+ final float knobScale = 3f;
+ final float knobHeight = ctrlSliderHeight * knobScale;
+ ctrlSlider = new RangeSlider(renderModes, new Vec2f(aratio - knobHeight, ctrlSliderHeight), knobScale, new Vec2f(0, 100), 0);
+ final float dx = knobHeight / 2f;
+ final float dy = ( knobHeight - ctrlSliderHeight ) * 0.5f;
+ ctrlSlider.setPaddding(new Padding(0, dx, ctrlCellHeight-dy, dx));
}
ctrlSlider.setName("mp.slider");
@@ -153,7 +157,7 @@ public class MediaPlayer extends Widget {
// System.err.println("MediaButton State: "+mp);
if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Init) ) {
System.err.println(mp.toString());
- ctrlSlider.setMinMax(0, mp.getDuration(), 0);
+ ctrlSlider.setMinMax(new Vec2f(0, mp.getDuration()), 0);
} else if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Play) ) {
playButton.setToggle(true);
} else if( eventMask.isSet(GLMediaPlayer.EventMask.Bit.Pause) ) {
diff --git a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java
index 495d81149..f6498974e 100644
--- a/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java
+++ b/src/graphui/classes/com/jogamp/graph/ui/widgets/RangeSlider.java
@@ -32,20 +32,26 @@ import com.jogamp.graph.curve.opengl.GLRegion;
import com.jogamp.graph.curve.opengl.RegionRenderer;
import com.jogamp.graph.ui.Group;
import com.jogamp.graph.ui.Shape;
+import com.jogamp.graph.ui.layout.Padding;
import com.jogamp.graph.ui.shapes.BaseButton;
import com.jogamp.graph.ui.shapes.Button;
import com.jogamp.graph.ui.shapes.Rectangle;
import com.jogamp.math.Vec2f;
import com.jogamp.math.Vec3f;
import com.jogamp.math.Vec4f;
+import com.jogamp.newt.event.KeyAdapter;
+import com.jogamp.newt.event.KeyEvent;
+import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.opengl.GL2ES2;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.texture.TextureSequence;
/**
- * RangeSlider {@link Widget}
- * @see #RangeSlider(int, float, float, float, float, float, float)
+ * RangeSlider {@link Widget} either utilizing a simple positional round knob
+ * or a rectangular page-sized knob.
+ * @see #RangeSlider(int, Vec2f, float, Vec2f, float)
+ * @see #RangeSlider(int, Vec2f, Vec2f, float, float)
*/
public final class RangeSlider extends Widget {
/**
@@ -59,7 +65,7 @@ public final class RangeSlider extends Widget {
/** Slider released down by user. */
void released(RangeSlider w, final MouseEvent e);
/**
- * Slide dragged by user
+ * Slide dragged by user (including clicked position)
* @param w the {@link RangeSlider} widget owning the slider
* @param old_val previous absolute value position of the slider
* @param val the absolute value position of the slider
@@ -69,60 +75,115 @@ public final class RangeSlider extends Widget {
void dragged(RangeSlider w, float old_val, float val, float old_val_pct, float val_pct);
}
+ private static final float pageKnobScale = 0.6f; // 0.6 * barWidth
+ private static final float pageBarLineScale = 0.25f; // 1/4 * ( barWidth - pageKnobWidth )
+ private static final float pageKnobSizePctMin = 5f/100f;
private final boolean horizontal;
- private final float knobSz;
- private final float width, height;
+ /** Width of knob orthogonal to sliding direction */
+ private float knobDiameter;
+ /** Half length of knob in sliding direction */
+ private float knobHalfLen;
+ private final Vec2f size;
private final Group barAndKnob;
private final Rectangle bar;
- private final BaseButton knob;
- private final Vec4f colBar = new Vec4f(0, 0, 1, 1);
- private final Vec4f colKnob = new Vec4f(1, 0, 0, 1);
+ private final Shape knob;
private SliderListener sliderListener = null;
- private float min, max;
- private float val, val_pct;
+ private final Vec2f minMax = new Vec2f(0, 100);
+ private float pageSize;
+ private float val=0, val_pct=0;
+ private boolean inverted=false;
/**
* Constructs a {@link RangeSlider}, i.e. its shapes and controls.
+ * <p>
+ * This slider comprises a background bar and a positional round knob.
+ * </p>
* @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
- * @param width width of this slider box. A horizontal slider has width >= height.
- * @param height height of this slider box. A vertical slider has width < height.
- * @param knobScale multiple of slider-bar height for {@link #getKnobSize()}
- * @param min minimum value of slider
- * @param max maximum value of slider
+ * @param size width and height of this slider box. A horizontal slider has width >= height.
+ * @param knobScale multiple of slider-bar height for {@link #getKnobHeight()}
+ * @param minMax minimum- and maximum-value of slider
* @param value current value of slider
*/
- public RangeSlider(final int renderModes, final float width, final float height, final float knobScale,
- final float min, final float max, final float value) {
- this.horizontal = width >= height;
- if( horizontal ) {
- knobSz = height*knobScale;
- this.width = width - knobSz; // half knobSz left and right
- this.height = height;
+ public RangeSlider(final int renderModes, final Vec2f size, final float knobScale,
+ final Vec2f minMax, final float value) {
+ this(renderModes, size, knobScale, minMax, Float.NaN, value);
+ }
+ /**
+ * Constructs a {@link RangeSlider}, i.e. its shapes and controls.
+ * <p>
+ * This slider comprises a framing bar and a rectangular page-sized knob.
+ * </p>
+ * @param renderModes Graph's {@link Region} render modes, see {@link GLRegion#create(GLProfile, int, TextureSequence) create(..)}.
+ * @param size width and height of this slider box. A horizontal slider has width >= height.
+ * @param minMax minimum- and maximum-value of slider
+ * @param pageSize size of one virtual-page, triggers rendering mode from knob to rectangle
+ * @param value current value of slider
+ */
+ public RangeSlider(final int renderModes, final Vec2f size,
+ final Vec2f minMax, final float pageSize, final float value) {
+ this(renderModes, size, 0, minMax, pageSize, value);
+ }
+ private RangeSlider(final int renderModes_, final Vec2f size, final float knobScale,
+ final Vec2f minMax, final float pageSz, final float value) {
+ // final int renderModes = ( renderModes_ & ~Region.AA_RENDERING_MASK ) | Region.COLORCHANNEL_RENDERING_BIT;
+ final int renderModes = renderModes_ & ~(Region.AA_RENDERING_MASK | Region.COLORCHANNEL_RENDERING_BIT);
+ this.pageSize = pageSz;
+ this.horizontal = size.x() >= size.y();
+ barAndKnob = new Group();
+ barAndKnob.setInteractive(true).setToggleable(false).setDraggable(false).setResizable(false);
+ this.size = new Vec2f(size);
+ if( Float.isNaN(pageSize) ) {
+ if( horizontal ) {
+ knobDiameter = size.y()*knobScale;
+ setPaddding(new Padding(knobHalfLen, 0, knobHalfLen, 0));
+ } else {
+ knobDiameter = size.x()*knobScale;
+ setPaddding(new Padding(0, knobHalfLen, 0, knobHalfLen));
+ }
+ knobHalfLen = knobDiameter * 0.5f;
+ bar = new Rectangle(renderModes, this.size.x(), this.size.y(), 0);
+ knob = new BaseButton(renderModes , knobDiameter*1.01f, knobDiameter);
+ setBackgroundBarColor(0.60f, 0.60f, 0.60f, 0.5f);
} else {
- knobSz = width*knobScale;
- this.width = width;
- this.height = height - knobSz; // half knobSz bottom and top
+ final float pageSizePct = Math.max(pageKnobSizePctMin, pageSize / getRange(minMax));
+ final float barLineWidth;
+ final float knobWidth, knobHeight;
+ if( horizontal ) {
+ knobHeight = size.y() * pageKnobScale;
+ knobWidth = pageSizePct * this.size.x();
+ barLineWidth = ( size.y() - knobHeight ) * pageBarLineScale;
+ knobHalfLen = knobWidth * 0.5f;
+ knobDiameter = knobHeight;
+ setPaddding(new Padding(size.y(), 0, size.y(), 0));
+ } else {
+ knobWidth = size.x() * pageKnobScale;
+ knobHeight = pageSizePct * this.size.y();
+ barLineWidth = ( size.x() - knobWidth ) * pageBarLineScale;
+ knobHalfLen = knobHeight * 0.5f;
+ knobDiameter = knobWidth;
+ setPaddding(new Padding(0, size.x(), 0, size.x()));
+ // System.err.println("ZZZ minMax "+minMax+", pageSize "+pageSize+" "+(pageSizePct*100f)+"% -> "+knobHeight+"/"+this.size.y());
+ }
+ bar = new Rectangle(renderModes, this.size.x(), this.size.y(), barLineWidth);
+ knob = new Rectangle(renderModes, knobWidth, knobHeight, 0);
}
- barAndKnob = new Group();
- barAndKnob.setInteractive(true).setDraggable(false).setToggleable(false);
- bar = new Rectangle(renderModes & ~Region.AA_RENDERING_MASK, this.width, this.height, 0);
- bar.setToggleable(false);
- bar.setColor(colBar);
- knob = new BaseButton(renderModes & ~Region.AA_RENDERING_MASK, knobSz*1.01f, knobSz);
- knob.setToggleable(false);
- knob.setColor(colKnob);
+ setColor(0.30f, 0.30f, 0.30f, 1.0f);
+
+ bar.setToggleable(false).setInteractive(false);
+ bar.setDraggable(false).setResizable(false);
+
+ knob.setToggleable(false).setResizable(false);
setName(getName());
barAndKnob.addShape( bar );
barAndKnob.addShape( knob );
addShape(barAndKnob);
- setMinMax(min, max, value);
+ setMinMax(minMax, value);
knob.onMove((final Shape s, final Vec3f origin, final Vec3f dest) -> {
final float old_val = val;
final float old_val_pct = val_pct;
- setValuePct( getKnobValuePct( dest.x(), dest.y(), knobSz*0.5f ) );
- // System.err.println("KnobMove "+getName()+": "+origin+" -> "+dest+": "+old_val+" -> "+val+", "+(old_val_pct*100f)+"% -> "+(val_pct*100f)+"%");
+ setValuePct( getKnobValuePct( dest.x(), dest.y(), knobHalfLen ) );
if( null != sliderListener ) {
sliderListener.dragged(this, old_val, val, old_val_pct, val_pct);
}
@@ -130,19 +191,61 @@ public final class RangeSlider extends Widget {
barAndKnob.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
+ final float old_val = val;
+ final float old_val_pct = val_pct;
final Shape.EventInfo shapeEvent = (Shape.EventInfo) e.getAttachment();
setValuePct( getKnobValuePct( shapeEvent.objPos.x(), shapeEvent.objPos.y(), 0 ) );
if( null != sliderListener ) {
+ sliderListener.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct);
sliderListener.clicked(RangeSlider.this, e);
}
}
+ @Override
+ public void mouseWheelMoved(final MouseEvent e) {
+ final float old_val = val;
+ final float old_val_pct = val_pct;
+ float v = old_val;
+ if( !e.isControlDown() ) {
+ if( e.getRotation()[1] < 0f ) {
+ if( inverted ) {
+ v++;
+ } else {
+ v--;
+ }
+ } else {
+ if( inverted ) {
+ v--;
+ } else {
+ v++;
+ }
+ }
+ } else if( !Float.isNaN(pageSize) ){
+ if( e.getRotation()[1] < 0f ) {
+ if( inverted ) {
+ v+=pageSize;
+ } else {
+ v-=pageSize;
+ }
+ } else {
+ if( inverted ) {
+ v-=pageSize;
+ } else {
+ v+=pageSize;
+ }
+ }
+ }
+ setValue( v );
+ if( null != sliderListener ) {
+ sliderListener.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct);
+ }
+ }
});
knob.addMouseListener(new Shape.MouseGestureAdapter() {
@Override
public void mouseClicked(final MouseEvent e) {
- if( null != sliderListener ) {
- sliderListener.clicked(RangeSlider.this, e);
- }
+ // if( null != sliderListener ) {
+ // sliderListener.clicked(RangeSlider.this, e);
+ // }
}
@Override
public void mousePressed(final MouseEvent e) {
@@ -156,11 +259,75 @@ public final class RangeSlider extends Widget {
sliderListener.released(RangeSlider.this, e);
}
}
+ });
+ final KeyListener keyListener = new KeyAdapter() {
@Override
- public void mouseWheelMoved(final MouseEvent e) {
- // Support ?
+ public void keyReleased(final KeyEvent e) {
+ final float old_val = val;
+ final float old_val_pct = val_pct;
+ float v = old_val;
+ final short keySym = e.getKeySymbol();
+ boolean action = false;
+ if( horizontal ) {
+ if( keySym == KeyEvent.VK_RIGHT ) {
+ action = true;
+ if( inverted ) {
+ v--;
+ } else {
+ v++;
+ }
+ } else if( keySym == KeyEvent.VK_LEFT ) {
+ action = true;
+ if( inverted ) {
+ v++;
+ } else {
+ v--;
+ }
+ }
+ } else {
+ if( keySym == KeyEvent.VK_DOWN ) {
+ action = true;
+ if( inverted ) {
+ v++;
+ } else {
+ v--;
+ }
+ } else if( keySym == KeyEvent.VK_UP ) {
+ action = true;
+ if( inverted ) {
+ v--;
+ } else {
+ v++;
+ }
+ }
+ }
+ if( !action && !Float.isNaN(pageSize) ) {
+ if( keySym == KeyEvent.VK_PAGE_DOWN ) {
+ action = true;
+ if( inverted ) {
+ v+=pageSize;
+ } else {
+ v-=pageSize;
+ }
+ } else if( keySym == KeyEvent.VK_PAGE_UP ) {
+ action = true;
+ if( inverted ) {
+ v-=pageSize;
+ } else {
+ v+=pageSize;
+ }
+ }
+ }
+ if( action ) {
+ setValue( v );
+ if( null != sliderListener ) {
+ sliderListener.dragged(RangeSlider.this, old_val, val, old_val_pct, val_pct);
+ }
+ }
}
- });
+ };
+ barAndKnob.addKeyListener(keyListener);
+ knob.addKeyListener(keyListener);
}
@Override
@@ -180,44 +347,64 @@ public final class RangeSlider extends Widget {
}
public Rectangle getBar() { return bar; }
- public BaseButton getKnob() { return knob; }
+ public Shape getKnob() { return knob; }
- public final float getWidth() { return width; }
- public final float getHeight() { return height; }
- public final float getKnobSize() { return knobSz; }
+ public final Vec2f getSize() { return size; }
+ /** Height of knob orthogonal to sliding direction */
+ public final float getKnobHeight() { return knobDiameter; }
+ /** Length of knob in sliding direction */
+ public final float getKnobLength() { return knobHalfLen*2f; }
- public float getMin() { return min; }
- public float getMax() { return max; }
- public float getRange() { return max - min; }
+ public Vec2f getMinMax() { return minMax; }
+ public float getRange() { return minMax.y() - minMax.x(); }
+ private float getRange(final Vec2f minMax) { return minMax.y() - minMax.x(); }
public float getValue() { return val; }
public float getValuePct() { return val_pct; }
+ public RangeSlider setPageSize(final float v) {
+ if( Float.isNaN(this.pageSize) || Float.isNaN(v) ) {
+ return this;
+ }
+ this.pageSize = v;
+ final float pageSizePct = Math.max(pageKnobSizePctMin, pageSize / getRange());
+ final float knobWidth, knobHeight;
+ if( horizontal ) {
+ knobHeight = size.y() * pageKnobScale;
+ knobWidth = pageSizePct * this.size.x();
+ knobHalfLen = knobWidth * 0.5f;
+ knobDiameter = knobHeight;
+ } else {
+ knobWidth = size.x() * pageKnobScale;
+ knobHeight = pageSizePct * this.size.y();
+ knobHalfLen = knobHeight * 0.5f;
+ knobDiameter = knobWidth;
+ }
+ ((Rectangle)knob).setDimension(knobWidth, knobHeight, 0);
+ return this;
+ }
+ public float getPageSize() { return this.pageSize; }
+
+ public RangeSlider setInverted(final boolean v) { inverted = v; return setValue(val); }
+
/**
* Sets slider value range and current value
- * @param min minimum value of slider
- * @param max maximum value of slider
+ * @param minMax minimum- and maximum-value of slider
* @param value current value of slider
* @return this instance of chaining
*/
- public RangeSlider setMinMax(final float min, final float max, final float value) {
- this.min = min;
- this.max = max;
- this.val = Math.max(min, Math.min(max, value));
- this.val_pct = ( value - min ) / getRange();
- setKnob();
- return this;
+ public RangeSlider setMinMax(final Vec2f minMax, final float value) {
+ this.minMax.set(minMax);
+ return setValue( value );
}
public RangeSlider setValuePct(final float v) {
- val_pct = v;
- val = min + ( val_pct * getRange() );
- setKnob();
- return this;
+ final float pct = Math.max(0.0f, Math.min(1.0f, v));
+ return setValue( minMax.x() + ( pct * getRange() ) );
}
public RangeSlider setValue(final float v) {
- val = v;
- val_pct = ( val - min ) / getRange();
+ val = Math.max(minMax.x(), Math.min(minMax.y(), v));
+ val_pct = ( val - minMax.x() ) / getRange();
setKnob();
return this;
}
@@ -226,27 +413,118 @@ public final class RangeSlider extends Widget {
* Knob position reflects value on its center and ranges from zero to max.
*/
private Vec2f getKnobPos(final Vec2f posRes, final float val_pct) {
+ final float v = inverted ? 1f - val_pct : val_pct;
if( horizontal ) {
- posRes.setX( val_pct*width - knobSz*0.5f );
- posRes.setY( -( knobSz - height ) * 0.5f );
+ posRes.setX( Math.max(0, Math.min(size.x(), v*size.x() - knobHalfLen)) );
+ posRes.setY( -( knobDiameter - size.y() ) * 0.5f );
} else {
- posRes.setX( -( knobSz - width ) * 0.5f );
- posRes.setY( val_pct*height - knobSz*0.5f );
+ posRes.setX( -( knobDiameter - size.x() ) * 0.5f );
+ posRes.setY( Math.max(0, Math.min(size.y() - 2*knobHalfLen, v*size.y() - knobHalfLen)) );
}
return posRes;
}
private float getKnobValuePct(final float pos_x, final float pos_y, final float adjustment) {
final float v;
if( horizontal ) {
- v = ( pos_x + adjustment ) / width;
+ v = ( pos_x + adjustment ) / size.x();
} else {
- v = ( pos_y + adjustment ) / height;
+ v = ( pos_y + adjustment ) / size.y();
}
- return Math.max(0.0f, Math.min(1.0f, v));
+ return Math.max(0.0f, Math.min(1.0f, inverted ? 1f - v : v));
}
private void setKnob() {
final Vec2f pos = getKnobPos(new Vec2f(), val_pct);
knob.moveTo(pos.x(), pos.y(), Button.DEFAULT_LABEL_ZOFFSET);
}
+
+ /**
+ * Sets the slider knob color.
+ * <p>
+ * If this slider comprises a rectangular page-sized knob,
+ * its rectangular frame also shares the same color.
+ * </p>
+ * <p>
+ * Base color w/o color channel, will be modulated w/ pressed- and toggle color
+ * </p>
+ * <p>
+ * Default RGBA value is 0.30f, 0.30f, 0.30f, 1.0f
+ * </p>
+ */
+ @Override
+ public final Shape setColor(final float r, final float g, final float b, final float a) {
+ super.setColor(r, g, b, a);
+ knob.setColor(r, g, b, a);
+ if( !Float.isNaN(pageSize) ) {
+ bar.setColor(r, g, b, a);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the slider knob color.
+ * <p>
+ * If this slider comprises a rectangular page-sized knob,
+ * its rectangular frame also shares the same color.
+ * </p>
+ * <p>
+ * Base color w/o color channel, will be modulated w/ pressed- and toggle color
+ * </p>
+ * <p>
+ * Default RGBA value is 0.30f, 0.30f, 0.30f, 1.0f
+ * </p>
+ */
+ @Override
+ public Shape setColor(final Vec4f c) {
+ this.rgbaColor.set(c);
+ knob.setColor(c);
+ if( !Float.isNaN(pageSize) ) {
+ bar.setColor(c);
+ }
+ return this;
+ }
+
+ /**
+ * Sets the slider background bar color, if this slider comprises only a positional round knob.
+ * <p>
+ * Default RGBA value is 0.60f, 0.60f, 0.60f, 0.5f
+ * </p>
+ */
+ public Shape setBackgroundBarColor(final float r, final float g, final float b, final float a) {
+ if( Float.isNaN(pageSize) ) {
+ bar.setColor(r, g, b, a);
+ }
+ return this;
+ }
+ /**
+ * Sets the slider background bar color, if this slider comprises only a positional round knob.
+ * <p>
+ * Default RGBA value is 0.60f, 0.60f, 0.60f, 0.5f
+ * </p>
+ */
+ public Shape setBackgroundBarColor(final Vec4f c) {
+ if( Float.isNaN(pageSize) ) {
+ bar.setColor(c);
+ }
+ return this;
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p>
+ * Sets the slider bar and knob pressed color modulation.
+ * </p>
+ */
+ @Override
+ public final Shape setPressedColorMod(final float r, final float g, final float b, final float a) {
+ super.setPressedColorMod(r, g, b, a);
+ bar.setPressedColorMod(r, g, b, a);
+ knob.setPressedColorMod(r, g, b, a);
+ return this;
+ }
+
+ @Override
+ public String getSubString() {
+ return super.getSubString()+", range["+minMax+"] @ "+val+", "+(100f*val_pct)+"%";
+ }
}