org.chromium.debug.ui/src/org/chromium/debug/ui/JsEvalContextManager.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/org.chromium.debug.ui/src/org/chromium/debug/ui/JsEvalContextManager.java	Wed Dec 23 17:13:18 2009 -0800
@@ -0,0 +1,189 @@
+// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.debug.ui;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.chromium.debug.core.model.StackFrame;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.debug.ui.DebugUITools;
+import org.eclipse.debug.ui.contexts.DebugContextEvent;
+import org.eclipse.debug.ui.contexts.IDebugContextListener;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.ui.IWindowListener;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPage;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * Keeps track of the evaluation context (selected StackFrame) in all the
+ * workbench parts. A singleton.
+ */
+public class JsEvalContextManager implements IWindowListener, IDebugContextListener {
+
+  private static final String DEBUGGER_ACTIVE = ChromiumDebugUIPlugin.PLUGIN_ID + ".debuggerActive"; //$NON-NLS-1$
+
+  private static JsEvalContextManager instance;
+
+  private IWorkbenchWindow activeWindow;
+
+  private final Map<IWorkbenchPage, StackFrame> pageToFrame =
+      new HashMap<IWorkbenchPage, StackFrame>();
+
+  protected JsEvalContextManager() {
+    DebugUITools.getDebugContextManager().addDebugContextListener(this);
+  }
+
+  /**
+   * This method will get called only once.
+   */
+  public static void startup() {
+    Runnable r = new Runnable() {
+      public void run() {
+        if (instance == null) {
+          instance = new JsEvalContextManager();
+          IWorkbench workbench = PlatformUI.getWorkbench();
+          workbench.addWindowListener(instance);
+          instance.activeWindow = workbench.getActiveWorkbenchWindow();
+        }
+      }
+    };
+    ChromiumDebugUIPlugin.getDisplay().asyncExec(r);
+  }
+
+  public void windowActivated(IWorkbenchWindow window) {
+    activeWindow = window;
+  }
+
+  public void windowClosed(IWorkbenchWindow window) {
+  }
+
+  public void windowDeactivated(IWorkbenchWindow window) {
+  }
+
+  public void windowOpened(IWorkbenchWindow window) {
+  }
+
+  public void debugContextChanged(DebugContextEvent event) {
+    if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) {
+      IWorkbenchPart part = event.getDebugContextProvider().getPart();
+      if (part == null) {
+        return;
+      }
+      IWorkbenchPage page = part.getSite().getPage();
+      ISelection selection = event.getContext();
+      if (selection instanceof IStructuredSelection) {
+        Object firstElement = ((IStructuredSelection) selection).getFirstElement();
+        if (firstElement instanceof IAdaptable) {
+          StackFrame frame = (StackFrame) ((IAdaptable) firstElement).getAdapter(StackFrame.class);
+          if (frame != null) {
+            putStackFrame(page, frame);
+            return;
+          }
+        }
+      }
+      // debug context for the |page| has been lost
+      removeStackFrame(page);
+    }
+  }
+
+  /**
+   * Returns the stackframe corresponding to the given {@code part}, or {@code
+   * null} if none.
+   *
+   * @param part the active part
+   * @return the stack frame in whose context the evaluation is performed, or
+   *         {@code null} if none
+   */
+  public static StackFrame getStackFrameFor(IWorkbenchPart part) {
+    IWorkbenchPage page = part.getSite().getPage();
+    StackFrame frame = getStackFrameFor(page);
+    if (frame == null) {
+      return getStackFrameFor(page.getWorkbenchWindow());
+    }
+    return frame;
+  }
+
+  /**
+   * Returns the stackframe corresponding to the given {@code window}, or
+   * {@code null} if none.
+   *
+   * @param window to find the StackFrame for. If {@code null}, the {@code
+   *        activeWindow} will be used instead
+   * @return the stack frame in whose the evaluation is performed, or {@code
+   *         null} if none
+   */
+  public static StackFrame getStackFrameFor(IWorkbenchWindow window) {
+    Set<IWorkbenchWindow> visitedWindows = new HashSet<IWorkbenchWindow>();
+    if (window == null) {
+      window = instance.activeWindow;
+    }
+    return getStackFrameFor(window, visitedWindows);
+  }
+
+  private static StackFrame getStackFrameFor(
+      IWorkbenchWindow window, Set<IWorkbenchWindow> visitedWindows) {
+    IWorkbenchPage activePage = window.getActivePage();
+    StackFrame frame = null;
+    // Check the active page in the window
+    if (activePage != null) {
+      frame = getStackFrameFor(activePage);
+      if (frame != null) {
+        return frame;
+      }
+    }
+    // Check all the current Eclipse window pages
+    for (IWorkbenchPage windowPage : window.getPages()) {
+      if (activePage != windowPage) {
+        frame = getStackFrameFor(windowPage);
+        if (frame != null) {
+          return frame;
+        }
+      }
+    }
+
+    // Last resort - check all other Eclipse windows
+    visitedWindows.add(window);
+
+    for (IWorkbenchWindow workbenchWindow : PlatformUI.getWorkbench().getWorkbenchWindows()) {
+      if (!visitedWindows.contains(workbenchWindow)) {
+        frame = getStackFrameFor(workbenchWindow, visitedWindows);
+        if (frame != null) {
+          return frame;
+        }
+      }
+    }
+
+    // Nothing found
+    return null;
+  }
+
+  private static StackFrame getStackFrameFor(IWorkbenchPage page) {
+    if (instance != null) {
+      return instance.pageToFrame.get(page);
+    }
+    return null;
+  }
+
+  private void removeStackFrame(IWorkbenchPage page) {
+    pageToFrame.remove(page);
+    if (pageToFrame.isEmpty()) {
+      // No more available frames
+      System.setProperty(DEBUGGER_ACTIVE, Boolean.FALSE.toString());
+    }
+  }
+
+  private void putStackFrame(IWorkbenchPage page, StackFrame frame) {
+    pageToFrame.put(page, frame);
+    System.setProperty(DEBUGGER_ACTIVE, Boolean.TRUE.toString());
+  }
+
+}