| /* |
| * Copyright 2011 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.dom.builder.client; |
| |
| import com.google.gwt.core.client.JavaScriptObject; |
| import com.google.gwt.core.shared.impl.StringCase; |
| import com.google.gwt.dom.builder.shared.StylesBuilder; |
| import com.google.gwt.dom.client.Style.BorderStyle; |
| import com.google.gwt.dom.client.Style.Cursor; |
| import com.google.gwt.dom.client.Style.Display; |
| import com.google.gwt.dom.client.Style.Float; |
| import com.google.gwt.dom.client.Style.FontStyle; |
| import com.google.gwt.dom.client.Style.FontWeight; |
| import com.google.gwt.dom.client.Style.ListStyleType; |
| import com.google.gwt.dom.client.Style.OutlineStyle; |
| import com.google.gwt.dom.client.Style.Overflow; |
| import com.google.gwt.dom.client.Style.Position; |
| import com.google.gwt.dom.client.Style.TableLayout; |
| import com.google.gwt.dom.client.Style.TextAlign; |
| import com.google.gwt.dom.client.Style.TextDecoration; |
| import com.google.gwt.dom.client.Style.TextJustify; |
| import com.google.gwt.dom.client.Style.TextOverflow; |
| import com.google.gwt.dom.client.Style.TextTransform; |
| import com.google.gwt.dom.client.Style.Unit; |
| import com.google.gwt.dom.client.Style.VerticalAlign; |
| import com.google.gwt.dom.client.Style.Visibility; |
| import com.google.gwt.regexp.shared.MatchResult; |
| import com.google.gwt.regexp.shared.RegExp; |
| import com.google.gwt.safehtml.shared.SafeUri; |
| |
| /** |
| * Builds the style object. |
| */ |
| class DomStylesBuilder implements StylesBuilder { |
| |
| /** |
| * A map of hyphenated style properties to their camelCase equivalents. |
| * |
| * The set of style property names is limited, and common ones are reused |
| * frequently, so caching saves us from converting every style property name |
| * from hyphenated to camelCase form. |
| * |
| * Use a {@link JavaScriptObject} to avoid the dynamic casts associated with |
| * the emulated version of {@link java.util.Map}. |
| */ |
| private static JavaScriptObject hyphenatedMap; |
| |
| /** |
| * Regex to match a word in a hyphenated phrase. A word starts with an a |
| * hyphen or a letter, followed by zero or more characters letters. For |
| * example, in the phrase background-url, the pattern matches "background" and |
| * "-url". |
| */ |
| private static RegExp maybeHyphenatedWord; |
| |
| /** |
| * Convert a hyphenated or camelCase string to a camelCase string. |
| * |
| * @param name the hyphenated or camelCase string to convert |
| * @return the hyphenated string |
| */ |
| // Visible for testing |
| static String toCamelCaseForm(String name) { |
| // Static initializers. |
| if (hyphenatedMap == null) { |
| hyphenatedMap = JavaScriptObject.createObject(); |
| maybeHyphenatedWord = RegExp.compile("([-]?)([a-z])([a-z0-9]*)", "g"); |
| } |
| |
| // Early exit if already in camelCase form. |
| if (!name.contains("-")) { |
| return name; |
| } |
| |
| // Check for the name in the cache. |
| String camelCase = getCamelCaseName(hyphenatedMap, name); |
| |
| // Convert the name to camelCase format if not in the cache. |
| if (camelCase == null) { |
| /* |
| * Strip of any leading hyphens, which are used in browser specified style |
| * properties such as "-webkit-border-radius". In this case, the first |
| * word "webkit" should remain lowercase. |
| */ |
| if (name.startsWith("-") && name.length() > 1) { |
| name = name.substring(1); |
| } |
| |
| camelCase = ""; |
| MatchResult matches; |
| while ((matches = maybeHyphenatedWord.exec(name)) != null) { |
| String word = matches.getGroup(0); |
| if (!word.startsWith("-")) { |
| // The word is not hyphenated. Probably the first word. |
| camelCase += word; |
| } else { |
| // Remove hyphen and uppercase next letter. |
| camelCase += StringCase.toUpper(matches.getGroup(2)); |
| if (matches.getGroupCount() > 2) { |
| camelCase += matches.getGroup(3); |
| } |
| } |
| } |
| putCamelCaseName(hyphenatedMap, name, camelCase); |
| } |
| |
| return camelCase; |
| } |
| |
| /** |
| * Get the camelCase form of a style name to a map. |
| * |
| * @param name the user specified style name |
| * @return the camelCase name, or null if not set |
| */ |
| private static native String getCamelCaseName(JavaScriptObject map, String name) /*-{ |
| return map[name] || null; |
| }-*/; |
| |
| /** |
| * Save the camelCase form of a style name to a map. |
| * |
| * @param name the user specified style name |
| * @param camelCase the camelCase name |
| */ |
| private static native void putCamelCaseName(JavaScriptObject map, String name, String camelCase) /*-{ |
| map[name] = camelCase; |
| }-*/; |
| |
| private final DomBuilderImpl delegate; |
| |
| /** |
| * Construct a new {@link DomStylesBuilder}. |
| * |
| * @param delegate the delegate that builds the style |
| */ |
| DomStylesBuilder(DomBuilderImpl delegate) { |
| this.delegate = delegate; |
| } |
| |
| @Override |
| public StylesBuilder backgroundImage(SafeUri uri) { |
| delegate.assertCanAddStyleProperty().setBackgroundImage(uri.asString()); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder borderStyle(BorderStyle value) { |
| delegate.assertCanAddStyleProperty().setBorderStyle(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder borderWidth(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setBorderWidth(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder bottom(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setBottom(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder cursor(Cursor value) { |
| delegate.assertCanAddStyleProperty().setCursor(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder display(Display value) { |
| delegate.assertCanAddStyleProperty().setDisplay(value); |
| return this; |
| } |
| |
| @Override |
| public void endStyle() { |
| delegate.endStyle(); |
| } |
| |
| @Override |
| public StylesBuilder floatprop(Float value) { |
| delegate.assertCanAddStyleProperty().setFloat(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder fontSize(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setFontSize(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder fontStyle(FontStyle value) { |
| delegate.assertCanAddStyleProperty().setFontStyle(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder fontWeight(FontWeight value) { |
| delegate.assertCanAddStyleProperty().setFontWeight(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder height(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setHeight(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder left(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setLeft(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder lineHeight(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setLineHeight(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder listStyleType(ListStyleType value) { |
| delegate.assertCanAddStyleProperty().setListStyleType(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder margin(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setMargin(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder marginBottom(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setMarginBottom(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder marginLeft(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setMarginLeft(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder marginRight(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setMarginRight(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder marginTop(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setMarginTop(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder opacity(double value) { |
| delegate.assertCanAddStyleProperty().setOpacity(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder outlineStyle(OutlineStyle value) { |
| delegate.assertCanAddStyleProperty().setOutlineStyle(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder outlineWidth(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setOutlineWidth(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder overflow(Overflow value) { |
| delegate.assertCanAddStyleProperty().setOverflow(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder overflowX(Overflow value) { |
| delegate.assertCanAddStyleProperty().setOverflowX(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder overflowY(Overflow value) { |
| delegate.assertCanAddStyleProperty().setOverflowY(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder padding(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setPadding(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder paddingBottom(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setPaddingBottom(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder paddingLeft(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setPaddingLeft(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder paddingRight(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setPaddingRight(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder paddingTop(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setPaddingTop(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder position(Position value) { |
| delegate.assertCanAddStyleProperty().setPosition(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder right(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setRight(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder tableLayout(TableLayout value) { |
| delegate.assertCanAddStyleProperty().setTableLayout(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textAlign(TextAlign value) { |
| delegate.assertCanAddStyleProperty().setTextAlign(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textDecoration(TextDecoration value) { |
| delegate.assertCanAddStyleProperty().setTextDecoration(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textIndent(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setTextIndent(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textJustify(TextJustify value) { |
| delegate.assertCanAddStyleProperty().setTextJustify(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textOverflow(TextOverflow value) { |
| delegate.assertCanAddStyleProperty().setTextOverflow(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder textTransform(TextTransform value) { |
| delegate.assertCanAddStyleProperty().setTextTransform(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder top(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setTop(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedBackgroundColor(String value) { |
| delegate.assertCanAddStyleProperty().setBackgroundColor(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedBackgroundImage(String value) { |
| delegate.assertCanAddStyleProperty().setBackgroundImage(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedBorderColor(String value) { |
| delegate.assertCanAddStyleProperty().setBorderColor(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedColor(String value) { |
| delegate.assertCanAddStyleProperty().setColor(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedOutlineColor(String value) { |
| delegate.assertCanAddStyleProperty().setOutlineColor(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedProperty(String name, double value, Unit unit) { |
| name = toCamelCaseForm(name); |
| delegate.assertCanAddStyleProperty().setProperty(name, value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder trustedProperty(String name, String value) { |
| name = toCamelCaseForm(name); |
| delegate.assertCanAddStyleProperty().setProperty(name, value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder verticalAlign(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setVerticalAlign(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder verticalAlign(VerticalAlign value) { |
| delegate.assertCanAddStyleProperty().setVerticalAlign(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder visibility(Visibility value) { |
| delegate.assertCanAddStyleProperty().setVisibility(value); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder width(double value, Unit unit) { |
| delegate.assertCanAddStyleProperty().setWidth(value, unit); |
| return this; |
| } |
| |
| @Override |
| public StylesBuilder zIndex(int value) { |
| delegate.assertCanAddStyleProperty().setZIndex(value); |
| return this; |
| } |
| } |