org.chromium.debug.ui/src/org/chromium/debug/ui/actions/JsInspectSnippetAction.java
changeset 2 e4420d2515f1
child 52 f577ea64429e
equal deleted inserted replaced
1:ef76fc2ac88c 2:e4420d2515f1
       
     1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
       
     2 // Use of this source code is governed by a BSD-style license that can be
       
     3 // found in the LICENSE file.
       
     4 
       
     5 package org.chromium.debug.ui.actions;
       
     6 
       
     7 import org.chromium.debug.core.model.StackFrame;
       
     8 import org.chromium.debug.ui.ChromiumDebugUIPlugin;
       
     9 import org.chromium.debug.ui.JsEvalContextManager;
       
    10 import org.chromium.debug.ui.editors.JavascriptUtil;
       
    11 import org.chromium.sdk.CallFrame;
       
    12 import org.chromium.sdk.JsVariable;
       
    13 import org.eclipse.debug.core.model.IExpression;
       
    14 import org.eclipse.debug.ui.DebugPopup;
       
    15 import org.eclipse.debug.ui.InspectPopupDialog;
       
    16 import org.eclipse.jface.action.IAction;
       
    17 import org.eclipse.jface.text.ITextSelection;
       
    18 import org.eclipse.jface.text.ITextViewer;
       
    19 import org.eclipse.jface.viewers.ISelection;
       
    20 import org.eclipse.jface.viewers.ISelectionProvider;
       
    21 import org.eclipse.swt.custom.StyledText;
       
    22 import org.eclipse.swt.graphics.GC;
       
    23 import org.eclipse.swt.graphics.Point;
       
    24 import org.eclipse.swt.widgets.Control;
       
    25 import org.eclipse.swt.widgets.Shell;
       
    26 import org.eclipse.ui.IEditorActionDelegate;
       
    27 import org.eclipse.ui.IEditorPart;
       
    28 import org.eclipse.ui.IPartListener;
       
    29 import org.eclipse.ui.IViewActionDelegate;
       
    30 import org.eclipse.ui.IViewPart;
       
    31 import org.eclipse.ui.IWorkbenchPage;
       
    32 import org.eclipse.ui.IWorkbenchPart;
       
    33 import org.eclipse.ui.IWorkbenchWindow;
       
    34 import org.eclipse.ui.IWorkbenchWindowActionDelegate;
       
    35 import org.eclipse.ui.texteditor.ITextEditor;
       
    36 
       
    37 /**
       
    38  * Action for inspecting a JavaScript snippet.
       
    39  */
       
    40 public class JsInspectSnippetAction implements IEditorActionDelegate,
       
    41     IWorkbenchWindowActionDelegate, IPartListener, IViewActionDelegate, CallFrame.EvaluateCallback {
       
    42 
       
    43   private static final String ACTION_DEFINITION_ID = "org.chromium.debug.ui.commands.Inspect"; //$NON-NLS-1$
       
    44 
       
    45   private IWorkbenchWindow window;
       
    46 
       
    47   private IWorkbenchPart targetPart;
       
    48 
       
    49   private IAction action;
       
    50 
       
    51   private String selectedText;
       
    52 
       
    53   private IExpression expression;
       
    54 
       
    55   private ITextEditor textEditor;
       
    56 
       
    57   private ISelection originalSelection;
       
    58 
       
    59   public void setActiveEditor(IAction action, IEditorPart targetEditor) {
       
    60     this.action = action;
       
    61     setTargetPart(targetEditor);
       
    62   }
       
    63 
       
    64   public void run(IAction action) {
       
    65     updateAction();
       
    66     run();
       
    67   }
       
    68 
       
    69   public void selectionChanged(IAction action, ISelection selection) {
       
    70     this.action = action;
       
    71   }
       
    72 
       
    73   public void dispose() {
       
    74     IWorkbenchWindow win = getWindow();
       
    75     if (win != null) {
       
    76       win.getPartService().removePartListener(this);
       
    77     }
       
    78   }
       
    79 
       
    80   private IWorkbenchWindow getWindow() {
       
    81     return window;
       
    82   }
       
    83 
       
    84   public void init(IWorkbenchWindow window) {
       
    85     this.window = window;
       
    86     IWorkbenchPage page = window.getActivePage();
       
    87     if (page != null) {
       
    88       setTargetPart(page.getActivePart());
       
    89     }
       
    90     window.getPartService().addPartListener(this);
       
    91   }
       
    92 
       
    93   public void partActivated(IWorkbenchPart part) {
       
    94     setTargetPart(part);
       
    95   }
       
    96 
       
    97   public void partBroughtToTop(IWorkbenchPart part) {
       
    98 
       
    99   }
       
   100 
       
   101   public void partClosed(IWorkbenchPart part) {
       
   102     if (part == getTargetPart()) {
       
   103       setTargetPart(null);
       
   104     }
       
   105   }
       
   106 
       
   107   private IWorkbenchPart getTargetPart() {
       
   108     return targetPart;
       
   109   }
       
   110 
       
   111   public void partDeactivated(IWorkbenchPart part) {
       
   112   }
       
   113 
       
   114   public void partOpened(IWorkbenchPart part) {
       
   115   }
       
   116 
       
   117   private void setTargetPart(IWorkbenchPart part) {
       
   118     this.targetPart = part;
       
   119   }
       
   120 
       
   121   public void init(IViewPart view) {
       
   122     setTargetPart(view);
       
   123   }
       
   124 
       
   125   private void updateAction() {
       
   126     if (action != null) {
       
   127       retrieveSelection();
       
   128     }
       
   129   }
       
   130 
       
   131   protected ISelection getTargetSelection() {
       
   132     IWorkbenchPart part = getTargetPart();
       
   133     if (part != null) {
       
   134       ISelectionProvider provider = part.getSite().getSelectionProvider();
       
   135       if (provider != null) {
       
   136         return provider.getSelection();
       
   137       }
       
   138     }
       
   139     return null;
       
   140   }
       
   141 
       
   142   private StackFrame getStackFrameContext() {
       
   143     IWorkbenchPart part = getTargetPart();
       
   144     return getStackFrameForPart(part);
       
   145   }
       
   146 
       
   147   private StackFrame getStackFrameForPart(IWorkbenchPart part) {
       
   148     StackFrame frame = part == null
       
   149         ? JsEvalContextManager.getStackFrameFor(getWindow())
       
   150         : JsEvalContextManager.getStackFrameFor(part);
       
   151     return frame;
       
   152   }
       
   153 
       
   154   private void run() {
       
   155     getStackFrameContext().getCallFrame().evaluateAsync(getSelectedText(), this, null);
       
   156   }
       
   157 
       
   158   protected String getSelectedText() {
       
   159     return selectedText;
       
   160   }
       
   161 
       
   162   protected Shell getShell() {
       
   163     if (getTargetPart() != null) {
       
   164       return getTargetPart().getSite().getShell();
       
   165     }
       
   166     return ChromiumDebugUIPlugin.getActiveWorkbenchShell();
       
   167   }
       
   168 
       
   169   private void retrieveSelection() {
       
   170     ISelection targetSelection = getTargetSelection();
       
   171     if (targetSelection instanceof ITextSelection) {
       
   172       ITextSelection ts = (ITextSelection) targetSelection;
       
   173       String text = ts.getText();
       
   174       if (textHasContent(text)) {
       
   175         selectedText = text;
       
   176       } else if (getTargetPart() instanceof IEditorPart) {
       
   177         IEditorPart editor = (IEditorPart) getTargetPart();
       
   178         if (editor instanceof ITextEditor) {
       
   179           selectedText = extractSurroundingWord(ts, (ITextEditor) editor);
       
   180         }
       
   181       }
       
   182     }
       
   183   }
       
   184 
       
   185   private String extractSurroundingWord(ITextSelection targetSelection, ITextEditor editor) {
       
   186     return JavascriptUtil.extractSurroundingJsIdentifier(
       
   187         editor.getDocumentProvider().getDocument(editor.getEditorInput()),
       
   188         targetSelection.getOffset());
       
   189   }
       
   190 
       
   191   private boolean textHasContent(String text) {
       
   192     return text != null && JavascriptUtil.ID_PATTERN.matcher(text).find();
       
   193   }
       
   194 
       
   195   public void success(JsVariable var) {
       
   196     if (ChromiumDebugUIPlugin.getDefault() == null) {
       
   197       return;
       
   198     }
       
   199     if (var != null) {
       
   200       if (ChromiumDebugUIPlugin.getDisplay().isDisposed()) {
       
   201         return;
       
   202       }
       
   203       displayResult(var, null);
       
   204     }
       
   205   }
       
   206 
       
   207   public void failure(String errorMessage) {
       
   208     displayResult(null, errorMessage);
       
   209   }
       
   210 
       
   211   protected void displayResult(final JsVariable var, String errorMessage) {
       
   212     IWorkbenchPart part = getTargetPart();
       
   213     final StyledText styledText = getStyledText(part);
       
   214     if (styledText == null) {
       
   215       return; // TODO(apavlov): fix this when adding inspected variables
       
   216     } else {
       
   217       expression = new JsInspectExpression(getStackFrameContext(), selectedText, var, errorMessage);
       
   218       ChromiumDebugUIPlugin.getDisplay().asyncExec(new Runnable() {
       
   219         public void run() {
       
   220           showPopup(styledText);
       
   221         }
       
   222       });
       
   223     }
       
   224   }
       
   225 
       
   226   protected void showPopup(StyledText textWidget) {
       
   227     IWorkbenchPart part = getTargetPart();
       
   228     if (part instanceof ITextEditor) {
       
   229       textEditor = (ITextEditor) part;
       
   230       originalSelection = getTargetSelection();
       
   231     }
       
   232     DebugPopup displayPopup =
       
   233         new InspectPopupDialog(getShell(), getPopupAnchor(textWidget), ACTION_DEFINITION_ID,
       
   234             expression) {
       
   235           @Override
       
   236           public boolean close() {
       
   237             boolean returnValue = super.close();
       
   238             if (textEditor != null && originalSelection != null) {
       
   239               textEditor.getSelectionProvider().setSelection(originalSelection);
       
   240               textEditor = null;
       
   241               originalSelection = null;
       
   242             }
       
   243             return returnValue;
       
   244           }
       
   245         };
       
   246     displayPopup.open();
       
   247   }
       
   248 
       
   249   private StyledText getStyledText(IWorkbenchPart part) {
       
   250     ITextViewer viewer = (ITextViewer) part.getAdapter(ITextViewer.class);
       
   251     StyledText textWidget = null;
       
   252     if (viewer == null) {
       
   253       Control control = (Control) part.getAdapter(Control.class);
       
   254       if (control instanceof StyledText) {
       
   255         textWidget = (StyledText) control;
       
   256       }
       
   257     } else {
       
   258       textWidget = viewer.getTextWidget();
       
   259     }
       
   260     return textWidget;
       
   261   }
       
   262 
       
   263   private static Point getPopupAnchor(StyledText textWidget) {
       
   264     if (textWidget != null) {
       
   265       Point docRange = textWidget.getSelectionRange();
       
   266       int midOffset = docRange.x + (docRange.y / 2);
       
   267       Point point = textWidget.getLocationAtOffset(midOffset);
       
   268       point = textWidget.toDisplay(point);
       
   269       point.y += getFontHeight(textWidget);
       
   270       return point;
       
   271     }
       
   272     return null;
       
   273   }
       
   274 
       
   275   private static int getFontHeight(StyledText textWidget) {
       
   276     GC gc = new GC(textWidget);
       
   277     gc.setFont(textWidget.getFont());
       
   278     int height = gc.getFontMetrics().getHeight();
       
   279     gc.dispose();
       
   280     return height;
       
   281   }
       
   282 
       
   283 }