--- /dev/null
+/*
+ * Copyright 2011, The gwtquery team.
+ *
+ * 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.google.gwt.query.client.plugins.effects;
+
+import com.google.gwt.core.client.GWT;
+import com.google.gwt.dom.client.Element;
+import com.google.gwt.query.client.GQuery;
+import com.google.gwt.query.client.css.BorderColorProperty;
+import com.google.gwt.query.client.css.CSS;
+import com.google.gwt.query.client.css.RGBColor;
+import com.google.gwt.query.client.js.JsNamedArray;
+import com.google.gwt.query.client.js.JsObjectArray;
+import com.google.gwt.query.client.js.JsRegexp;
+import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Effect;
+
+public class ColorEffect extends Effect {
+
+ /**
+ * Specific class handle specific borderColor shortcut properties
+ *
+ */
+ public static class BorderColorEffect extends ColorEffect {
+
+ private static BorderColorProperty[] borderColorProperties = {
+ CSS.BORDER_BOTTOM_COLOR, CSS.BORDER_TOP_COLOR, CSS.BORDER_LEFT_COLOR,
+ CSS.BORDER_RIGHT_COLOR};
+ private JsNamedArray<int[]> startColors;
+
+
+ public BorderColorEffect(Element e, String endColorString) {
+
+ endColor = parseColor(endColorString);
+ startColors = JsNamedArray.create();
+
+ GQuery $e = GQuery.$(e);
+
+ for (BorderColorProperty border : borderColorProperties){
+ int[] startColor = parseColor($e.css(border, true));
+ startColors.put(border.getCssName(), startColor);
+ }
+ }
+
+
+ @Override
+ public void applyValue(GQuery g, double progress) {
+ for (BorderColorProperty border : borderColorProperties){
+ startColor = startColors.get(border.getCssName());
+ attr = border.getCssName();
+ super.applyValue(g, progress);
+ }
+ }
+ }
+
+ // hexadecimal regex
+ private static JsRegexp HEXADECIMAL_COLOR_PATTERN = new JsRegexp(
+ "#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})");
+ private static JsNamedArray<int[]> htmlColorToRgb;
+
+ // rgb and rgba regex
+ private static JsRegexp RGB_COLOR_PATTERN = new JsRegexp(
+ "rgba?\\(\\s*([0-9]{1,3}%?)\\s*,\\s*([0-9]{1,3}%?)\\s*,\\s*([0-9]{1,3}%?).*\\)$");
+
+ static {
+ htmlColorToRgb = JsNamedArray.create();
+ htmlColorToRgb.put("white", new int[]{255, 255, 255});
+ htmlColorToRgb.put("aqua", new int[]{0, 255, 255});
+ htmlColorToRgb.put("azure", new int[]{240, 255, 255});
+ htmlColorToRgb.put("beige", new int[]{245, 245, 220});
+ htmlColorToRgb.put("black", new int[]{0, 0, 0});
+ htmlColorToRgb.put("blue", new int[]{0, 0, 255});
+ htmlColorToRgb.put("brown", new int[]{165, 42, 42});
+ htmlColorToRgb.put("cyan", new int[]{0, 255, 255});
+ htmlColorToRgb.put("darkblue", new int[]{0, 0, 139});
+ htmlColorToRgb.put("darkcyan", new int[]{0, 139, 139});
+ htmlColorToRgb.put("darkgrey", new int[]{169, 169, 169});
+ htmlColorToRgb.put("darkgreen", new int[]{0, 100, 0});
+ htmlColorToRgb.put("darkkhaki", new int[]{189, 183, 107});
+ htmlColorToRgb.put("darkmagenta", new int[]{139, 0, 139});
+ htmlColorToRgb.put("darkolivegreen", new int[]{85, 107, 47});
+ htmlColorToRgb.put("darkorange", new int[]{255, 140, 0});
+ htmlColorToRgb.put("darkorchid", new int[]{153, 50, 204});
+ htmlColorToRgb.put("darkred", new int[]{139, 0, 0});
+ htmlColorToRgb.put("darksalmon", new int[]{233, 150, 122});
+ htmlColorToRgb.put("darkviolet", new int[]{148, 0, 211});
+ htmlColorToRgb.put("fuchsia", new int[]{255, 0, 255});
+ htmlColorToRgb.put("gold", new int[]{255, 215, 0});
+ htmlColorToRgb.put("green", new int[]{0, 128, 0});
+ htmlColorToRgb.put("indigo", new int[]{75, 0, 130});
+ htmlColorToRgb.put("khaki", new int[]{240, 230, 140});
+ htmlColorToRgb.put("lightblue", new int[]{173, 216, 230});
+ htmlColorToRgb.put("lightcyan", new int[]{224, 255, 255});
+ htmlColorToRgb.put("lightgreen", new int[]{144, 238, 144});
+ htmlColorToRgb.put("lightgrey", new int[]{211, 211, 211});
+ htmlColorToRgb.put("lightpink", new int[]{255, 182, 193});
+ htmlColorToRgb.put("lightyellow", new int[]{255, 255, 224});
+ htmlColorToRgb.put("lime", new int[]{0, 255, 0});
+ htmlColorToRgb.put("magenta", new int[]{255, 0, 255});
+ htmlColorToRgb.put("maroon", new int[]{128, 0, 0});
+ htmlColorToRgb.put("navy", new int[]{0, 0, 128});
+ htmlColorToRgb.put("olive", new int[]{128, 128, 0});
+ htmlColorToRgb.put("orange", new int[]{255, 165, 0});
+ htmlColorToRgb.put("pink", new int[]{255, 192, 203});
+ htmlColorToRgb.put("purple", new int[]{128, 0, 128});
+ htmlColorToRgb.put("violet", new int[]{128, 0, 128});
+ htmlColorToRgb.put("red", new int[]{255, 0, 0});
+ htmlColorToRgb.put("silver", new int[]{192, 192, 192});
+ htmlColorToRgb.put("white", new int[]{255, 255, 255});
+ htmlColorToRgb.put("yellow", new int[]{255, 255, 0});
+
+ }
+
+ protected int[] endColor;
+ protected int[] startColor;
+
+ ColorEffect(String attr, String startColorString, String endColorString) {
+ assert startColorString != null && endColorString != null;
+ this.attr = attr;
+ startColor = parseColor(startColorString);
+ endColor = parseColor(endColorString);
+ GWT.log("startColorString" + startColorString);
+ };
+
+ private ColorEffect(){}
+
+ @Override
+ public void applyValue(GQuery g, double progress) {
+ int[] result = new int[3];
+ for (int i = 0; i < 3; i++) {
+ int composante = (int) Math.round(startColor[i] + progress
+ * (endColor[i] - startColor[i]));
+ result[i] = Math.max(0, Math.min(255, composante));
+ }
+ String value = RGBColor.rgb(result[0], result[1], result[2]).getCssName();
+
+ g.css(attr, value);
+ }
+
+ public int[] getEndColor() {
+ return endColor;
+ }
+
+ public int[] getStartColor() {
+ return startColor;
+ }
+
+
+ protected int[] parseColor(String color) {
+ JsObjectArray<String> matches = RGB_COLOR_PATTERN.exec(color);
+ if (matches != null) {
+ return parseRGBColor(matches);
+ }
+
+ matches = HEXADECIMAL_COLOR_PATTERN.exec(color);
+ if (matches != null) {
+ return parseHexColor(matches);
+ }
+
+ return parseLiteralColor(color);
+ }
+
+ private int[] parseHexColor(JsObjectArray<String> matches) {
+ assert matches.length() == 2;
+ int[] result = new int[3];
+
+ String hexCode = matches.get(1);
+
+ int step = (hexCode.length() == 3) ? 1 : 2;
+
+ for (int i = 0; i < 3; i++) {
+ String color = hexCode.substring(i * step, (i * step) + step);
+ if (step == 1) {
+ color += color;
+ }
+ result[i] = Math.max(0, Math.min(255, Integer.parseInt(color, 16)));
+
+ }
+
+ return result;
+ }
+
+ private int[] parseLiteralColor(String color) {
+ return htmlColorToRgb.get(color);
+ }
+
+ private int[] parseRGBColor(JsObjectArray<String> matches) {
+ assert matches.length() == 4;
+ int[] result = new int[3];
+
+ for (int i = 1; i < 4; i++) {
+ String valueString = matches.get(i);
+ int value = -1;
+ if (valueString.endsWith("%")) {
+ int percentage = Integer.parseInt(valueString.substring(0,
+ valueString.length() - 1));
+ value = Math.round((float) 2.55 * percentage);
+ } else {
+ value = Integer.parseInt(valueString);
+ }
+ result[i - 1] = Math.max(0, Math.min(255, value));
+ }
+ return result;
+ }
+
+}
\ No newline at end of file
*/\r
package com.google.gwt.query.client.plugins.effects;\r
\r
-import java.util.ArrayList;\r
-\r
import com.google.gwt.animation.client.Animation;\r
import com.google.gwt.dom.client.Element;\r
import com.google.gwt.query.client.Function;\r
import com.google.gwt.query.client.js.JsObjectArray;\r
import com.google.gwt.query.client.js.JsRegexp;\r
import com.google.gwt.query.client.plugins.Effects;\r
+import com.google.gwt.query.client.plugins.effects.ColorEffect.BorderColorEffect;\r
+\r
+import java.util.ArrayList;\r
\r
/**\r
- * Animation effects on any numeric CSS property. \r
+ * Animation effects on any numeric CSS property.\r
*/\r
public class PropertiesAnimation extends Animation {\r
\r
*/\r
public static interface Easing {\r
public double interpolate(double progress);\r
- \r
- public Easing LINEAR = new Easing() { \r
+\r
+ public Easing LINEAR = new Easing() {\r
public double interpolate(double progress) {\r
return progress;\r
}\r
};\r
- \r
- public Easing SWING = new Easing() { \r
+\r
+ public Easing SWING = new Easing() {\r
public double interpolate(double progress) {\r
- return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;\r
+ return (1 + Math.cos(Math.PI + progress * Math.PI)) / 2;\r
}\r
};\r
}\r
- \r
+\r
/**\r
* A pojo to store effect values.\r
*/\r
public static class Effect {\r
-
+\r
public String attr;\r
public double end;\r
public double start;\r
public String unit;\r
public String value;\r
\r
- Effect(String attr, String value, double start, double end,\r
- String unit) {\r
+ Effect() {\r
+ end = start = -1;\r
+ }\r
+\r
+ Effect(String attr, String value, double start, double end, String unit) {\r
this.attr = attr;\r
this.value = value;\r
this.start = start;\r
this.unit = unit;\r
}\r
\r
- public String getVal(double progress) {\r
+ public void applyValue(GQuery g, double progress) {\r
+\r
double ret = (start + ((end - start) * progress));\r
- return ("px".equals(unit) ? ((int) ret) : ret) + unit;\r
+ String value = ("px".equals(unit) ? ((int) ret) : ret) + unit;\r
+\r
+ g.css(attr, value);\r
}\r
- \r
+\r
public String toString() {\r
- return ("attr=" + attr + " value=" + value + " start=" + start + " end=" + end + " unit=" + unit).replaceAll("\\.0([^\\d])", "$1");\r
+ return ("attr=" + attr + " value=" + value + " start=" + start + " end="\r
+ + end + " unit=" + unit).replaceAll("\\.0([^\\d])", "$1");\r
}\r
}\r
- \r
- private static final String[] attrsToSave = new String[] { "overflow",\r
- "visibility" };\r
+\r
+ private static final String[] attrsToSave = new String[]{\r
+ "overflow", "visibility"};\r
\r
private static JsRegexp nonPxRegExp = new JsRegexp(\r
"z-?index|font-?weight|opacity|zoom|line-?height", "i");\r
- \r
- \r
+\r
+ private static JsRegexp colorRegExp = new JsRegexp(".*color$", "i");\r
+ public static JsRegexp RGB_COLOR_PATTERN = new JsRegexp(\r
+ "rgb\\(\\s*([0-9]{1,3}%?)\\s*,\\s*([0-9]{1,3}%?)\\s*,\\s*([0-9]{1,3}%?)\\s*\\)$");\r
+ public static JsRegexp HEXADECIMAL_COLOR_PATTERN = new JsRegexp(\r
+ "^#([a-fA-F0-9]{6}|[a-fA-F0-9]{3})$");\r
+\r
public static Effect computeFxProp(Element e, String key, String val,\r
boolean hidden) {\r
+\r
+ if (colorRegExp.test(key)) {\r
+ return computeFxColorProp(e, key, val);\r
+ }\r
+\r
+ return computeFxNumericProp(e, key, val, hidden);\r
+ }\r
+\r
+ private static Effect computeFxColorProp(Element e, String key, String val) {\r
+\r
+ if ("BORDERCOLOR".equals(key.toUpperCase())) {\r
+ return new BorderColorEffect(e, val);\r
+ }\r
+\r
+ String initialColor = null;\r
+\r
+ if ("BACKGROUNDCOLOR".equals(key.toUpperCase())) {\r
+ // find the first parent having a background-color value (other than\r
+ // transparent)\r
+ Element current = e;\r
+\r
+ while ((initialColor == null || initialColor.length() == 0 || initialColor.equals("transparent"))\r
+ && current != null) {\r
+ initialColor = GQuery.$(current).css(key);\r
+ current = !"body".equalsIgnoreCase(current.getTagName())\r
+ ? current.getParentElement() : null;\r
+ }\r
+ if (initialColor == null || initialColor.length() == 0\r
+ || initialColor.equals("transparent")) {\r
+ initialColor = "white";\r
+ }\r
+ } else {\r
+ initialColor = GQuery.$(e).css(key, true);\r
+ }\r
+\r
+ return new ColorEffect(key, initialColor, val);\r
+ }\r
+\r
+ public static Effect computeFxNumericProp(Element e, String key, String val,\r
+ boolean hidden) {\r
+\r
GQuery g = Effects.$(e);\r
String unit = "";\r
if ("toggle".equals(val)) {\r
val = hidden ? "show" : "hide";\r
}\r
- \r
- if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden){\r
+\r
+ if (("show".equals(val) && !hidden) || ("hide").equals(val) && hidden) {\r
return null;\r
}\r
- \r
- if (hidden){\r
+\r
+ if (hidden) {\r
g.show();\r
}\r
double start = g.cur(key, true), end = start;\r
- \r
+\r
if ("show".equals(val)) {\r
g.saveCssAttrs(key);\r
start = 0;\r
String $2 = parts.get(2);\r
String $3 = parts.get(3);\r
end = Double.parseDouble($2);\r
- unit = nonPxRegExp.test(key) ? "" : $3 == null || $3.isEmpty() ? "px" : $3;\r
+ unit = nonPxRegExp.test(key) ? "" : $3 == null || $3.isEmpty() ? "px"\r
+ : $3;\r
if (!"px".equals(unit)) {\r
double to = end == 0 ? 1 : end;\r
g.css(key, to + unit);\r
}\r
}\r
}\r
- \r
+\r
Effect fx = new Effect(key, val, start, end, unit);\r
return fx;\r
}\r
+\r
private Element e;\r
private Easing easing = Easing.SWING;\r
private ArrayList<Effect> effects = new ArrayList<Effect>();\r
} else if ("show".equals(l.value)) {\r
g.show();\r
g.restoreCssAttrs(l.attr);\r
- } \r
+ }\r
}\r
g.restoreCssAttrs(attrsToSave);\r
g.each(funcs);\r
boolean move = false;\r
boolean hidden = !g.visible();\r
Effect fx;\r
- //g.show();\r
+ // g.show();\r
for (String key : prps.keys()) {\r
String val = prps.getStr(key);\r
if ((fx = computeFxProp(e, key, val, hidden)) != null) {\r
g.css("overflow", "hidden");\r
}\r
if (move && !g.css("position", true).matches("absolute|relative")) {\r
- g.css("position", "relative"); \r
+ g.css("position", "relative");\r
}\r
g.css("visibility", "visible");\r
super.onStart();\r
@Override\r
public void onUpdate(double progress) {\r
for (Effect fx : effects) {\r
- g.css(fx.attr, fx.getVal(progress));\r
+ fx.applyValue(g, progress);\r
+\r
}\r
}\r
\r
@Override\r
protected double interpolate(double progress) {\r
- if (easing != null){\r
+ if (easing != null) {\r
return easing.interpolate(progress);\r
}\r
- //maybe return super.interpolate() instead ?\r
+ // maybe return super.interpolate() instead ?\r
return progress;\r
}\r
\r
import com.google.gwt.junit.client.GWTTestCase;
import com.google.gwt.query.client.GQuery.Offset;
import com.google.gwt.query.client.plugins.Effects;
+import com.google.gwt.query.client.plugins.effects.ColorEffect;
import com.google.gwt.query.client.plugins.effects.PropertiesAnimation;
import com.google.gwt.query.client.plugins.effects.PropertiesAnimation.Easing;
import com.google.gwt.user.client.Timer;
.toString());
}
+ public void testColorEffectParsing(){
+ String html = "<div id='test' style='color: #112233'>Test</div>";
+ $(e).html(html);
+
+ ColorEffect effect = (ColorEffect) PropertiesAnimation.computeFxProp($("#test",e).get(0), "color", "#ffffff", false);
+ assertEquals(17, effect.getStartColor()[0]); //#11
+ assertEquals(34, effect.getStartColor()[1]); //#22
+ assertEquals(51, effect.getStartColor()[2]); //#33
+
+ assertEquals(255, effect.getEndColor()[0]);
+ assertEquals(255, effect.getEndColor()[1]);
+ assertEquals(255, effect.getEndColor()[2]);
+
+ effect = (ColorEffect) PropertiesAnimation.computeFxProp(e, "color", "rgb(255,255,255)", false);
+ assertEquals(255, effect.getEndColor()[0]);
+ assertEquals(255, effect.getEndColor()[1]);
+ assertEquals(255, effect.getEndColor()[2]);
+
+ effect = (ColorEffect) PropertiesAnimation.computeFxProp(e, "color", "rgb(100%, 100%, 100%)", false);
+ assertEquals(255, effect.getEndColor()[0]);
+ assertEquals(255, effect.getEndColor()[1]);
+ assertEquals(255, effect.getEndColor()[2]);
+
+ effect = (ColorEffect) PropertiesAnimation.computeFxProp(e, "color", "white", false);
+ assertEquals(255, effect.getEndColor()[0]);
+ assertEquals(255, effect.getEndColor()[1]);
+ assertEquals(255, effect.getEndColor()[2]);
+ }
+
private void assertPosition(GQuery g, Offset min, Offset max) {
int a = Math.min(min.top, max.top);
int b = Math.max(min.top, max.top);
+ " - " + b;
assertTrue(msg, c);
}
-
+
}