KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > debug > internal > ui > views > variables > details > DefaultDetailPane


1 /*******************************************************************************
2  * Copyright (c) 2006, 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  * QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640)
11  *******************************************************************************/

12 package org.eclipse.debug.internal.ui.views.variables.details;
13
14 import java.util.Iterator JavaDoc;
15 import java.util.ResourceBundle JavaDoc;
16
17 import org.eclipse.core.commands.operations.IUndoContext;
18 import org.eclipse.core.runtime.CoreException;
19 import org.eclipse.core.runtime.IAdaptable;
20 import org.eclipse.core.runtime.IProgressMonitor;
21 import org.eclipse.core.runtime.IStatus;
22 import org.eclipse.core.runtime.Status;
23 import org.eclipse.core.runtime.jobs.Job;
24 import org.eclipse.debug.core.DebugException;
25 import org.eclipse.debug.core.model.IDebugElement;
26 import org.eclipse.debug.core.model.IExpression;
27 import org.eclipse.debug.core.model.IValue;
28 import org.eclipse.debug.core.model.IVariable;
29 import org.eclipse.debug.internal.ui.DebugPluginImages;
30 import org.eclipse.debug.internal.ui.DebugUIPlugin;
31 import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
32 import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
33 import org.eclipse.debug.internal.ui.LazyModelPresentation;
34 import org.eclipse.debug.internal.ui.VariablesViewModelPresentation;
35 import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneAssignValueAction;
36 import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneMaxLengthAction;
37 import org.eclipse.debug.internal.ui.actions.variables.details.DetailPaneWordWrapAction;
38 import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
39 import org.eclipse.debug.internal.ui.views.variables.IndexedValuePartition;
40 import org.eclipse.debug.internal.ui.views.variables.StatusLineContributionItem;
41 import org.eclipse.debug.ui.IDebugModelPresentation;
42 import org.eclipse.debug.ui.IDebugUIConstants;
43 import org.eclipse.debug.ui.IDebugView;
44 import org.eclipse.debug.ui.IValueDetailListener;
45 import org.eclipse.jface.action.IAction;
46 import org.eclipse.jface.action.IMenuListener;
47 import org.eclipse.jface.action.IMenuManager;
48 import org.eclipse.jface.action.IStatusLineManager;
49 import org.eclipse.jface.action.MenuManager;
50 import org.eclipse.jface.action.Separator;
51 import org.eclipse.jface.commands.ActionHandler;
52 import org.eclipse.jface.resource.JFaceResources;
53 import org.eclipse.jface.text.BadLocationException;
54 import org.eclipse.jface.text.Document;
55 import org.eclipse.jface.text.DocumentEvent;
56 import org.eclipse.jface.text.IDocument;
57 import org.eclipse.jface.text.IDocumentListener;
58 import org.eclipse.jface.text.IFindReplaceTarget;
59 import org.eclipse.jface.text.ITextOperationTarget;
60 import org.eclipse.jface.text.ITextViewer;
61 import org.eclipse.jface.text.IUndoManager;
62 import org.eclipse.jface.text.IUndoManagerExtension;
63 import org.eclipse.jface.text.source.ISourceViewer;
64 import org.eclipse.jface.text.source.SourceViewer;
65 import org.eclipse.jface.text.source.SourceViewerConfiguration;
66 import org.eclipse.jface.util.IPropertyChangeListener;
67 import org.eclipse.jface.util.PropertyChangeEvent;
68 import org.eclipse.jface.viewers.ISelectionChangedListener;
69 import org.eclipse.jface.viewers.IStructuredSelection;
70 import org.eclipse.jface.viewers.SelectionChangedEvent;
71 import org.eclipse.swt.SWT;
72 import org.eclipse.swt.custom.StyledText;
73 import org.eclipse.swt.events.FocusAdapter;
74 import org.eclipse.swt.events.FocusEvent;
75 import org.eclipse.swt.events.KeyEvent;
76 import org.eclipse.swt.events.KeyListener;
77 import org.eclipse.swt.events.MouseEvent;
78 import org.eclipse.swt.events.MouseListener;
79 import org.eclipse.swt.graphics.Point;
80 import org.eclipse.swt.layout.GridData;
81 import org.eclipse.swt.widgets.Composite;
82 import org.eclipse.swt.widgets.Control;
83 import org.eclipse.swt.widgets.Menu;
84 import org.eclipse.ui.IWorkbenchActionConstants;
85 import org.eclipse.ui.PlatformUI;
86 import org.eclipse.ui.actions.ActionFactory;
87 import org.eclipse.ui.console.actions.TextViewerAction;
88 import org.eclipse.ui.handlers.IHandlerService;
89 import org.eclipse.ui.operations.OperationHistoryActionHandler;
90 import org.eclipse.ui.operations.RedoActionHandler;
91 import org.eclipse.ui.operations.UndoActionHandler;
92 import org.eclipse.ui.progress.WorkbenchJob;
93 import org.eclipse.ui.texteditor.FindReplaceAction;
94 import org.eclipse.ui.texteditor.IAbstractTextEditorHelpContextIds;
95 import org.eclipse.ui.texteditor.ITextEditorActionConstants;
96 import org.eclipse.ui.texteditor.ITextEditorActionDefinitionIds;
97 import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
98
99 import com.ibm.icu.text.MessageFormat;
100
101 /**
102  * This detail pane uses a source viewer to display detailed information about the current
103  * selection. It incorporates a large number of actions into its context menu. It is the
104  * default detail pane.
105  *
106  * @see DefaultDetailPaneFactory
107  * @since 3.3
108  *
109  */

110 public class DefaultDetailPane extends AbstractDetailPane implements IAdaptable, IPropertyChangeListener{
111
112     /**
113      * These are the IDs for the actions in the context menu
114      */

115     protected static final String JavaDoc DETAIL_COPY_ACTION = ActionFactory.COPY.getId() + ".SourceDetailPane"; //$NON-NLS-1$
116
protected static final String JavaDoc DETAIL_SELECT_ALL_ACTION = IDebugView.SELECT_ALL_ACTION + ".SourceDetailPane"; //$NON-NLS-1$
117
protected static final String JavaDoc DETAIL_PASTE_ACTION = ActionFactory.PASTE.getId();
118     protected static final String JavaDoc DETAIL_CUT_ACTION = ActionFactory.CUT.getId();
119     
120     protected static final String JavaDoc DETAIL_FIND_REPLACE_TEXT_ACTION = "FindReplaceText"; //$NON-NLS-1$
121
protected static final String JavaDoc DETAIL_CONTENT_ASSIST_ACTION = "ContentAssist"; //$NON-NLS-1$
122
protected static final String JavaDoc DETAIL_ASSIGN_VALUE_ACTION = "AssignValue"; //$NON-NLS-1$
123

124     protected static final String JavaDoc DETAIL_WORD_WRAP_ACTION = IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP;
125     protected static final String JavaDoc DETAIL_MAX_LENGTH_ACTION = "MaxLength"; //$NON-NLS-1$
126

127     /**
128      * The ID, name and description of this pane are stored in constants so that the class
129      * does not have to be instantiated to access them.
130      */

131     public static final String JavaDoc ID = DetailMessages.DefaultDetailPane_0;
132     public static final String JavaDoc NAME = DetailMessages.DefaultDetailPane_1;
133     public static final String JavaDoc DESCRIPTION = DetailMessages.DefaultDetailPane_57;
134     
135     /**
136      * Data structure for the position label value.
137      */

138     private static class PositionLabelValue {
139         
140         public int fValue;
141         
142         public String JavaDoc toString() {
143             return String.valueOf(fValue);
144         }
145     }
146     
147     /**
148      * Internal interface for a cursor listener. I.e. aggregation
149      * of mouse and key listener.
150      * @since 3.0
151      */

152     interface ICursorListener extends MouseListener, KeyListener {
153     }
154     
155     /**
156      * Job to compute the details for a selection
157      */

158     class DetailJob extends Job implements IValueDetailListener {
159         
160         private IStructuredSelection fElements;
161         private IDebugModelPresentation fModel;
162         private boolean fFirst = true;
163         // whether a result was collected
164
private boolean fComputed = false;
165         private IProgressMonitor fMonitor;
166         
167         public DetailJob(IStructuredSelection elements, IDebugModelPresentation model) {
168             super("compute variable details"); //$NON-NLS-1$
169
setSystem(true);
170             fElements = elements;
171             fModel = model;
172         }
173         
174         /* (non-Javadoc)
175          * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
176          */

177         protected IStatus run(IProgressMonitor monitor) {
178             fMonitor = monitor;
179             Iterator JavaDoc iterator = fElements.iterator();
180             String JavaDoc message = null;
181             while (iterator.hasNext()) {
182                 if (monitor.isCanceled()) {
183                     break;
184                 }
185                 Object JavaDoc element = iterator.next();
186                 IValue val = null;
187                 if (element instanceof IVariable) {
188                     try {
189                         val = ((IVariable)element).getValue();
190                     } catch (DebugException e) {
191                         detailComputed(null, e.getStatus().getMessage());
192                     }
193                 } else if (element instanceof IExpression) {
194                     val = ((IExpression)element).getValue();
195                 }
196                 // When selecting a index partition, clear the pane
197
if (val instanceof IndexedValuePartition) {
198                     detailComputed(null, ""); //$NON-NLS-1$
199
val = null;
200                 }
201                 if (element instanceof String JavaDoc) {
202                     message = (String JavaDoc) element;
203                 }
204                 if (val != null && !monitor.isCanceled()) {
205                     fModel.computeDetail(val, this);
206                     synchronized (this) {
207                         try {
208                             // wait for a max of 30 seconds for result, then cancel
209
wait(30000);
210                             if (!fComputed) {
211                                 fMonitor.setCanceled(true);
212                             }
213                         } catch (InterruptedException JavaDoc e) {
214                             break;
215                         }
216                     }
217                 }
218             }
219             // If no details were computed for the selected variable, clear the pane
220
// or use the message, if the variable was a java.lang.String
221
if (!fComputed){
222                 if (message == null) {
223                     detailComputed(null,""); //$NON-NLS-1$
224
} else {
225                     detailComputed(null, message);
226                 }
227             }
228             return Status.OK_STATUS;
229         }
230         
231         /* (non-Javadoc)
232          * @see org.eclipse.core.runtime.jobs.Job#canceling()
233          */

234         protected void canceling() {
235             super.canceling();
236             synchronized (this) {
237                 notifyAll();
238             }
239         }
240
241         /* (non-Javadoc)
242          * @see org.eclipse.debug.ui.IValueDetailListener#detailComputed(org.eclipse.debug.core.model.IValue, java.lang.String)
243          */

244         public void detailComputed(IValue value, final String JavaDoc result) {
245             synchronized (this) {
246                 fComputed = true;
247             }
248             if (!fMonitor.isCanceled()) {
249                 WorkbenchJob append = new WorkbenchJob("append details") { //$NON-NLS-1$
250
public IStatus runInUIThread(IProgressMonitor monitor) {
251                         if (!fMonitor.isCanceled()) {
252                             String JavaDoc insert = result;
253                             int length = 0;
254                             if (!fFirst) {
255                                 length = getDetailDocument().getLength();
256                             }
257                             if (length > 0) {
258                                 insert = "\n" + result; //$NON-NLS-1$
259
}
260                             try {
261                                 int max = DebugUIPlugin.getDefault().getPreferenceStore().getInt(IDebugUIConstants.PREF_MAX_DETAIL_LENGTH);
262                                 if (max > 0 && insert.length() > max) {
263                                     insert = insert.substring(0, max) + "..."; //$NON-NLS-1$
264
}
265                                 if (fFirst) {
266                                     getDetailDocument().set(insert);
267                                     fFirst = false;
268                                 } else {
269                                     getDetailDocument().replace(length, 0,insert);
270                                 }
271                             } catch (BadLocationException e) {
272                                 DebugUIPlugin.log(e);
273                             }
274                         }
275                         return Status.OK_STATUS;
276                     }
277                 };
278                 append.setSystem(true);
279                 append.schedule();
280             }
281             synchronized (this) {
282                 notifyAll();
283             }
284             
285         }
286
287     }
288     
289     /**
290      * The model presentation used to produce the string details for a
291      * selected variable.
292      */

293     private VariablesViewModelPresentation fModelPresentation;
294     private String JavaDoc fDebugModelIdentifier;
295     
296     /**
297      * Controls the status line while the details area has focus.
298      * Displays the current cursor position in the text (line:character).
299      */

300     private StatusLineContributionItem fStatusLineItem;
301
302     /**
303      * The source viewer in which the computed string detail
304      * of selected variables will be displayed.
305      */

306     private SourceViewer fSourceViewer;
307     
308     /**
309      * The last selection displayed in the source viewer.
310      */

311     private IStructuredSelection fLastDisplayed = null;
312     
313     /**
314      * Variables used to create the detailed information for a selection
315      */

316     private IDocument fDetailDocument;
317     private DetailJob fDetailJob = null;
318     private final String JavaDoc fPositionLabelPattern = DetailMessages.DefaultDetailPane_56;
319     private final PositionLabelValue fLineLabel = new PositionLabelValue();
320     private final PositionLabelValue fColumnLabel = new PositionLabelValue();
321     private final Object JavaDoc[] fPositionLabelPatternArguments = new Object JavaDoc[] {
322             fLineLabel, fColumnLabel };
323     private ICursorListener fCursorListener;
324     
325     /* (non-Javadoc)
326      * @see org.eclipse.debug.ui.IDetailPane#createControl(org.eclipse.swt.widgets.Composite)
327      */

328     public Control createControl(Composite parent) {
329         
330         fModelPresentation = new VariablesViewModelPresentation();
331         
332         createSourceViewer(parent);
333         
334         if (isInView()){
335             createViewSpecificComponents();
336             createActions();
337             DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
338             JFaceResources.getFontRegistry().addListener(this);
339         }
340         
341         return fSourceViewer.getControl();
342     }
343
344     /**
345      * Creates the source viewer in the given parent composite
346      *
347      * @param parent Parent composite to create the source viewer in
348      */

349     private void createSourceViewer(Composite parent) {
350         
351         // Create & configure a SourceViewer
352
fSourceViewer = new SourceViewer(parent, null, SWT.V_SCROLL | SWT.H_SCROLL);
353         fSourceViewer.setDocument(getDetailDocument());
354         fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IInternalDebugUIConstants.DETAIL_PANE_FONT));
355         fSourceViewer.getTextWidget().setWordWrap(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP));
356         fSourceViewer.setEditable(false);
357         PlatformUI.getWorkbench().getHelpSystem().setHelp(fSourceViewer.getTextWidget(), IDebugHelpContextIds.DETAIL_PANE);
358         Control control = fSourceViewer.getControl();
359         GridData gd = new GridData(GridData.FILL_BOTH);
360         control.setLayoutData(gd);
361     }
362
363     /**
364      * Creates listeners and other components that should only be added to the
365      * source viewer when this detail pane is inside a view.
366      */

367     private void createViewSpecificComponents(){
368         
369         // Add a document listener so actions get updated when the document changes
370
getDetailDocument().addDocumentListener(new IDocumentListener() {
371             public void documentAboutToBeChanged(DocumentEvent event) {}
372             public void documentChanged(DocumentEvent event) {
373                 updateSelectionDependentActions();
374             }
375         });
376         
377         // Add the selection listener so selection dependent actions get updated.
378
fSourceViewer.getSelectionProvider().addSelectionChangedListener(new ISelectionChangedListener() {
379             public void selectionChanged(SelectionChangedEvent event) {
380                 updateSelectionDependentActions();
381             }
382         });
383         
384         // Add a focus listener to update actions when details area gains focus
385
fSourceViewer.getControl().addFocusListener(new FocusAdapter() {
386             public void focusGained(FocusEvent e) {
387                 
388                 getViewSite().setSelectionProvider(fSourceViewer.getSelectionProvider());
389                 
390                 setGlobalAction(IDebugView.SELECT_ALL_ACTION, getAction(DETAIL_SELECT_ALL_ACTION));
391                 setGlobalAction(IDebugView.CUT_ACTION, getAction(DETAIL_CUT_ACTION));
392                 setGlobalAction(IDebugView.COPY_ACTION, getAction(DETAIL_COPY_ACTION));
393                 setGlobalAction(IDebugView.PASTE_ACTION, getAction(DETAIL_PASTE_ACTION));
394                 setGlobalAction(IDebugView.FIND_ACTION, getAction(DETAIL_FIND_REPLACE_TEXT_ACTION));
395                 IAction action = getAction(DETAIL_ASSIGN_VALUE_ACTION);
396                 setGlobalAction(action.getActionDefinitionId(), action);
397                 action = getAction(DETAIL_CONTENT_ASSIST_ACTION);
398                 setGlobalAction(action.getActionDefinitionId(),action);
399                 
400                 getViewSite().getActionBars().updateActionBars();
401                 
402                 updateAction(DETAIL_FIND_REPLACE_TEXT_ACTION);
403                 
404             }
405             
406             public void focusLost(FocusEvent e) {
407                 
408                 getViewSite().setSelectionProvider(null);
409                 
410                 setGlobalAction(IDebugView.SELECT_ALL_ACTION, null);
411                 setGlobalAction(IDebugView.CUT_ACTION, null);
412                 setGlobalAction(IDebugView.COPY_ACTION, null);
413                 setGlobalAction(IDebugView.PASTE_ACTION, null);
414                 setGlobalAction(IDebugView.FIND_ACTION, null);
415                 setGlobalAction(getAction(DETAIL_ASSIGN_VALUE_ACTION).getActionDefinitionId(), null);
416                 setGlobalAction(getAction(DETAIL_CONTENT_ASSIST_ACTION).getActionDefinitionId(), null);
417                 
418                 getViewSite().getActionBars().updateActionBars();
419                 
420             }
421         });
422         
423         // Create a status line item displaying the current cursor location
424
fStatusLineItem = new StatusLineContributionItem("ModeContributionItem"); //$NON-NLS-1$
425
IStatusLineManager manager= getViewSite().getActionBars().getStatusLineManager();
426         manager.add(fStatusLineItem);
427         fSourceViewer.getTextWidget().addMouseListener(getCursorListener());
428         fSourceViewer.getTextWidget().addKeyListener(getCursorListener());
429         
430         // Add a context menu to the detail area
431
createDetailContextMenu(fSourceViewer.getTextWidget());
432         
433     }
434     
435     /**
436      * Creates the actions to add to the context menu
437      */

438     private void createActions() {
439        
440         TextViewerAction textAction= new TextViewerAction(fSourceViewer, ISourceViewer.CONTENTASSIST_PROPOSALS);
441         textAction.setActionDefinitionId(ITextEditorActionDefinitionIds.CONTENT_ASSIST_PROPOSALS);
442         textAction.configureAction(DetailMessages.DefaultDetailPane_Co_ntent_Assist_3, "",""); //$NON-NLS-1$ //$NON-NLS-2$
443
textAction.setImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_ELCL_CONTENT_ASSIST));
444         textAction.setHoverImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_LCL_CONTENT_ASSIST));
445         textAction.setDisabledImageDescriptor(DebugPluginImages.getImageDescriptor(IDebugUIConstants.IMG_DLCL_CONTENT_ASSIST));
446         PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_CONTENT_ASSIST_ACTION);
447         setAction(DETAIL_CONTENT_ASSIST_ACTION, textAction);
448         
449         ActionHandler actionHandler = new ActionHandler(textAction);
450         IHandlerService handlerService = (IHandlerService) getViewSite().getService(IHandlerService.class);
451         handlerService.activateHandler(textAction.getActionDefinitionId(), actionHandler);
452             
453         textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.SELECT_ALL);
454         textAction.configureAction(DetailMessages.DefaultDetailPane_Select__All_5, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
455
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.SELECT_ALL);
456         PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_SELECT_ALL_ACTION);
457         setAction(DETAIL_SELECT_ALL_ACTION, textAction);
458         
459         textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.COPY);
460         textAction.configureAction(DetailMessages.DefaultDetailPane__Copy_8, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
461
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.COPY);
462         PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_COPY_ACTION);
463         setAction(DETAIL_COPY_ACTION, textAction);
464         
465         textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.CUT);
466         textAction.configureAction(DetailMessages.DefaultDetailPane_Cu_t_11, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
467
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.CUT);
468         PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_CUT_ACTION);
469         setAction(DETAIL_CUT_ACTION, textAction);
470         
471         textAction= new TextViewerAction(fSourceViewer, ITextOperationTarget.PASTE);
472         textAction.configureAction(DetailMessages.DefaultDetailPane__Paste_14, "", ""); //$NON-NLS-1$ //$NON-NLS-2$
473
textAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.PASTE);
474         PlatformUI.getWorkbench().getHelpSystem().setHelp(textAction, IDebugHelpContextIds.DETAIL_PANE_PASTE_ACTION);
475         setAction(ActionFactory.PASTE.getId(), textAction);
476         
477         setSelectionDependantAction(DETAIL_COPY_ACTION);
478         setSelectionDependantAction(DETAIL_CUT_ACTION);
479         setSelectionDependantAction(DETAIL_PASTE_ACTION);
480         
481         // TODO: Still using "old" resource access, find/replace won't work in popup dialogs
482
ResourceBundle JavaDoc bundle= ResourceBundle.getBundle("org.eclipse.debug.internal.ui.views.variables.VariablesViewResourceBundleMessages"); //$NON-NLS-1$
483
IAction action = new FindReplaceAction(bundle, "find_replace_action_", getWorkbenchPartSite().getShell(), new FindReplaceTargetWrapper(fSourceViewer.getFindReplaceTarget())); //$NON-NLS-1$
484
action.setActionDefinitionId(IWorkbenchActionDefinitionIds.FIND_REPLACE);
485         PlatformUI.getWorkbench().getHelpSystem().setHelp(action, IDebugHelpContextIds.DETAIL_PANE_FIND_REPLACE_ACTION);
486         setAction(DETAIL_FIND_REPLACE_TEXT_ACTION, action);
487             
488         updateSelectionDependentActions();
489         
490         action = new DetailPaneWordWrapAction(fSourceViewer);
491         setAction(DETAIL_WORD_WRAP_ACTION, action);
492         
493         action = new DetailPaneMaxLengthAction(fSourceViewer.getControl().getShell());
494         setAction(DETAIL_MAX_LENGTH_ACTION,action);
495         
496         action = new DetailPaneAssignValueAction(fSourceViewer,getViewSite());
497         setAction(DETAIL_ASSIGN_VALUE_ACTION, action);
498     }
499     
500     /**
501      * Create the context menu particular to the detail pane. Note that anyone
502      * wishing to contribute an action to this menu must use
503      * <code>IDebugUIConstants.VARIABLE_VIEW_DETAIL_ID</code> as the
504      * <code>targetID</code> in the extension XML.
505      */

506     protected void createDetailContextMenu(Control menuControl) {
507         MenuManager menuMgr= new MenuManager();
508         menuMgr.setRemoveAllWhenShown(true);
509         menuMgr.addMenuListener(new IMenuListener() {
510             public void menuAboutToShow(IMenuManager mgr) {
511                 fillDetailContextMenu(mgr);
512             }
513         });
514         Menu menu= menuMgr.createContextMenu(menuControl);
515         menuControl.setMenu(menu);
516
517         getViewSite().registerContextMenu(IDebugUIConstants.VARIABLE_VIEW_DETAIL_ID, menuMgr, fSourceViewer.getSelectionProvider());
518
519     }
520     
521     /**
522     * Adds items to the detail pane's context menu including any extension defined
523     * actions.
524     *
525     * @param menu The menu to add the item to.
526     */

527     protected void fillDetailContextMenu(IMenuManager menu) {
528         
529         menu.add(new Separator(IDebugUIConstants.VARIABLE_GROUP));
530         if (isInView()){
531             menu.add(getAction(DETAIL_ASSIGN_VALUE_ACTION));
532             menu.add(getAction(DETAIL_CONTENT_ASSIST_ACTION));
533         }
534         menu.add(new Separator());
535         menu.add(getAction(DETAIL_CUT_ACTION));
536         menu.add(getAction(DETAIL_COPY_ACTION));
537         menu.add(getAction(DETAIL_PASTE_ACTION));
538         menu.add(getAction(DETAIL_SELECT_ALL_ACTION));
539         menu.add(new Separator("FIND")); //$NON-NLS-1$
540
if (isInView()){
541             menu.add(getAction(DETAIL_FIND_REPLACE_TEXT_ACTION));
542         }
543         menu.add(new Separator());
544         menu.add(getAction(DETAIL_WORD_WRAP_ACTION));
545         menu.add(getAction(DETAIL_MAX_LENGTH_ACTION));
546         menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
547         
548     }
549     
550     /* (non-Javadoc)
551      * @see org.eclipse.debug.ui.IDetailPane#display(org.eclipse.jface.viewers.IStructuredSelection)
552      */

553     public void display(IStructuredSelection selection) {
554         
555         if (selection == null){
556             clearSourceViewer();
557             return;
558         }
559                 
560         fLastDisplayed = selection;
561         if (isInView()){
562             fSourceViewer.setEditable(true);
563         }
564                         
565         if (selection.isEmpty()){
566             clearSourceViewer();
567             return;
568         }
569         
570         Object JavaDoc firstElement = selection.getFirstElement();
571         if (firstElement != null && firstElement instanceof IDebugElement) {
572             String JavaDoc modelID = ((IDebugElement)firstElement).getModelIdentifier();
573             setDebugModel(modelID);
574         }
575         
576         if (isInView()){
577             IAction assignAction = getAction(DETAIL_ASSIGN_VALUE_ACTION);
578             if (assignAction instanceof DetailPaneAssignValueAction){
579                 ((DetailPaneAssignValueAction)assignAction).updateCurrentVariable(selection);
580             }
581         }
582         
583         synchronized (this) {
584             if (fDetailJob != null) {
585                 fDetailJob.cancel();
586             }
587             fDetailJob = new DetailJob(selection,fModelPresentation);
588             fDetailJob.schedule();
589         }
590         
591     }
592     
593     /* (non-Javadoc)
594      * @see org.eclipse.debug.ui.IDetailPane#setFocus()
595      */

596     public boolean setFocus(){
597         if (fSourceViewer != null){
598             fSourceViewer.getTextWidget().setFocus();
599             return true;
600         }
601         return false;
602     }
603     
604     /* (non-Javadoc)
605      * @see org.eclipse.debug.internal.ui.views.variables.details.AbstractDetailPane#dispose()
606      */

607     public void dispose(){
608         super.dispose();
609         
610         if (fDetailJob != null) fDetailJob.cancel();
611         if (fModelPresentation != null) fModelPresentation.dispose();
612         fDebugModelIdentifier = null; // Setting this to null makes sure the source viewer is reconfigured with the model presentation after disposal
613
if (fSourceViewer != null && fSourceViewer.getControl() != null) fSourceViewer.getControl().dispose();
614         
615         if (isInView()){
616             disposeUndoRedoAction(ITextEditorActionConstants.UNDO);
617             disposeUndoRedoAction(ITextEditorActionConstants.REDO);
618             
619             getViewSite().getActionBars().getStatusLineManager().remove(fStatusLineItem);
620             
621             DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
622             JFaceResources.getFontRegistry().removeListener(this);
623         }
624     }
625     
626     /* (non-Javadoc)
627      * @see org.eclipse.debug.ui.IDetailPane#getDescription()
628      */

629     public String JavaDoc getDescription() {
630         return DESCRIPTION;
631     }
632
633     /* (non-Javadoc)
634      * @see org.eclipse.debug.ui.IDetailPane#getID()
635      */

636     public String JavaDoc getID() {
637         return ID;
638     }
639
640     /* (non-Javadoc)
641      * @see org.eclipse.debug.ui.IDetailPane#getName()
642      */

643     public String JavaDoc getName() {
644         return NAME;
645     }
646     
647     /* (non-Javadoc)
648      * @see org.eclipse.core.runtime.IAdaptable#getAdapter(java.lang.Class)
649      */

650     public Object JavaDoc getAdapter(Class JavaDoc required) {
651         if (IFindReplaceTarget.class.equals(required)) {
652             return fSourceViewer.getFindReplaceTarget();
653         }
654         if (ITextViewer.class.equals(required)) {
655             return fSourceViewer;
656         }
657         return null;
658     }
659     
660     /**
661      * Lazily instantiate and return a Document for the detail pane text viewer.
662      */

663     protected IDocument getDetailDocument() {
664         if (fDetailDocument == null) {
665             fDetailDocument = new Document();
666         }
667         return fDetailDocument;
668     }
669     
670     /**
671      * Clears the source viewer, removes all text.
672      */

673     protected void clearSourceViewer(){
674         if (fDetailJob != null) {
675             fDetailJob.cancel();
676         }
677         fLastDisplayed = null;
678         fDetailDocument.set(""); //$NON-NLS-1$
679
fSourceViewer.setEditable(false);
680     }
681
682     /**
683      * Configures the details viewer for the debug model
684      * currently being displayed
685      */

686     protected void configureDetailsViewer() {
687         LazyModelPresentation mp = (LazyModelPresentation)fModelPresentation.getPresentation(getDebugModel());
688         SourceViewerConfiguration svc = null;
689         if (mp != null) {
690             try {
691                 svc = mp.newDetailsViewerConfiguration();
692             } catch (CoreException e) {
693                 DebugUIPlugin.errorDialog(fSourceViewer.getControl().getShell(), DetailMessages.DefaultDetailPane_Error_1, DetailMessages.DefaultDetailPane_2, e);
694             }
695         }
696         
697         if (svc == null) {
698             svc = new SourceViewerConfiguration();
699             fSourceViewer.setEditable(false);
700         }
701         fSourceViewer.unconfigure();
702         fSourceViewer.configure(svc);
703         //update actions that depend on the configuration of the source viewer
704

705         if (isInView()){
706             updateAction(DETAIL_ASSIGN_VALUE_ACTION);
707             updateAction(DETAIL_CONTENT_ASSIST_ACTION);
708         }
709         
710         if (isInView()){
711             createUndoRedoActions();
712         }
713     }
714
715     /**
716      * @return The formatted string describing cursor position
717      */

718     protected String JavaDoc getCursorPosition() {
719         
720         if (fSourceViewer == null) {
721             return ""; //$NON-NLS-1$
722
}
723         
724         StyledText styledText= fSourceViewer.getTextWidget();
725         int caret= styledText.getCaretOffset();
726         IDocument document= fSourceViewer.getDocument();
727     
728         if (document == null) {
729             return ""; //$NON-NLS-1$
730
}
731     
732         try {
733             
734             int line= document.getLineOfOffset(caret);
735     
736             int lineOffset= document.getLineOffset(line);
737             int tabWidth= styledText.getTabs();
738             int column= 0;
739             for (int i= lineOffset; i < caret; i++)
740                 if ('\t' == document.getChar(i)) {
741                     column += tabWidth - (tabWidth == 0 ? 0 : column % tabWidth);
742                 } else {
743                     column++;
744                 }
745                     
746             fLineLabel.fValue= line + 1;
747             fColumnLabel.fValue= column + 1;
748             return MessageFormat.format(fPositionLabelPattern, fPositionLabelPatternArguments);
749             
750         } catch (BadLocationException x) {
751             return ""; //$NON-NLS-1$
752
}
753     }
754
755     /**
756      * Returns this view's "cursor" listener to be installed on the view's
757      * associated details viewer. This listener is listening to key and mouse button events.
758      * It triggers the updating of the status line.
759      *
760      * @return the listener
761      */

762     private ICursorListener getCursorListener() {
763         if (fCursorListener == null) {
764             fCursorListener= new ICursorListener() {
765                 
766                 public void keyPressed(KeyEvent e) {
767                     fStatusLineItem.setText(getCursorPosition());
768                 }
769                 
770                 public void keyReleased(KeyEvent e) {
771                 }
772                 
773                 public void mouseDoubleClick(MouseEvent e) {
774                 }
775                 
776                 public void mouseDown(MouseEvent e) {
777                 }
778                 
779                 public void mouseUp(MouseEvent e) {
780                     fStatusLineItem.setText(getCursorPosition());
781                 }
782             };
783         }
784         return fCursorListener;
785     }
786     
787     /**
788      * Returns the identifier of the debug model being displayed
789      * in this view, or <code>null</code> if none.
790      *
791      * @return debug model identifier
792      */

793     protected String JavaDoc getDebugModel() {
794         return fDebugModelIdentifier;
795     }
796
797     /**
798      * Sets the identifier of the debug model being displayed
799      * in this view, or <code>null</code> if none.
800      *
801      * @param id debug model identifier of the type of debug
802      * elements being displayed in this view
803      */

804     protected void setDebugModel(String JavaDoc id) {
805         if (id != fDebugModelIdentifier) {
806             fDebugModelIdentifier = id;
807             configureDetailsViewer();
808         }
809     }
810     
811     /**
812      * Creates this editor's undo/re-do actions.
813      * <p>
814      * Subclasses may override or extend.</p>
815      *
816      * @since 3.2
817      */

818     protected void createUndoRedoActions() {
819         disposeUndoRedoAction(ITextEditorActionConstants.UNDO);
820         disposeUndoRedoAction(ITextEditorActionConstants.REDO);
821         IUndoContext undoContext= getUndoContext();
822         if (undoContext != null) {
823             // Use actions provided by global undo/re-do
824

825             // Create the undo action
826
OperationHistoryActionHandler undoAction= new UndoActionHandler(getViewSite(), undoContext);
827             PlatformUI.getWorkbench().getHelpSystem().setHelp(undoAction, IAbstractTextEditorHelpContextIds.UNDO_ACTION);
828             undoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.UNDO);
829             setAction(ITextEditorActionConstants.UNDO, undoAction);
830             setGlobalAction(ITextEditorActionConstants.UNDO, undoAction);
831             
832             // Create the re-do action.
833
OperationHistoryActionHandler redoAction= new RedoActionHandler(getViewSite(), undoContext);
834             PlatformUI.getWorkbench().getHelpSystem().setHelp(redoAction, IAbstractTextEditorHelpContextIds.REDO_ACTION);
835             redoAction.setActionDefinitionId(IWorkbenchActionDefinitionIds.REDO);
836             setAction(ITextEditorActionConstants.REDO, redoAction);
837             setGlobalAction(ITextEditorActionConstants.REDO, redoAction);
838             
839             getViewSite().getActionBars().updateActionBars();
840         }
841     }
842     
843     /**
844      * Disposes of the action with the specified ID
845      *
846      * @param actionId the ID of the action to disposed
847      */

848     protected void disposeUndoRedoAction(String JavaDoc actionId) {
849         OperationHistoryActionHandler action = (OperationHistoryActionHandler) getAction(actionId);
850         if (action != null) {
851             action.dispose();
852             setAction(actionId, null);
853         }
854     }
855     
856     /**
857      * Returns this editor's viewer's undo manager undo context.
858      *
859      * @return the undo context or <code>null</code> if not available
860      * @since 3.2
861      */

862     private IUndoContext getUndoContext() {
863         IUndoManager undoManager= fSourceViewer.getUndoManager();
864         if (undoManager instanceof IUndoManagerExtension)
865             return ((IUndoManagerExtension)undoManager).getUndoContext();
866         return null;
867     }
868
869     /* (non-Javadoc)
870      * @see org.eclipse.jface.util.IPropertyChangeListener#propertyChange(org.eclipse.jface.util.PropertyChangeEvent)
871      */

872     public void propertyChange(PropertyChangeEvent event) {
873         String JavaDoc propertyName= event.getProperty();
874         if (propertyName.equals(IInternalDebugUIConstants.DETAIL_PANE_FONT)) {
875             fSourceViewer.getTextWidget().setFont(JFaceResources.getFont(IInternalDebugUIConstants.DETAIL_PANE_FONT));
876         } else if (propertyName.equals(IDebugUIConstants.PREF_MAX_DETAIL_LENGTH)) {
877             display(fLastDisplayed);
878         } else if (propertyName.equals(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP)) {
879             fSourceViewer.getTextWidget().setWordWrap(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP));
880             getAction(DETAIL_WORD_WRAP_ACTION).setChecked(DebugUIPlugin.getDefault().getPreferenceStore().getBoolean(IDebugPreferenceConstants.PREF_DETAIL_PANE_WORD_WRAP));
881         }
882         
883     }
884
885     /**
886      * Wrapper class that wraps around an IFindReplaceTarget. Allows the detail pane to scroll
887      * to text selected by the find/replace action. The source viewer treats the text as a single
888      * line, even when the text is wrapped onto several lines so the viewer will not scroll properly
889      * on it's own. See bug 178106.
890      */

891     class FindReplaceTargetWrapper implements IFindReplaceTarget{
892         
893         private IFindReplaceTarget fTarget;
894         
895         /**
896          * Constructor
897          *
898          * @param target find/replace target this class will wrap around.
899          */

900         public FindReplaceTargetWrapper(IFindReplaceTarget target){
901             fTarget = target;
902         }
903
904         /* (non-Javadoc)
905          * @see org.eclipse.jface.text.IFindReplaceTarget#canPerformFind()
906          */

907         public boolean canPerformFind() {
908             return fTarget.canPerformFind();
909         }
910
911         /* (non-Javadoc)
912          * @see org.eclipse.jface.text.IFindReplaceTarget#findAndSelect(int, java.lang.String, boolean, boolean, boolean)
913          */

914         public int findAndSelect(int widgetOffset, String JavaDoc findString, boolean searchForward, boolean caseSensitive, boolean wholeWord) {
915             int position = fTarget.findAndSelect(widgetOffset, findString, searchForward, caseSensitive, wholeWord);
916             // Explicitly tell the widget to show the selection because the viewer thinks the text is all on one line, even if wrapping is turned on.
917
if (fSourceViewer != null){
918                 StyledText text = fSourceViewer.getTextWidget();
919                 if(text != null && !text.isDisposed()) {
920                     text.showSelection();
921                 }
922             }
923             return position;
924         }
925
926         /* (non-Javadoc)
927          * @see org.eclipse.jface.text.IFindReplaceTarget#getSelection()
928          */

929         public Point getSelection() {
930             return fTarget.getSelection();
931         }
932
933         /* (non-Javadoc)
934          * @see org.eclipse.jface.text.IFindReplaceTarget#getSelectionText()
935          */

936         public String JavaDoc getSelectionText() {
937             return fTarget.getSelectionText();
938         }
939
940         /* (non-Javadoc)
941          * @see org.eclipse.jface.text.IFindReplaceTarget#isEditable()
942          */

943         public boolean isEditable() {
944             return fTarget.isEditable();
945         }
946
947         /* (non-Javadoc)
948          * @see org.eclipse.jface.text.IFindReplaceTarget#replaceSelection(java.lang.String)
949          */

950         public void replaceSelection(String JavaDoc text) {
951             fTarget.replaceSelection(text);
952         }
953     }
954     
955 }
956
957
Popular Tags