blob: 1578095b0bfff3f30e6e78333c38a40c0b538073 [file] [log] [blame]
/*
* Copyright 2008 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.client;
import com.google.gwt.resources.ext.DefaultExtensions;
import com.google.gwt.resources.ext.ResourceGeneratorType;
import com.google.gwt.resources.rg.CssResourceGenerator;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Aggregates and minifies CSS stylesheets. A CssResource represents a regular
* CSS file with GWT-specific at-rules.
* <p>
* Currently-supported accessor functions:
*
* <ul>
* <li>{@code String someClassName();} will allow the css class
* <code>.someClassName</code> to be obfuscated at runtime. The function will
* return the obfuscated class name.</li>
* <li>{@code <primitive numeric type or String> someDefName();} will allow
* access to the values defined by {@literal @def} rules within the CSS file.
* The defined value must be a raw number, a CSS length, or a percentage value
* if it is to be returned as a numeric type.
* </ul>
*
* <p>
* Currently-supported rules:
*
* <ul>
* <li>{@code @def NAME replacement-expression; .myClass background: NAME;}
* Define a static constant. The replacement expression may be any CSS that
* would be valid in a property value context. A {@code @def} may refer to
* previously-defined rules, but no forward-references will be honored.</li>
* <li>{@code @eval NAME Java-expression; .myClass background: NAME;} Define a
* constant based on a Java expression.</li>
* <li>{@code @external class-name, class-name, ...;} Disable obfuscation for
* specific class selectors and exclude those class selectors from strictness
* requirements.</li>
* <li><code>{@literal @if} [!]property list of values {ruleBlock}</code> Include or
* exclude CSS rules based on the value of a deferred-binding property. Also
* {@code @elif} and {@code @else} follow the same pattern.<br/>
* This might look like {@code @if user.agent ie6 safari ...}.</li>
* <li><code>{@literal @if} (Java-expression) {ruleBlock}</code> Include or exclude
* CSS rules based on a boolean Java expression.</li>
* <li><code>{@literal @noflip} { rules }</code> will suppress the automatic
* right-to-left transformation applied to the CSS when the module is compiled
* for an RTL language.</li>
* <li>
* <code>{@literal @}sprite .any .selector {gwt-image: "imageResourceFunction";}</code>
* . The appearance, size, and height of the sprite will be affected by any
* {@link ImageResource.ImageOptions} annotations present on the related
* {@link ImageResource} accessor function. Additional properties may be
* specified in the rule block.</li>
* <li>{@code @url NAME siblingDataResource; .myClass background: NAME
* repeat-x;} Use a {@link DataResource} to generate a <code>url('...'}</code> value.</li>
* </ul>
*
* <p>
* Currently-supported CSS functions:
*
* <ul>
* <li>{@code literal("expression")} substitutes a property value that does not
* conform to CSS2 parsing rules. The escape sequences {@code \"} and {@code \\}
* will be replaced with {@code "} and {@code \} respectively.
* <li>{@code value("bundleFunction.someFunction[.other[...]]" [, "suffix"])}
* substitute the value of a sequence of named zero-arg function invocations. An
* optional suffix will be appended to the return value of the function. The
* first name is resolved relative to the bundle interface passed to
* {@link com.google.gwt.core.client.GWT#create(Class)}. An example:
*
* <pre>
* .bordersTheSizeOfAnImage {
* border-left: value('leftBorderImageResource.getWidth', 'px') solid blue;
* }
* </pre>
* </li>
* </ul>
*
* <p>
* Any class selectors that do not correspond with a String accessor method in
* the return type will trigger a compilation error. This ensures that the
* CssResource does not contribute any unobfuscated class selectors into the
* global CSS namespace. Strict mode can be disabled by annotating the
* ClientBundle method declaration with {@link NotStrict}, however this is only
* recommended for interacting with legacy CSS.
*
* <p>
* Given these interfaces:
*
* <pre>
* interface MyCss extends CssResource {
* String someClass();
* }
*
* interface MyBundle extends ClientBundle {
* {@literal @Source("my.css")}
* MyCss css();
* }
* </pre>
*
* the source CSS will fail to compile if it does not contain exactly the one
* class selector defined in the MyCss type.
* <p>
* The {@code @external} at-rule can be used in strict mode to indicate that
* certain class selectors are exempt from the strict semantics. Class selectors
* marked as external will not be obfuscated and are not required to have string
* accessor functions. Consider the following example in conjunction with the
* above <code>MyCss</code> interface:
*
* <pre>
* {@literal @external} .foo, .bar;
* .foo .someClass .bar { .... }
* </pre>
*
* The resulting CSS would look like:
*
* <pre>
* .foo .A1234 .bar { .... }
* </pre>
*
* If a <code>String foo()</code> method were defined in <code>MyCss</code>, it
* would return the string value "<code>foo</code>".
* <p>
* The utility tool <code>com.google.gwt.resources.css.InterfaceGenerator</code>
* can be used to automatically generate a Java interface from a
* CssResource-compatible CSS file.
*
* @see <a href="http://code.google.com/p/google-web-toolkit/wiki/CssResource"
* >CssResource design doc</a>
*/
@DefaultExtensions(value = {".css"})
@ResourceGeneratorType(CssResourceGenerator.class)
public interface CssResource extends ResourcePrototype {
/**
* The original CSS class name specified in the resource. This allows CSS
* classes that do not correspond to Java identifiers to be mapped onto
* obfuscated class accessors.
*
* <pre>
* .some-non-java-ident { background: blue; }
*
* interface MyCssResource extends CssResource {
* {@literal @}ClassName("some-non-java-ident")
* String classAccessor();
* }
* </pre>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface ClassName {
String value();
}
/**
* Makes class selectors from other CssResource types available in the raw
* source of a CssResource. String accessor methods can be referred to using
* the value of the imported type's {@link ImportedWithPrefix} value.
* <p>
* This is an example of creating a descendant selector with two unrelated
* types:
*
* <pre>
*{@literal @ImportedWithPrefix}("some-prefix")
* interface ToImport extends CssResource {
* String widget();
* }
*
*{@literal @ImportedWithPrefix}("other-import")
* interface OtherImport extends CssResource {
* String widget();
* }
*
* interface Resources extends ClientBundle {
* {@literal @Import}(value = {ToImport.class, OtherImport.class})
* {@literal @Source}("my.css")
* CssResource usesImports();
* }
*
* my.css:
* // Now I can refer to these classes defined elsewhere with no
* // fear of name collisions
* .some-prefix-widget .other-import-widget {...}
* </pre>
*
* If the imported CssResource type is lacking an {@link ImportedWithPrefix}
* annotation, the simple name of the type will be used instead. In the above
* example, without the annotation on <code>ToImport</code>, the class
* selector would have been <code>.ToImport-widget</code>. Notice also that
* both interfaces defined a method called <code>widget()</code>, which would
* prevent meaningful composition of the original interfaces.
* <p>
* It is an error to import multiple classes with the same prefix into one
* CssResource.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Import {
Class<? extends CssResource>[] value();
}
/**
* Specifies the string prefix to use when one CssResource is imported into
* the scope of another CssResource.
*
* @see Import
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ImportedWithPrefix {
String value();
}
/**
* The presence of this annotation on a CssResource accessor method indicates
* that any class selectors that do not correspond with a String accessor
* method in the return type or an {@code @external} declaration should not
* trigger a compilation error. This annotation is not recommended for new
* code.
*
* <pre>
* interface Resources extends ClientBundle {
* {@literal @NotStrict}
* {@literal @Source}("legacy.css")
* CssResource css();
* }
* </pre>
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface NotStrict {
}
/**
* Indicates that the String accessor methods defined in a CssResource will
* return the same values across all implementations of that type.
* <p>
* This is an example of "stateful" class selectors being used:
*
* <pre>
*{@literal @Shared}
* interface FocusCss extends CssResource {
* String focused();
* String unfocused();
* }
*
* interface PanelCss extends CssResource, FocusCss {
* String widget();
* }
*
* interface InputCss extends CssResource, FocusCss {
* String widget();
* }
*
* input.css:
* *.focused .widget {border: thin solid blue;}
*
* Application.java:
* myPanel.add(myInputWidget);
* myPanel.addStyleName(instanceOfPanelCss.focused());
* </pre>
*
* Because the <code>FocusCss</code> interface is tagged with {@code @Shared},
* the <code>focused()</code> method on the instance of <code>PanelCss</code>
* will match the <code>.focused</code> parent selector in
* <code>input.css</code>.
* <p>
* The effect of inheriting an {@code Shared} interface can be replicated by
* use use of the {@link Import} annotation (e.g. {@code .FocusCss-focused
* .widget}), however the use of state-bearing descendant selectors is common
* enough to warrant an easier use-case.
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Shared {
}
/**
* This annotation is a no-op.
*
* @deprecated Strict mode is now the default behavior for CssResource
*/
@Deprecated
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Strict {
}
/**
* Calls
* {@link com.google.gwt.dom.client.StyleInjector#injectStylesheet(String)} to
* inject the contents of the CssResource into the DOM. Repeated calls to this
* method on an instance of a CssResources will have no effect.
*
* @return <code>true</code> if this method mutated the DOM.
*/
boolean ensureInjected();
/**
* Provides the contents of the CssResource.
*/
String getText();
}