1) Implement variable hover for XDebug.
[phpeclipse.git] / net.sourceforge.phpeclipse.debug.ui / src / net / sourceforge / phpdt / internal / debug / ui / PHPDebugHover.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.debug.ui;
12
13 import net.sourceforge.phpdt.internal.debug.core.model.PHPStackFrame;
14 import net.sourceforge.phpdt.internal.debug.core.model.PHPValue;
15 import net.sourceforge.phpdt.internal.ui.text.HTMLTextPresenter;
16 import net.sourceforge.phpdt.internal.ui.text.JavaWordFinder;
17 import net.sourceforge.phpdt.ui.PreferenceConstants;
18 import net.sourceforge.phpdt.ui.text.java.hover.IJavaEditorTextHover;
19
20 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugStackFrame;
21 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget;
22 import net.sourceforge.phpeclipse.xdebug.php.model.XDebugValue;
23
24 import org.eclipse.core.runtime.IAdaptable;
25 import org.eclipse.debug.core.DebugException;
26 import org.eclipse.debug.core.model.IValue;
27 import org.eclipse.debug.core.model.IVariable;
28 import org.eclipse.debug.ui.IDebugUIConstants;
29 import org.eclipse.jface.text.BadLocationException;
30 import org.eclipse.jface.text.DefaultInformationControl;
31 import org.eclipse.jface.text.IDocument;
32 import org.eclipse.jface.text.IInformationControl;
33 import org.eclipse.jface.text.IInformationControlCreator;
34 import org.eclipse.jface.text.IRegion;
35 import org.eclipse.jface.text.ITextHoverExtension;
36 import org.eclipse.jface.text.ITextViewer;
37 import org.eclipse.jface.viewers.ISelection;
38 import org.eclipse.jface.viewers.IStructuredSelection;
39 import org.eclipse.jface.viewers.ITreeSelection;
40 import org.eclipse.jface.viewers.TreePath;
41 //import org.eclipse.swt.SWT;
42 import org.eclipse.swt.widgets.Shell;
43 import org.eclipse.ui.IEditorPart;
44 import org.eclipse.ui.IPartListener;
45 import org.eclipse.ui.ISelectionListener;
46 import org.eclipse.ui.IWorkbenchPage;
47 import org.eclipse.ui.IWorkbenchPart;
48
49 public class PHPDebugHover implements IJavaEditorTextHover,
50                 ITextHoverExtension, ISelectionListener, IPartListener {
51
52         protected IEditorPart fEditor;
53
54         protected ISelection fSelection = null;
55
56         /*
57          * (non-Javadoc)
58          *
59          * @see org.eclipse.ui.IPartListener#partActivated(org.eclipse.ui.IWorkbenchPart)
60          */
61         public void partActivated(IWorkbenchPart part) {
62         }
63
64         /*
65          * (non-Javadoc)
66          *
67          * @see org.eclipse.ui.IPartListener#partBroughtToTop(org.eclipse.ui.IWorkbenchPart)
68          */
69         public void partBroughtToTop(IWorkbenchPart part) {
70         }
71
72         /*
73          * (non-Javadoc)
74          *
75          * @see org.eclipse.ui.IPartListener#partClosed(org.eclipse.ui.IWorkbenchPart)
76          */
77         public void partClosed(IWorkbenchPart part) {
78                 if (part.equals(fEditor)) {
79                         IWorkbenchPage page = fEditor.getSite().getPage();
80                         page.removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
81                         page.removePartListener(this);
82                         fSelection = null;
83                         fEditor = null;
84                 }
85         }
86
87         /*
88          * (non-Javadoc)
89          *
90          * @see org.eclipse.ui.IPartListener#partDeactivated(org.eclipse.ui.IWorkbenchPart)
91          */
92         public void partDeactivated(IWorkbenchPart part) {
93         }
94
95         /*
96          * (non-Javadoc)
97          *
98          * @see org.eclipse.ui.IPartListener#partOpened(org.eclipse.ui.IWorkbenchPart)
99          */
100         public void partOpened(IWorkbenchPart part) {
101         }
102
103         /*
104          * (non-Javadoc)
105          *
106          * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
107          *      org.eclipse.jface.viewers.ISelection)
108          */
109         public void selectionChanged(IWorkbenchPart part, ISelection selection) {
110                 fSelection = selection;
111         }
112
113         public PHPDebugHover() {
114         }
115
116         /*
117          * (non-Javadoc)
118          *
119          * @see org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover#setEditor(org.eclipse.ui.IEditorPart)
120          */
121         public void setEditor(IEditorPart editor) {
122                 if (editor != null) {
123                         fEditor = editor;
124                         final IWorkbenchPage page = editor.getSite().getPage();
125                         page.addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
126                         page.addPartListener(this);
127                         // initialize selection
128                         Runnable r = new Runnable() {
129                                 public void run() {
130                                         fSelection = page
131                                                         .getSelection(IDebugUIConstants.ID_DEBUG_VIEW);
132                                 }
133                         };
134                         PHPDebugUiPlugin.getStandardDisplay().asyncExec(r);
135                 }
136         }
137
138         /*
139          * (non-Javadoc)
140          *
141          * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer,
142          *      int)
143          */
144         public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
145                 return JavaWordFinder.findWord(textViewer.getDocument(), offset);
146         }
147
148         /**
149          * Returns the stack frame in which to search for variables, or
150          * <code>null</code> if none.
151          *
152          * @return the stack frame in which to search for variables, or
153          *         <code>null</code> if none
154          */
155         protected PHPStackFrame getFrame() {
156                 if (fSelection instanceof IStructuredSelection) {
157                         IStructuredSelection selection = (IStructuredSelection) fSelection;
158                         if (selection.size() == 1) {
159                                 Object el = selection.getFirstElement();
160                                 if (el instanceof IAdaptable) {
161                                         return (PHPStackFrame) ((IAdaptable) el)
162                                                         .getAdapter(PHPStackFrame.class);
163                                 }
164                         }
165                 }
166                 return null;
167         }
168
169     protected XDebugStackFrame getXDebugFrame() {
170         if (fSelection instanceof IStructuredSelection) {
171             IStructuredSelection selection = (IStructuredSelection) fSelection;
172             if (selection.size() == 1) {
173                 Object el = selection.getFirstElement();
174                 if (el instanceof IAdaptable) {
175                     return (XDebugStackFrame) ((IAdaptable) el)
176                             .getAdapter(XDebugStackFrame.class);
177                 }
178             }
179         }
180         return null;
181     }
182
183         /*
184          * (non-Javadoc)
185          *
186          * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer,
187          *      org.eclipse.jface.text.IRegion)
188          */
189         public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
190             IVariable        variable = null;
191                 PHPStackFrame    frameDBG = null;
192                 XDebugStackFrame frameXD  = null;
193
194                 TreePath paths[] = ((ITreeSelection) fSelection).getPaths ();
195                 Object target = paths[0].getSegment (1);
196
197                 if (target.getClass().getName ().equals ("net.sourceforge.phpeclipse.xdebug.php.model.XDebugTarget") ) {
198                     frameXD = getXDebugFrame ();
199                 }
200                 else {
201                     frameDBG = getFrame();
202                 }
203
204                 if ((frameDBG != null) || (frameXD != null)) {
205                         try {
206                                 IDocument document = textViewer.getDocument();
207
208                                 if (document == null)
209                                         return null;
210
211                                 String variableName = document.get (hoverRegion.getOffset(), hoverRegion.getLength());
212
213                                 StringBuffer buffer = new StringBuffer();
214                                 try {
215                                     if (frameDBG != null) {
216                                         variable = frameDBG.findVariable(variableName);
217                                     }
218                                     else if (frameXD != null) {
219                                     if (variableName.startsWith ("$")) {
220                                         variable = frameXD.findVariable (variableName.substring (1));
221                                     }
222                                     else {
223                                             variable = frameXD.findVariable (variableName);
224                                     }
225                                     }
226
227                                         if (variable != null) {
228                                                 appendVariable(buffer, variable);
229                                         }
230                                 } catch (DebugException x) {
231                                         // if (x.getStatus().getCode() !=
232                                         // IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
233                                         PHPDebugUiPlugin.log(x);
234                                         // }
235                                 }
236
237                                 if (buffer.length() > 0) {
238                                         return buffer.toString();
239                                 }
240
241                         } catch (BadLocationException x) {
242                                 PHPDebugUiPlugin.log(x);
243                         }
244                 }
245
246                 return null;
247         }
248
249         /**
250          * Append HTML for the given variable to the given buffer
251          */
252         private static void appendVariable(StringBuffer buffer, IVariable variable)
253                         throws DebugException {
254
255                 buffer.append("<p>"); //$NON-NLS-1$
256                 buffer.append("<pre>").append(variable.getName()).append("</pre>"); //$NON-NLS-1$ //$NON-NLS-2$
257                 buffer.append(" ="); //$NON-NLS-1$
258
259                 String type = getTypeName(variable);
260                 String value = "<b><pre>" + variable.getValue().getValueString() + "</pre></b>"; //$NON-NLS-1$ //$NON-NLS-2$
261
262                 if (type == null) {
263                         buffer.append(" null"); //$NON-NLS-1$
264                 } else if (type.equals("java.lang.String")) { //$NON-NLS-1$
265                         buffer.append(" \""); //$NON-NLS-1$
266                         buffer.append(value);
267                         buffer.append('"');
268                 } else if (type.equals("boolean") ||          // in dbg it's boolean
269                            type.equals("bool")) {             // in XDebug it's bool   $NON-NLS-1$
270                         buffer.append(' ');
271                         buffer.append(value);
272                 } else {
273                         buffer.append(" ("); //$NON-NLS-1$
274                         buffer.append("<pre>").append(type).append("</pre>"); //$NON-NLS-1$ //$NON-NLS-2$
275                         buffer.append(") "); //$NON-NLS-1$
276                         buffer.append(value);
277                 }
278                 buffer.append("</p>"); //$NON-NLS-1$
279         }
280
281         private static String getTypeName(IVariable variable) throws DebugException {
282                 IValue value = variable.getValue();
283
284                 if (value instanceof PHPValue)
285                         return ((PHPValue) value).getReferenceTypeName();
286
287                 if (value instanceof XDebugValue)
288                         return ((XDebugValue) value).getReferenceTypeName ();
289
290                 return null;
291         }
292
293         /*
294          * (non-Javadoc)
295          *
296          * @see org.eclipse.jface.text.ITextHoverExtension#getInformationControlCreator()
297          */
298 //      public IInformationControlCreator getInformationControlCreator() {
299 //              // if
300 //              // (Platform.getPlugin("org.eclipse.jdt.ui").getPluginPreferences().getBoolean(PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE))
301 //              // { //$NON-NLS-1$
302 //              return new IInformationControlCreator() {
303 //                      public IInformationControl createInformationControl(Shell parent) {
304 ////incastrix
305 //                              //                              return new DefaultInformationControl(parent, SWT.NONE,
306 ////                                            new HTMLTextPresenter(true), PHPDebugUiMessages
307 ////                                                            .getString("JavaDebugHover.16")); //$NON-NLS-1$
308 //                              return new DefaultInformationControl(parent, PHPDebugUiMessages.getString("JavaDebugHover.16"),
309 //                                              new HTMLTextPresenter(true));
310 //                      }
311 //              };
312 //              // }
313 //              // return null;
314 //      }
315
316         /*
317          * (non-Javadoc)
318          *
319          * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
320          */
321         public IInformationControlCreator getHoverControlCreator() {
322                 if (PreferenceConstants.getPreferenceStore().getBoolean(
323                                 PreferenceConstants.EDITOR_SHOW_TEXT_HOVER_AFFORDANCE)) { //$NON-NLS-1$
324                         return new IInformationControlCreator() {
325                                 public IInformationControl createInformationControl(Shell parent) {
326 //incastrix
327                                         //                                      return new DefaultInformationControl(parent, SWT.NONE,
328 //                                                      new HTMLTextPresenter(true), PHPDebugUiMessages
329 //                                                                      .getString("PHPDebugHover.16")); //$NON-NLS-1$
330                                         return new DefaultInformationControl(parent, PHPDebugUiMessages.getString("JavaDebugHover.16"),
331                                                         new HTMLTextPresenter(true));
332                                 }
333                         };
334                 }
335                 return null;
336         }
337 }