blob: 2ec1102b3bb8179886e6cac6c9cb306b4a68e4dd [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.user.client.ui;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.i18n.shared.HasDirectionEstimator;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.safehtml.shared.annotations.SuppressIsSafeHtmlCastCheck;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
/**
* A widget that serves as an "internal" hyperlink. That is, it is a link to
* another state of the running application. When clicked, it will create a new
* history frame using {@link com.google.gwt.user.client.History#newItem}, but
* without reloading the page.
*
* <p>
* If you want an HTML hyperlink (&lt;a&gt; tag) without interacting with the
* history system, use {@link Anchor} instead.
* </p>
*
* <p>
* Being a true hyperlink, it is also possible for the user to "right-click,
* open link in new window", which will cause the application to be loaded in a
* new window at the state specified by the hyperlink.
* </p>
*
* <p>
* <h3>Built-in Bidi Text Support</h3>
* This widget is capable of automatically adjusting its direction according to
* its content. This feature is controlled by {@link #setDirectionEstimator} or
* passing a DirectionEstimator parameter to the constructor, and is off by
* default.
* </p>
*
* <p>
* <img class='gallery' src='doc-files/Hyperlink.png'/>
* </p>
*
* <h3>CSS Style Rules</h3>
* <ul class='css'>
* <li>.gwt-Hyperlink { }</li>
* </ul>
*
* <p>
* <h3>Example</h3> {@example com.google.gwt.examples.HistoryExample}
* </p>
*
* @see Anchor
*/
@SuppressWarnings("deprecation")
public class Hyperlink extends Widget implements HasHTML, SourcesClickEvents,
HasClickHandlers, HasDirectionEstimator, HasDirectionalSafeHtml {
public static final DirectionEstimator DEFAULT_DIRECTION_ESTIMATOR =
DirectionalTextHelper.DEFAULT_DIRECTION_ESTIMATOR;
private static HyperlinkImpl impl = GWT.create(HyperlinkImpl.class);
protected final DirectionalTextHelper directionalTextHelper;
private final Element anchorElem = DOM.createAnchor();
private String targetHistoryToken;
/**
* Creates an empty hyperlink.
*/
public Hyperlink() {
this(DOM.createDiv());
}
/**
* Creates a hyperlink with its html and target history token specified.
*
* @param html the hyperlink's safe html
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
public Hyperlink(SafeHtml html, String targetHistoryToken) {
this(html.asString(), true, targetHistoryToken);
}
/**
* Creates a hyperlink with its html and target history token specified.
*
* @param html the hyperlink's safe html
* @param dir the html's direction
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
public Hyperlink(SafeHtml html, Direction dir, String targetHistoryToken) {
this(html.asString(), true, dir, targetHistoryToken);
}
/**
* Creates a hyperlink with its html and target history token specified.
*
* @param html the hyperlink's safe html
* @param directionEstimator A DirectionEstimator object used for automatic
* direction adjustment. For convenience,
* {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
public Hyperlink(SafeHtml html, DirectionEstimator directionEstimator,
String targetHistoryToken) {
this(html.asString(), true, directionEstimator, targetHistoryToken);
}
/**
* Creates a hyperlink with its text and target history token specified.
*
* @param text the hyperlink's text
* @param targetHistoryToken the history token to which it will link, which
* may not be null (use {@link Anchor} instead if you don't need
* history processing)
*/
@SuppressIsSafeHtmlCastCheck
public Hyperlink(String text, String targetHistoryToken) {
this(text, false, targetHistoryToken);
}
/**
* Creates a hyperlink with its text and target history token specified.
*
* @param text the hyperlink's text
* @param dir the text's direction
* @param targetHistoryToken the history token to which it will link, which
* may not be null (use {@link Anchor} instead if you don't need
* history processing)
*/
@SuppressIsSafeHtmlCastCheck
public Hyperlink(String text, Direction dir, String targetHistoryToken) {
this(text, false, dir, targetHistoryToken);
}
/**
* Creates a hyperlink with its text and target history token specified.
*
* @param text the hyperlink's text
* @param directionEstimator A DirectionEstimator object used for automatic
* direction adjustment. For convenience,
* {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
* @param targetHistoryToken the history token to which it will link, which
* may not be null (use {@link Anchor} instead if you don't need
* history processing)
*/
@SuppressIsSafeHtmlCastCheck
public Hyperlink(String text, DirectionEstimator directionEstimator, String targetHistoryToken) {
this(text, false, directionEstimator, targetHistoryToken);
}
/**
* Creates a hyperlink with its text and target history token specified.
*
* @param text the hyperlink's text
* @param asHTML <code>true</code> to treat the specified text as html
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
public Hyperlink(@IsSafeHtml String text, boolean asHTML, String targetHistoryToken) {
this();
directionalTextHelper.setTextOrHtml(text, asHTML);
setTargetHistoryToken(targetHistoryToken);
}
protected Hyperlink(Element elem) {
if (elem == null) {
setElement(anchorElem);
} else {
setElement(elem);
DOM.appendChild(getElement(), anchorElem);
}
sinkEvents(Event.ONCLICK);
setStyleName("gwt-Hyperlink");
directionalTextHelper = new DirectionalTextHelper(anchorElem,
/* is inline */ true);
}
/**
* Creates a hyperlink with its text target history token specified.
*
* @param text the hyperlink's text
* @param asHTML <code>true</code> to treat the specified text as html
* @param dir the text's direction
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
private Hyperlink(
@IsSafeHtml String text, boolean asHTML, Direction dir, String targetHistoryToken) {
this();
directionalTextHelper.setTextOrHtml(text, dir, asHTML);
setTargetHistoryToken(targetHistoryToken);
}
/**
* Creates a hyperlink with its text and target history token specified.
*
* @param text the hyperlink's text
* @param asHTML <code>true</code> to treat the specified text as html
* @param directionEstimator A DirectionEstimator object used for automatic
* direction adjustment. For convenience,
* {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
* @param targetHistoryToken the history token to which it will link
* @see #setTargetHistoryToken
*/
private Hyperlink(
@IsSafeHtml String text,
boolean asHTML,
DirectionEstimator directionEstimator,
String targetHistoryToken) {
this();
directionalTextHelper.setDirectionEstimator(directionEstimator);
directionalTextHelper.setTextOrHtml(text, asHTML);
setTargetHistoryToken(targetHistoryToken);
}
/**
* @deprecated Use {@link Anchor#addClickHandler} instead and call
* History.newItem from the handler if you need to process the
* click before the history token is set.
*/
@Deprecated
public HandlerRegistration addClickHandler(ClickHandler handler) {
return addHandler(handler, ClickEvent.getType());
}
/**
* @deprecated Use {@link Anchor#addClickHandler} instead and call
* History.newItem from the handler if you need to process the
* click before the history token is set.
*/
@Deprecated
public void addClickListener(ClickListener listener) {
ListenerWrapper.WrappedClickListener.add(this, listener);
}
public DirectionEstimator getDirectionEstimator() {
return directionalTextHelper.getDirectionEstimator();
}
public String getHTML() {
return directionalTextHelper.getHtml();
}
/**
* Gets the history token referenced by this hyperlink.
*
* @return the target history token
* @see #setTargetHistoryToken
*/
public String getTargetHistoryToken() {
return targetHistoryToken;
}
public String getText() {
return directionalTextHelper.getText();
}
public Direction getTextDirection() {
return directionalTextHelper.getTextDirection();
}
@Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
if (DOM.eventGetType(event) == Event.ONCLICK && impl.handleAsClick(event)) {
History.newItem(getTargetHistoryToken());
event.preventDefault();
}
}
/**
* @deprecated Use the {@link HandlerRegistration#removeHandler}
* method on the object returned by an add*Handler method instead
*/
@Deprecated
public void removeClickListener(ClickListener listener) {
ListenerWrapper.WrappedClickListener.remove(this, listener);
}
/**
* {@inheritDoc}
* <p>
* See note at {@link #setDirectionEstimator(DirectionEstimator)}.
*/
public void setDirectionEstimator(boolean enabled) {
directionalTextHelper.setDirectionEstimator(enabled);
}
/**
* {@inheritDoc}
* <p>
* Note: DirectionEstimator should be set before the widget has any content;
* it's highly recommended to set it using a constructor. Reason: if the
* widget already has non-empty content, this will update its direction
* according to the new estimator's result. This may cause flicker, and thus
* should be avoided.
*/
public void setDirectionEstimator(DirectionEstimator directionEstimator) {
directionalTextHelper.setDirectionEstimator(directionEstimator);
}
public void setHTML(SafeHtml html) {
setHTML(html.asString());
}
public void setHTML(@IsSafeHtml String html) {
directionalTextHelper.setHtml(html);
}
public void setHTML(SafeHtml html, Direction dir) {
directionalTextHelper.setHtml(html, dir);
}
/**
* Sets the history token referenced by this hyperlink. This is the history
* token that will be passed to {@link History#newItem} when this link is
* clicked.
*
* @param targetHistoryToken the new history token, which may not be null (use
* {@link Anchor} instead if you don't need history processing)
*/
public void setTargetHistoryToken(String targetHistoryToken) {
assert targetHistoryToken != null
: "targetHistoryToken must not be null, consider using Anchor instead";
this.targetHistoryToken = targetHistoryToken;
String hash = History.encodeHistoryToken(targetHistoryToken);
anchorElem.setPropertyString("href", "#" + hash);
}
public void setText(String text) {
directionalTextHelper.setText(text);
}
public void setText(String text, Direction dir) {
directionalTextHelper.setText(text, dir);
}
/**
* <b>Affected Elements:</b>
* <ul>
* <li>-wrapper = the div around the link.</li>
* </ul>
*
* @see UIObject#onEnsureDebugId(String)
*/
@Override
protected void onEnsureDebugId(String baseID) {
ensureDebugId(anchorElem, "", baseID);
ensureDebugId(getElement(), baseID, "wrapper");
}
}