Package org.eclipse.ui.internal

Source Code of org.eclipse.ui.internal.NavigationHistory

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

package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;

import org.eclipse.core.runtime.Assert;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.INavigationHistory;
import org.eclipse.ui.INavigationLocation;
import org.eclipse.ui.INavigationLocationProvider;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.tweaklets.TabBehaviour;
import org.eclipse.ui.internal.tweaklets.Tweaklets;

/**
* Implementation of the back and forward actions.
*/
public class NavigationHistory implements INavigationHistory {

    private static final int CAPACITY = 50;

    private NavigationHistoryAction backwardAction;

    private NavigationHistoryAction forwardAction;

    private int ignoreEntries;

    private ArrayList history = new ArrayList(CAPACITY);
   
    Map perTabHistoryMap = new HashMap();

    private ArrayList editors = new ArrayList(CAPACITY);

    private WorkbenchPage page;

    private int activeEntry = 0;

    /**
     * Creates a new NavigationHistory to keep the NavigationLocation
     * entries of the specified page.
     */
    public NavigationHistory(final WorkbenchPage page) {
        this.page = page;
        page.addPartListener(new IPartListener2() {
            public void partActivated(IWorkbenchPartReference partRef) {
            }

            public void partBroughtToTop(IWorkbenchPartReference partRef) {
            }

            public void partDeactivated(IWorkbenchPartReference partRef) {
            }

            public void partOpened(IWorkbenchPartReference partRef) {
            }
     
            public void partHidden(IWorkbenchPartReference partRef) {
            }
     
            public void partVisible(IWorkbenchPartReference partRef) {
            }

            public void partClosed(IWorkbenchPartReference partRef) {
              if (isPerTabHistoryEnabled() && partRef instanceof EditorReference) {
                if (!((EditorReference)partRef).isDisposed()) {
                  Object editorTabCookie = ((EditorReference)partRef).getPane();
                  disposeHistoryForTab(editorTabCookie);
                  updateActions();
                }
              }
        updateNavigationHistory(partRef, true);
            }
     
      public void partInputChanged(IWorkbenchPartReference partRef) {
        updateNavigationHistory(partRef, false);
      }
     
      private void updateNavigationHistory(IWorkbenchPartReference partRef, boolean partClosed) {
                if (partRef != null && partRef.getPart(false) instanceof IEditorPart) {
                    IEditorPart editor = (IEditorPart) partRef.getPart(false);
                    IEditorInput input = editor.getEditorInput();
                    String id = editor.getSite().getId();
                    Iterator e = editors.iterator();
                    NavigationHistoryEditorInfo info = null;
                    NavigationHistoryEditorInfo currentInfo = null;
                    NavigationHistoryEntry current = getEntry(activeEntry);
                    if (current != null) {
            currentInfo = current.editorInfo;
          }
                    while (e.hasNext()) {
                        info = (NavigationHistoryEditorInfo) e.next();
                        if (id.equals(info.editorID)
                                && input.equals(info.editorInput)) {
                            if (partClosed && info != currentInfo) {
                info.handlePartClosed();
              }
                            break;
                        }
            info = null;
                    }
                    if (info == null) {
            return;
          }
                    boolean isEntryDisposed = false;
                    e = history.iterator();
                    int i = 0;
                    while (e.hasNext()) {
                        NavigationHistoryEntry entry = (NavigationHistoryEntry) e
                                .next();
                        if (entry.editorInfo == info) {
              if (!entry.handlePartClosed()) {
                                // update the active entry since we are removing an item
                                if (i < activeEntry) {
                                    activeEntry--;
                                } else if (i == activeEntry) {
                                    if (i != 0) {
                    activeEntry--;
                  }
                                } else {
                                    // activeEntry is before item we deleted
                                    i++;
                                }
                                isEntryDisposed = true;
                                e.remove();
                                disposeEntry(entry);
                            } else {
                                i++;
                            }
            }
                    }
                   
                    /*
                     * Promote the entry of the last closed editor to be the active
                     * one, see: https://bugs.eclipse.org/bugs/show_bug.cgi?id=154431
                     */
                    if (!isEntryDisposed && page.getActiveEditor() == null && activeEntry < history.size())
                      activeEntry++;
                   
                    updateActions();
                }
            }
        });
    }

    private Display getDisplay() {
        return page.getWorkbenchWindow().getShell().getDisplay();
    }
   
    private boolean isPerTabHistoryEnabled() {
      return ((TabBehaviour)Tweaklets.get(TabBehaviour.KEY)).isPerTabHistoryEnabled();
    }

    /*
     * Adds an editor to the editor history without getting its location.
     */
    public void markEditor(final IEditorPart part) {
        if (ignoreEntries > 0 || part == null) {
      return;
    }
        /* Ignore all entries until the async exec runs. Workaround to avoid
         * extra entry when using Open Declaration (F3) that opens another editor. */
        ignoreEntries++;
        getDisplay().asyncExec(new Runnable() {
            public void run() {
                if (--ignoreEntries == 0) {
                  if (part.getEditorSite() instanceof EditorSite) {
            EditorSite site = (EditorSite) part.getEditorSite();
                    Control c = site.getPane().getControl();
                    if (c == null || c.isDisposed()) {
              return;
            }
                    NavigationHistoryEntry e = getEntry(activeEntry);
                    if (e != null
                            && part.getEditorInput() != e.editorInfo.editorInput) {
              updateEntry(e);
            }
                    addEntry(part);
                  }
                }
            }
        });
    }

    /*
     * (non-Javadoc)
     * Method declared on INavigationHistory.
     */
    public void markLocation(IEditorPart part) {
        addEntry(part);
    }

    /*
     * Return the backward history entries.  Return in restore order (i.e., the
     * first entry is the entry that would become active if the "Backward" action
     * was executed).
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    NavigationHistoryEntry[] getBackwardEntries() {
      if (isPerTabHistoryEnabled()) {
        return getEntriesForTab(false);
      }
        int length = activeEntry;
        NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length];
        for (int i = 0; i < activeEntry; i++) {
            entries[activeEntry - 1 - i] = getEntry(i);
        }
        return entries;
    }

    /*
     * Return the forward history entries.  Return in restore order (i.e., the first
     * entry is the entry that would become active if the "Forward" action was
     * executed).
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    NavigationHistoryEntry[] getForwardEntries() {
      if (isPerTabHistoryEnabled()) {
        return getEntriesForTab(true);
      }
        int length = history.size() - activeEntry - 1;
        length = Math.max(0, length);
        NavigationHistoryEntry[] entries = new NavigationHistoryEntry[length];
        for (int i = activeEntry + 1; i < history.size(); i++) {
            entries[i - activeEntry - 1] = getEntry(i);
        }
        return entries;
    }

    /*
     * (non-Javadoc)
     * Method declared on INavigationHistory.
     */
    public INavigationLocation[] getLocations() {
        INavigationLocation result[] = new INavigationLocation[history.size()];
        for (int i = 0; i < result.length; i++) {
            NavigationHistoryEntry e = (NavigationHistoryEntry) history.get(i);
            result[i] = e.location;
        }
        return result;
    }

    /*
     * (non-Javadoc)
     * Method declared on INavigationHistory.
     */
    public INavigationLocation getCurrentLocation() {
        NavigationHistoryEntry entry = getEntry(activeEntry);
        return entry == null ? null : entry.location;
    }

    /**
     * Disposes this NavigationHistory and all entries.
     */
    public void dispose() {
      disposeHistoryForTabs();
        Iterator e = history.iterator();
        while (e.hasNext()) {
            NavigationHistoryEntry entry = (NavigationHistoryEntry) e.next();
            disposeEntry(entry);
        }
    }

    /**
     * Keeps a reference to the forward action to update its state
     * whenever needed.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    void setForwardAction(NavigationHistoryAction action) {
        forwardAction = action;
        updateActions();
    }

    /**
     * Keeps a reference to the backward action to update its state
     * whenever needed.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    void setBackwardAction(NavigationHistoryAction action) {
        backwardAction = action;
        updateActions();
    }

    /*
     * Returns the history entry indexed by <code>index</code>
     */
    private NavigationHistoryEntry getEntry(int index) {
        if (0 <= index && index < history.size()) {
      return (NavigationHistoryEntry) history.get(index);
    }
        return null;
    }

    /*
     * Adds the specified entry to the history.
     */
    private void add(NavigationHistoryEntry entry) {
        removeForwardEntries();
        if (history.size() == CAPACITY) {
            NavigationHistoryEntry e = (NavigationHistoryEntry) history
                    .remove(0);
            disposeEntry(e);
        }
        history.add(entry);
        activeEntry = history.size() - 1;
    }

    /*
     * Remove all entries after the active entry.
     */
    private void removeForwardEntries() {
        int length = history.size();
        for (int i = activeEntry + 1; i < length; i++) {
            NavigationHistoryEntry e = (NavigationHistoryEntry) history
                    .remove(activeEntry + 1);
            disposeEntry(e);
        }
    }

    /*
     * Adds a location to the history.
     */
    private void addEntry(IEditorPart part) {
        if (ignoreEntries > 0 || part == null) {
      return;
    }

        if (isPerTabHistoryEnabled()) {
          markLocationForTab(part);
        }
        INavigationLocation location = null;
        if (part instanceof INavigationLocationProvider) {
      location = ((INavigationLocationProvider) part)
                    .createNavigationLocation();
    }

        NavigationHistoryEntry current = getEntry(activeEntry);
        if (current != null && current.editorInfo.memento != null) {
            current.editorInfo.restoreEditor();
            checkDuplicates(current.editorInfo);
        }
        NavigationHistoryEntry e = createEntry(page, part, location);
        if (current == null) {
            add(e);
        } else {
            if (e.mergeInto(current)) {
                disposeEntry(e);
                removeForwardEntries();
            } else {
                add(e);
            }
        }
        printEntries("added entry"); //$NON-NLS-1$
        updateActions();
    }

    /*
     * Prints all the entries in the console. For debug only.
     */
    private void printEntries(String label) {
        if (false) {
            System.out.println("+++++ " + label + "+++++ "); //$NON-NLS-1$ //$NON-NLS-2$
            int size = history.size();
            for (int i = 0; i < size; i++) {
                String append = activeEntry == i ? ">>" : ""; //$NON-NLS-1$ //$NON-NLS-2$
                System.out.println(append
                        + "Index: " + i + " " + history.get(i)); //$NON-NLS-1$ //$NON-NLS-2$
            }
        }
    }

    /*
     * Returns true if the forward action can be performed otherwise returns false.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    /* package */boolean canForward() {
      if (isPerTabHistoryEnabled()) {
        return hasEntriesForTab(true);
      }
        return (0 <= activeEntry + 1) && (activeEntry + 1 < history.size());
    }

    /*
     * Returns true if the backward action can be performed otherwise returns false.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    /* package */boolean canBackward() {
      if (isPerTabHistoryEnabled()) {
        return hasEntriesForTab(false);
      }
        return (0 <= activeEntry - 1) && (activeEntry - 1 < history.size());
    }

    /*
     * Update the actions enable/disable and tooltip state.
     */
    private void updateActions() {
        if (backwardAction != null) {
      backwardAction.update();
    }
        if (forwardAction != null) {
      forwardAction.update();
    }
    }

    /*
     * Restore the specified entry
     */
    private void gotoEntry(NavigationHistoryEntry entry) {
        if (entry == null) {
      return;
    }
        try {
            ignoreEntries++;
            if (entry.editorInfo.memento != null) {
                entry.editorInfo.restoreEditor();
                checkDuplicates(entry.editorInfo);
            }
            entry.restoreLocation();
            updateActions();
            printEntries("goto entry"); //$NON-NLS-1$
        } finally {
            ignoreEntries--;
        }
    }

    /*
     * update the active entry
     */
    private void updateEntry(NavigationHistoryEntry activeEntry) {
        if (activeEntry == null || activeEntry.location == null) {
      return;
    }
        activeEntry.location.update();
        printEntries("updateEntry"); //$NON-NLS-1$
    }

    /*
     * Perform the forward action by getting the next location and restoring
     * its context.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    void forward() {
      if (isPerTabHistoryEnabled()) {
        forwardForTab();
        return;
      }
        if (canForward()) {
      shiftEntry(true);
    }
    }

    /*
     * Perform the backward action by getting the previous location and restoring
     * its context.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    void backward() {
      if (isPerTabHistoryEnabled()) {
        backwardForTab();
        return;
      }
        if (canBackward()) {
      shiftEntry(false);
    }
    }

    /*
     * Shift the history back or forward
     */
    private void shiftEntry(boolean forward) {
        updateEntry(getEntry(activeEntry));
        if (forward) {
      activeEntry++;
    } else {
      activeEntry--;
    }
        NavigationHistoryEntry entry = getEntry(activeEntry);
        if (entry != null) {
      gotoEntry(entry);
    }
    }

    /*
     * Shift the history to the given entry.
     * <p>
     * (Called by NavigationHistoryAction)
     * </p>
     */
    void shiftCurrentEntry(NavigationHistoryEntry entry, boolean forward) {
      if (isPerTabHistoryEnabled()) {
        gotoEntryForTab(entry, forward);
        return;
      }
        updateEntry(getEntry(activeEntry));
        activeEntry = history.indexOf(entry);
        gotoEntry(entry);
    }

    /**
     * Save the state of this history into the memento.
     */
    void saveState(IMemento memento) {
        NavigationHistoryEntry cEntry = getEntry(activeEntry);
        if (cEntry == null || !cEntry.editorInfo.isPersistable()) {
      return;
    }

        ArrayList editors = (ArrayList) this.editors.clone();
        for (Iterator iter = editors.iterator(); iter.hasNext();) {
            NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter
                    .next();
            if (!info.isPersistable()) {
        iter.remove();
      }
        }
        IMemento editorsMem = memento
                .createChild(IWorkbenchConstants.TAG_EDITORS);
        for (Iterator iter = editors.iterator(); iter.hasNext();) {
            NavigationHistoryEditorInfo info = (NavigationHistoryEditorInfo) iter
                    .next();
            info.saveState(editorsMem
                    .createChild(IWorkbenchConstants.TAG_EDITOR));
        }

        ArrayList list = new ArrayList(history.size());
        int size = history.size();
        for (int i = 0; i < size; i++) {
            NavigationHistoryEntry entry = (NavigationHistoryEntry) history
                    .get(i);
            if (entry.editorInfo.isPersistable()) {
        list.add(entry);
      }
        }
        size = list.size();
        for (int i = 0; i < size; i++) {
            NavigationHistoryEntry entry = (NavigationHistoryEntry) list.get(i);
            IMemento childMem = memento
                    .createChild(IWorkbenchConstants.TAG_ITEM);
            if (entry == cEntry) {
        childMem.putString(IWorkbenchConstants.TAG_ACTIVE, "true"); //$NON-NLS-1$
      }
            entry.saveState(childMem, list);
            childMem.putInteger(IWorkbenchConstants.TAG_INDEX, editors
                    .indexOf(entry.editorInfo));
        }
    }

    /**
     * Restore the state of this history from the memento.
     */
    void restoreState(IMemento memento) {
        IMemento editorsMem = memento.getChild(IWorkbenchConstants.TAG_EDITORS);
        IMemento items[] = memento.getChildren(IWorkbenchConstants.TAG_ITEM);
        if (items.length == 0 || editorsMem == null) {
            if (page.getActiveEditor() != null) {
        markLocation(page.getActiveEditor());
      }
            return;
        }

        IMemento children[] = editorsMem
                .getChildren(IWorkbenchConstants.TAG_EDITOR);
        NavigationHistoryEditorInfo editorsInfo[] = new NavigationHistoryEditorInfo[children.length];
        for (int i = 0; i < editorsInfo.length; i++) {
            editorsInfo[i] = new NavigationHistoryEditorInfo(children[i]);
            editors.add(editorsInfo[i]);
        }

        for (int i = 0; i < items.length; i++) {
            IMemento item = items[i];
            int index = item.getInteger(IWorkbenchConstants.TAG_INDEX)
                    .intValue();
            NavigationHistoryEditorInfo info = editorsInfo[index];
            info.refCount++;
            NavigationHistoryEntry entry = new NavigationHistoryEntry(info,
                    page, null, null);
            history.add(entry);
            entry.restoreState(item);
            if (item.getString(IWorkbenchConstants.TAG_ACTIVE) != null) {
        activeEntry = i;
      }
        }

        final NavigationHistoryEntry entry = getEntry(activeEntry);
        if (entry != null && entry.editorInfo.editorInput != null) {
            if (page.getActiveEditor() == page
                    .findEditor(entry.editorInfo.editorInput)) {
              StartupThreading.runWithoutExceptions(new StartupRunnable() {

          public void runWithException() throws Throwable {
            gotoEntry(entry);
          }});   
      }
        }
    }

    public NavigationHistoryEntry createEntry(IWorkbenchPage page,
            IEditorPart part, INavigationLocation location) {
        String editorID = part.getSite().getId();
        IEditorInput editorInput = part.getEditorInput();
        NavigationHistoryEditorInfo info = null;
        for (Iterator iter = editors.iterator(); iter.hasNext();) {
            info = (NavigationHistoryEditorInfo) iter.next();
            if (editorID.equals(info.editorID)
                    && editorInput.equals(info.editorInput)) {
                info.refCount++;
                break;
            } else {
                info = null;
            }
        }
        if (info == null) {
            info = new NavigationHistoryEditorInfo(part);
            info.refCount++;
            editors.add(info);
        }
        return new NavigationHistoryEntry(info, page, part, location);
    }

    public void disposeEntry(NavigationHistoryEntry entry) {
        if (entry.editorInfo == null) {
      return;
    }
        entry.editorInfo.refCount--;
        if (entry.editorInfo.refCount == 0) {
      editors.remove(entry.editorInfo);
    }
        entry.dispose();
    }

    void checkDuplicates(NavigationHistoryEditorInfo info) {
        NavigationHistoryEditorInfo dup = null;
        if (info.editorInput == null) {
      return;
    }
        for (Iterator iter = editors.iterator(); iter.hasNext();) {
            dup = (NavigationHistoryEditorInfo) iter.next();
            if (info != dup && info.editorID.equals(dup.editorID)
                    && info.editorInput.equals(dup.editorInput)) {
        break;
      } else {
        dup = null;
      }
        }
        if (dup == null) {
      return;
    }
        for (Iterator iter = history.iterator(); iter.hasNext();) {
            NavigationHistoryEntry entry = (NavigationHistoryEntry) iter.next();
            if (entry.editorInfo == dup) {
                entry.editorInfo = info;
                info.refCount++;
            }
        }
        editors.remove(dup);
    }
   
    /*********************************************************/
    /*** new per-tab history code                          ***/
    /*********************************************************/
   
   
    private static class PerTabHistory {
      LinkedList backwardEntries = new LinkedList();
      NavigationHistoryEntry currentEntry = null;
      LinkedList forwardEntries = new LinkedList();
    }
   
    private void setNewCurrentEntryForTab(PerTabHistory perTabHistory, NavigationHistoryEntry entry) {
      if (perTabHistory.currentEntry != null) {
        perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry);
      }
      perTabHistory.currentEntry = entry;
      removeEntriesForTab(perTabHistory.forwardEntries);
    }
   
    private Object getCookieForTab(IEditorPart part) {
      if (part != null) {
          IWorkbenchPartSite site = part.getSite();
          if (site instanceof PartSite) {
            PartSite partSite = (PartSite) site;
            WorkbenchPartReference ref = (WorkbenchPartReference) partSite.getPartReference();
            if (!ref.isDisposed()) {
              return partSite.getPane();
            }
          }
      }
      return null;
    }
   
    private void markLocationForTab(IEditorPart part) {
      if (part instanceof ErrorEditorPart) {
        updateActions();
        return;
      }
    Object tabCookie = getCookieForTab(part);
    if (tabCookie != null) {
      INavigationLocation location = null;
      if (part instanceof INavigationLocationProvider) {
        location = ((INavigationLocationProvider) part)
            .createNavigationLocation();
      }
      PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap
          .get(tabCookie);
      if (perTabHistory == null) {
        perTabHistory = new PerTabHistory();
        perTabHistoryMap.put(tabCookie, perTabHistory);
      }
      NavigationHistoryEntry current = perTabHistory.currentEntry;
      if (current != null && current.editorInfo.memento != null) {
        current.editorInfo.restoreEditor();
        checkDuplicates(current.editorInfo);
      }
      NavigationHistoryEntry entry = createEntry(page, part, location);
      if (current != null && entry.mergeInto(current)) {
        disposeEntry(entry);
        removeEntriesForTab(perTabHistory.forwardEntries);
      } else {
        setNewCurrentEntryForTab(perTabHistory, entry);
      }
    }
    updateActions();
  }
   
    public void updateCookieForTab(Object oldCookie, Object newCookie) {
      if (newCookie.equals(oldCookie)) {
        return;
      }
      PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(oldCookie);
      if (perTabHistory != null) {
        perTabHistoryMap.put(newCookie, perTabHistory);
      }
    }
   
    private void gotoEntryForTab(NavigationHistoryEntry target, boolean forward) {
      Object editorTabCookie = getCookieForTab(page.getActiveEditor());
      if (editorTabCookie!=null) {
        PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
        if (perTabHistory != null) {
          LinkedList source = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries;
          LinkedList destination = forward ? perTabHistory.backwardEntries : perTabHistory.forwardEntries;
        if (perTabHistory.currentEntry != null) {
          if (perTabHistory.currentEntry.location != null) {
            perTabHistory.currentEntry.location.update();
          }
          destination.addFirst(perTabHistory.currentEntry);
        }
        NavigationHistoryEntry newCurrent = null;
          while (!source.isEmpty() && newCurrent==null) {
            NavigationHistoryEntry entry = (NavigationHistoryEntry) source
              .removeFirst();
            if (entry.equals(target)) {
              newCurrent = entry;
            } else {
              destination.addFirst(entry);
            }
          }
          Assert.isTrue(newCurrent != null);
          perTabHistory.currentEntry = newCurrent;
              try {
                  ignoreEntries++;
                  if (newCurrent.editorInfo.memento != null) {
                    newCurrent.editorInfo.restoreEditor();
                    checkDuplicates(newCurrent.editorInfo);
                  }
                  newCurrent.restoreLocation();
                  updateActions();
              } finally {
                ignoreEntries--;
              }
        }
      }
    }
   
  private void forwardForTab() {
      Object editorTabCookie = getCookieForTab(page.getActiveEditor());
      if (editorTabCookie!=null) {
        PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
        if (perTabHistory != null && !perTabHistory.forwardEntries.isEmpty()) {
          NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.forwardEntries
            .removeFirst();
          if (perTabHistory.currentEntry != null) {
            final INavigationLocation location = perTabHistory.currentEntry.location;
            if (location!=null) {
              location.update();
            }
            perTabHistory.backwardEntries.addFirst(perTabHistory.currentEntry);
          }
          perTabHistory.currentEntry = newCurrent;
              try {
                  ignoreEntries++;
                  if (newCurrent.editorInfo.memento != null) {
                    newCurrent.editorInfo.restoreEditor();
                    checkDuplicates(newCurrent.editorInfo);
                  }
                  newCurrent.restoreLocation();
                  updateActions();
              } finally {
                ignoreEntries--;
              }
        }
      }
    }
   
    private void backwardForTab() {
      Object editorTabCookie = getCookieForTab(page.getActiveEditor());
      if (editorTabCookie!=null) {
        PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
        if (perTabHistory != null && !perTabHistory.backwardEntries.isEmpty()) {
          NavigationHistoryEntry newCurrent = (NavigationHistoryEntry) perTabHistory.backwardEntries
              .removeFirst();
          if (perTabHistory.currentEntry != null) {
            perTabHistory.currentEntry.location.update();
            perTabHistory.forwardEntries.addFirst(perTabHistory.currentEntry);
          }
          perTabHistory.currentEntry = newCurrent;
              try {
                  ignoreEntries++;
                  if (newCurrent.editorInfo.memento != null) {
                    newCurrent.editorInfo.restoreEditor();
                    checkDuplicates(newCurrent.editorInfo);
                  }
                  newCurrent.restoreLocation();
                  updateActions();
              } finally {
                ignoreEntries--;
              }
        }
      }
    }
   
    private boolean hasEntriesForTab(boolean forward) {
      Object editorTabCookie = getCookieForTab(page.getActiveEditor());
      if (editorTabCookie!=null) {
        PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.get(editorTabCookie);
        if (perTabHistory != null) {
          LinkedList entries = forward ? perTabHistory.forwardEntries : perTabHistory.backwardEntries;
          return !entries.isEmpty();
        }
      }
      return false;
    }

    /**
     * Returns entries in restore order.
     * @param editorTabCookie
     * @param forward
     * @return
     */
    private NavigationHistoryEntry[] getEntriesForTab(boolean forward) {
    Object editorTabCookie = getCookieForTab(page.getActiveEditor());
    if (editorTabCookie != null) {
      PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap
          .get(editorTabCookie);
      if (perTabHistory != null) {
        LinkedList entries = forward ? perTabHistory.forwardEntries
            : perTabHistory.backwardEntries;
        return (NavigationHistoryEntry[]) entries
        .toArray(new NavigationHistoryEntry[entries.size()]);
      }
    }
    return new NavigationHistoryEntry[0];
  }
   
    private void disposeHistoryForTabs() {
      Object[] keys = perTabHistoryMap.keySet().toArray();
      for (int i = 0; i < keys.length; i++) {
      disposeHistoryForTab(keys[i]);
    }
    }

    void disposeHistoryForTab(Object editorTabCookie) {
      PerTabHistory perTabHistory = (PerTabHistory) perTabHistoryMap.remove(editorTabCookie);
      if (perTabHistory != null) {
        if (perTabHistory.currentEntry != null) {
          disposeEntry(perTabHistory.currentEntry);
          perTabHistory.currentEntry = null;
        }
        removeEntriesForTab(perTabHistory.backwardEntries);
        removeEntriesForTab(perTabHistory.forwardEntries);
      }
    }

  private void removeEntriesForTab(LinkedList entries) {
    for (Iterator it = entries.iterator(); it.hasNext();) {
      NavigationHistoryEntry entry = (NavigationHistoryEntry) it.next();
      disposeEntry(entry);
      it.remove();
    }
  }
}
TOP

Related Classes of org.eclipse.ui.internal.NavigationHistory

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.