/* * Copyright 2008-2009 Adam Tacy <adam.tacy AT gmail.com> * * 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. */ /* * Copyright 2011 Vancouver Ywebb Consulting Ltd * * 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 org.adamtacy.client.ui.effects.impl; import java.util.HashMap; import java.util.Iterator; import java.util.Vector; import org.adamtacy.client.ui.effects.NEffect; import org.adamtacy.client.ui.effects.RequiresDimensions; import org.adamtacy.client.ui.effects.core.ChangeInterface; import org.adamtacy.client.ui.effects.core.NChangeScalarAction; import org.adamtacy.client.ui.effects.impl.css.StyleImplementation; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Node; import com.google.gwt.dom.client.NodeList; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HasVerticalAlignment; import com.google.gwt.user.client.ui.HasHorizontalAlignment.HorizontalAlignmentConstant; import com.google.gwt.user.client.ui.HasVerticalAlignment.VerticalAlignmentConstant; public class Resize extends NEffect implements RequiresDimensions { static Vector<String> triggerDOM = new Vector<String>(); static public void addToTriggerDOM(String newName){ triggerDOM.add(newName); } static public void addToTriggerDOM(Vector<String> newNames) { triggerDOM.addAll(newNames); } static public void setTriggerDOM(Vector<String> names) { triggerDOM = names; } HashMap<Element, Vector<ChangeInterface>> determinedEffects; Element effectElement; int endX = 0; double endXRatio; int endY = 0; double endYRatio; Vector<String> fontSizes = new Vector<String>(); double fontSizeScalingFactor = 1.2; HorizontalAlignmentConstant horizAlign = HasHorizontalAlignment.ALIGN_LEFT; int standardFontSize = 14; String standardFontUnit = "px"; int standardIndex = 4; int startX = 100; double startXRatio; int startY = 100; double startYRatio; VerticalAlignmentConstant vertAlign = HasVerticalAlignment.ALIGN_TOP; /** * Initialise effect and set up the basic set of DOM elements that resizing * will be applied to If more elements are needed to be included, use the * addToTriggerDOM(Vector<String> arg) method, or you can replace completely * using the setTriggerDOM(Vector<String> arg) method. */ public Resize() { super(); triggerDOM.add("IMG"); triggerDOM.add("TABLE"); triggerDOM.add("DIV"); } public Resize(Element el) { this(); addEffectElement(el); } public Resize(Element el, int start, int end) { this(start, end); addEffectElement(el); } public Resize(int start, int end) { this(); startX = start; startY = start; endX = end; endY = end; } private void createInternalEffectsPerElement(Element currEl) { NodeList<Node> nodes = currEl.getChildNodes(); if (nodes != null) { for (int i = 0; i < nodes.getLength(); i++) { Node n = nodes.getItem(i); if (n.getNodeType() == Node.ELEMENT_NODE) { createInternalEffectsPerElement((Element) nodes.getItem(i)); } } } Vector<ChangeInterface> temp = new Vector<ChangeInterface>(); String name = currEl.getNodeName(); if (triggerDOM.contains(name)) { GWT.log("Resize Effect is Processing: " + name, null); int startVal; int endVal; // Deal with Widths startVal = getStartWidth(currEl); endVal = getEndWidth(currEl); if (startVal!=endVal){ NChangeScalarAction theWidthChange = new NChangeScalarAction(startVal + "px", endVal + "px"); temp.add(theWidthChange); theWidthChange.setUp(currEl, "width", 0); } // Deal with Heights startVal = getStartHeight(currEl); endVal = getEndHeight(currEl); if (startVal!=endVal){ NChangeScalarAction theHeightChange = new NChangeScalarAction(startVal + "px", endVal + "px"); temp.add(theHeightChange); theHeightChange.setUp(currEl, "height", 0); } // Deal with Fonts String res = StyleImplementation.getComputedStyle(currEl, "fontSize"); if (res != null) { // We have a font to play with String unit = StyleImplementation.getUnits(res); double value = -1; if (unit==null || unit.equals("")) { // Assume we're dealing with a named font-size, as there are no units // so, find where this name is in our vector of font size names int scale = fontSizes.indexOf(res); // If we found it, calculate the font size if (scale>-1) { value = (double) Math.round(Math.pow(fontSizeScalingFactor, (scale - standardIndex)) * standardFontSize); unit = standardFontUnit; } } else { // Not a named font-size, so get the value value = (new Double(StyleImplementation.getValue(res, unit))).doubleValue(); } if (value>-1){ NChangeScalarAction theFontChange = new NChangeScalarAction( (int) (value * startXRatio) + unit, (int) (value * endXRatio) + unit); theFontChange.setUp(currEl, "fontSize", 0); temp.add(theFontChange); } else { GWT.log("Don't know what to do with this font-size definition: "+res, null); } } // Do we need to manage bounding box aspects, e.g. margin etc? if (managesMargin) temp.addAll(getBoxChanges("margin", currEl)); if (managesBorder) temp.addAll(getBoxChanges("border", currEl)); if (managesPadding) temp.addAll(getBoxChanges("padding", currEl)); // Put all ChangeInterfaces together into the determinedEffects object for future management determinedEffects.put(currEl, temp); } else { GWT.log("Resize Effect is Not Processing: " + name, null); } temp = null; } protected Vector<NChangeScalarAction> getBoxChanges(String boxAspect, Element currEl){ Vector<NChangeScalarAction> temp2 = new Vector<NChangeScalarAction>(); String end = ""; if (boxAspect.equals("border")) end = "Width"; int startVal; int endVal; startVal = getStartBoxHoriz(boxAspect+"Left"+end, currEl); endVal = getEndBoxHoriz(boxAspect+"Left"+end, currEl); if (startVal!=endVal){ NChangeScalarAction marginLeft = new NChangeScalarAction(startVal + "px", endVal + "px"); marginLeft.setUp(currEl, boxAspect+"Left"+end, 0); temp2.add(marginLeft); } startVal = getStartBoxVert(boxAspect+"Bottom"+end, currEl); endVal = getEndBoxVert(boxAspect+"Bottom"+end, currEl); if (startVal!=endVal){ NChangeScalarAction marginBottom = new NChangeScalarAction(startVal + "px", endVal + "px"); marginBottom.setUp(currEl, boxAspect+"Bottom"+end, 0); temp2.add(marginBottom); } startVal = getStartBoxHoriz(boxAspect+"Right"+end, currEl); endVal = getEndBoxHoriz(boxAspect+"Right"+end, currEl); if (startVal!=endVal){ NChangeScalarAction marginRight = new NChangeScalarAction(startVal + "px", endVal + "px"); marginRight.setUp(currEl, boxAspect+"Right"+end, 0); temp2.add(marginRight); } startVal = getStartBoxVert(boxAspect+"Top"+end, currEl); endVal = getEndBoxVert(boxAspect+"Top"+end, currEl); if (startVal!=endVal){ NChangeScalarAction marginTop = new NChangeScalarAction(startVal + "px", endVal + "px"); marginTop.setUp(currEl, boxAspect+"Top"+end, 0); temp2.add(marginTop); } return temp2; } // Do not manage margin, padding etc by default. boolean managesMargin = false; public boolean isManagesMargin() { return managesMargin; } public void setManagesMargin(boolean managesMargin) { this.managesMargin = managesMargin; } public boolean isManagesBorder() { return managesBorder; } public void setManagesBorder(boolean managesBorder) { this.managesBorder = managesBorder; } public boolean isManagesPadding() { return managesPadding; } public void setManagesPadding(boolean managesPadding) { this.managesPadding = managesPadding; } boolean managesBorder = false; boolean managesPadding = false; protected int getBoxSizeVert(){ return 0; } protected int getBoxSizeHoriz(){ return 0; } protected int getEndHeight(Element theWidget) { //int val = (int) ((theWidget.getOffsetHeight() - (2*getBoxSizeVert())) * endYRatio); int val = (int) (Double.parseDouble(StyleImplementation.getValue(StyleImplementation.getComputedStyle(theWidget, "height")))* endYRatio); return val; } protected int getEndBoxHoriz(String css, Element theWidget) { String val = StyleImplementation.getComputedStyle(theWidget, css); if (!val.equals("auto")&&!val.equals("undefined")){ double dVal = Double.parseDouble(StyleImplementation.getValue(val)); return (int) (dVal * endXRatio); } else { GWT.log("Unable to calculate style "+css+" for widget",null); return -1; } } protected int getStartBoxHoriz(String css, Element theWidget) { String val = StyleImplementation.getComputedStyle(theWidget, css); if (!val.equals("auto")&&!val.equals("undefined")){ double dVal = Double.parseDouble(StyleImplementation.getValue(val)); return (int) (dVal * startXRatio); } else { GWT.log("Unable to calculate style "+css+" for widget",null); return -1; } } protected int getEndBoxVert(String css, Element theWidget) { String val = StyleImplementation.getComputedStyle(theWidget, css); if (!val.equals("auto")&&!val.equals("undefined")){ double dVal = Double.parseDouble(StyleImplementation.getValue(val)); return (int) (dVal * endYRatio); } else { GWT.log("Unable to calculate style "+css+" for widget",null); return -1; } } protected int getStartBoxVert(String css, Element theWidget) { String val = StyleImplementation.getComputedStyle(theWidget, css); if (!val.equals("auto")&&!val.equals("undefined")){ double dVal = Double.parseDouble(StyleImplementation.getValue(val)); return (int) (dVal * startYRatio); } else { GWT.log("Unable to calculate style "+css+" for widget",null); return -1; } } protected int getEndLeft(Element theWidget) { if (horizAlign == HasHorizontalAlignment.ALIGN_RIGHT) { return (int) (((double) theWidget.getOffsetWidth() / 2 - theWidget.getOffsetWidth() * endXRatio) / 2); } else { return (int) ((theWidget.getOffsetWidth() - theWidget.getOffsetWidth() * endXRatio) / 4); } } protected int getEndTop(Element theWidget) { if (vertAlign == HasVerticalAlignment.ALIGN_BOTTOM) { return (int) ((double) theWidget.getOffsetHeight() / 2) - (int) (theWidget.getOffsetHeight() * endYRatio / 2); } else { return (int) ((double) theWidget.getOffsetHeight() / 4) - (int) (theWidget.getOffsetHeight() * endYRatio / 4); } } protected int getEndWidth(Element theWidget) { //int val = (int) ((theWidget.getOffsetWidth() - (2*getBoxSizeHoriz())) * endYRatio); int val = (int) (Double.parseDouble(StyleImplementation.getValue(StyleImplementation.getComputedStyle(theWidget, "width")))* endXRatio); return val; } protected int getStartHeight(Element theWidget) { //int val = (int) ((theWidget.getOffsetHeight() - (2*getBoxSizeVert())) * startYRatio); int val = (int) (Double.parseDouble(StyleImplementation.getValue(StyleImplementation.getComputedStyle(theWidget, "height")))* startYRatio); return val; } protected int getStartLeft(Element theWidget) { if (horizAlign == HasHorizontalAlignment.ALIGN_RIGHT) { return (int) ((theWidget.getOffsetWidth() - theWidget.getOffsetWidth() * startXRatio) / 2); } else { return (int) ((theWidget.getOffsetWidth() - theWidget.getOffsetWidth() * startXRatio) / 4); } } protected int getStartTop(Element theWidget) { if (vertAlign == HasVerticalAlignment.ALIGN_BOTTOM) { return (int) ((double) theWidget.getOffsetHeight() / 2) - (int) (theWidget.getOffsetHeight() * startYRatio / 2); } else { return (int) ((double) theWidget.getOffsetHeight() / 4) - (int) (theWidget.getOffsetHeight() * startYRatio / 4); } } protected int getStartWidth(Element theWidget) { //int val = (int) ((theWidget.getOffsetWidth() - (2*getBoxSizeHoriz())) * startYRatio); int val = (int) (Double.parseDouble(StyleImplementation.getValue(StyleImplementation.getComputedStyle(theWidget, "width")))* startXRatio); return val; } @Override protected void onUpdate(double progress) { super.onUpdate(progress); for (Iterator<Element> it = determinedEffects.keySet().iterator(); it.hasNext();) { Element theChange = it.next(); Vector<ChangeInterface> currChange = determinedEffects.get(theChange); for (int loop = 0; loop < currChange.size(); loop++) { currChange.get(loop).performStep(theChange, "", progress); } } } /** * Set the ending height for the resize. * * @param percentage Ending height in percentage. */ public void setEndHeightPercentage(int percentage) { assert (percentage >= 0); endY = percentage; } /** * Set Ending percentage for width and height * * @param percentage */ public void setEndPercentage(int percentage) { setEndHeightPercentage(percentage); setEndWidthPercentage(percentage); } /** * Set the ending width for the resize. * * @param percentage Ending width in percentage. */ public void setEndWidthPercentage(int percentage) { assert (percentage >= 0); endX = percentage; } public void setHorizAlignment(HorizontalAlignmentConstant newHorizAlign) { horizAlign = newHorizAlign; } /** * Set the starting height for the resize. * * @param percentage Starting height in percentage. */ public void setStartHeightPercentage(int percentage) { assert (percentage >= 0); startY = percentage; } /** * Set Starting percentage for width and height; * * @param percentage */ public void setStartPercentage(int percentage) { setStartHeightPercentage(percentage); setStartWidthPercentage(percentage); } /** * Set the starting width for the resize. * * @param percentage Starting width in percentage. */ public void setStartWidthPercentage(int percentage) { assert (percentage >= 0); startX = percentage; } @Override public void setUpEffect() { registerEffectElement(); if (effectElement == null) effectElement = (Element) effectElements.get(0); startXRatio = (double) startX / 100; startYRatio = (double) startY / 100; endXRatio = (double) endX / 100; endYRatio = (double) endY / 100; if (determinedEffects == null) determinedEffects = new HashMap<Element, Vector<ChangeInterface>>(); else determinedEffects.clear(); Vector<ChangeInterface> temp2 = null; // Deal with top if not default to align_top if (vertAlign != HasVerticalAlignment.ALIGN_TOP) { if (temp2 == null) temp2 = new Vector<ChangeInterface>(); NChangeScalarAction theTopChange = new NChangeScalarAction( getStartTop((Element) effectElement) + "px", getEndTop((Element) effectElement) + "px"); theTopChange.setUp(effectElement, "top", 0); temp2.add(theTopChange); } if (horizAlign != HasHorizontalAlignment.ALIGN_LEFT) { if (temp2 == null) temp2 = new Vector<ChangeInterface>(); NChangeScalarAction theLeftChange = new NChangeScalarAction( getStartLeft((Element) effectElement) + "px", getEndLeft((Element) effectElement) + "px"); theLeftChange.setUp(effectElement, "left", 0); temp2.add(theLeftChange); } if (temp2 != null) determinedEffects.put((Element) effectElement, temp2); createInternalEffectsPerElement((Element) effectElement); GWT.log("Number of Determined Effects: " + determinedEffects.size(), null); // Set up the font-size name list fontSizes.add("xx-small"); fontSizes.add("x-small"); fontSizes.add("small"); fontSizes.add("medium"); fontSizes.add("large"); fontSizes.add("x-large"); fontSizes.add("xx-large"); this.isInitialised = true; } public void setVertAlignment(VerticalAlignmentConstant newVertAlign) { vertAlign = newVertAlign; } @Override public void tearDownEffect() { for (Iterator<Element> it = determinedEffects.keySet().iterator(); it.hasNext();) { Element theChange = it.next(); Vector<ChangeInterface> currChange = determinedEffects.get(theChange); for (int loop = 0; loop < currChange.size(); loop++) { currChange.get(loop).performStep(theChange, "", 0); } } determinedEffects = null; } public String toString() { String toRet = ""; for (Iterator<Element> it = determinedEffects.keySet().iterator(); it.hasNext();) { Element theChange = it.next(); Vector<ChangeInterface> currChange = determinedEffects.get(theChange); for (int loop = 0; loop < currChange.size(); loop++) { toRet += currChange.get(loop).toString() + "; "; } } return toRet; } }