Browse Source

Slider component serverside almost complete.

ISlider implementation started (minimal support for horizontal sliding).

svn changeset:1918/svn branch:trunk
tags/6.7.0.beta1
Jouni Koivuviita 17 years ago
parent
commit
556ba33b7b

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

@@ -162,6 +162,20 @@ public interface PaintTarget {
* if the paint operation failed.
*/
public void addAttribute(String name, long value) throws PaintException;
/**
* 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, float value) throws PaintException;

/**
* Adds a string attribute to component. Atributes must be added before any
@@ -208,6 +222,38 @@ public interface PaintTarget {
*/
public void addVariable(VariableOwner owner, String name, int value)
throws PaintException;
/**
* Adds a long 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, long value)
throws PaintException;
/**
* 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, float value)
throws PaintException;

/**
* Adds a boolean type variable.

+ 17
- 14
src/com/itmill/toolkit/terminal/gwt/client/DefaultWidgetFactory.java View File

@@ -17,6 +17,7 @@ import com.itmill.toolkit.terminal.gwt.client.ui.IPasswordField;
import com.itmill.toolkit.terminal.gwt.client.ui.IPopupCalendar;
import com.itmill.toolkit.terminal.gwt.client.ui.IScrollTable;
import com.itmill.toolkit.terminal.gwt.client.ui.ISelect;
import com.itmill.toolkit.terminal.gwt.client.ui.ISlider;
import com.itmill.toolkit.terminal.gwt.client.ui.ITablePaging;
import com.itmill.toolkit.terminal.gwt.client.ui.ITabsheet;
import com.itmill.toolkit.terminal.gwt.client.ui.ITextArea;
@@ -39,52 +40,52 @@ public class DefaultWidgetFactory implements WidgetFactory {
return new ICheckBox();
return new IButton();
}
if ("window".equals(tag))
else if ("window".equals(tag))
return new IWindow();
if ("orderedlayout".equals(tag)) {
else if ("orderedlayout".equals(tag)) {
if ("horizontal".equals(uidl.getStringAttribute("orientation")))
return new IHorizontalLayout();
else
return new IVerticalLayout();
}
if ("label".equals(tag))
else if ("label".equals(tag))
return new ILabel();
if ("gridlayout".equals(tag))
else if ("gridlayout".equals(tag))
return new IGridLayout();
if ("tree".equals(tag))
else if ("tree".equals(tag))
return new ITree();
if ("select".equals(tag)) {
else if ("select".equals(tag)) {
if("optiongroup".equals(uidl.getStringAttribute("style")))
return new IOptionGroup();
else if("twincol".equals(uidl.getStringAttribute("style")))
return new ITwinColSelect();
return new ISelect();
}
if ("panel".equals(tag))
else if ("panel".equals(tag))
return new IPanel();
if ("component".equals(tag))
else if ("component".equals(tag))
return new IComponent();
if ("tabsheet".equals(tag))
else if ("tabsheet".equals(tag))
return new ITabsheet();
if ("embedded".equals(tag))
else if ("embedded".equals(tag))
return new IEmbedded();
if ("customlayout".equals(tag))
else if ("customlayout".equals(tag))
return new ICustomLayout();
if ("textfield".equals(tag)) {
else if ("textfield".equals(tag)) {
if(uidl.hasAttribute("multiline"))
return new ITextArea();
else if(uidl.getBooleanAttribute("secret"))
return new IPasswordField();
return new ITextField();
}
if ("table".equals(tag)) {
else if ("table".equals(tag)) {
if(uidl.hasAttribute("style")) {
if("paging".equals(uidl.getStringAttribute("style")))
return new ITablePaging();
}
return new IScrollTable();
}
if("datefield".equals(tag)) {
else if("datefield".equals(tag)) {
if(uidl.hasAttribute("style"))
if("calendar".equals(uidl.getStringAttribute("style")))
return new ICalendar();
@@ -92,6 +93,8 @@ public class DefaultWidgetFactory implements WidgetFactory {
return new ITextualDate();
return new IPopupCalendar();
}
else if("slider".equals(tag))
return new ISlider();

return new IUnknownComponent();
}

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

@@ -77,6 +77,14 @@ public class UIDL {
return s;
}

public HashSet getStringArrayAttributeAsSet(String string) {
JSONArray a = getArrayVariable(string);
HashSet s = new HashSet();
for (int i = 0; i < a.size(); i++)
s.add(((JSONString) a.get(i)).stringValue());
return s;
}

/**
* Get attributes value as string whateever the type is
*
@@ -296,6 +304,20 @@ public class UIDL {
return (int) t.getValue();
}

public long getLongVariable(String name) {
JSONNumber t = (JSONNumber) getVariableHash().get(name);
if (t == null)
throw new IllegalArgumentException("No such variable: " + name);
return (long) t.getValue();
}
public float getFloatVariable(String name) {
JSONNumber t = (JSONNumber) getVariableHash().get(name);
if (t == null)
throw new IllegalArgumentException("No such variable: " + name);
return (float) t.getValue();
}

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

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

@@ -1,7 +1,13 @@
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;
@@ -9,26 +15,204 @@ import com.itmill.toolkit.terminal.gwt.client.UIDL;
public class ISlider extends Widget implements Paintable {
public static final String CLASSNAME = "i-slider";
ApplicationConnection client;
String id;
private boolean immediate;
private boolean disabled;
private boolean readonly;
private int handleSize;
private float min;
private float max;
private int resolution;
private Object value;
private HashSet values;
private boolean vertical;
private int size = -1;
/* DOM element for slider's base */
private Element base;
/* DOM element for slider's handle */
private Element handle;
private boolean dragging;
public ISlider() {
super();
setElement(DOM.createElement("div"));
base = DOM.createElement("div");
DOM.appendChild(getElement(), base);
handle = DOM.createElement("div");
DOM.appendChild(base, handle);
setElement(base);
setStyleName(CLASSNAME);
DOM.setAttribute(base, "className", CLASSNAME+"-base");
DOM.setAttribute(handle, "className", CLASSNAME+"-handle");
DOM.sinkEvents(base, Event.MOUSEEVENTS);
DOM.sinkEvents(handle, Event.MOUSEEVENTS);
}
public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
this.client = client;
// Ensure correct implementation (handle own caption)
if (client.updateComponent(this, uidl, false))
return;
immediate = uidl.getBooleanAttribute("immediate");
disabled = uidl.getBooleanAttribute("disabled");
readonly = uidl.getBooleanAttribute("readonly");
vertical = uidl.hasAttribute("vertical");
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;
}
handleSize = uidl.getIntAttribute("hsize");
if(uidl.hasAttribute("size"))
size = uidl.getIntAttribute("size");
buildBase();
if(!vertical) {
// Draw handle with a delay to allow base to gain maximum width
Timer delay = new Timer() {
public void run() {
buildHandle();
setHandlePosition(value);
}
};
delay.schedule(100);
} else {
buildHandle();
setHandlePosition(value);
}
}
private void buildBase() {
if(vertical) {
if(size > -1)
DOM.setStyleAttribute(base, "height", size + "px");
else DOM.setStyleAttribute(base, "height", "120px");
} else {
if(size > -1)
DOM.setStyleAttribute(base, "width", size + "px");
else DOM.setStyleAttribute(base, "width", "100%");
}
// Allow absolute positioning of handle
DOM.setStyleAttribute(base, "position", "relative");
// TODO attach listeners for clicking on base, focusing and arrow keys
}
private void buildHandle() {
// Allow absolute positioning
DOM.setStyleAttribute(handle, "position", "absolute");
if(vertical) {
// TODO
} else {
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);
DOM.setStyleAttribute(handle, "width", w+"px");
}
}
private void setHandlePosition(Object value) {
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);
}
}
this.value = value;
}
public void onBrowserEvent(Event event) {
if(DOM.compare(DOM.eventGetTarget(event), handle))
processHandleEvent(event);
else
processBaseEvent(event);
super.onBrowserEvent(event);
}
private void processHandleEvent(Event event) {
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEDOWN:
client.console.log("Slider handle: mousedown");
if(!disabled && !readonly) {
dragging = true;
DOM.setCapture(handle);
DOM.eventPreventDefault(event); // prevent selecting text
}
break;
case Event.ONMOUSEMOVE:
if (dragging) {
client.console.log("Slider handle: dragging...");
int x = DOM.eventGetClientX(event);
int y = DOM.eventGetClientY(event);
if(vertical) {
// TODO
} else {
if(values == null) {
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
}
}
}
break;
case Event.ONMOUSEUP:
dragging = false;
DOM.releaseCapture(handle);
break;
default:
break;
}
}
private void processBaseEvent(Event event) {
// TODO
super.onBrowserEvent(event);
}
}

+ 2
- 1
src/com/itmill/toolkit/terminal/gwt/public/component-themes/collection.css View File

@@ -4,4 +4,5 @@
@import "panel/css/panel.css";
@import "tabsheet/css/tabsheet.css";
@import "datefield/css/datefield.css";
@import "table/css/table.css";
@import "table/css/table.css";
@import "slider/css/slider.css";

+ 11
- 0
src/com/itmill/toolkit/terminal/gwt/public/component-themes/slider/css/slider.css View File

@@ -0,0 +1,11 @@
.i-slider {
}
.i-slider-base {
background: #eee;
}
.i-slider-handle {
background: #ccc;
}

+ 83
- 14
src/com/itmill/toolkit/terminal/gwt/server/JsonPaintTarget.java View File

@@ -28,6 +28,13 @@

package com.itmill.toolkit.terminal.gwt.server;

import java.io.PrintWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;

import com.itmill.toolkit.Application;
import com.itmill.toolkit.terminal.ApplicationResource;
import com.itmill.toolkit.terminal.ExternalResource;
@@ -36,22 +43,8 @@ import com.itmill.toolkit.terminal.PaintTarget;
import com.itmill.toolkit.terminal.Paintable;
import com.itmill.toolkit.terminal.Resource;
import com.itmill.toolkit.terminal.ThemeResource;
import com.itmill.toolkit.terminal.UploadStream;
import com.itmill.toolkit.terminal.VariableOwner;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Set;
import java.util.Stack;
import java.util.Vector;

/**
* User Interface Description Language Target.
*
@@ -423,6 +416,22 @@ public class JsonPaintTarget implements PaintTarget {
public void addAttribute(String name, long 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, float value) throws PaintException {
tag.addAttribute("\"" + name + "\":" + String.valueOf(value));
}

/**
* Adds a string attribute to component. Atributes must be added before any
@@ -505,6 +514,40 @@ public class JsonPaintTarget implements PaintTarget {
throws PaintException {
tag.addVariable(new IntVariable(owner, name, value));
}
/**
* Adds a long 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, long value) throws PaintException {
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, float value) throws PaintException {
tag.addVariable(new FloatVariable(owner, name, value));
}

/**
* Adds a boolean type variable.
@@ -928,6 +971,32 @@ public class JsonPaintTarget implements PaintTarget {
return "\"" + name + "\":" + value;
}
}
class LongVariable extends Variable {
long value;

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

public String getJsonPresentation() {
return "\"" + name + "\":" + value;
}
}
class FloatVariable extends Variable {
float value;

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

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

class ArrayVariable extends Variable {
String[] value;

+ 172
- 89
src/com/itmill/toolkit/ui/Slider.java View File

@@ -1,74 +1,95 @@
package com.itmill.toolkit.ui;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import com.itmill.toolkit.event.Action;
import com.itmill.toolkit.event.ShortcutAction;
import com.itmill.toolkit.terminal.PaintException;
import com.itmill.toolkit.terminal.PaintTarget;
import com.itmill.toolkit.ui.Button.ClickEvent;
public class Slider extends AbstractComponent {
public class Slider extends AbstractField {
public static final int ORIENTATION_HORIZONTAL = 0;
public static final int ORIENTATION_VERTICAL = 1;
/* Minimum value of slider */
private int min = 0;
/* Maximum value of slider */
private int max = 100;
/** Minimum value of slider */
private float min = 0;
/** Maximum value of slider */
private float max = 100;
/* Resolution, how many digits are considered relevant after desimal point */
private int resolution = 2;
/* Current value */
private Object value;
/**
* Resolution, how many digits are considered relevant after desimal point.
* Must be a non-negative value
*/
private int resolution = 0;
/* Object values for slider in stead of numeric.
/**
* Object values for slider in stead of numeric (usually strings).
* If this is set, min, max and resolution values are ignored.
*/
private Object[] values;
private Set values;
/**
* Slider orientation (horizontal==default/vertical).
*/
private int orientation = ORIENTATION_HORIZONTAL;
private List listeners;
/**
* Slider size in pixels.
* In horizontal mode if set to -1, allow 100% with container.
* In vertical mode if set to -1, default height 120 pixels.
*/
private int size = -1;
private int width;
private int height;
/**
* Handle size in percents related to base size.
* Must be a value between 1-100.
*/
private int handleSize = 20;
public Object getValue() {
return value;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
public Slider() {
super();
super.setValue(new Float(min));
}
public int getMax() {
public float getMax() {
return max;
}
public void setMax(int max) {
/**
* Set the maximum value of the Slider. As a side-effect nullifies the "values" Set.
* @param max
*/
public void setMax(float 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));
}
requestRepaint();
}
public int getMin() {
public float getMin() {
return min;
}
public void setMin(int min) {
/**
* Set the minimum value of the Slider. As a side-effect nullifies the "values" Set.
* @param max
*/
public void setMin(float min) {
this.min = min;
this.values = null;
try {
if((new Float(getValue().toString())).floatValue() < min)
super.setValue(new Float(min));
} catch(ClassCastException e) {
super.setValue(new Float(min));
}
requestRepaint();
}
public int getOrientation() {
@@ -77,6 +98,7 @@ public class Slider extends AbstractComponent {
public void setOrientation(int orientation) {
this.orientation = orientation;
requestRepaint();
}
public int getResolution() {
@@ -84,48 +106,107 @@ public class Slider extends AbstractComponent {
}
public void setResolution(int resolution) {
if(resolution < 0)
return;
this.resolution = resolution;
requestRepaint();
}
public Object[] getValues() {
public Set getValues() {
return values;
}
public void setValues(Object[] values) {
public void setValues(Set values) {
this.values = values;
requestRepaint();
}
public int getWidth() {
return width;
public void setValue(Float value, boolean repaintIsNotNeeded) throws ValueOutOfBoundsException {
float v = new Float(value.toString()).floatValue();
Object 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())
throw new ValueOutOfBoundsException(value);
} else {
newValue = new Float((int) v);
if(min > ((Float)newValue).intValue() || max < ((Float)newValue).intValue())
throw new ValueOutOfBoundsException(value);
}
super.setValue(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 {
setValue(value, false);
}
public void setWidth(int width) {
this.width = width;
public int getSize() {
return size;
}
public List getListeners() {
return listeners;
public void setSize(int size) {
this.size = size;
requestRepaint();
}
public void addListener(SlideListener l) {
addListener(SlideEvent.class, l, SLIDER_SLIDE_METHOD);
public int getHandleSize() {
return handleSize;
}
public void removeListener(SlideListener l) {
removeListener(SlideEvent.class, l, SLIDER_SLIDE_METHOD);
public void setHandleSize(int handleSize) {
if(handleSize > 100 || handleSize < 1)
return;
this.handleSize = handleSize;
requestRepaint();
}
public String getTag() {
return "slider";
}
public interface SlideListener {
public void slide(SlideEvent s);
}
public void paintContent(PaintTarget target) throws PaintException {
super.paintContent(target);
// TODO
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()]));
}
if(orientation == ORIENTATION_VERTICAL)
target.addAttribute("vertical", true);
if(size > -1)
target.addAttribute("size", size);
target.addAttribute("hsize", handleSize);
}
/**
@@ -137,48 +218,50 @@ public class Slider extends AbstractComponent {
*/
public void changeVariables(Object source, Map variables) {
if (variables.containsKey("value")) {
// TODO update value
fireSlide();
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
}
}
}
/* **************************************************
* Event handling classes and methods
*/
public class SlideEvent extends Component.Event {
public SlideEvent(Component source) {
super(source);
}
public Slider getSlider() {
return (Slider) getSource();
}
public class ValueOutOfBoundsException extends Exception {
/**
* Serial generated by Eclipse.
*/
private static final long serialVersionUID = -2092497444591455077L;
private static final long serialVersionUID = -6451298598644446340L;
private Object value;
/**
* Constructs an <code>ValueOutOfBoundsException</code> with the specified
* detail message.
*
* @param valueOutOfBounds
*/
public ValueOutOfBoundsException(Object valueOutOfBounds) {
this.value = valueOutOfBounds;
}
public Object getValue() {
return this.value;
}
}
protected void fireSlide() {
fireEvent(new Slider.SlideEvent(this));
}
/* Slide event ************************************************ */
private static final Method SLIDER_SLIDE_METHOD;
static {
try {
SLIDER_SLIDE_METHOD = SlideListener.class.getDeclaredMethod(
"slide", new Class[] { ClickEvent.class });
} catch (java.lang.NoSuchMethodException e) {
// This should never happen
throw new java.lang.RuntimeException();
}
public Class getType() {
if(values == null)
return Float.class;
return String.class;
}
}

Loading…
Cancel
Save