/*
Copyright (C) Paul Falstad and Iain Sharp
This file is part of CircuitJS1.
CircuitJS1 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
CircuitJS1 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lushprojects.circuitjs1.client;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.canvas.dom.client.Context2d;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.MouseDownHandler;
import com.google.gwt.event.dom.client.MouseDownEvent;
import com.google.gwt.event.dom.client.MouseMoveHandler;
import com.google.gwt.event.dom.client.MouseMoveEvent;
import com.google.gwt.event.dom.client.MouseUpHandler;
import com.google.gwt.event.dom.client.MouseUpEvent;
import com.google.gwt.event.dom.client.MouseOutEvent;
import com.google.gwt.event.dom.client.MouseOutHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Event;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.CanvasElement;
import com.google.gwt.dom.client.Touch;
import com.google.gwt.event.dom.client.MouseWheelEvent;
import com.google.gwt.event.dom.client.MouseWheelHandler;
import com.google.gwt.event.dom.client.TouchCancelEvent;
import com.google.gwt.event.dom.client.TouchCancelHandler;
import com.google.gwt.event.dom.client.TouchEndEvent;
import com.google.gwt.event.dom.client.TouchEndHandler;
import com.google.gwt.event.dom.client.TouchMoveEvent;
import com.google.gwt.event.dom.client.TouchMoveHandler;
import com.google.gwt.event.dom.client.TouchStartEvent;
import com.google.gwt.event.dom.client.TouchStartHandler;
public class Scrollbar extends Composite implements
ClickHandler, MouseDownHandler, MouseMoveHandler, MouseUpHandler, MouseOutHandler, MouseOverHandler,
MouseWheelHandler, TouchStartHandler, TouchCancelHandler, TouchEndHandler, TouchMoveHandler {
static int HORIZONTAL =1;
static int HMARGIN=2;
static int SCROLLHEIGHT=14;
static int BARWIDTH=3;
static int BARMARGIN=3;
Canvas can;
VerticalPanel pan;
Context2d g;
int min;
int max;
int val;
boolean dragging=false;
boolean enabled=true;
Command command=null;
CircuitElm attachedElm=null;
public Scrollbar(int orientation, int value, int visible, int minimum, int maximum) {
min=minimum;
max=maximum-1;
val=value;
pan = new VerticalPanel();
can = Canvas.createIfSupported();
can.setWidth((CirSim.VERTICALPANELWIDTH)+" px");
can.setHeight("40 px");
can.setCoordinateSpaceWidth(CirSim.VERTICALPANELWIDTH);
can.setCoordinateSpaceHeight(SCROLLHEIGHT);
pan.add(can);
g=can.getContext2d();
g.setFillStyle("#ffffff");
can.addClickHandler( this);
can.addMouseDownHandler(this);
can.addMouseUpHandler(this);
can.addMouseMoveHandler(this);
can.addMouseOutHandler(this);
can.addMouseOverHandler(this);
can.addMouseWheelHandler(this);
// our hack from CirSim doesn't work here so we have to handle touch events explicitly
can.addTouchStartHandler(this);
can.addTouchMoveHandler(this);
can.addTouchEndHandler(this);
can.addTouchCancelHandler(this);
this.draw();
initWidget(pan);
}
public Scrollbar(int orientation, int value, int visible, int minimum, int maximum,
Command cmd, CircuitElm e) {
this(orientation,value,visible,minimum,maximum);
this.command=cmd;
attachedElm=e;
}
// public Scrollbar(int orientation, int value, int visible, int minimum, int maximum, Command cmd) {
// this(orientation, value, visible, minimum, maximum);
// this.command=cmd;
// }
void draw() {
if (enabled)
g.setStrokeStyle("#000000");
else
g.setStrokeStyle("lightgrey");
g.setLineWidth(1.0);
g.fillRect(0,0,CirSim.VERTICALPANELWIDTH,SCROLLHEIGHT);
g.beginPath();
g.moveTo(HMARGIN+SCROLLHEIGHT-3, 0);
g.lineTo(HMARGIN, SCROLLHEIGHT/2);
g.lineTo(HMARGIN+SCROLLHEIGHT-3, SCROLLHEIGHT);
g.moveTo(CirSim.VERTICALPANELWIDTH-HMARGIN-SCROLLHEIGHT+3, 0);
g.lineTo(CirSim.VERTICALPANELWIDTH-HMARGIN, SCROLLHEIGHT/2);
g.lineTo(CirSim.VERTICALPANELWIDTH-HMARGIN-SCROLLHEIGHT+3, SCROLLHEIGHT);
g.stroke();
if (enabled)
g.setStrokeStyle("grey");
g.beginPath();
g.setLineWidth(5.0);
g.moveTo(HMARGIN+SCROLLHEIGHT+BARMARGIN, SCROLLHEIGHT/2);
g.lineTo(CirSim.VERTICALPANELWIDTH-HMARGIN-SCROLLHEIGHT-BARMARGIN, SCROLLHEIGHT/2);
g.stroke();
double p=HMARGIN+SCROLLHEIGHT+BARMARGIN+((CirSim.VERTICALPANELWIDTH-2*(HMARGIN+SCROLLHEIGHT+BARMARGIN))*((double)(val-min)))/(max-min);
if (enabled) {
if (attachedElm!=null && attachedElm.needsHighlight())
g.setStrokeStyle("cyan");
else
g.setStrokeStyle("red");
g.beginPath();
g.moveTo(HMARGIN+SCROLLHEIGHT+BARMARGIN, SCROLLHEIGHT/2);
g.lineTo(p, SCROLLHEIGHT/2);
g.stroke();
g.setStrokeStyle("#000000");
// g.beginPath();
// g.moveTo(p, 0);
// g.lineTo(p, SCROLLHEIGHT);
g.setLineWidth(2.0);
g.fillRect(p-2, 2, 5, SCROLLHEIGHT-4);
g.strokeRect(p-2, 2, 5, SCROLLHEIGHT-4);
// g.stroke();
}
}
int calcValueFromPos(int x){
int v;
v= min+(max-min)*(x-HMARGIN-SCROLLHEIGHT-BARMARGIN)/(CirSim.VERTICALPANELWIDTH-2*(HMARGIN+SCROLLHEIGHT+BARMARGIN));
if (v<min)
v=min;
if (v>max)
v=max;
return v;
}
public void onMouseDown(MouseDownEvent e){
// GWT.log("Down");
dragging=false;
e.preventDefault();
doMouseDown(e.getX(), true);
}
void doMouseDown(int x, boolean mouse) {
if (enabled){
if (x < HMARGIN+SCROLLHEIGHT ) {
if (val>min)
val--;
}
else {
if (x > CirSim.VERTICALPANELWIDTH-HMARGIN-SCROLLHEIGHT ) {
if (val<max)
val++;
}
else {
val=calcValueFromPos(x);
dragging=true;
// setCapture doesn't work on touch for some reason; touchend/touchmoved events
// don't get sent
if (mouse)
Event.setCapture(can.getElement());
}
}
draw();
if (command!=null)
command.execute();
}
}
public void onMouseMove(MouseMoveEvent e){
// GWT.log("Move");
e.preventDefault();
doMouseMove(e.getX());
}
void doMouseMove(int x) {
if (enabled) {
if (dragging) {
val=calcValueFromPos(x);
draw();
if (command!=null)
command.execute();
}
}
}
public void onMouseUp(MouseUpEvent e){
// GWT.log("Up");
e.preventDefault();
Event.releaseCapture(can.getElement());
if (enabled && dragging) {
val=calcValueFromPos(e.getX());
dragging=false;
draw();
if (command!=null)
command.execute();
}
}
public void onMouseOut(MouseOutEvent e){
// GWT.log("Out");
// e.preventDefault();
if (dragging)
return;
if (enabled && attachedElm!=null && attachedElm.isMouseElm())
CircuitElm.sim.setMouseElm(null);
}
public void onMouseOver(MouseOverEvent e){
if (enabled && attachedElm!=null)
CircuitElm.sim.setMouseElm(attachedElm);
}
public void onMouseWheel(MouseWheelEvent e) {
e.preventDefault();
if (enabled)
setValue(val+e.getDeltaY()/3);
}
public void onClick(ClickEvent e) {
// GWT.log("Click");
e.preventDefault();
// if (e.getX()<HMARGIN+SCROLLHEIGHT ) {
// if (val>min)
// val--;
// }
// else {
// if (e.getX()>CirSim.VERTICALPANELWIDTH-HMARGIN-SCROLLHEIGHT ) {
// if (val<max)
// val++;
// }
// else {
// val=calcValueFromPos(e.getX()); }
// }
// draw();
}
public int getValue(){
return val;
}
public void setValue(int i){
if (i<min)
i=min;
else if (i>max)
i=max;
val =i;
draw();
if (command!=null)
command.execute();
}
public void enable() {
enabled=true;
draw();
}
public void disable() {
enabled=false;
dragging=false;
draw();
}
public void onTouchMove(TouchMoveEvent e) {
// GWT.log("touchmove");
e.preventDefault();
Touch t = e.getTouches().get(0);
doMouseMove(t.getRelativeX(getElement()));
}
public void onTouchEnd(TouchEndEvent event) {
// GWT.log("touchend");;
event.preventDefault();
if (enabled && dragging) {
dragging=false;
draw();
if (command!=null)
command.execute();
}
}
public void onTouchCancel(TouchCancelEvent event) {
// GWT.log("touchcancel");;
event.preventDefault();
dragging = false;
}
public void onTouchStart(TouchStartEvent event) {
// GWT.log("touchstart");
event.preventDefault();
dragging=false;
Touch t = event.getTouches().get(0);
doMouseDown(t.getRelativeX(getElement()), false);
}
}