blob: c2f9616744d099f52aabf74bd2f0d78446cd60f2 [file] [log] [blame]
/*
* Copyright 2009 Google Inc.
*
* 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.resources.css;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.resources.client.ImageResource.ImageOptions;
import com.google.gwt.resources.client.ImageResource.RepeatStyle;
import com.google.gwt.resources.css.ast.Context;
import com.google.gwt.resources.css.ast.CssCompilerException;
import com.google.gwt.resources.css.ast.CssModVisitor;
import com.google.gwt.resources.css.ast.CssProperty;
import com.google.gwt.resources.css.ast.CssProperty.DotPathValue;
import com.google.gwt.resources.css.ast.CssProperty.ExpressionValue;
import com.google.gwt.resources.css.ast.CssProperty.IdentValue;
import com.google.gwt.resources.css.ast.CssRule;
import com.google.gwt.resources.css.ast.CssSprite;
import com.google.gwt.resources.ext.ResourceContext;
import com.google.gwt.resources.ext.ResourceGeneratorUtil;
import java.util.List;
/**
* Replaces CssSprite nodes with CssRule nodes that will display the sprited
* image. The real trick with spriting the images is to reuse the ImageResource
* processing framework by requiring the sprite to be defined in terms of an
* ImageResource.
*/
public class Spriter extends CssModVisitor {
private final ResourceContext context;
private final TreeLogger logger;
public Spriter(TreeLogger logger, ResourceContext context) {
this.logger = logger.branch(TreeLogger.DEBUG,
"Creating image sprite classes");
this.context = context;
}
@Override
public void endVisit(CssSprite x, Context ctx) {
JClassType bundleType = context.getClientBundleType();
DotPathValue functionName = x.getResourceFunction();
if (functionName == null) {
logger.log(TreeLogger.ERROR, "The @sprite rule " + x.getSelectors()
+ " must specify the " + CssSprite.IMAGE_PROPERTY_NAME + " property");
throw new CssCompilerException("No image property specified");
}
JClassType imageResourceType = context.getGeneratorContext().getTypeOracle().findType(
ImageResource.class.getName());
assert imageResourceType != null;
// Find the image accessor method
JMethod imageMethod;
try {
imageMethod = ResourceGeneratorUtil.getMethodByPath(bundleType,
functionName.getParts(), imageResourceType);
} catch (NotFoundException e) {
logger.log(TreeLogger.ERROR, "Unable to find ImageResource method "
+ functionName + " in " + bundleType.getQualifiedSourceName() + " : "
+ e.getMessage());
throw new CssCompilerException("Cannot find image function");
}
ImageOptions options = imageMethod.getAnnotation(ImageOptions.class);
RepeatStyle repeatStyle;
if (options != null) {
repeatStyle = options.repeatStyle();
} else {
repeatStyle = RepeatStyle.None;
}
String instance = "(" + context.getImplementationSimpleSourceName()
+ ".this." + functionName.getExpression() + ")";
CssRule replacement = new CssRule();
replacement.getSelectors().addAll(x.getSelectors());
List<CssProperty> properties = replacement.getProperties();
if (repeatStyle == RepeatStyle.None
|| repeatStyle == RepeatStyle.Horizontal) {
properties.add(new CssProperty("height", new ExpressionValue(instance
+ ".getHeight() + \"px\""), false));
}
if (repeatStyle == RepeatStyle.None || repeatStyle == RepeatStyle.Vertical) {
properties.add(new CssProperty("width", new ExpressionValue(instance
+ ".getWidth() + \"px\""), false));
}
properties.add(new CssProperty("overflow", new IdentValue("hidden"), false));
String repeatText;
switch (repeatStyle) {
case None:
repeatText = " no-repeat";
break;
case Horizontal:
repeatText = " repeat-x";
break;
case Vertical:
repeatText = " repeat-y";
break;
case Both:
repeatText = " repeat";
break;
default:
throw new RuntimeException("Unknown repeatStyle " + repeatStyle);
}
String backgroundExpression = "\"url(\\\"\" + " + instance
+ ".getSafeUri().asString() + \"\\\") -\" + " + instance + ".getLeft() + \"px -\" + "
+ instance + ".getTop() + \"px " + repeatText + "\"";
properties.add(new CssProperty("background", new ExpressionValue(
backgroundExpression), false));
// Retain any user-specified properties
properties.addAll(x.getProperties());
ctx.replaceMe(replacement);
}
}