/*
* Ext GWT - Ext for GWT
* Copyright(c) 2007-2009, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.util;
import java.util.Date;
import com.extjs.gxt.ui.client.core.El;
import com.extjs.gxt.ui.client.event.BaseObservable;
import com.extjs.gxt.ui.client.event.ClickRepeaterEvent;
import com.extjs.gxt.ui.client.event.EventType;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.PreviewEvent;
import com.extjs.gxt.ui.client.widget.ComponentAttachable;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.EventListener;
import com.google.gwt.user.client.Timer;
public class ClickRepeater extends BaseObservable implements ComponentAttachable {
private boolean accelerate;
private int delay = 250;
private El el;
private int interval = 20;
private Date mousedownTime;
private BaseEventPreview preview;
private String pressClass;
private Timer timer;
private boolean waitForMouseOut;
private boolean waitForMouseOver;
public ClickRepeater(El el) {
this.el = el;
preview = new BaseEventPreview() {
protected boolean onPreview(PreviewEvent pe) {
if (pe.getEventTypeInt() == Event.ONMOUSEUP) {
ClickRepeater.this.handleMouseUp();
}
return true;
}
};
preview.setAutoHide(false);
el.addEventsSunk(Event.ONMOUSEDOWN | Event.ONMOUSEOUT | Event.ONMOUSEOVER);
}
public void doAttach() {
DOM.setEventListener(el.dom, new EventListener() {
public void onBrowserEvent(Event event) {
switch (event.getTypeInt()) {
case Event.ONMOUSEDOWN:
handleMouseDown();
break;
case Event.ONMOUSEOUT:
handleMouseOut();
break;
case Event.ONMOUSEOVER:
handleMouseReturn();
break;
}
}
});
el.disableTextSelection(true);
preview.add();
}
public void doDetach() {
DOM.setEventListener(el.dom, null);
el.disableTextSelection(false);
preview.remove();
}
public boolean fireEvent(EventType eventType) {
return fireEvent(eventType, new ClickRepeaterEvent(this, el));
}
public int getDelay() {
return delay;
}
public El getEl() {
return el;
}
public int getInterval() {
return interval;
}
public String getPressClass() {
return pressClass;
}
public boolean isAccelerate() {
return accelerate;
}
public void setAccelerate(boolean accelerate) {
this.accelerate = accelerate;
}
public void setDelay(int delay) {
this.delay = delay;
}
public void setInterval(int interval) {
this.interval = interval;
}
public void setPressClass(String pressClass) {
this.pressClass = pressClass;
}
// private
protected void click() {
fireEvent(Events.OnClick);
timer.schedule(accelerate ? easeOutExpo(new Date().getTime()
- mousedownTime.getTime(), 400, -390, 12000) : interval);
}
protected int easeOutExpo(long t, int b, int c, int d) {
return (int) ((t == d) ? b + c : c * (-Math.pow(2, -10 * t / d) + 1) + b);
}
protected void handleMouseDown() {
if (timer == null) {
timer = new Timer() {
public void run() {
click();
}
};
}
timer.cancel();
el.blur();
if (pressClass != null) {
el.addStyleName(pressClass);
}
mousedownTime = new Date();
waitForMouseOut = true;
fireEvent(Events.OnMouseDown);
fireEvent(Events.OnClick);
// Do not honor delay or interval if acceleration wanted.
if (accelerate) {
delay = 400;
}
timer.schedule(delay);
}
protected void handleMouseUp() {
if (waitForMouseOut) {
timer.cancel();
waitForMouseOut = false;
waitForMouseOver = false;
el.removeStyleName(pressClass);
fireEvent(Events.OnMouseUp);
}
}
protected void handleMouseOut() {
if (waitForMouseOut) {
timer.cancel();
if (pressClass != null) {
el.removeStyleName(pressClass);
}
waitForMouseOver = true;
}
}
protected void handleMouseReturn() {
if (waitForMouseOver) {
waitForMouseOver = false;
if (pressClass != null) {
el.addStyleName(pressClass);
}
click();
}
}
}