001: /*******************************************************************************
002: * Copyright (c) 2004, 2005 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal.intro.impl.model;
011:
012: import java.util.List;
013: import java.util.Vector;
014:
015: import org.eclipse.ui.internal.intro.impl.model.url.IntroURLParser;
016:
017: /*
018: * Intro History Model.
019: */
020: public class History {
021: // History of Intro Pages and real URL visited by Intro Browser. All
022: // elements are all of type HistoryObject.
023: private Vector history = new Vector();
024: private int navigationLocation = 0;
025:
026: // Model class for history objects. A history object may be a url or an
027: // Intro page. A url is a regular URL navigated to from a fully qualified
028: // link. An intro page may be an IFrame page. IFrame pages are not created
029: // for every Help topic navigated in an embedded IFrame. Instead the same
030: // IFrame is stored in history as a different object with the IFrameURL set.
031: // This way the model actually creates one page for every embedded Help
032: // Topic target but the navigation history updates the IFrame accordingly.
033: class HistoryObject {
034: AbstractIntroPage page;
035: String iframeUrl;
036: String url;
037:
038: HistoryObject(Object location) {
039: if (location instanceof String)
040: this .url = (String) location;
041:
042: if (location instanceof AbstractIntroPage) {
043: this .page = (AbstractIntroPage) location;
044: // will be set to null if the page is not an IFrame page.
045: this .iframeUrl = this .page.getIFrameURL();
046: }
047: }
048:
049: /**
050: * returns the history page. If iframe page, updated to correct url.
051: *
052: * @return
053: */
054: AbstractIntroPage getPage() {
055: if (page.isIFramePage())
056: // when page was stored, the IFrame url was also stored. Make
057: // sure to return the same state. The page is the same, only the
058: // IFrame url changes.
059: page.setIFrameURL(getIFrameUrl());
060: return page;
061: }
062:
063: String getPageId() {
064: return page.getId();
065: }
066:
067: String getIFrameUrl() {
068: return iframeUrl;
069: }
070:
071: String getUrl() {
072: return url;
073: }
074:
075: boolean isURL() {
076: return (url != null) ? true : false;
077: }
078:
079: boolean isIntroPage() {
080: return (page != null) ? true : false;
081: }
082:
083: boolean isIFramePage() {
084: return (iframeUrl != null) ? true : false;
085: }
086:
087: }
088:
089: /**
090: * Updates the UI navigation history with either a real URL, or a page ID.
091: *
092: * @param pageId
093: */
094: public void updateHistory(String location) {
095: // quick exit.
096: if (!history.isEmpty() && isSameLocation(location))
097: // resetting the same location is useless.
098: return;
099: doUpdateHistory(location);
100: }
101:
102: /**
103: * Updates the UI navigation history with either a real URL, or a page ID.
104: *
105: * @param page
106: */
107: public void updateHistory(AbstractIntroPage page) {
108: // quick exit.
109: if (!history.isEmpty() && isSameLocation(page))
110: // resetting the same location is useless.
111: return;
112: doUpdateHistory(page);
113: }
114:
115: private void doUpdateHistory(Object location) {
116: // we got here due to an intro URL listener or an SWT Form hyperlink
117: // listener. location may be a url or an IntroPage.
118: if (navigationLocation == getHistoryEndPosition())
119: // we are at the end of the vector, just push.
120: pushToHistory(location);
121: else
122: // we already navigated. add item at current location, and clear
123: // rest of history. (Same as browser behavior.)
124: trimHistory(location);
125: }
126:
127: private boolean isSameLocation(Object location) {
128: HistoryObject currentLocation = getCurrentLocation();
129: if (location instanceof String && currentLocation.isURL())
130: return currentLocation.getUrl().equals(location);
131:
132: if (location instanceof AbstractIntroPage
133: && currentLocation.isIntroPage()) {
134:
135: AbstractIntroPage locationPage = (AbstractIntroPage) location;
136: // be carefull here with calling getPage on historyOvject.
137: if (!currentLocation.getPageId().equals(
138: locationPage.getId()))
139: return false;
140:
141: // both pages have same ids, they are either both regular pages or
142: // both are Iframe pages. check if they have the same IFrame urls
143: if (currentLocation.isIFramePage()
144: && locationPage.isIFramePage())
145: return currentLocation.getIFrameUrl().equals(
146: locationPage.getIFrameURL());
147:
148: // both pages are not IFrame pages, and they have same id.
149: return true;
150: }
151:
152: return false;
153: }
154:
155: private void pushToHistory(Object location) {
156: history.add(new HistoryObject(location));
157: // point the nav location to the end of the vector.
158: navigationLocation = getHistoryEndPosition();
159: }
160:
161: public void removeLastHistory() {
162: history.remove(getHistoryEndPosition());
163: // point the nav location to the end of the vector.
164: navigationLocation = getHistoryEndPosition();
165: }
166:
167: private void trimHistory(Object location) {
168: List newHistory = history.subList(0, navigationLocation + 1);
169: history = new Vector(newHistory);
170: history.add(new HistoryObject(location));
171: // point the nav location to the end of the vector.
172: navigationLocation = getHistoryEndPosition();
173: }
174:
175: /**
176: * Return the position of the last element in the navigation history. If
177: * vector is empty, return 0.
178: *
179: * @param vector
180: * @return
181: */
182: private int getHistoryEndPosition() {
183: if (history.isEmpty())
184: return 0;
185: return history.size() - 1;
186: }
187:
188: public void navigateHistoryBackward() {
189: if (badNavigationLocation(navigationLocation - 1))
190: // do nothing. We are at the begining.
191: return;
192: --navigationLocation;
193: }
194:
195: /**
196: * Navigate forward in the history.
197: *
198: * @return
199: */
200: public void navigateHistoryForward() {
201: if (badNavigationLocation(navigationLocation + 1))
202: // do nothing. We are at the begining.
203: return;
204: ++navigationLocation;
205: }
206:
207: private boolean badNavigationLocation(int navigationLocation) {
208: if (navigationLocation < 0
209: || navigationLocation >= history.size())
210: // bad nav location.
211: return true;
212: return false;
213: }
214:
215: /**
216: * Returns true if the current location in the navigation history represents
217: * a URL. False if the location is an Intro Page id.
218: *
219: * @return Returns the locationIsURL.
220: */
221: private HistoryObject getCurrentLocation() {
222: return (HistoryObject) history.elementAt(navigationLocation);
223: }
224:
225: public boolean canNavigateForward() {
226: return navigationLocation != getHistoryEndPosition() ? true
227: : false;
228: }
229:
230: public boolean canNavigateBackward() {
231: return navigationLocation == 0 ? false : true;
232: }
233:
234: public boolean currentLocationIsUrl() {
235: return getCurrentLocation().isURL();
236: }
237:
238: public String getCurrentLocationAsUrl() {
239: return getCurrentLocation().getUrl();
240: }
241:
242: public AbstractIntroPage getCurrentLocationAsPage() {
243: return getCurrentLocation().getPage();
244: }
245:
246: public static boolean isURL(String aString) {
247: IntroURLParser parser = new IntroURLParser(aString);
248: if (parser.hasProtocol())
249: return true;
250: return false;
251: }
252:
253: public void clear() {
254: history.clear();
255: navigationLocation = 0;
256: }
257:
258: }
|