blob: 0252d9de6570a4ea1d954d564387d86e2801298b [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.sample.showcase.client;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.HeadElement;
import com.google.gwt.dom.client.LinkElement;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.DeferredCommand;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.RootPanel;
/**
* A utility class that loads style sheets.
*/
public class StyleSheetLoader {
/**
* A {@link Timer} that creates a small reference widget used to determine
* when a new style sheet has finished loading. The widget has a natural width
* of 0px, but when the style sheet is loaded, the width changes to 5px. The
* style sheet should contain a style definition that is passed into the
* constructor that defines a height and width greater than 0px.
*/
private static class StyleTesterTimer extends Timer {
private Command callback;
private Label refWidget;
/**
* Create a new {@link StyleTesterTimer}.
*
* @param refStyleName the reference style name
* @param callback the callback to execute when the style sheet loads
*/
public StyleTesterTimer(String refStyleName, Command callback) {
this.callback = callback;
// Create the reference Widget
refWidget = new Label();
refWidget.setStyleName(refStyleName);
refWidget.getElement().getStyle().setProperty("position", "absolute");
refWidget.getElement().getStyle().setProperty("visibility", "hidden");
refWidget.getElement().getStyle().setProperty("display", "inline");
refWidget.getElement().getStyle().setPropertyPx("padding", 0);
refWidget.getElement().getStyle().setPropertyPx("margin", 0);
refWidget.getElement().getStyle().setPropertyPx("border", 0);
refWidget.getElement().getStyle().setPropertyPx("top", 0);
refWidget.getElement().getStyle().setPropertyPx("left", 0);
RootPanel.get().add(refWidget);
}
@Override
public void run() {
// Redisplay the reference widget so it redraws itself
refWidget.setVisible(false);
refWidget.setVisible(true);
// Check the dimensions of the reference widget
if (refWidget.getOffsetWidth() > 0) {
RootPanel.get().remove(refWidget);
// Fire the callback in a DeferredCommand to ensure the browser has
// enough time to parse the styles. Otherwise, we'll get weird styling
// issues.
DeferredCommand.addCommand(callback);
} else {
schedule(10);
}
}
}
/**
* Convenience method for getting the document's head element.
*
* @return the document's head element
*/
public static native HeadElement getHeadElement()
/*-{
return $doc.getElementsByTagName("head")[0];
}-*/;
/**
* Load a style sheet onto the page.
*
* @param href the url of the style sheet
*/
public static void loadStyleSheet(String href) {
LinkElement linkElem = Document.get().createLinkElement();
linkElem.setRel("stylesheet");
linkElem.setType("text/css");
linkElem.setHref(href);
getHeadElement().appendChild(linkElem);
}
/**
* Load a style sheet onto the page and fire a callback when it has loaded.
* The style sheet should contain a style definition called refStyleName that
* defines a height and width greater than 0px.
*
* @param href the url of the style sheet
* @param refStyleName the style name of the reference element
* @param callback the callback executed when the style sheet has loaded
*/
public static void loadStyleSheet(String href, String refStyleName,
Command callback) {
loadStyleSheet(href);
waitForStyleSheet(refStyleName, callback);
}
/**
* Detect when a style sheet has loaded by placing an element on the page that
* is affected by a rule in the style sheet, as described in
* {@link #loadStyleSheet(String, String, Command)}. When the style sheet has
* loaded, the callback will be executed.
*
* @param refStyleName the style name of the reference element
* @param callback the callback executed when the style sheet has loaded
*/
public static void waitForStyleSheet(String refStyleName, Command callback) {
new StyleTesterTimer(refStyleName, callback).run();
}
}