001: /*
002: * Copyright 2007 Google Inc.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License"); you may not
005: * use this file except in compliance with the License. You may obtain a copy of
006: * the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
012: * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
013: * License for the specific language governing permissions and limitations under
014: * the License.
015: */
016: package com.google.gwt.user.client;
017:
018: import com.google.gwt.core.client.GWT;
019: import com.google.gwt.core.client.GWT.UncaughtExceptionHandler;
020: import com.google.gwt.user.client.impl.HistoryImpl;
021:
022: import java.util.ArrayList;
023:
024: /**
025: * This class allows you to interact with the browser's history stack. Each
026: * "item" on the stack is represented by a single string, referred to as a
027: * "token". You can create new history items (which have a token associated with
028: * them when they are created), and you can programmatically force the current
029: * history to move back or forward.
030: *
031: * <p>
032: * In order to receive notification of user-directed changes to the current
033: * history item, implement the
034: * {@link com.google.gwt.user.client.HistoryListener} interface and attach it
035: * via {@link #addHistoryListener}.
036: * </p>
037: *
038: * <p>
039: * <h3>Example</h3>
040: * {@example com.google.gwt.examples.HistoryExample}
041: * </p>
042: */
043: public class History {
044:
045: private static ArrayList<HistoryListener> historyListeners = new ArrayList<HistoryListener>();
046: private static HistoryImpl impl;
047:
048: static {
049: impl = GWT.create(HistoryImpl.class);
050: if (!impl.init()) {
051: // Set impl to null as a flag to no-op future calls.
052: impl = null;
053:
054: // Tell the user.
055: GWT
056: .log(
057: "Unable to initialize the history subsystem; did you "
058: + "include the history frame in your host page? Try "
059: + "<iframe src=\"javascript:''\" id='__gwt_historyFrame' style='position:absolute;width:0;height:0;border:0'>"
060: + "</iframe>", null);
061: }
062: }
063:
064: /**
065: * Adds a listener to be informed of changes to the browser's history stack.
066: *
067: * @param listener the listener to be added
068: */
069: public static void addHistoryListener(HistoryListener listener) {
070: historyListeners.add(listener);
071: }
072:
073: /**
074: * Programmatic equivalent to the user pressing the browser's 'back' button.
075: */
076: public static native void back() /*-{
077: $wnd.history.back();
078: }-*/;
079:
080: /**
081: * Programmatic equivalent to the user pressing the browser's 'forward'
082: * button.
083: */
084: public static native void forward() /*-{
085: $wnd.history.forward();
086: }-*/;
087:
088: /**
089: * Gets the current history token. The listener will not receive an
090: * onHistoryChanged() event for the initial token; requiring that an
091: * application request the token explicitly on startup gives it an opportunity
092: * to run different initialization code in the presence or absence of an
093: * initial token.
094: *
095: * @return the initial token, or the empty string if none is present.
096: */
097: public static String getToken() {
098: return impl != null ? impl.getToken() : "";
099: }
100:
101: /**
102: * Adds a new browser history entry. In hosted mode, the 'back' and 'forward'
103: * actions are accessible via the standard Alt-Left and Alt-Right keystrokes.
104: * Calling this method will cause {@link #onHistoryChanged} to be called as
105: * well.
106: *
107: * @param historyToken the token to associate with the new history item
108: */
109: public static void newItem(String historyToken) {
110: if (impl != null) {
111: impl.newItem(historyToken);
112: }
113: }
114:
115: public static void onHistoryChanged(String historyToken) {
116: UncaughtExceptionHandler handler = GWT
117: .getUncaughtExceptionHandler();
118: if (handler != null) {
119: fireHistoryChangedAndCatch(historyToken, handler);
120: } else {
121: fireHistoryChangedImpl(historyToken);
122: }
123: }
124:
125: /**
126: * Removes a history listener.
127: *
128: * @param listener the listener to be removed
129: */
130: public static void removeHistoryListener(HistoryListener listener) {
131: historyListeners.remove(listener);
132: }
133:
134: private static void fireHistoryChangedAndCatch(String historyToken,
135: UncaughtExceptionHandler handler) {
136: try {
137: fireHistoryChangedImpl(historyToken);
138: } catch (Throwable e) {
139: handler.onUncaughtException(e);
140: }
141: }
142:
143: private static void fireHistoryChangedImpl(String historyToken) {
144: for (HistoryListener listener : historyListeners) {
145: listener.onHistoryChanged(historyToken);
146: }
147: }
148: }
|