package com.akjava.gwt.html5.client; import java.util.ArrayList; import java.util.List; import com.google.gwt.canvas.client.Canvas; import com.google.gwt.dom.client.Element; import com.google.gwt.editor.client.LeafValueEditor; import com.google.gwt.editor.client.adapters.TakesValueEditor; import com.google.gwt.event.dom.client.MouseDownEvent; import com.google.gwt.event.dom.client.MouseDownHandler; import com.google.gwt.event.dom.client.MouseMoveEvent; import com.google.gwt.event.dom.client.MouseMoveHandler; import com.google.gwt.event.dom.client.MouseOutEvent; import com.google.gwt.event.dom.client.MouseOutHandler; import com.google.gwt.event.dom.client.MouseUpEvent; import com.google.gwt.event.dom.client.MouseUpHandler; public class CanvasInputRange extends InputRangeWidget implements IInputRange{ private Canvas canvas; private int width; private int height; private int min=0; private int max=100; private int value=0; private boolean mousePressed; private boolean mouseObscure; private int pointX; private int margin=8; private String pressedColor="#eee"; private String defaultColor="#fff"; private boolean enabled=true; public void setSize(int w,int h){ width=w; height=h; canvas.setCoordinateSpaceWidth(w); canvas.setCoordinateSpaceHeight(h); canvas.setSize(w+"px", h+"px"); } @Override public void setSize(String width, String height) { setWidth(width); setHeight(height); } @Override public void setWidth(String width){ super.setWidth(width); if(width.endsWith("px")){ try{ int w=Integer.parseInt(width.substring(0,width.length()-2)); setWidth(w); }catch(Exception e){} } } @Override public void setHeight(String height){ super.setHeight(height); if(height.endsWith("px")){ try{ int h=Integer.parseInt(height.substring(0,height.length()-2)); setHeight(h); }catch(Exception e){} } } public CanvasInputRange(){ this(0,100,0); } public CanvasInputRange(int min,int max,int current){ super(); this.width=130; this.height=26; this.min=min; this.max=max; this.value=current; canvas=Canvas.createIfSupported(); canvas.setCoordinateSpaceWidth(width); canvas.setCoordinateSpaceHeight(height); canvas.setSize(width+"px", height+"px"); add(canvas); /* canvas.addClickHandler(new ClickHandler() { @Override public void onClick(ClickEvent event) { if(!enabled){ return; } pointX=event.getX(); update(); } }); */ canvas.addMouseUpHandler(new MouseUpHandler() { @Override public void onMouseUp(MouseUpEvent event) { if(!enabled){ return; } mousePressed=false; mouseObscure=false; canvas.setFocus(false); } }); canvas.addMouseDownHandler(new MouseDownHandler() { @Override public void onMouseDown(MouseDownEvent event) { if(!enabled){ return; } mousePressed=true; pointX=event.getX(); update();//for value change before mouse up; } }); canvas.addMouseMoveHandler(new MouseMoveHandler() { @Override public void onMouseMove(MouseMoveEvent event) { if(!enabled){ return; } if(!mousePressed){ int x=event.getX(); if(mouseObscure && (x<8 ||x>canvas.getCoordinateSpaceWidth()-8)){ return; }else{ return; } } pointX=event.getX(); update(); if(pointX<margin){ mousePressed=false; mouseObscure=false; canvas.setFocus(false); } if(pointX>canvas.getCoordinateSpaceWidth()-margin){ mousePressed=false; mouseObscure=false; canvas.setFocus(false); } } }); canvas.addMouseOutHandler(new MouseOutHandler() { @Override public void onMouseOut(MouseOutEvent event) { if(!enabled){ return; } mousePressed=false; mouseObscure=true; canvas.setFocus(false); } }); lastValue=current+1; update(current); disableSelectionStart(canvas.getElement()); } public native final static void disableSelectionStart(Element element)/*-{ element.onselectstart = function () { return false; } }-*/; int lastValue; private void update(int value){ this.value=value; int vwidth=canvas.getCoordinateSpaceWidth()-margin*2; int p=(int) (vwidth*getParsent(value)); pointX=margin+p; updateCanvas(); if(value!=lastValue){ fireEvent(); lastValue=value; } } public double getParsent(int value){ int total=max-min; return (double)(value-min)/total; } private int getValueByXPoint(int point){ if(max-min<(width-margin*2)){ int mx=point-margin; double perpixel=(getRealWidth())/(getRealMax()+1); //GWT.log(min+" - "+max+",per:"+perpixel+" "+",realwidth="+getRealWidth()+",realMax="+getRealMax()); int pt=(int) (mx/perpixel); return pt+min; }else{ point-=margin; int maxPoint=canvas.getCoordinateSpaceWidth()-margin*2; double parsent=(double)point/maxPoint; return (int) (parsent*(max-min)+min); } } private int getRealWidth(){ return width-margin*2; } private int getRealMax(){ return max-min; } private void update(){ //updateCanvas(); value=getValueByXPoint(pointX); value=Math.max(value,min); value=Math.min(value,max); update(value); } private void updateCanvas(){ canvas.getContext2d().clearRect(0, 0, width, height); drawLine("#ccc"); String color=enabled?"#000":"#ccc"; drawValue(color,pointX); } private void drawLine(String color){ double middle=canvas.getCoordinateSpaceHeight()/2; canvas.getContext2d().save(); canvas.getContext2d().setStrokeStyle(color); canvas.getContext2d().beginPath(); canvas.getContext2d().moveTo(margin, middle); canvas.getContext2d().lineTo(canvas.getCoordinateSpaceWidth()-margin, middle); canvas.getContext2d().closePath(); canvas.getContext2d().stroke(); canvas.getContext2d().restore(); } private void drawValue(String color,double ptx){ if(ptx<margin){ ptx=margin; } if(ptx>canvas.getCoordinateSpaceWidth()-margin){ ptx=canvas.getCoordinateSpaceWidth()-margin; } double middle=canvas.getCoordinateSpaceHeight()/2; canvas.getContext2d().save(); if(mousePressed){ canvas.getContext2d().setFillStyle(pressedColor); }else{ canvas.getContext2d().setFillStyle(defaultColor); } canvas.getContext2d().setStrokeStyle(color); canvas.getContext2d().beginPath(); canvas.getContext2d().moveTo(ptx, middle+12); canvas.getContext2d().lineTo(ptx-4, middle+4); canvas.getContext2d().lineTo(ptx-4, middle-4); canvas.getContext2d().lineTo(ptx+4, middle-4); canvas.getContext2d().lineTo(ptx+4, middle+4); canvas.getContext2d().lineTo(ptx, middle+12); canvas.getContext2d().closePath(); canvas.getContext2d().fill(); canvas.getContext2d().stroke(); canvas.getContext2d().restore(); } @Override public void setMax(int max) { this.max=max; update(); } @Override public void setMin(int min) { this.min=min; update(); } @Override public void setValue(Integer value) { if(value<getMin()){ value=getMin(); } if(value>getMax()){ value=getMax(); } update(value); } @Override public Integer getValue() { return value; } private List<InputRangeListener> listeners=new ArrayList<InputRangeListener>(); public synchronized void addInputRangeListener(InputRangeListener listener){ listeners.add(listener); } public synchronized void removeInputRangeListener(InputRangeListener listener){ listeners.remove(listener); } public synchronized void fireEvent(){ for(InputRangeListener listener:listeners){ listener.changed(getValue()); } } @Override public void setEnabled(boolean bool) { enabled=bool; updateCanvas(); } @Override public void setWidth(int width) { this.width=width; canvas.setWidth(width+"px"); canvas.setCoordinateSpaceWidth(width); update(getValue()); } @Override public int getMin() { return min; } @Override public int getMax() { return max; } @Override public void setHeight(int height) { this.height=height; canvas.setWidth(height+"px"); canvas.setCoordinateSpaceWidth(height); update(getValue()); } private LeafValueEditor<Integer> editor; @Override public LeafValueEditor<Integer> asEditor() { if (editor == null) { editor = TakesValueEditor.of(this); } return editor; } }