| /* |
| * 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); |
| } |
| } |