KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > NavigationHistory


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.HashMap JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.LinkedList JavaDoc;
18 import java.util.Map JavaDoc;
19
20 import org.eclipse.core.runtime.Assert;
21 import org.eclipse.swt.widgets.Control;
22 import org.eclipse.swt.widgets.Display;
23 import org.eclipse.ui.IEditorInput;
24 import org.eclipse.ui.IEditorPart;
25 import org.eclipse.ui.IMemento;
26 import org.eclipse.ui.INavigationHistory;
27 import org.eclipse.ui.INavigationLocation;
28 import org.eclipse.ui.INavigationLocationProvider;
29 import org.eclipse.ui.IPartListener2;
30 import org.eclipse.ui.IWorkbenchPage;
31 import org.eclipse.ui.IWorkbenchPartReference;
32 import org.eclipse.ui.IWorkbenchPartSite;
33 import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
34 import org.eclipse.ui.internal.tweaklets.TabBehaviour;
35 import org.eclipse.ui.internal.tweaklets.Tweaklets;
36
37 /**
38  * Implementation of the back and forward actions.
39  */

40 public class NavigationHistory implements INavigationHistory {
41
42     private static final int CAPACITY = 50;
43
44     private NavigationHistoryAction backwardAction;
45
46     private NavigationHistoryAction forwardAction;
47
48     private int ignoreEntries;
49
50     private ArrayList JavaDoc history = new ArrayList JavaDoc(CAPACITY);
51     
52     Map JavaDoc perTabHistoryMap = new HashMap JavaDoc();
53
54     private ArrayList JavaDoc editors = new ArrayList JavaDoc(CAPACITY);
55
56     private WorkbenchPage page;
57
58     private int activeEntry = 0;
59
60     /**
61      * Creates a new NavigationHistory to keep the NavigationLocation
62      * entries of the specified page.
63      */

64     public NavigationHistory(final WorkbenchPage page) {
65         this.page = page;
66         page.addPartListener(new IPartListener2() {
67             public void partActivated(IWorkbenchPartReference partRef) {
68             }
69
70             public void partBroughtToTop(IWorkbenchPartReference partRef) {
71             }
72
73             public void partDeactivated(IWorkbenchPartReference partRef) {
74             }
75
76             public void partOpened(IWorkbenchPartReference partRef) {
77             }
78             
79             public void partHidden(IWorkbenchPartReference partRef) {
80             }
81             
82             public void partVisible(IWorkbenchPartReference partRef) {
83             }
84
85             public void partClosed(IWorkbenchPartReference partRef) {
86                 if (isPerTabHistoryEnabled() && partRef instanceof EditorReference) {
87                     if (!((EditorReference)partRef).isDisposed()) {
88                         Object JavaDoc editorTabCookie = ((EditorReference)partRef).getPane();
89                         disposeHistoryForTab(editorTabCookie);
90                         updateActions();
91                     }
92                 }
93                 updateNavigationHistory(partRef, true);
94             }
95             
96             public void partInputChanged(IWorkbenchPartReference partRef) {
97                 updateNavigationHistory(partRef, false);
98             }
99             
100             private void updateNavigationHistory(IWorkbenchPartReference partRef, boolean partClosed) {
101                 if (partRef != null && partRef.getPart(false) instanceof IEditorPart) {
102                     IEditorPart editor = (IEditorPart) partRef.getPart(false);
103                     IEditorInput input = editor.getEditorInput();
104                     String JavaDoc id = editor.getSite().getId();
105                     Iterator JavaDoc e = editors.iterator();
106                     NavigationHistoryEditorInfo info = null;
107                     NavigationHistoryEditorInfo currentInfo = null;
108                     NavigationHistoryEntry current = getEntry(activeEntry);
109                     if (current != null) {
110                         currentInfo = current.editorInfo;
111                     }
112                     while (e.hasNext()) {
113                         info = (NavigationHistoryEditorInfo) e.next();
114                         if (id.equals(info.editorID)
115                                 && input.equals(info.editorInput)) {
116                             if (partClosed && info != currentInfo) {
117                                 info.handlePartClosed();
118                             }
119                             break;
120                         }
121                         info = null;
122                     }
123                     if (info == null) {
124                         return;
125                     }
126                     boolean isEntryDisposed = false;
127                     e = history.iterator();
128                     int i = 0;
129                     while (e.hasNext()) {
130                         NavigationHistoryEntry entry = (NavigationHistoryEntry) e
131                                 .next();
132                         if (entry.editorInfo == info) {
133                             if (!entry.handlePartClosed()) {
134                                 // update the active entry since we are removing an item
135
if (i < activeEntry) {
136                                     activeEntry--;
137                                 } else if (i == activeEntry) {
138                                     if (i != 0) {
139                                         activeEntry--;
140                                     }
141                                 } else {
142                                     // activeEntry is before item we deleted
143
i++;
144                                 }
145                                 isEntryDisposed = true;
146                                 e.remove();
147                                 disposeEntry(entry);
148                             } else {
149                                 i++;
150                             }
151                         }
152                     }
153                     
154                     /*
155                      * Promote the entry of the last closed editor to be the active
156                      * one, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=154431
157                      */

158                     if (!isEntryDisposed && page.getActiveEditor() == null && activeEntry < history.size())
159                         activeEntry++;
160                     
161                     updateActions();
162                 }
163             }
164         });
165     }
166
167     private Display getDisplay() {
168         return page.getWorkbenchWindow().getShell().getDisplay();
169     }
170     
171     private boolean isPerTabHistoryEnabled() {
172         return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).isPerTabHistoryEnabled();
173     }
174
175     /*
176      * Adds an editor to the editor history without getting its location.
177      */

178     public void markEditor(final IEditorPart part) {
179         if (ignoreEntries > 0 || part == null) {
180             return;
181         }
182         /* Ignore all entries until the async exec runs. Workaround to avoid
183          * extra entry when using Open Declaration (F3) that opens another editor. */

184         ignoreEntries++;
185         getDisplay().asyncExec(new Runnable JavaDoc() {
186             public void run() {
187                 if (--ignoreEntries == 0) {
188                     if (part.getEditorSite() instanceof EditorSite) {
189                         EditorSite site = (EditorSite) part.getEditorSite();
190                         Control c = site.getPane().getControl();
191                         if (c == null || c.isDisposed()) {
192                             return;
193                         }
194                         NavigationHistoryEntry e = getEntry(activeEntry);
195                         if (e != null
196                                 && part.getEditorInput() != e.editorInfo.editorInput) {
197                             updateEntry(e);
198                         }
199                         addEntry(part);
200                     }
201                 }
202             }
203         });
204     }
205
206     /*
207      * (non-Javadoc)
208      * Method declared on INavigationHistory.
209      */

210     public void markLocation(IEditorPart part) {
211         addEntry(part);
212     }
213
214     /*
215      * Return the backward history entries. Return in restore order (i.e., the
216      * first entry is the entry that would become active if the "Backward" action
217      * was executed).
218      * <p>
219      * (Called by NavigationHistoryAction)
220      * </p>
221      */

222     NavigationHistoryEntry[] getBackwardEntries() {
223         if (isPerTabHistoryEnabled()) {
224             return getEntriesForTab(false);
225         }
226         int length = activeEntry;
227         NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length];
228         for (int i = 0; i < activeEntry; i++) {
229             entries[activeEntry - 1 - i] = getEntry(i);
230         }
231         return entries;
232     }
233
234     /*
235      * Return the forward history entries. Return in restore order (i.e., the first
236      * entry is the entry that would become active if the "Forward" action was
237      * executed).
238      * <p>
239      * (Called by NavigationHistoryAction)
240      * </p>
241      */

242     NavigationHistoryEntry[] getForwardEntries() {
243         if (isPerTabHistoryEnabled()) {
244             return getEntriesForTab(true);
245         }
246         int length = history.size() - activeEntry - 1;
247         length = Math.max(0, length);
248         NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length];
249         for (int i = activeEntry + 1; i < history.size(); i++) {
250             entries[i - activeEntry - 1] = getEntry(i);
251         }
252         return entries;
253     }
254
255     /*
256      * (non-Javadoc)
257      * Method declared on INavigationHistory.
258      */

259     public INavigationLocation[] getLocations() {
260         INavigationLocation result[] = new INavigationLocation[history.size()];
261         for (int i = 0; i < result.length; i++) {
262             NavigationHistoryEntry e = (NavigationHistoryEntry) history.get(i);
263             result[i] = e.location;
264         }
265         return result;
266     }
267
268     /*
269      * (non-Javadoc)
270      * Method declared on INavigationHistory.
271      */

272     public INavigationLocation getCurrentLocation() {
273         NavigationHistoryEntry entry = getEntry(activeEntry);
274         return entry == null ? null : entry.location;
275     }
276
277     /**
278      * Disposes this NavigationHistory and all entries.
279      */

280     public void dispose() {
281         disposeHistoryForTabs();
282         Iterator JavaDoc e = history.iterator();
283         while (e.hasNext()) {
284             NavigationHistoryEntry entry = (NavigationHistoryEntry) e.next();
285             disposeEntry(entry);
286         }
287     }
288
289     /**
290      * Keeps a reference to the forward action to update its state
291      * whenever needed.
292      * <p>
293      * (Called by NavigationHistoryAction)
294      * </p>
295      */

296     void setForwardAction(NavigationHistoryAction action) {
297         forwardAction = action;
298         updateActions();
299     }
300
301     /**
302      * Keeps a reference to the backward action to update its state
303      * whenever needed.
304      * <p>
305      * (Called by NavigationHistoryAction)
306      * </p>
307      */

308     void setBackwardAction(NavigationHistoryAction action) {
309         backwardAction = action;
310         updateActions();
311     }
312
313     /*
314      * Returns the history entry indexed by <code>index</code>
315      */

316     private NavigationHistoryEntry getEntry(int index) {
317         if (0 <= index && index < history.size()) {
318             return (NavigationHistoryEntry) history.get(index);
319         }
320         return null;
321     }
322
323     /*
324      * Adds the specified entry to the history.
325      */

326     private void add(NavigationHistoryEntry entry) {
327         removeForwardEntries();
328         if (history.size() == CAPACITY) {
329             NavigationHistoryEntry e = (NavigationHistoryEntry) history
330                     .remove(0);
331             disposeEntry(e);
332         }
333         history.add(entry);
334         activeEntry = history.size() - 1;
335     }
336
337     /*
338      * Remove all entries after the active entry.
339      */

340     private void removeForwardEntries() {
341         int length = history.size();
342         for (int i = activeEntry + 1; i < length; i++) {
343             NavigationHistoryEntry e = (NavigationHistoryEntry) history
344                     .remove(activeEntry + 1);
345             disposeEntry(e);
346         }
347     }
348
349     /*
350      * Adds a location to the history.
351      */

352     private void addEntry(IEditorPart part) {
353         if (ignoreEntries > 0 || part == null) {
354             return;
355         }
356
357         if (isPerTabHistoryEnabled()) {
358             markLocationForTab(part);
359         }
360         INavigationLocation location = null;
361         if (part instanceof INavigationLocationProvider) {
362             location = ((INavigationLocationProvider) part)
363                     .createNavigationLocation();
364         }
365
366         NavigationHistoryEntry current = getEntry(activeEntry);
367         if (current != null && current.editorInfo.memento != null) {
368             current.editorInfo.restoreEditor();
369             checkDuplicates(current.editorInfo);
370         }
371         NavigationHistoryEntry e = createEntry(page, part, location);
372         if (current == null) {
373             add(e);
374         } else {
375             if (e.mergeInto(current)) {
376                 disposeEntry(e);
377                 removeForwardEntries();
378             } else {
379                 add(e);
380             }
381         }
382         printEntries("added entry"); //$NON-NLS-1$
383
updateActions();
384     }
385
386     /*
387      * Prints all the entries in the console. For debug only.
388      */

389     private void printEntries(String JavaDoc label) {
390         if (false) {
391             System.out.println("+++++ " + label + "+++++ "); //$NON-NLS-1$ //$NON-NLS-2$
392
int size = history.size();
393             for (int i = 0; i < size; i++) {
394                 String JavaDoc append = activeEntry == i ? ">>" : ""; //$NON-NLS-1$ //$NON-NLS-2$
395
System.out.println(append
396                         + "Index: " + i + " " + history.get(i)); //$NON-NLS-1$ //$NON-NLS-2$
397
}
398         }
399     }
400
401     /*
402      * Returns true if the forward action can be performed otherwise returns false.
403      * <p>
404      * (Called by NavigationHistoryAction)
405      * </p>
406      */

407     /* package */boolean canForward() {
408         if (isPerTabHistoryEnabled()) {
409             return hasEntriesForTab(true);
410         }
411         return (0 <= activeEntry + 1) && (activeEntry + 1 < history.size());
412     }
413
414     /*
415      * Returns true if the backward action can be performed otherwise returns false.
416      * <p>
417      * (Called by NavigationHistoryAction)
418      * </p>
419      */

420     /* package */boolean canBackward() {
421         if (isPerTabHistoryEnabled()) {
422             return hasEntriesForTab(false);
423         }
424         return (0 <= activeEntry - 1) && (activeEntry - 1 < history.size());
425     }
426
427     /*
428      * Update the actions enable/disable and tooltip state.
429      */

430     private void updateActions() {
431         if (backwardAction != null) {
432             backwardAction.update();
433         }
434         if (forwardAction != null) {
435             forwardAction.update();
436         }
437     }
438
439     /*
440      * Restore the specified entry
441      */

442     private void gotoEntry(NavigationHistoryEntry entry) {
443         if (entry == null) {
444             return;
445         }
446         try {
447             ignoreEntries++;
448             if (entry.editorInfo.memento != null) {
449                 entry.editorInfo.restoreEditor();
450                 checkDuplicates(entry.editorInfo);
451             }
452             entry.restoreLocation();
453             updateActions();
454             printEntries("goto entry"); //$NON-NLS-1$
455
} finally {
456             ignoreEntries--;
457         }
458     }
459
460     /*
461      * update the active entry
462      */

463     private void updateEntry(NavigationHistoryEntry activeEntry) {
464         if (activeEntry == null || activeEntry.location == null) {
465             return;
466         }
467         activeEntry.location.update();
468         printEntries("updateEntry"); //$NON-NLS-1$
469
}
470
471     /*
472      * Perform the forward action by getting the next location and restoring
473      * its context.
474      * <p>
475      * (Called by NavigationHistoryAction)
476      * </p>
477      */

478     void forward() {
479         if (isPerTabHistoryEnabled()) {
480             forwardForTab();
481             return;
482         }
483         if (canForward()) {
484             shiftEntry(true);
485         }
486     }
487
488     /*
489      * Perform the backward action by getting the previous location and restoring
490      * its context.
491      * <p>
492      * (Called by NavigationHistoryAction)
493      * </p>
494      */

495     void backward() {
496         if (isPerTabHistoryEnabled()) {
497             backwardForTab();
498             return;
499         }
500         if (canBackward()) {
501             shiftEntry(false);
502         }
503     }
504
505     /*
506      * Shift the history back or forward
507      */

508     private void shiftEntry(boolean forward) {
509         updateEntry(getEntry(activeEntry));
510         if (forward) {
511             activeEntry++;
512         } else {
513             activeEntry--;
514         }
515         NavigationHistoryEntry entry = getEntry(activeEntry);
516         if (entry != null) {
517             gotoEntry(entry);
518         }
519     }
520
521     /*
522      * Shift the history to the given entry.
523      * <p>
524      * (Called by NavigationHistoryAction)
525      * </p>
526      */

527     void shiftCurrentEntry(NavigationHistoryEntry entry, boolean forward) {
528         if (isPerTabHistoryEnabled()) {
529             gotoEntryForTab(entry, forward);
530             return;
531         }
532         updateEntry(getEntry(activeEntry));
533         activeEntry = history.indexOf(entry);
534         gotoEntry(entry);
535     }
536
537     /**
538      * Save the state of this history into the memento.
539      */

540     void saveState(IMemento memento) {
541         NavigationHistoryEntry cEntry = getEntry(activeEntry);
542         if (cEntry == null || !cEntry.editorInfo.isPersistable()) {
543             return;
544         }
545
546         ArrayList JavaDoc editors = (ArrayList JavaDoc) this.editors.clone();
547         for (Iterator JavaDoc iter = editors.iterator(); iter.hasNext();) {
548             NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter
549                     .next();
550             if (!info.isPersistable()) {
551                 iter.remove();
552             }
553         }
554         IMemento editorsMem = memento
555                 .createChild(IWorkbenchConstants.TAG_EDITORS);
556         for (Iterator JavaDoc iter = editors.iterator(); iter.hasNext();) {
557             NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter
558                     .next();
559             info.saveState(editorsMem
560                     .createChild(IWorkbenchConstants.TAG_EDITOR));
561         }
562
563         ArrayList JavaDoc list = new ArrayList JavaDoc(history.size());
564         int size = history.size();
565         for (int i = 0; i < size; i++) {
566             NavigationHistoryEntry entry = (NavigationHistoryEntry) history
567                     .get(i);
568             if (entry.editorInfo.isPersistable()) {
569                 list.add(entry);
570             }
571         }
572         size = list.size();
573         for (int i = 0; i < size; i++) {
574             NavigationHistoryEntry entry = (NavigationHistoryEntry) list.get(i);
575             IMemento childMem = memento
576                     .createChild(IWorkbenchConstants.TAG_ITEM);
577             if (entry == cEntry) {
578                 childMem.putString(IWorkbenchConstants.TAG_ACTIVE, "true"); //$NON-NLS-1$
579
}
580             entry.saveState(childMem, list);
581             childMem.putInteger(IWorkbenchConstants.TAG_INDEX, editors
582                     .indexOf(entry.editorInfo));
583         }
584     }
585
586     /**
587      * Restore the state of this history from the memento.
588      */

589     void restoreState(IMemento memento) {
590         IMemento editorsMem = memento.getChild(IWorkbenchConstants.TAG_EDITORS);
591         IMemento items[] = memento.getChildren(IWorkbenchConstants.TAG_ITEM);
592         if (items.length == 0 || editorsMem == null) {
593             if (page.getActiveEditor() != null) {
594                 markLocation(page.getActiveEditor());
595             }
596             return;
597         }
598
599         IMemento children[] = editorsMem
600                 .getChildren(IWorkbenchConstants.TAG_EDITOR);
601         NavigationHistoryEditorInfo editorsInfo[] = new NavigationHistoryEditorInfo[children.length];
602         for (int i = 0; i < editorsInfo.length; i++) {
603             editorsInfo[i] = new NavigationHistoryEditorInfo(children[i]);
604             editors.add(editorsInfo[i]);
605         }
606
607         for (int i = 0; i < items.length; i++) {
608             IMemento item = items[i];
609             int index = item.getInteger(IWorkbenchConstants.TAG_INDEX)
610                     .intValue();
611             NavigationHistoryEditorInfo info = editorsInfo[index];
612             info.refCount++;
613             NavigationHistoryEntry entry = new NavigationHistoryEntry(info,
614                     page, null, null);
615             history.add(entry);
616             entry.restoreState(item);
617             if (item.getString(IWorkbenchConstants.TAG_ACTIVE) != null) {
618                 activeEntry = i;
619             }
620         }
621
622         final NavigationHistoryEntry entry = getEntry(activeEntry);
623         if (entry != null && entry.editorInfo.editorInput != null) {
624             if (page.getActiveEditor() == page
625                     .findEditor(entry.editorInfo.editorInput)) {
626                 StartupThreading.runWithoutExceptions(new StartupRunnable() {
627
628                     public void runWithException() throws Throwable JavaDoc {
629                         gotoEntry(entry);
630                     }});
631             }
632         }
633     }
634
635     public NavigationHistoryEntry createEntry(IWorkbenchPage page,
636             IEditorPart part, INavigationLocation location) {
637         String JavaDoc editorID = part.getSite().getId();
638         IEditorInput editorInput = part.getEditorInput();
639         NavigationHistoryEditorInfo info = null;
640         for (Iterator JavaDoc iter = editors.iterator(); iter.hasNext();) {
641             info = (NavigationHistoryEditorInfo) iter.next();
642             if (editorID.equals(info.editorID)
643                     && editorInput.equals(info.editorInput)) {
644                 info.refCount++;
645                 break;
646             } else {
647                 info = null;
648             }
649         }
650         if (info == null) {
651             info = new NavigationHistoryEditorInfo(part);
652             info.refCount++;
653             editors.add(info);
654         }
655         return new NavigationHistoryEntry(info, page, part, location);
656     }
657
658     public void disposeEntry(NavigationHistoryEntry entry) {
659         if (entry.editorInfo == null) {
660             return;
661         }
662         entry.editorInfo.refCount--;
663         if (entry.editorInfo.refCount == 0) {
664             editors.remove(entry.editorInfo);
665         }
666         entry.dispose();
667     }
668
669     void checkDuplicates(NavigationHistoryEditorInfo info) {
670         NavigationHistoryEditorInfo dup = null;
671         if (info.editorInput == null) {
672             return;
673         }
674         for (Iterator JavaDoc iter = editors.iterator(); iter.hasNext();) {
675             dup = (NavigationHistoryEditorInfo) iter.next();
676             if (info != dup && info.editorID.equals(dup.editorID)
677                     && info.editorInput.equals(dup.editorInput)) {
678                 break;
679             } else {
680                 dup = null;
681             }
682         }
683         if (dup == null) {
684             return;
685         }
686         for (Iterator JavaDoc iter = history.iterator(); iter.hasNext();) {
687             NavigationHistoryEntry entry = (NavigationHistoryEntry) iter.next();
688             if (entry.editorInfo == dup) {
689                 entry.editorInfo = info;
690                 info.refCount++;
691             }
692         }
693         editors.remove(dup);
694     }
695     
696     /*********************************************************/
697     /*** new per-tab history code ***/
698     /*********************************************************/
699     
700     
701     private static class PerTabHistory {
702         LinkedList JavaDoc backwardEntries = new LinkedList JavaDoc();
703         NavigationHistoryEntry currentEntry = null;
704         LinkedList JavaDoc forwardEntries = new LinkedList JavaDoc();
705     }
706     
707     private void setNewCurrentEntryForTab(PerTabHistory perTabHistory, NavigationHistoryEntry entry) {
708         if (perTabHistory.currentEntry != null) {
709             perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry);
710         }
711         perTabHistory.currentEntry = entry;
712         removeEntriesForTab(perTabHistory.forwardEntries);
713     }
714     
715     private Object JavaDoc getCookieForTab(IEditorPart part) {
716         if (part != null) {
717             IWorkbenchPartSite site = part.getSite();
718             if (site instanceof PartSite) {
719                 PartSite partSite = (PartSite) site;
720                 WorkbenchPartReference ref = (WorkbenchPartReference) partSite.getPartReference();
721                 if (!ref.isDisposed()) {
722                     return partSite.getPane();
723                 }
724             }
725         }
726         return null;
727     }
728     
729     private void markLocationForTab(IEditorPart part) {
730         if (part instanceof ErrorEditorPart) {
731             updateActions();
732             return;
733         }
734         Object JavaDoc tabCookie = getCookieForTab(part);
735         if (tabCookie != null) {
736             INavigationLocation location = null;
737             if (part instanceof INavigationLocationProvider) {
738                 location = ((INavigationLocationProvider) part)
739                         .createNavigationLocation();
740             }
741             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap
742                     .get(tabCookie);
743             if (perTabHistory == null) {
744                 perTabHistory = new PerTabHistory();
745                 perTabHistoryMap.put(tabCookie, perTabHistory);
746             }
747             NavigationHistoryEntry current = perTabHistory.currentEntry;
748             if (current != null && current.editorInfo.memento != null) {
749                 current.editorInfo.restoreEditor();
750                 checkDuplicates(current.editorInfo);
751             }
752             NavigationHistoryEntry entry = createEntry(page, part, location);
753             if (current != null && entry.mergeInto(current)) {
754                 disposeEntry(entry);
755                 removeEntriesForTab(perTabHistory.forwardEntries);
756             } else {
757                 setNewCurrentEntryForTab(perTabHistory, entry);
758             }
759         }
760         updateActions();
761     }
762     
763     public void updateCookieForTab(Object JavaDoc oldCookie, Object JavaDoc newCookie) {
764         if (newCookie.equals(oldCookie)) {
765             return;
766         }
767         PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(oldCookie);
768         if (perTabHistory != null) {
769             perTabHistoryMap.put(newCookie, perTabHistory);
770         }
771     }
772     
773     private void gotoEntryForTab(NavigationHistoryEntry target, boolean forward) {
774         Object JavaDoc editorTabCookie = getCookieForTab(page.getActiveEditor());
775         if (editorTabCookie!=null) {
776             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
777             if (perTabHistory != null) {
778                 LinkedList JavaDoc source = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries;
779                 LinkedList JavaDoc destination = forward ? perTabHistory.backwardEntries : perTabHistory.forwardEntries;
780                 if (perTabHistory.currentEntry != null) {
781                     if (perTabHistory.currentEntry.location != null) {
782                         perTabHistory.currentEntry.location.update();
783                     }
784                     destination.addFirst(perTabHistory.currentEntry);
785                 }
786                 NavigationHistoryEntry newCurrent = null;
787                 while (!source.isEmpty() && newCurrent==null) {
788                     NavigationHistoryEntry entry = (NavigationHistoryEntry) source
789                             .removeFirst();
790                     if (entry.equals(target)) {
791                         newCurrent = entry;
792                     } else {
793                         destination.addFirst(entry);
794                     }
795                 }
796                 Assert.isTrue(newCurrent != null);
797                 perTabHistory.currentEntry = newCurrent;
798                 try {
799                     ignoreEntries++;
800                     if (newCurrent.editorInfo.memento != null) {
801                         newCurrent.editorInfo.restoreEditor();
802                         checkDuplicates(newCurrent.editorInfo);
803                     }
804                     newCurrent.restoreLocation();
805                     updateActions();
806                 } finally {
807                     ignoreEntries--;
808                 }
809             }
810         }
811     }
812     
813     private void forwardForTab() {
814         Object JavaDoc editorTabCookie = getCookieForTab(page.getActiveEditor());
815         if (editorTabCookie!=null) {
816             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
817             if (perTabHistory != null && !perTabHistory.forwardEntries.isEmpty()) {
818                 NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.forwardEntries
819                         .removeFirst();
820                 if (perTabHistory.currentEntry != null) {
821                     final INavigationLocation location = perTabHistory.currentEntry.location;
822                     if (location!=null) {
823                         location.update();
824                     }
825                     perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry);
826                 }
827                 perTabHistory.currentEntry = newCurrent;
828                 try {
829                     ignoreEntries++;
830                     if (newCurrent.editorInfo.memento != null) {
831                         newCurrent.editorInfo.restoreEditor();
832                         checkDuplicates(newCurrent.editorInfo);
833                     }
834                     newCurrent.restoreLocation();
835                     updateActions();
836                 } finally {
837                     ignoreEntries--;
838                 }
839             }
840         }
841     }
842     
843     private void backwardForTab() {
844         Object JavaDoc editorTabCookie = getCookieForTab(page.getActiveEditor());
845         if (editorTabCookie!=null) {
846             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
847             if (perTabHistory != null && !perTabHistory.backwardEntries.isEmpty()) {
848                 NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.backwardEntries
849                         .removeFirst();
850                 if (perTabHistory.currentEntry != null) {
851                     perTabHistory.currentEntry.location.update();
852                     perTabHistory.forwardEntries.addFirst(perTabHistory.currentEntry);
853                 }
854                 perTabHistory.currentEntry = newCurrent;
855                 try {
856                     ignoreEntries++;
857                     if (newCurrent.editorInfo.memento != null) {
858                         newCurrent.editorInfo.restoreEditor();
859                         checkDuplicates(newCurrent.editorInfo);
860                     }
861                     newCurrent.restoreLocation();
862                     updateActions();
863                 } finally {
864                     ignoreEntries--;
865                 }
866             }
867         }
868     }
869     
870     private boolean hasEntriesForTab(boolean forward) {
871         Object JavaDoc editorTabCookie = getCookieForTab(page.getActiveEditor());
872         if (editorTabCookie!=null) {
873             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
874             if (perTabHistory != null) {
875                 LinkedList JavaDoc entries = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries;
876                 return !entries.isEmpty();
877             }
878         }
879         return false;
880     }
881
882     /**
883      * Returns entries in restore order.
884      * @param editorTabCookie
885      * @param forward
886      * @return
887      */

888     private NavigationHistoryEntry[] getEntriesForTab(boolean forward) {
889         Object JavaDoc editorTabCookie = getCookieForTab(page.getActiveEditor());
890         if (editorTabCookie != null) {
891             PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap
892                     .get(editorTabCookie);
893             if (perTabHistory != null) {
894                 LinkedList JavaDoc entries = forward ? perTabHistory.forwardEntries
895                         : perTabHistory.backwardEntries;
896                 return (NavigationHistoryEntry[]) entries
897                 .toArray(new NavigationHistoryEntry[entries.size()]);
898             }
899         }
900         return new NavigationHistoryEntry[0];
901     }
902     
903     private void disposeHistoryForTabs() {
904         Object JavaDoc[] keys = perTabHistoryMap.keySet().toArray();
905         for (int i = 0; i < keys.length; i++) {
906             disposeHistoryForTab(keys[i]);
907         }
908     }
909
910     void disposeHistoryForTab(Object JavaDoc editorTabCookie) {
911         PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(editorTabCookie);
912         if (perTabHistory != null) {
913             if (perTabHistory.currentEntry != null) {
914                 disposeEntry(perTabHistory.currentEntry);
915                 perTabHistory.currentEntry = null;
916             }
917             removeEntriesForTab(perTabHistory.backwardEntries);
918             removeEntriesForTab(perTabHistory.forwardEntries);
919         }
920     }
921
922     private void removeEntriesForTab(LinkedList JavaDoc entries) {
923         for (Iterator JavaDoc it = entries.iterator(); it.hasNext();) {
924             NavigationHistoryEntry entry = (NavigationHistoryEntry) it.next();
925             disposeEntry(entry);
926             it.remove();
927         }
928     }
929 }
930
Popular Tags