/*
* Copyright 2008 Jeff Dwyer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.apress.progwt.client.calculator;
import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Widget;
public class GUIEffects {
private abstract class GUITimer extends Timer {
public static final int FREQ = 100;
private int curStep;
private Element element;
private int steps;
public GUITimer(Widget widget, int steps) {
this.element = widget.getElement();
this.steps = steps;
curStep = 0;
}
protected abstract void doStep(double pct);
public Element getElement() {
return element;
}
public int getSteps() {
return steps;
}
@Override
public void run() {
doStep(curStep / (double) steps);
curStep++;
if (curStep > steps) {
cancel();
} else {
schedule(FREQ);
}
}
}
private class MoveTimer extends GUITimer {
private int curX;
private int curY;
private int dx;
private int dy;
public MoveTimer(Widget widget, int x, int y, int steps) {
super(widget, steps);
this.dx = x / steps;
this.dy = y / steps;
this.curX = DOM.getIntStyleAttribute(getElement(), "left");
this.curY = DOM.getIntStyleAttribute(getElement(), "top");
}
protected void doStep(double pct) {
DOM.setIntStyleAttribute(getElement(), "left", curX);
DOM.setIntStyleAttribute(getElement(), "top", curY);
curX += dx;
curY += dy;
}
}
private class OpacityTimer extends GUITimer {
private double diff;
private double start;
public OpacityTimer(Widget widget, double from, double to,
int steps) {
super(widget, steps);
this.start = from;
this.diff = to - from;
}
protected void doStep(double pct) {
double cur = pct * diff + start;
String ieStr = "alpha(opacity = " + (int) (cur * 100) + ")";
DOM.setStyleAttribute(getElement(), "filter", ieStr);
DOM.setStyleAttribute(getElement(), "-moz-opacity", cur + "");
DOM.setStyleAttribute(getElement(), "opacity", cur + "");
DOM.setStyleAttribute(getElement(), "-khtml-opacity", cur
+ "");
}
}
private static final int HIGHLIGHT_DURATION = 1000;
private static GUIEffects singleInstance = new GUIEffects();
/**
*
* @param toAppear
* @param duration
*/
public static void appear(Widget toAppear, int duration) {
opacity(toAppear, .1, 1.0, duration);
}
/**
* Hook into the native close method.
*
* NOTE some eclipse styling errors will occur when these comments
* begin on the close() line. Each time we save the file, it will push
* the native code to the right.
*/
public static native void close()/*-{
$wnd.close();
}-*/;
public static void fade(Widget w, int duration) {
opacity(w, 1.0, 0.0, duration);
}
public static void fadeAndRemove(Widget w, int removeInX) {
fade(w, 500);
removeInXMilSecs(w, removeInX);
}
/**
* Utility to fade & remove a widget after a short time using 2 timers
*
* @param w
* @param i
*/
public static void fadeAndRemove(final Widget w, int fadeInX,
int removeInX) {
fade(w, fadeInX);
removeInXMilSecs(w, removeInX);
}
/**
* highligh from FFFE7F to FFFFFF
*
* @param toHighlight
*/
public static void highlight(Widget toHighlight) {
highlight(toHighlight, "FF", "FE", "7F", "FF", "FF", "FF");
}
private static void highlight(Widget toHighlight, String sR,
String sG, String sB, String eR, String eG, String eB) {
highlight(toHighlight, Integer.parseInt(sR, 16), Integer
.parseInt(sG, 16), Integer.parseInt(sB, 16), Integer
.parseInt(eR, 16), Integer.parseInt(eG, 16), Integer
.parseInt(eB, 16), HIGHLIGHT_DURATION);
}
/**
* highlight from start color to end color
*
* @param toHighlight -
* the Widget to highlight
* @param startColor -
* start color such as "FFFE7F" note no leading #
* @param endColor -
* end color such as "FFFFFF" note no leading #
*/
public static void highlight(Widget toHighlight, String startColor,
String endColor) {
Log.debug("start color: " + startColor);
Log.debug("end color: " + endColor);
final int startR = Integer.parseInt(startColor.substring(0, 2),
16);
final int endR = Integer.parseInt(endColor.substring(0, 2), 16);
final int startG = Integer.parseInt(startColor.substring(2, 4),
16);
final int endG = Integer.parseInt(endColor.substring(2, 4), 16);
final int startB = Integer.parseInt(startColor.substring(4, 6),
16);
final int endB = Integer.parseInt(endColor.substring(4, 6), 16);
highlight(toHighlight, startR, startG, startB, endR, endG, endB,
HIGHLIGHT_DURATION);
}
/**
* Highlight with rgb parameters split out. To get a smooth transition
* we must move each color element individually
*
* @param toHighlight
* @param startR
* @param startG
* @param startB
* @param endR
* @param endG
* @param endB
*/
public static void highlight(Widget toHighlight, final int startR,
final int startG, final int startB, int endR, int endG,
int endB, int duration) {
int steps = duration / MoveTimer.FREQ;
final int diffR = endR - startR;
final int diffG = endG - startG;
final int diffB = endB - startB;
GUITimer mover = singleInstance.new GUITimer(toHighlight, steps) {
@Override
protected void doStep(double pct) {
int cR = (int) (startR + diffR * pct);
int cG = (int) (startG + diffG * pct);
int cB = (int) (startB + diffB * pct);
StringBuffer sb = new StringBuffer("#");
sb.append(Integer.toHexString(cR));
sb.append(Integer.toHexString(cG));
sb.append(Integer.toHexString(cB));
// note NOT background-color. the '-' in style names
// breaks.
DOM.setStyleAttribute(getElement(), "backgroundColor", sb
.toString());
}
};
mover.schedule(100);
}
/**
* options are not safe in Hosted GWT
*
* @param toMove
* @param i
* @param x
* @param cloud_move_sec
*/
public static void move(Widget toMove, int x, int y, int duration) {
int steps = duration / MoveTimer.FREQ;
MoveTimer mover = singleInstance.new MoveTimer(toMove, x, y,
steps);
mover.schedule(100);
}
public static void opacity(Widget widget, double from, double to,
int duration) {
int steps = duration / OpacityTimer.FREQ;
OpacityTimer opacity = singleInstance.new OpacityTimer(widget,
from, to, steps);
opacity.schedule(100);
}
/**
* Utility to remove a widget after a short time, for instance after
* we Effect.fade()
*
* @param w
* @param i
*/
public static void removeInXMilSecs(final Widget w, int i) {
Timer t = new Timer() {
public void run() {
w.removeFromParent();
}
};
t.schedule(i);
}
}