Browse Source

Slider component updated with proper implementation and styles.

svn changeset:1925/svn branch:trunk
tags/6.7.0.beta1
Jouni Koivuviita 17 years ago
parent
commit
b88e9d23a5

+ 30
- 0
src/com/itmill/toolkit/terminal/PaintTarget.java View File

@@ -176,6 +176,20 @@ public interface PaintTarget {
* if the paint operation failed.
*/
public void addAttribute(String name, float value) throws PaintException;
/**
* Adds a double attribute to component. Atributes must be added before any
* content is written.
*
* @param name
* the Attribute name.
* @param value
* the Attribute value.
*
* @throws PaintException
* if the paint operation failed.
*/
public void addAttribute(String name, double value) throws PaintException;

/**
* Adds a string attribute to component. Atributes must be added before any
@@ -254,6 +268,22 @@ public interface PaintTarget {
*/
public void addVariable(VariableOwner owner, String name, float value)
throws PaintException;
/**
* Adds a double type variable.
*
* @param owner
* the Listener for variable changes.
* @param name
* the Variable name.
* @param value
* the Variable initial value.
*
* @throws PaintException
* if the paint operation failed.
*/
public void addVariable(VariableOwner owner, String name, double value)
throws PaintException;

/**
* Adds a boolean type variable.

+ 23
- 0
src/com/itmill/toolkit/terminal/gwt/client/UIDL.java View File

@@ -61,6 +61,22 @@ public class UIDL {
double num = ((JSONNumber) val).getValue();
return (long) num;
}
public float getFloatAttribute(String name) {
JSONValue val = ((JSONObject) json.get(1)).get(name);
if (val == null)
return 0;
double num = ((JSONNumber) val).getValue();
return (float) num;
}
public double getDoubleAttribute(String name) {
JSONValue val = ((JSONObject) json.get(1)).get(name);
if (val == null)
return 0;
double num = ((JSONNumber) val).getValue();
return (double) num;
}

public boolean getBooleanAttribute(String name) {
JSONValue val = ((JSONObject) json.get(1)).get(name);
@@ -317,6 +333,13 @@ public class UIDL {
throw new IllegalArgumentException("No such variable: " + name);
return (float) t.getValue();
}
public double getDoubleVariable(String name) {
JSONNumber t = (JSONNumber) getVariableHash().get(name);
if (t == null)
throw new IllegalArgumentException("No such variable: " + name);
return (double) t.getValue();
}

public boolean getBooleanVariable(String name) {
JSONBoolean t = (JSONBoolean) getVariableHash().get(name);

+ 178
- 64
src/com/itmill/toolkit/terminal/gwt/client/ui/ISlider.java View File

@@ -1,13 +1,9 @@
package com.itmill.toolkit.terminal.gwt.client.ui;
import java.util.HashSet;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.MouseListener;
import com.google.gwt.user.client.ui.SourcesMouseEvents;
import com.google.gwt.user.client.ui.Widget;
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;
import com.itmill.toolkit.terminal.gwt.client.Paintable;
@@ -26,13 +22,13 @@ public class ISlider extends Widget implements Paintable {
private boolean readonly;
private int handleSize;
private float min;
private float max;
private double min;
private double max;
private int resolution;
private Object value;
private HashSet values;
private Double value;
private boolean vertical;
private int size = -1;
private boolean arrows;
/* DOM element for slider's base */
private Element base;
@@ -40,21 +36,44 @@ public class ISlider extends Widget implements Paintable {
/* DOM element for slider's handle */
private Element handle;
private boolean dragging;
/* DOM element for decrement arrow */
private Element smaller;
/* DOM element for increment arrow */
private Element bigger;
/* Temporary dragging/animation variables */
private boolean dragging = false;
private Timer anim;
public ISlider() {
super();
setElement(DOM.createElement("div"));
base = DOM.createElement("div");
DOM.appendChild(getElement(), base);
handle = DOM.createElement("div");
DOM.appendChild(base, handle);
setElement(DOM.createDiv());
base = DOM.createDiv();
handle = DOM.createDiv();
smaller = DOM.createDiv();
bigger = DOM.createDiv();
setStyleName(CLASSNAME);
DOM.setAttribute(base, "className", CLASSNAME+"-base");
DOM.setAttribute(handle, "className", CLASSNAME+"-handle");
DOM.setAttribute(smaller, "className", CLASSNAME+"-smaller");
DOM.setAttribute(bigger, "className", CLASSNAME+"-bigger");
DOM.appendChild(getElement(), bigger);
DOM.appendChild(getElement(), smaller);
DOM.appendChild(getElement(), base);
DOM.appendChild(base, handle);
// Hide initially
DOM.setStyleAttribute(smaller, "display", "none");
DOM.setStyleAttribute(bigger, "display", "none");
DOM.sinkEvents(base, Event.MOUSEEVENTS);
DOM.sinkEvents(base, Event.ONMOUSEDOWN);
DOM.sinkEvents(handle, Event.MOUSEEVENTS);
DOM.sinkEvents(smaller, Event.ONMOUSEDOWN);
DOM.sinkEvents(bigger, Event.ONMOUSEDOWN);
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
@@ -70,22 +89,27 @@ public class ISlider extends Widget implements Paintable {
readonly = uidl.getBooleanAttribute("readonly");
vertical = uidl.hasAttribute("vertical");
arrows = uidl.hasAttribute("arrows");
if(arrows) {
DOM.setStyleAttribute(smaller, "display", "block");
DOM.setStyleAttribute(bigger, "display", "block");
if(vertical) {
int arrowSize = Integer.parseInt(DOM.getAttribute(smaller, "offsetWidth"));
DOM.setStyleAttribute(bigger, "marginLeft", arrowSize+"px");
DOM.setStyleAttribute(bigger, "marginRight", arrowSize+"px");
}
}
if(vertical)
addStyleName(CLASSNAME+"-vertical");
else
removeStyleName(CLASSNAME+"-vertical");
if(uidl.hasAttribute("values")) {
values = uidl.getStringArrayAttributeAsSet("values");
value = uidl.getStringVariable("value");
} else {
min = uidl.getLongAttribute("min");
max = uidl.getLongAttribute("max");
resolution = uidl.getIntAttribute("resolution");
value = new Float(uidl.getFloatVariable("value"));
values = null;
}
min = uidl.getDoubleAttribute("min");
max = uidl.getDoubleAttribute("max");
resolution = uidl.getIntAttribute("resolution");
value = new Double(uidl.getDoubleVariable("value"));
handleSize = uidl.getIntAttribute("hsize");
@@ -99,13 +123,13 @@ public class ISlider extends Widget implements Paintable {
Timer delay = new Timer() {
public void run() {
buildHandle();
setHandlePosition(value);
setValue(value, true);
}
};
delay.schedule(100);
} else {
buildHandle();
setHandlePosition(value);
setValue(value, true);
}
}
@@ -117,7 +141,24 @@ public class ISlider extends Widget implements Paintable {
} else {
if(size > -1)
DOM.setStyleAttribute(base, "width", size + "px");
else DOM.setStyleAttribute(base, "width", "100%");
else {
Element p = DOM.getParent(getElement());
if(Integer.parseInt(DOM.getAttribute(p, "offsetWidth")) > 50)
DOM.setStyleAttribute(base, "width", "auto");
else {
// Set minimum of 50px width and adjust after all
// components have (supposedly) been drawn completely.
DOM.setStyleAttribute(base, "width", "50px");
Timer adjust = new Timer() {
public void run() {
Element p = DOM.getParent(getElement());
if(Integer.parseInt(DOM.getAttribute(p, "offsetWidth")) > 50)
DOM.setStyleAttribute(base, "width", "auto");
}
};
adjust.schedule(100);
}
}
}
// Allow absolute positioning of handle
DOM.setStyleAttribute(base, "position", "relative");
@@ -135,68 +176,86 @@ public class ISlider extends Widget implements Paintable {
int t = Integer.parseInt(DOM.getAttribute(base, "offsetHeight")) - Integer.parseInt(DOM.getAttribute(handle, "offsetHeight"));
DOM.setStyleAttribute(handle, "top", (t/2)+"px");
DOM.setStyleAttribute(handle, "left", "0px");
int w = (int) (Float.parseFloat(DOM.getAttribute(base, "offsetWidth")) / 100 * handleSize);
int w = (int) (Double.parseDouble(DOM.getAttribute(base, "offsetWidth")) / 100 * handleSize);
DOM.setStyleAttribute(handle, "width", w+"px");
}
}
private void setHandlePosition(Object value) {
private void setValue(Double value, boolean animate) {
if(vertical) {
// TODO
} else {
if(values == null) {
int handleWidth = Integer.parseInt(DOM.getAttribute(handle, "offsetWidth"));
int baseWidth = Integer.parseInt(DOM.getAttribute(base, "offsetWidth"));
int range = baseWidth - handleWidth;
float v = ((Float)value).floatValue();
float valueRange = max - min;
float pos = range * ((v - min) / valueRange);
DOM.setStyleAttribute(handle, "left", pos+"px");
DOM.setAttribute(handle, "title", ""+v);
}
int handleWidth = Integer.parseInt(DOM.getAttribute(handle, "offsetWidth"));
int baseWidth = Integer.parseInt(DOM.getAttribute(base, "offsetWidth"));
int range = baseWidth - handleWidth;
double v = value.doubleValue();
double valueRange = max - min;
final double pos = range * ((v - min) / valueRange);
String styleLeft = DOM.getStyleAttribute(handle, "left");
int left = Integer.parseInt(styleLeft.substring(0, styleLeft.length()-2));
if((int)pos != left && animate) {
if(anim != null)
anim.cancel();
anim = new Timer() {
private int left;
private int goal = (int)pos;
private int dir = 0;
public void run() {
String styleLeft = DOM.getStyleAttribute(handle, "left");
left = Integer.parseInt(styleLeft.substring(0, styleLeft.length()-2));
// Determine direction
if(dir == 0)
dir = (goal-left)/Math.abs(goal-left);
if((dir > 0 && left >= goal) || (dir < 0 && left <= goal)) {
this.cancel();
return;
}
int increment = (goal - left) / 2;
DOM.setStyleAttribute(handle, "left", (left+increment)+"px");
}
};
anim.scheduleRepeating(50);
} else DOM.setStyleAttribute(handle, "left", pos+"px");
DOM.setAttribute(handle, "title", ""+v);
}
this.value = value;
}
public void onBrowserEvent(Event event) {
if(dragging || DOM.compare(DOM.eventGetTarget(event), handle))
Element targ = DOM.eventGetTarget(event);
if(dragging || DOM.compare(targ, handle)) {
processHandleEvent(event);
else
} else if(DOM.compare(targ, smaller)) {
if(DOM.eventGetType(event) == Event.ONMOUSEDOWN)
decrease();
} else if(DOM.compare(targ, bigger)) {
if(DOM.eventGetType(event) == Event.ONMOUSEDOWN)
increase();
} else {
processBaseEvent(event);
}
}
private void processHandleEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
client.console.log("Slider handle: mousedown");
if(!disabled && !readonly) {
anim.cancel();
dragging = true;
DOM.setCapture(handle);
DOM.eventPreventDefault(event); // prevent selecting text
DOM.eventCancelBubble(event, true);
}
break;
case Event.ONMOUSEMOVE:
if (dragging) {
int x = DOM.eventGetClientX(event);
int y = DOM.eventGetClientY(event);
if(vertical) {
// TODO
} else {
if(values == null) {
client.console.log("Slider handle: dragging..." + x);
float handleW = Integer.parseInt(DOM.getAttribute(handle, "offsetWidth"));
float baseX = DOM.getAbsoluteLeft(base);
float baseW = Integer.parseInt(DOM.getAttribute(base, "offsetWidth"));
float v = ((x-baseX)/(baseW-baseX)) * (max-min) + min;
if(resolution > 0) {
setHandlePosition(new Float(v));
} else
setHandlePosition(new Float((int)v));
} else {
// TODO
}
}
setValueByEvent(event, false);
}
break;
case Event.ONMOUSEUP:
@@ -209,8 +268,63 @@ public class ISlider extends Widget implements Paintable {
}
private void processBaseEvent(Event event) {
// TODO
super.onBrowserEvent(event);
if(DOM.eventGetType(event) == Event.ONMOUSEDOWN) {
if(!disabled && !readonly && !dragging) {
setValueByEvent(event, true);
DOM.eventCancelBubble(event, true);
}
}
}
private void setValueByEvent(Event event, boolean animate) {
int x = DOM.eventGetClientX(event);
int y = DOM.eventGetClientY(event);
double v = min; // Fallback to min
if(vertical) {
// TODO
} else {
double handleW = Integer.parseInt(DOM.getAttribute(handle, "offsetWidth"));
double baseX = DOM.getAbsoluteLeft(base) + handleW/2;
double baseW = Integer.parseInt(DOM.getAttribute(base, "offsetWidth"));
v = ((x-baseX)/(baseW-handleW)) * (max-min) + min;
}
if(v < min)
v = min;
else if(v > max)
v = max;
if(resolution > 0) {
v = (int)(v * (double)Math.pow(10, resolution));
v = v / (double)Math.pow(10, resolution);
setValue(new Double(v), animate);
} else
setValue(new Double((int)v), animate);
}
private void decrease() {
double diff = (max-min)/max*10 + (max-min)/10;
double v = value.doubleValue()-diff;
if(resolution > 0) {
v = (int)(v * (double)Math.pow(10, resolution));
v = v / (double)Math.pow(10, resolution);
} else v = (int)v;
if(v < min)
v = min;
setValue(new Double(v), true);
}
private void increase() {
double diff = (max-min)/max*10 + (max-min)/10;
double v = value.doubleValue()+diff;
if(resolution > 0) {
v = (int)(v * (double)Math.pow(10, resolution));
v = v / (double)Math.pow(10, resolution);
} else v = (int)v;
if(v > max)
v = max;
setValue(new Double(v), true);
}
}

BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/arrow-left-over.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/arrow-left.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/arrow-right-over.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/arrow-right.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/bg.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/handle-bg.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/handle-left.png View File


BIN
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/img/handle-right.png View File


+ 46
- 0
src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java View File

@@ -432,6 +432,22 @@ public class JsonPaintTarget implements PaintTarget {
public void addAttribute(String name, float value) throws PaintException {
tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
}
/**
* Adds a float attribute to component. Atributes must be added before any
* content is written.
*
* @param name
* the Attribute name.
* @param value
* the Attribute value.
*
* @throws PaintException
* if the paint operation failed.
*/
public void addAttribute(String name, double value) throws PaintException {
tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
}

/**
* Adds a string attribute to component. Atributes must be added before any
@@ -532,6 +548,23 @@ public class JsonPaintTarget implements PaintTarget {
tag.addVariable(new LongVariable(owner, name, value));
}
/**
* Adds a float type variable.
*
* @param owner
* the Listener for variable changes.
* @param name
* the Variable name.
* @param value
* the Variable initial value.
*
* @throws PaintException
* if the paint operation failed.
*/
public void addVariable(VariableOwner owner, String name, double value) throws PaintException {
tag.addVariable(new DoubleVariable(owner, name, value));
}
/**
* Adds a float type variable.
*
@@ -997,6 +1030,19 @@ public class JsonPaintTarget implements PaintTarget {
return "\"" + name + "\":" + value;
}
}
class DoubleVariable extends Variable {
double value;

public DoubleVariable(VariableOwner owner, String name, double v) {
value = v;
this.name = name;
}

public String getJsonPresentation() {
return "\"" + name + "\":" + value;
}
}

class ArrayVariable extends Variable {
String[] value;

+ 85
- 84
src/com/itmill/toolkit/ui/Slider.java View File

@@ -1,7 +1,6 @@
package com.itmill.toolkit.ui;
import java.util.Map;
import java.util.Set;
import com.itmill.toolkit.terminal.PaintException;
import com.itmill.toolkit.terminal.PaintTarget;
@@ -12,9 +11,9 @@ public class Slider extends AbstractField {
public static final int ORIENTATION_VERTICAL = 1;
/** Minimum value of slider */
private float min = 0;
private double min = 0;
/** Maximum value of slider */
private float max = 100;
private double max = 100;
/**
* Resolution, how many digits are considered relevant after desimal point.
@@ -22,12 +21,6 @@ public class Slider extends AbstractField {
*/
private int resolution = 0;
/**
* Object values for slider in stead of numeric (usually strings).
* If this is set, min, max and resolution values are ignored.
*/
private Set values;
/**
* Slider orientation (horizontal==default/vertical).
*/
@@ -44,15 +37,45 @@ public class Slider extends AbstractField {
* Handle size in percents related to base size.
* Must be a value between 1-100.
*/
private int handleSize = 20;
private int handleSize = -1;
/**
* Show arrows that can be pressed to slide the
* handle in some increments (client-side
* implementation decides the increment).
*/
private boolean arrows = true;
public Slider() {
super();
super.setValue(new Float(min));
super.setValue(new Double(min));
}
public Slider(String caption) {
this();
setCaption(caption);
}
public Slider(double min, double max, int resolution) {
this();
setMin(min);
setMax(max);
setResolution(resolution);
}
public Slider(int min, int max) {
this();
setMin(min);
setMax(max);
setResolution(0);
}
public Slider(String caption, int min, int max) {
this(min, max);
setCaption(caption);
}
public float getMax() {
public double getMax() {
return max;
}
@@ -60,19 +83,20 @@ public class Slider extends AbstractField {
* Set the maximum value of the Slider. As a side-effect nullifies the "values" Set.
* @param max
*/
public void setMax(float max) {
public void setMax(double max) {
this.max = max;
this.values = null;
try {
if((new Float(getValue().toString())).floatValue() > max)
super.setValue(new Float(min));
} catch(ClassCastException e) {
super.setValue(new Float(max));
}
if(handleSize == -1)
handleSize = (int) ((max-min)/max*10 + (max-min)/10);
requestRepaint();
}
public float getMin() {
public double getMin() {
return min;
}
@@ -80,15 +104,16 @@ public class Slider extends AbstractField {
* Set the minimum value of the Slider. As a side-effect nullifies the "values" Set.
* @param max
*/
public void setMin(float min) {
public void setMin(double min) {
this.min = min;
this.values = null;
try {
if((new Float(getValue().toString())).floatValue() < min)
super.setValue(new Float(min));
if((new Double(getValue().toString())).doubleValue() < min)
super.setValue(new Double(min));
} catch(ClassCastException e) {
super.setValue(new Float(min));
super.setValue(new Double(min));
}
if(handleSize == -1)
handleSize = (int) ((max-min)/max*10 + (max-min)/10);
requestRepaint();
}
@@ -112,47 +137,24 @@ public class Slider extends AbstractField {
requestRepaint();
}
public Set getValues() {
return values;
}
public void setValues(Set values) {
this.values = values;
requestRepaint();
}
public void setValue(Float value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException {
float v = new Float(value.toString()).floatValue();
Object newValue;
public void setValue(Double value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException {
double v = new Double(value.toString()).doubleValue();
double newValue;
if(resolution>0) {
// Round up to resolution
newValue = new Float(v * (resolution*10) / (resolution*10));
if(min > ((Float)newValue).floatValue() || max < ((Float)newValue).floatValue())
newValue = (int) (v * (double) Math.pow(10, resolution));
newValue = newValue / (double) Math.pow(10, resolution);
if(min > newValue || max < newValue)
throw new ValueOutOfBoundsException(value);
} else {
newValue = new Float((int) v);
if(min > ((Float)newValue).intValue() || max < ((Float)newValue).intValue())
newValue = (int) v;
if(min > newValue || max < newValue)
throw new ValueOutOfBoundsException(value);
}
super.setValue(newValue, repaintIsNotNeeded);
super.setValue(new Double(newValue), repaintIsNotNeeded);
}
public void setValue(Float value)throws ValueOutOfBoundsException {
setValue(value, false);
}
public void setValue(String value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException {
if(this.values != null) {
String v = new String(value.toString());
if(this.values.contains(v))
super.setValue(v, repaintIsNotNeeded);
else throw new ValueOutOfBoundsException(value);
} else {
// TODO
}
}
public void setValue(String value) throws ValueOutOfBoundsException {
public void setValue(Double value) throws ValueOutOfBoundsException {
setValue(value, false);
}
@@ -175,6 +177,15 @@ public class Slider extends AbstractField {
this.handleSize = handleSize;
requestRepaint();
}
public void setArrows(boolean visible) {
arrows = visible;
requestRepaint();
}
public boolean arrowsVisible() {
return arrows;
}
public String getTag() {
return "slider";
@@ -182,26 +193,22 @@ public class Slider extends AbstractField {
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
if(values == null) {
target.addAttribute("min", (long) min);
target.addAttribute("max", (long) max);
target.addAttribute("resolution", resolution);
if(resolution > 0)
target.addVariable(this, "value", ((Float)getValue()).floatValue());
else
target.addVariable(this, "value", ((Float)getValue()).intValue());
} else {
target.addVariable(this, "value", getValue().toString());
target.addAttribute("values", values.toArray(new String[values.size()]));
}
target.addAttribute("min", min);
target.addAttribute("max", max);
target.addAttribute("resolution", resolution);
if(resolution > 0)
target.addVariable(this, "value", ((Double)getValue()).doubleValue());
else
target.addVariable(this, "value", ((Double)getValue()).intValue());
if(orientation == ORIENTATION_VERTICAL)
target.addAttribute("vertical", true);
if(arrows)
target.addAttribute("arrows", true);
if(size > -1)
target.addAttribute("size", size);
@@ -219,16 +226,12 @@ public class Slider extends AbstractField {
public void changeVariables(Object source, Map variables) {
if (variables.containsKey("value")) {
Object newValue = variables.get("value");
if(values == null) {
if(resolution >0)
newValue = new Long(newValue.toString());
else
newValue = new Integer(newValue.toString());
if(newValue != null && newValue != getValue() && !newValue.equals(getValue())) {
setValue(newValue);
}
} else {
// TODO
if(resolution > 0)
newValue = new Double(newValue.toString());
else
newValue = new Integer(newValue.toString());
if(newValue != null && newValue != getValue() && !newValue.equals(getValue())) {
setValue(newValue, true);
}
}
}
@@ -240,7 +243,7 @@ public class Slider extends AbstractField {
*/
private static final long serialVersionUID = -6451298598644446340L;
private Object value;
private Double value;
/**
* Constructs an <code>ValueOutOfBoundsException</code> with the specified
@@ -248,20 +251,18 @@ public class Slider extends AbstractField {
*
* @param valueOutOfBounds
*/
public ValueOutOfBoundsException(Object valueOutOfBounds) {
public ValueOutOfBoundsException(Double valueOutOfBounds) {
this.value = valueOutOfBounds;
}
public Object getValue() {
public Double getValue() {
return this.value;
}
}
public Class getType() {
if(values == null)
return Float.class;
return String.class;
return Double.class;
}
}

Loading…
Cancel
Save