001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 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.views.framelist;
011:
012: import java.util.ArrayList;
013: import java.util.List;
014:
015: import org.eclipse.core.commands.common.EventManager;
016: import org.eclipse.core.runtime.Assert;
017: import org.eclipse.jface.util.IPropertyChangeListener;
018: import org.eclipse.jface.util.PropertyChangeEvent;
019:
020: /**
021: * Supports a web-browser style of navigation by maintaining a list
022: * of frames. Each frame holds a snapshot of a view at some point
023: * in time.
024: * <p>
025: * The frame list obtains a snapshot of the current frame from a frame source
026: * on creation, and whenever switching to a different frame.
027: * </p>
028: * <p>
029: * A property change notification is sent whenever the current page changes.
030: * </p>
031: */
032: public class FrameList extends EventManager {
033:
034: /** Property name constant for the current frame. */
035: public static final String P_CURRENT_FRAME = "currentFrame"; //$NON-NLS-1$
036:
037: private IFrameSource source;
038:
039: private List frames;
040:
041: private int current;
042:
043: /**
044: * Creates a new frame list with the given source.
045: *
046: * @param source the frame source
047: */
048: public FrameList(IFrameSource source) {
049: this .source = source;
050: Frame frame = source.getFrame(IFrameSource.CURRENT_FRAME, 0);
051: frame.setParent(this );
052: frame.setIndex(0);
053: frames = new ArrayList();
054: frames.add(frame);
055: current = 0;
056: }
057:
058: /**
059: * Adds a property change listener.
060: * Has no effect if an identical listener is already registered.
061: *
062: * @param listener a property change listener
063: */
064: public void addPropertyChangeListener(
065: IPropertyChangeListener listener) {
066: addListenerObject(listener);
067: }
068:
069: /**
070: * Moves the frame pointer back by one.
071: * Has no effect if there is no frame before the current one.
072: * Fires a <code>P_CURRENT_FRAME</code> property change event.
073: */
074: public void back() {
075: if (current > 0) {
076: setCurrent(current - 1);
077: }
078: }
079:
080: /**
081: * Notifies any property change listeners that a property has changed.
082: * Only listeners registered at the time this method is called are notified.
083: *
084: * @param event the property change event
085: *
086: * @see IPropertyChangeListener#propertyChange
087: */
088: protected void firePropertyChange(PropertyChangeEvent event) {
089: Object[] listeners = getListeners();
090: for (int i = 0; i < listeners.length; ++i) {
091: ((IPropertyChangeListener) listeners[i])
092: .propertyChange(event);
093: }
094: }
095:
096: /**
097: * Moves the frame pointer forward by one.
098: * Has no effect if there is no frame after the current one.
099: * Fires a <code>P_CURRENT_FRAME</code> property change event.
100: */
101: public void forward() {
102: if (current < frames.size() - 1) {
103: setCurrent(current + 1);
104: }
105: }
106:
107: /**
108: * Returns the current frame.
109: * Returns <code>null</code> if there is no current frame.
110: *
111: * @return the current frame, or <code>null</code>
112: */
113: public Frame getCurrentFrame() {
114: return getFrame(current);
115: }
116:
117: /**
118: * Returns the index of the current frame.
119: *
120: * @return the index of the current frame
121: */
122: public int getCurrentIndex() {
123: return current;
124: }
125:
126: /**
127: * Returns the frame at the given index, or <code>null</code>
128: * if the index is ≤ 0 or ≥ <code>size()</code>.
129: *
130: * @param index the index of the requested frame
131: * @return the frame at the given index or <code>null</code>
132: */
133: public Frame getFrame(int index) {
134: if (index < 0 || index >= frames.size()) {
135: return null;
136: }
137: return (Frame) frames.get(index);
138: }
139:
140: /**
141: * Returns the frame source.
142: */
143: public IFrameSource getSource() {
144: return source;
145: }
146:
147: /**
148: * Adds the given frame after the current frame,
149: * and advances the pointer to the new frame.
150: * Before doing so, updates the current frame, and removes any frames following the current frame.
151: * Fires a <code>P_CURRENT_FRAME</code> property change event.
152: *
153: * @param frame the frame to add
154: */
155: public void gotoFrame(Frame frame) {
156: for (int i = frames.size(); --i > current;) {
157: frames.remove(i);
158: }
159: frame.setParent(this );
160: int index = frames.size();
161: frame.setIndex(index);
162: frames.add(frame);
163: setCurrent(index);
164: }
165:
166: /**
167: * Removes a property change listener.
168: * Has no effect if an identical listener is not registered.
169: *
170: * @param listener a property change listener
171: */
172: public void removePropertyChangeListener(
173: IPropertyChangeListener listener) {
174: removeListenerObject(listener);
175: }
176:
177: /**
178: * Sets the current frame to the one with the given index.
179: * Updates the old current frame, and fires a <code>P_CURRENT_FRAME</code> property change event
180: * if the current frame changes.
181: *
182: * @param newCurrent the index of the frame
183: */
184: void setCurrent(int newCurrent) {
185: Assert.isTrue(newCurrent >= 0 && newCurrent < frames.size());
186: int oldCurrent = this .current;
187: if (oldCurrent != newCurrent) {
188: updateCurrentFrame();
189: this .current = newCurrent;
190: firePropertyChange(new PropertyChangeEvent(this ,
191: P_CURRENT_FRAME, getFrame(oldCurrent),
192: getFrame(newCurrent)));
193: }
194: }
195:
196: /**
197: * Sets the current frame to the frame with the given index.
198: * Fires a <code>P_CURRENT_FRAME</code> property change event
199: * if the current frame changes.
200: */
201: public void setCurrentIndex(int index) {
202: if (index != -1 && index != current) {
203: setCurrent(index);
204: }
205: }
206:
207: /**
208: * Returns the number of frames in the frame list.
209: */
210: public int size() {
211: return frames.size();
212: }
213:
214: /**
215: * Replaces the current frame in this list with the current frame
216: * from the frame source. No event is fired.
217: */
218: public void updateCurrentFrame() {
219: Assert.isTrue(current >= 0);
220: Frame frame = source.getFrame(IFrameSource.CURRENT_FRAME,
221: IFrameSource.FULL_CONTEXT);
222: frame.setParent(this);
223: frame.setIndex(current);
224: frames.set(current, frame);
225: }
226: }
|