import com.google.gwt.user.client.Timer;\r
import com.google.gwt.user.client.ui.Widget;\r
import com.itmill.toolkit.terminal.gwt.client.ApplicationConnection;\r
+import com.itmill.toolkit.terminal.gwt.client.ContainerResizedListener;\r
import com.itmill.toolkit.terminal.gwt.client.Paintable;\r
import com.itmill.toolkit.terminal.gwt.client.UIDL;\r
+import com.itmill.toolkit.terminal.gwt.client.Util;\r
\r
-public class ISlider extends Widget implements Paintable {\r
+public class ISlider extends Widget implements Paintable,\r
+ ContainerResizedListener {\r
\r
public static final String CLASSNAME = "i-slider";\r
\r
+ /**\r
+ * Minimum size (width or height, depending on orientation) of the slider\r
+ * base.\r
+ */\r
+ private static final int MIN_SIZE = 50;\r
+\r
ApplicationConnection client;\r
\r
String id;\r
private boolean immediate;\r
private boolean disabled;\r
private boolean readonly;\r
+ private boolean scrollbarStyle;\r
\r
private int handleSize;\r
private double min;\r
DOM.setStyleAttribute(bigger, "display", "none");\r
DOM.setStyleAttribute(handle, "visibility", "hidden");\r
\r
- DOM.sinkEvents(base, Event.ONMOUSEDOWN);\r
+ DOM.sinkEvents(getElement(), Event.MOUSEEVENTS);\r
+ DOM.sinkEvents(base, Event.ONCLICK);\r
DOM.sinkEvents(handle, Event.MOUSEEVENTS);\r
- DOM.sinkEvents(smaller, Event.ONMOUSEDOWN | Event.ONMOUSEUP);\r
- DOM.sinkEvents(bigger, Event.ONMOUSEDOWN | Event.ONMOUSEUP);\r
+ DOM.sinkEvents(smaller, Event.ONMOUSEDOWN | Event.ONMOUSEUP\r
+ | Event.ONMOUSEOUT);\r
+ DOM.sinkEvents(bigger, Event.ONMOUSEDOWN | Event.ONMOUSEUP\r
+ | Event.ONMOUSEOUT);\r
}\r
\r
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {\r
vertical = uidl.hasAttribute("vertical");\r
arrows = uidl.hasAttribute("arrows");\r
\r
+ String style = "";\r
+ if (uidl.hasAttribute("style"))\r
+ style = uidl.getStringAttribute("style");\r
+\r
+ scrollbarStyle = style.indexOf("scrollbar") > -1;\r
+\r
if (arrows) {\r
DOM.setStyleAttribute(smaller, "display", "block");\r
DOM.setStyleAttribute(bigger, "display", "block");\r
- if (vertical) {\r
- int arrowSize = Integer.parseInt(DOM.getElementProperty(\r
- smaller, "offsetWidth"));\r
- DOM.setStyleAttribute(bigger, "marginLeft", arrowSize + "px");\r
- DOM.setStyleAttribute(bigger, "marginRight", arrowSize + "px");\r
- }\r
}\r
\r
if (vertical)\r
\r
if (!vertical) {\r
// Draw handle with a delay to allow base to gain maximum width\r
- // TODO implement with onLoad or DeferredCommand ??\r
- Timer delay = new Timer() {\r
- public void run() {\r
+ DeferredCommand.addCommand(new Command() {\r
+ public void execute() {\r
buildHandle();\r
setValue(value, false, false);\r
}\r
- };\r
- delay.schedule(100);\r
+ });\r
} else {\r
buildHandle();\r
setValue(value, false, false);\r
}\r
\r
private void buildBase() {\r
- if (vertical) {\r
- // TODO\r
- } else {\r
- if (size > -1)\r
- DOM.setStyleAttribute(getElement(), "width", size + "px");\r
- else {\r
- Element p = DOM.getParent(getElement());\r
- if (Integer.parseInt(DOM.getElementProperty(p, "offsetWidth")) > 50)\r
- DOM.setStyleAttribute(getElement(), "width", "auto");\r
- else {\r
- // Set minimum of 50px width and adjust after all\r
- // components have (supposedly) been drawn completely.\r
- DOM.setStyleAttribute(getElement(), "width", "50px");\r
- DeferredCommand.addCommand(new Command() {\r
- public void execute() {\r
- Element p = DOM.getParent(getElement());\r
- if (Integer.parseInt(DOM.getElementProperty(p,\r
- "offsetWidth")) > 50)\r
- DOM.setStyleAttribute(getElement(), "width",\r
- "auto");\r
- }\r
- });\r
- }\r
+ final String styleAttribute = vertical ? "height" : "width";\r
+ final String domProperty = vertical ? "offsetHeight" : "offsetWidth";\r
+\r
+ if (size == -1) {\r
+ Element p = DOM.getParent(getElement());\r
+ if (DOM.getElementPropertyInt(p, domProperty) > 50) {\r
+ if (vertical)\r
+ setHeight();\r
+ else\r
+ DOM.setStyleAttribute(base, styleAttribute, "");\r
+ } else {\r
+ // Set minimum size and adjust after all components have\r
+ // (supposedly) been drawn completely.\r
+ DOM.setStyleAttribute(base, styleAttribute, MIN_SIZE + "px");\r
+ DeferredCommand.addCommand(new Command() {\r
+ public void execute() {\r
+ Element p = DOM.getParent(getElement());\r
+ if (DOM.getElementPropertyInt(p, domProperty) > 50)\r
+ if (vertical) {\r
+ setHeight();\r
+ } else\r
+ DOM.setStyleAttribute(base, styleAttribute, "");\r
+ }\r
+ });\r
}\r
- }\r
- // Allow absolute positioning of handle\r
- DOM.setStyleAttribute(base, "position", "relative");\r
+ } else\r
+ DOM.setStyleAttribute(base, styleAttribute, size + "px");\r
\r
- // TODO attach listeners for focusing and arrow keys\r
+ // TODO attach listeners for focusing and arrow keys + scroll wheel\r
}\r
\r
private void buildHandle() {\r
- // Allow absolute positioning\r
- DOM.setStyleAttribute(handle, "position", "absolute");\r
+ String styleAttribute = vertical ? "height" : "width";\r
+ String handleAttribute = vertical ? "marginTop" : "marginLeft";\r
+ String domProperty = vertical ? "offsetHeight" : "offsetWidth";\r
\r
- if (vertical) {\r
- // TODO\r
- } else {\r
- int t = Integer.parseInt(DOM.getElementProperty(base,\r
- "offsetHeight"))\r
- - Integer.parseInt(DOM.getElementProperty(handle,\r
- "offsetHeight"));\r
- DOM.setStyleAttribute(handle, "top", (t / 2) + "px");\r
- DOM.setStyleAttribute(handle, "left", "0px");\r
- int w = (int) (Double.parseDouble(DOM.getElementProperty(base,\r
- "offsetWidth")) / 100 * handleSize);\r
+ DOM.setStyleAttribute(handle, handleAttribute, "0");\r
+\r
+ if (scrollbarStyle) {\r
+ // Only stretch the handle if scrollbar style is set.\r
+ int s = (int) (Double.parseDouble(DOM.getElementProperty(base,\r
+ domProperty)) / 100 * handleSize);\r
if (handleSize == -1) {\r
- int baseW = Integer.parseInt(DOM.getElementProperty(base,\r
- "offsetWidth"));\r
+ int baseS = Integer.parseInt(DOM.getElementProperty(base,\r
+ domProperty));\r
double range = (max - min) * (resolution + 1) * 3;\r
- w = (int) (baseW - range);\r
+ s = (int) (baseS - range);\r
}\r
- if (w < 3)\r
- w = 3;\r
- DOM.setStyleAttribute(handle, "width", w + "px");\r
- }\r
+ if (s < 3)\r
+ s = 3;\r
+ DOM.setStyleAttribute(handle, styleAttribute, s + "px");\r
+ } else\r
+ DOM.setStyleAttribute(handle, styleAttribute, "");\r
\r
+ // Restore visibility\r
DOM.setStyleAttribute(handle, "visibility", "visible");\r
\r
}\r
\r
private void setValue(Double value, boolean animate, boolean updateToServer) {\r
- if (vertical) {\r
- // TODO\r
- } else {\r
- int handleWidth = Integer.parseInt(DOM.getElementProperty(handle,\r
- "offsetWidth"));\r
- int baseWidth = Integer.parseInt(DOM.getElementProperty(base,\r
- "offsetWidth"));\r
- int range = baseWidth - handleWidth;\r
- double v = value.doubleValue();\r
- double valueRange = max - min;\r
- double p = 0;\r
- if (valueRange != 0)\r
- p = range * ((v - min) / valueRange);\r
- if (p < 0)\r
- p = 0;\r
- final double pos = p;\r
-\r
- String styleLeft = DOM.getStyleAttribute(handle, "left");\r
- int left = Integer.parseInt(styleLeft.substring(0, styleLeft\r
- .length() - 2));\r
-\r
- if ((int) (Math.round(pos)) != left && animate) {\r
- if (anim != null)\r
- anim.cancel();\r
- anim = new Timer() {\r
- private int left;\r
- private int goal = (int) Math.round(pos);\r
- private int dir = 0;\r
-\r
- public void run() {\r
- String styleLeft = DOM\r
- .getStyleAttribute(handle, "left");\r
- left = Integer.parseInt(styleLeft.substring(0,\r
- styleLeft.length() - 2));\r
-\r
- // Determine direction\r
- if (dir == 0)\r
- dir = (goal - left) / Math.abs(goal - left);\r
-\r
- if ((dir > 0 && left >= goal)\r
- || (dir < 0 && left <= goal)) {\r
- this.cancel();\r
- return;\r
- }\r
- int increment = (goal - left) / 2;\r
- DOM.setStyleAttribute(handle, "left",\r
- (left + increment) + "px");\r
+ final String styleAttribute = vertical ? "marginTop" : "marginLeft";\r
+ String domProperty = vertical ? "offsetHeight" : "offsetWidth";\r
+ int handleSize = Integer.parseInt(DOM.getElementProperty(handle,\r
+ domProperty));\r
+ int baseSize = Integer.parseInt(DOM.getElementProperty(base,\r
+ domProperty));\r
+ int range = baseSize - handleSize;\r
+ double v = value.doubleValue();\r
+ double valueRange = max - min;\r
+ double p = 0;\r
+ if (valueRange > 0)\r
+ p = range * ((v - min) / valueRange);\r
+ if (p < 0)\r
+ p = 0;\r
+ if (vertical)\r
+ p = range - p - (Util.isIE6() ? 1 : 0);\r
+ final double pos = p;\r
+\r
+ int current = DOM.getIntStyleAttribute(handle, styleAttribute);\r
+\r
+ if ((int) (Math.round(pos)) != current && animate) {\r
+ if (anim != null)\r
+ anim.cancel();\r
+ anim = new Timer() {\r
+ private int current;\r
+ private int goal = (int) Math.round(pos);\r
+ private int dir = 0;\r
+\r
+ public void run() {\r
+ current = DOM.getIntStyleAttribute(handle, styleAttribute);\r
+\r
+ // Determine direction\r
+ if (dir == 0)\r
+ dir = (goal - current) / Math.abs(goal - current);\r
+\r
+ if ((dir > 0 && current >= goal)\r
+ || (dir < 0 && current <= goal)) {\r
+ this.cancel();\r
+ return;\r
}\r
- };\r
- anim.scheduleRepeating(50);\r
- } else\r
- DOM.setStyleAttribute(handle, "left", ((int) pos) + "px");\r
- // DOM.setAttribute(handle, "title", ""+v);\r
- }\r
+ int increment = (goal - current) / 2;\r
+ DOM.setStyleAttribute(handle, styleAttribute,\r
+ (current + increment) + "px");\r
+ }\r
+ };\r
+ anim.scheduleRepeating(50);\r
+ } else\r
+ DOM.setStyleAttribute(handle, styleAttribute, ((int) pos) + "px");\r
+\r
+ DOM.setElementAttribute(handle, "title", "" + v);\r
\r
if (value.doubleValue() < min)\r
value = new Double(min);\r
Element targ = DOM.eventGetTarget(event);\r
if (dragging || DOM.compare(targ, handle)) {\r
processHandleEvent(event);\r
-\r
} else if (DOM.compare(targ, smaller)) {\r
- // Decrease value by resolution\r
- if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {\r
- setValue(new Double(value.doubleValue()\r
- - Math.pow(10, -resolution)), false, true);\r
- if (anim != null)\r
- anim.cancel();\r
- anim = new Timer() {\r
- public void run() {\r
- if (value.doubleValue() - Math.pow(10, -resolution) > min)\r
- setValue(new Double(value.doubleValue()\r
- - Math.pow(10, -resolution)), false, true);\r
- }\r
- };\r
- anim.scheduleRepeating(100);\r
- DOM.eventCancelBubble(event, true);\r
- } else if (DOM.eventGetType(event) == Event.ONMOUSEUP) {\r
- anim.cancel();\r
- }\r
-\r
+ decreaseValue(event);\r
} else if (DOM.compare(targ, bigger)) {\r
- // Increase value by resolution\r
- if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {\r
- setValue(new Double(value.doubleValue()\r
- + Math.pow(10, -resolution)), false, true);\r
- if (anim != null)\r
- anim.cancel();\r
- anim = new Timer() {\r
- public void run() {\r
- if (value.doubleValue() - Math.pow(10, -resolution) < max)\r
- setValue(new Double(value.doubleValue()\r
- + Math.pow(10, -resolution)), false, true);\r
- }\r
- };\r
- anim.scheduleRepeating(100);\r
- DOM.eventCancelBubble(event, true);\r
- } else if (DOM.eventGetType(event) == Event.ONMOUSEUP) {\r
- anim.cancel();\r
- }\r
-\r
+ increaseValue(event);\r
} else\r
processBaseEvent(event);\r
}\r
break;\r
case Event.ONMOUSEMOVE:\r
if (dragging) {\r
- DOM.setCapture(getElement());\r
+ // DOM.setCapture(getElement());\r
setValueByEvent(event, false, false);\r
}\r
break;\r
setValueByEvent(event, true, true);\r
DOM.eventCancelBubble(event, true);\r
}\r
+ } else if (DOM.eventGetType(event) == Event.ONMOUSEDOWN && dragging) {\r
+ dragging = false;\r
+ DOM.releaseCapture(getElement());\r
+ setValueByEvent(event, true, true);\r
}\r
}\r
\r
+ private void decreaseValue(Event event) {\r
+ if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {\r
+ setValue(\r
+ new Double(value.doubleValue() - Math.pow(10, -resolution)),\r
+ false, true);\r
+ if (anim != null)\r
+ anim.cancel();\r
+ anim = new Timer() {\r
+ public void run() {\r
+ if (value.doubleValue() - Math.pow(10, -resolution) > min)\r
+ setValue(new Double(value.doubleValue()\r
+ - Math.pow(10, -resolution)), false, true);\r
+ }\r
+ };\r
+ anim.scheduleRepeating(100);\r
+ DOM.eventCancelBubble(event, true);\r
+ } else\r
+ anim.cancel();\r
+ }\r
+\r
+ private void increaseValue(Event event) {\r
+ if (DOM.eventGetType(event) == Event.ONMOUSEDOWN) {\r
+ setValue(\r
+ new Double(value.doubleValue() + Math.pow(10, -resolution)),\r
+ false, true);\r
+ if (anim != null)\r
+ anim.cancel();\r
+ anim = new Timer() {\r
+ public void run() {\r
+ if (value.doubleValue() - Math.pow(10, -resolution) < max)\r
+ setValue(new Double(value.doubleValue()\r
+ + Math.pow(10, -resolution)), false, true);\r
+ }\r
+ };\r
+ anim.scheduleRepeating(100);\r
+ DOM.eventCancelBubble(event, true);\r
+ } else\r
+ anim.cancel();\r
+ }\r
+\r
private void setValueByEvent(Event event, boolean animate, boolean roundup) {\r
- int x = DOM.eventGetClientX(event);\r
- // int y = DOM.eventGetClientY(event);\r
double v = min; // Fallback to min\r
- if (vertical) {\r
- // TODO\r
- } else {\r
- double handleW = Integer.parseInt(DOM.getElementProperty(handle,\r
- "offsetWidth"));\r
- double baseX = DOM.getAbsoluteLeft(base) + handleW / 2;\r
- double baseW = Integer.parseInt(DOM.getElementProperty(base,\r
- "offsetWidth"));\r
- v = ((x - baseX) / (baseW - handleW)) * (max - min) + min;\r
- }\r
+\r
+ int coord = vertical ? DOM.eventGetClientY(event) : DOM\r
+ .eventGetClientX(event);\r
+ String domProperty = vertical ? "offsetHeight" : "offsetWidth";\r
+\r
+ double handleSize = Integer.parseInt(DOM.getElementProperty(handle,\r
+ domProperty));\r
+ double baseSize = Integer.parseInt(DOM.getElementProperty(base,\r
+ domProperty));\r
+ double baseOffset = vertical ? DOM.getAbsoluteTop(base) - handleSize\r
+ / 2 : DOM.getAbsoluteLeft(base) + handleSize / 2;\r
+\r
+ if (vertical)\r
+ v = ((baseSize - (coord - baseOffset)) / (baseSize - handleSize))\r
+ * (max - min) + min;\r
+ else\r
+ v = ((coord - baseOffset) / (baseSize - handleSize)) * (max - min)\r
+ + min;\r
\r
if (v < min)\r
v = min;\r
setValue(new Double(v), animate, roundup);\r
}\r
\r
+ public void iLayout() {\r
+ if (vertical) {\r
+ setHeight();\r
+ }\r
+ // Update handle position\r
+ setValue(value, false, false);\r
+ }\r
+\r
+ private void setHeight() {\r
+ if (size == -1) {\r
+ // Calculate decoration size\r
+ DOM.setStyleAttribute(base, "height", "0");\r
+ DOM.setStyleAttribute(base, "overflow", "hidden");\r
+ int decoHeight = DOM.getElementPropertyInt(getElement(),\r
+ "offsetHeight");\r
+ // Get available space size\r
+ int availableHeight = DOM.getElementPropertyInt(DOM\r
+ .getParent(getElement()), "offsetHeight");\r
+ int h = availableHeight - decoHeight;\r
+ if (h < MIN_SIZE)\r
+ h = MIN_SIZE;\r
+ DOM.setStyleAttribute(base, "height", h + "px");\r
+ } else {\r
+ DOM.setStyleAttribute(base, "height", size + "px");\r
+ }\r
+ DOM.setStyleAttribute(base, "overflow", "");\r
+ }\r
+\r
}\r