KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*******************************************************************************
2  * Copyright (c) 2000, 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;
13
14 import java.io.ByteArrayInputStream JavaDoc;
15 import java.io.ByteArrayOutputStream JavaDoc;
16 import java.io.IOException JavaDoc;
17 import java.io.InputStreamReader JavaDoc;
18 import java.io.OutputStreamWriter JavaDoc;
19
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.internal.ui.DebugUIPlugin;
26 import org.eclipse.debug.internal.ui.DelegatingModelPresentation;
27 import org.eclipse.debug.internal.ui.IDebugHelpContextIds;
28 import org.eclipse.debug.internal.ui.IInternalDebugUIConstants;
29 import org.eclipse.debug.internal.ui.LazyModelPresentation;
30 import org.eclipse.debug.internal.ui.VariablesViewModelPresentation;
31 import org.eclipse.debug.internal.ui.actions.CollapseAllAction;
32 import org.eclipse.debug.internal.ui.actions.ConfigureColumnsAction;
33 import org.eclipse.debug.internal.ui.actions.variables.ChangeVariableValueAction;
34 import org.eclipse.debug.internal.ui.actions.variables.ShowTypesAction;
35 import org.eclipse.debug.internal.ui.actions.variables.ToggleDetailPaneAction;
36 import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
37 import org.eclipse.debug.internal.ui.viewers.model.VirtualFindAction;
38 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener;
39 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta;
40 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor;
41 import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy;
42 import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext;
43 import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate;
44 import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener;
45 import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer;
46 import org.eclipse.debug.internal.ui.views.DebugModelPresentationContext;
47 import org.eclipse.debug.internal.ui.views.IDebugExceptionHandler;
48 import org.eclipse.debug.internal.ui.views.variables.details.AvailableDetailPanesAction;
49 import org.eclipse.debug.internal.ui.views.variables.details.DetailPaneProxy;
50 import org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer;
51 import org.eclipse.debug.ui.AbstractDebugView;
52 import org.eclipse.debug.ui.DebugUITools;
53 import org.eclipse.debug.ui.IDebugModelPresentation;
54 import org.eclipse.debug.ui.IDebugUIConstants;
55 import org.eclipse.debug.ui.contexts.DebugContextEvent;
56 import org.eclipse.debug.ui.contexts.IDebugContextListener;
57 import org.eclipse.jface.action.IAction;
58 import org.eclipse.jface.action.IMenuListener;
59 import org.eclipse.jface.action.IMenuManager;
60 import org.eclipse.jface.action.IStatusLineManager;
61 import org.eclipse.jface.action.IToolBarManager;
62 import org.eclipse.jface.action.MenuManager;
63 import org.eclipse.jface.action.Separator;
64 import org.eclipse.jface.preference.IPreferenceStore;
65 import org.eclipse.jface.resource.JFaceResources;
66 import org.eclipse.jface.util.IPropertyChangeListener;
67 import org.eclipse.jface.util.PropertyChangeEvent;
68 import org.eclipse.jface.viewers.DoubleClickEvent;
69 import org.eclipse.jface.viewers.ISelection;
70 import org.eclipse.jface.viewers.ISelectionChangedListener;
71 import org.eclipse.jface.viewers.IStructuredSelection;
72 import org.eclipse.jface.viewers.SelectionChangedEvent;
73 import org.eclipse.jface.viewers.StructuredViewer;
74 import org.eclipse.jface.viewers.TreeViewer;
75 import org.eclipse.jface.viewers.Viewer;
76 import org.eclipse.swt.SWT;
77 import org.eclipse.swt.custom.SashForm;
78 import org.eclipse.swt.events.FocusAdapter;
79 import org.eclipse.swt.events.FocusEvent;
80 import org.eclipse.swt.widgets.Composite;
81 import org.eclipse.swt.widgets.Control;
82 import org.eclipse.swt.widgets.Event;
83 import org.eclipse.swt.widgets.Listener;
84 import org.eclipse.ui.IActionBars;
85 import org.eclipse.ui.IMemento;
86 import org.eclipse.ui.IPerspectiveDescriptor;
87 import org.eclipse.ui.IPerspectiveListener;
88 import org.eclipse.ui.IViewSite;
89 import org.eclipse.ui.IWorkbenchActionConstants;
90 import org.eclipse.ui.IWorkbenchPage;
91 import org.eclipse.ui.IWorkbenchPart;
92 import org.eclipse.ui.IWorkbenchPartSite;
93 import org.eclipse.ui.PartInitException;
94 import org.eclipse.ui.WorkbenchException;
95 import org.eclipse.ui.XMLMemento;
96 import org.eclipse.ui.progress.UIJob;
97 import org.eclipse.ui.texteditor.IUpdate;
98
99 /**
100  * This view shows variables and their values for a particular stack frame
101  */

102 public class VariablesView extends AbstractDebugView implements IDebugContextListener,
103     IPropertyChangeListener, IDebugExceptionHandler,
104     IPerspectiveListener, IModelChangedListener,
105     IViewerUpdateListener, IDetailPaneContainer {
106     
107     /**
108      * The model presentation used as the label provider for the tree viewer,
109      * and also as the detail information provider for the detail pane.
110      */

111     private VariablesViewModelPresentation fModelPresentation;
112     
113     /**
114      * The UI construct that provides a sliding sash between the variables tree
115      * and the detail pane.
116      */

117     private SashForm fSashForm;
118     
119     /**
120      * The detail pane that displays detailed information about the current selection
121      * @since 3.3
122      */

123     private DetailPaneProxy fDetailPane;
124     
125     /**
126      * Stores whether the tree viewer was the last control to have focus in the
127      * view. Used to give focus to the correct component if the user leaves the view.
128      * @since 3.3
129      */

130     private boolean fTreeHasFocus = true;
131     
132     /**
133      * Various listeners used to update the enabled state of actions and also to
134      * populate the detail pane.
135      */

136     private ISelectionChangedListener fTreeSelectionChangedListener;
137     
138     /**
139      * Listener added to the control of the detail pane, allows view to keep track of which
140      * part last had focus, the tree or the detail pane.
141      */

142     private Listener fDetailPaneActivatedListener;
143     
144     /**
145      * These are used to initialize and persist the position of the sash that
146      * separates the tree viewer from the detail pane.
147      */

148     private static final int[] DEFAULT_SASH_WEIGHTS = {13, 6};
149     private int[] fLastSashWeights;
150     private boolean fToggledDetailOnce;
151     private String JavaDoc fCurrentDetailPaneOrientation = IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN;
152     private ToggleDetailPaneAction[] fToggleDetailPaneActions;
153     private ConfigureColumnsAction fConfigureColumnsAction;
154     
155     protected String JavaDoc PREF_STATE_MEMENTO = "pref_state_memento."; //$NON-NLS-1$
156

157     public static final String JavaDoc LOGICAL_STRUCTURE_TYPE_PREFIX = "VAR_LS_"; //$NON-NLS-1$
158

159     /**
160      * Presentation context property.
161      * TODO: make API
162      * @since 3.3
163      */

164     public static final String JavaDoc PRESENTATION_SHOW_LOGICAL_STRUCTURES = "PRESENTATION_SHOW_LOGICAL_STRUCTURES"; //$NON-NLS-1$
165

166     /**
167      * the preference name for the view part of the sash form
168      * @since 3.2
169      */

170     protected static final String JavaDoc SASH_VIEW_PART = DebugUIPlugin.getUniqueIdentifier() + ".SASH_VIEW_PART"; //$NON-NLS-1$
171
/**
172      * the preference name for the details part of the sash form
173      * @since 3.2
174      */

175     protected static final String JavaDoc SASH_DETAILS_PART = DebugUIPlugin.getUniqueIdentifier() + ".SASH_DETAILS_PART"; //$NON-NLS-1$
176

177     /**
178      * Key for "Find..." action.
179      */

180     protected static final String JavaDoc VARIABLES_FIND_ELEMENT_ACTION = FIND_ACTION + ".Variables"; //$NON-NLS-1$
181

182     /**
183      * Key for "Select All" action.
184      */

185     protected static final String JavaDoc VARIABLES_SELECT_ALL_ACTION = SELECT_ALL_ACTION + ".Variables"; //$NON-NLS-1$
186

187     /**
188      * Key for "Select All" action.
189      */

190     protected static final String JavaDoc VARIABLES_COPY_ACTION = COPY_ACTION + ".Variables"; //$NON-NLS-1$
191

192     /**
193      * Visits deltas to determine if details should be displayed
194      */

195     class Visitor implements IModelDeltaVisitor {
196         /**
197          * Whether to trigger details display.
198          *
199          * @since 3.3
200          */

201         private boolean fTriggerDetails = false;
202         /* (non-Javadoc)
203          * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor#visit(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta, int)
204          */

205         public boolean visit(IModelDelta delta, int depth) {
206             if ((delta.getFlags() & IModelDelta.CONTENT) > 0) {
207                 fTriggerDetails = true;
208                 return false;
209             }
210             return true;
211         }
212         
213         public void reset() {
214             fTriggerDetails = false;
215         }
216         
217         public boolean isTriggerDetails() {
218             return fTriggerDetails;
219         }
220         
221     }
222     /**
223      * Delta visitor
224      */

225     private Visitor fVisitor = new Visitor();
226     
227     /**
228      * Job to update details in the UI thread.
229      */

230     private Job fTriggerDetailsJob = new UIJob("trigger details") { //$NON-NLS-1$
231

232         public IStatus runInUIThread(IProgressMonitor monitor) {
233             if (monitor.isCanceled()) {
234                 return Status.CANCEL_STATUS;
235             }
236             refreshDetailPaneContents();
237             return Status.OK_STATUS;
238         }
239     };
240     
241     /**
242      * Remove myself as a selection listener
243      * and preference change listener.
244      *
245      * @see IWorkbenchPart#dispose()
246      */

247     public void dispose() {
248         
249         DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).removeDebugContextListener(this);
250         getSite().getWorkbenchWindow().removePerspectiveListener(this);
251         DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this);
252         JFaceResources.getFontRegistry().removeListener(this);
253         TreeModelViewer viewer = getVariablesViewer();
254         if (viewer != null) {
255             viewer.removeModelChangedListener(this);
256             viewer.removeViewerUpdateListener(this);
257         }
258         if (fDetailPane != null) fDetailPane.dispose();
259         super.dispose();
260     }
261
262     /**
263      * Sets the input to the viewer
264      * @param context the object context
265      */

266     protected void setViewerInput(Object JavaDoc context) {
267         
268         if (context == null) {
269             // Clear the detail pane
270
fDetailPane.display(null);
271         }
272         
273         Object JavaDoc current = getViewer().getInput();
274         
275         if (current == null && context == null) {
276             return;
277         }
278
279         if (current != null && current.equals(context)) {
280             return;
281         }
282         
283         showViewer();
284         getViewer().setInput(context);
285     }
286     
287     /**
288      * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent)
289      */

290     public void propertyChange(PropertyChangeEvent event) {
291         String JavaDoc propertyName= event.getProperty();
292         if (propertyName.equals(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR) ||
293                 propertyName.equals(IInternalDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND) ||
294                 propertyName.equals(IInternalDebugUIConstants.VARIABLE_TEXT_FONT)) {
295             getViewer().refresh();
296         }
297     }
298     
299     /* (non-Javadoc)
300      * @see org.eclipse.debug.ui.AbstractDebugView#createViewer(Composite)
301      */

302     public Viewer createViewer(Composite parent) {
303         
304         fTriggerDetailsJob.setSystem(true);
305         
306         // create the sash form that will contain the tree viewer & text viewer
307
fSashForm = new SashForm(parent, SWT.NONE);
308         
309         fModelPresentation = new VariablesViewModelPresentation();
310         DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this);
311         JFaceResources.getFontRegistry().addListener(this);
312
313         TreeModelViewer variablesViewer = createTreeViewer(fSashForm);
314             
315         fSashForm.setMaximizedControl(variablesViewer.getControl());
316             
317         fDetailPane = new DetailPaneProxy(this);
318         fDetailPane.display(null); // Bring up the default pane so the user doesn't see an empty composite
319

320         createOrientationActions(variablesViewer);
321         IPreferenceStore prefStore = DebugUIPlugin.getDefault().getPreferenceStore();
322         String JavaDoc orientation = prefStore.getString(getDetailPanePreferenceKey());
323         for (int i = 0; i < fToggleDetailPaneActions.length; i++) {
324             fToggleDetailPaneActions[i].setChecked(fToggleDetailPaneActions[i].getOrientation().equals(orientation));
325         }
326         setDetailPaneOrientation(orientation);
327         IMemento memento = getMemento();
328         if (memento != null) {
329             variablesViewer.initState(memento);
330         }
331         
332         variablesViewer.addModelChangedListener(this);
333         variablesViewer.addViewerUpdateListener(this);
334         
335         return variablesViewer;
336     }
337     
338     /* (non-Javadoc)
339      * @see org.eclipse.ui.IViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
340      */

341     public void init(IViewSite site, IMemento memento) throws PartInitException {
342         super.init(site, memento);
343         PREF_STATE_MEMENTO = PREF_STATE_MEMENTO + site.getId();
344         IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore();
345         String JavaDoc string = store.getString(PREF_STATE_MEMENTO);
346         if(string.length() > 0) {
347             ByteArrayInputStream JavaDoc bin = new ByteArrayInputStream JavaDoc(string.getBytes());
348             InputStreamReader JavaDoc reader = new InputStreamReader JavaDoc(bin);
349             try {
350                 XMLMemento stateMemento = XMLMemento.createReadRoot(reader);
351                 setMemento(stateMemento);
352             } catch (WorkbenchException e) {
353             } finally {
354                 try {
355                     reader.close();
356                     bin.close();
357                 } catch (IOException JavaDoc e){}
358             }
359         }
360         IMemento mem = getMemento();
361         // check the weights to makes sure they are valid -- bug 154025
362
setLastSashWeights(DEFAULT_SASH_WEIGHTS);
363         if (mem != null) {
364             Integer JavaDoc sw = mem.getInteger(SASH_VIEW_PART);
365             if(sw != null) {
366                 int view = sw.intValue();
367                 sw = mem.getInteger(SASH_DETAILS_PART);
368                 if(sw != null) {
369                     int details = sw.intValue();
370                     if(view > -1 & details > -1) {
371                         setLastSashWeights(new int[] {view, details});
372                     }
373                 }
374             }
375         }
376         site.getWorkbenchWindow().addPerspectiveListener(this);
377     }
378     
379     /* (non-Javadoc)
380      * @see org.eclipse.ui.part.PageBookView#partDeactivated(org.eclipse.ui.IWorkbenchPart)
381      */

382     public void partDeactivated(IWorkbenchPart part) {
383         String JavaDoc id = part.getSite().getId();
384         if (id.equals(getSite().getId())) {
385             ByteArrayOutputStream JavaDoc bout = new ByteArrayOutputStream JavaDoc();
386             OutputStreamWriter JavaDoc writer = new OutputStreamWriter JavaDoc(bout);
387
388             try {
389                 XMLMemento memento = XMLMemento.createWriteRoot("VariablesViewMemento"); //$NON-NLS-1$
390
saveViewerState(memento);
391                 memento.save(writer);
392
393                 IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore();
394                 String JavaDoc xmlString = bout.toString();
395                 store.putValue(PREF_STATE_MEMENTO, xmlString);
396             } catch (IOException JavaDoc e) {
397             } finally {
398                 try {
399                     writer.close();
400                     bout.close();
401                 } catch (IOException JavaDoc e) {
402                 }
403             }
404         }
405         super.partDeactivated(part);
406     }
407
408     /**
409      * Saves the current state of the viewer
410      * @param memento the memento to write the viewer state into
411      */

412     public void saveViewerState(IMemento memento) {
413         if (fSashForm != null && !fSashForm.isDisposed()) {
414             int[] weights = fSashForm.getWeights();
415             memento.putInteger(SASH_VIEW_PART, weights[0]);
416             memento.putInteger(SASH_DETAILS_PART, weights[1]);
417         }
418         getVariablesViewer().saveState(memento);
419     }
420
421     /**
422      * @return the pref key for the variables view details pane
423      */

424     protected String JavaDoc getDetailPanePreferenceKey() {
425         return IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_ORIENTATION;
426     }
427         
428     /**
429      * Create and return the main tree viewer that displays variable.
430      */

431     protected TreeModelViewer createTreeViewer(Composite parent) {
432         
433         int style = getViewerStyle();
434         final TreeModelViewer variablesViewer = new TreeModelViewer(parent, style,
435                 new DebugModelPresentationContext(getPresentationContextId(), fModelPresentation));
436         
437         variablesViewer.getControl().addFocusListener(new FocusAdapter() {
438             public void focusGained(FocusEvent e) {
439                 fTreeHasFocus = true;
440                 getSite().setSelectionProvider(variablesViewer);
441                 setAction(SELECT_ALL_ACTION, getAction(VARIABLES_SELECT_ALL_ACTION));
442                 setAction(COPY_ACTION, getAction(VARIABLES_COPY_ACTION));
443                 setAction(FIND_ACTION, getAction(VARIABLES_FIND_ELEMENT_ACTION));
444                 getViewSite().getActionBars().updateActionBars();
445             }
446             
447             public void focusLost(FocusEvent e){
448                 getSite().setSelectionProvider(null);
449                 setAction(SELECT_ALL_ACTION, null);
450                 setAction(COPY_ACTION,null);
451                 setAction(FIND_ACTION, null);
452                 getViewSite().getActionBars().updateActionBars();
453             }
454         });
455         variablesViewer.getPresentationContext().addPropertyChangeListener(
456                 new IPropertyChangeListener() {
457                     public void propertyChange(PropertyChangeEvent event) {
458                         if (IPresentationContext.PROPERTY_COLUMNS.equals(event.getProperty())) {
459                             IAction action = getAction("ShowTypeNames"); //$NON-NLS-1$
460
if (action != null) {
461                                 action.setEnabled(event.getNewValue() == null);
462                             }
463                         }
464                     }
465                 });
466         
467         getSite().setSelectionProvider(variablesViewer);
468         variablesViewer.addPostSelectionChangedListener(getTreeSelectionChangedListener());
469         DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).addDebugContextListener(this);
470         return variablesViewer;
471     }
472
473     /**
474      * Returns the presentation context id for this view.
475      *
476      * @return context id
477      */

478     protected String JavaDoc getPresentationContextId() {
479         return IDebugUIConstants.ID_VARIABLE_VIEW;
480     }
481     
482     /**
483      * Returns the style bits for the viewer.
484      *
485      * @return SWT style
486      */

487     protected int getViewerStyle() {
488         return SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL | SWT.FULL_SELECTION;
489     }
490     
491     /* (non-Javadoc)
492      * @see org.eclipse.debug.ui.AbstractDebugView#getHelpContextId()
493      */

494     protected String JavaDoc getHelpContextId() {
495         return IDebugHelpContextIds.VARIABLE_VIEW;
496     }
497     
498     /**
499      * Set the orientation of the details pane so that is one of:
500      * - underneath the main tree view
501      * - to the right of the main tree view
502      * - not visible
503      */

504     public void setDetailPaneOrientation(String JavaDoc orientation) {
505         if (orientation.equals(fCurrentDetailPaneOrientation)) {
506             return;
507         }
508         if (orientation.equals(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN)) {
509             hideDetailPane();
510         } else {
511             int vertOrHoriz = orientation.equals(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_UNDERNEATH) ? SWT.VERTICAL : SWT.HORIZONTAL;
512             fSashForm.setOrientation(vertOrHoriz);
513             if (IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN.equals(fCurrentDetailPaneOrientation)) {
514                 showDetailPane();
515             }
516         }
517         fCurrentDetailPaneOrientation = orientation;
518         DebugUIPlugin.getDefault().getPreferenceStore().setValue(getDetailPanePreferenceKey(), orientation);
519     }
520     
521     /**
522      * Hides the details pane
523      */

524     private void hideDetailPane() {
525         if (fToggledDetailOnce) {
526             setLastSashWeights(fSashForm.getWeights());
527         }
528         fSashForm.setMaximizedControl(getViewer().getControl());
529     }
530     
531     /**
532      * Shows the details pane
533      */

534     private void showDetailPane() {
535         fSashForm.setMaximizedControl(null);
536         fSashForm.setWeights(getLastSashWeights());
537         refreshDetailPaneContents();
538         revealTreeSelection();
539         fToggledDetailOnce = true;
540     }
541
542     /**
543      * Make sure the currently selected item in the tree is visible.
544      */

545     protected void revealTreeSelection() {
546         StructuredViewer viewer = (StructuredViewer) getViewer();
547         if (viewer != null) {
548             ISelection selection = viewer.getSelection();
549             if (selection instanceof IStructuredSelection) {
550                 Object JavaDoc selected = ((IStructuredSelection)selection).getFirstElement();
551                 if (selected != null) {
552                     viewer.reveal(selected);
553                 }
554             }
555         }
556     }
557
558     /**
559      * Return the relative weights that were in effect the last time both panes were
560      * visible in the sash form, or the default weights if:
561      * <ul>
562      * <li> both panes have not yet been made visible</li>
563      * <li> one of the values persisted before is an invalid value</li>
564      * </ul>
565      */

566     protected int[] getLastSashWeights() {
567         if (fLastSashWeights == null) {
568             fLastSashWeights = DEFAULT_SASH_WEIGHTS;
569         }
570         //check the weights to makes sure they are valid -- bug 154025
571
else if(fLastSashWeights[0] < 0 || fLastSashWeights[1] < 0) {
572             fLastSashWeights = DEFAULT_SASH_WEIGHTS;
573         }
574         return fLastSashWeights;
575     }
576     
577     /**
578      * Set the current relative weights of the controls in the sash form, so that
579      * the sash form can be reset to this layout at a later time.
580      */

581     protected void setLastSashWeights(int[] weights) {
582         fLastSashWeights = weights;
583     }
584     
585     /* (non-Javadoc)
586      * @see org.eclipse.debug.ui.AbstractDebugView#createActions()
587      */

588     protected void createActions() {
589         IAction action = new ShowTypesAction(this);
590         setAction("ShowTypeNames",action); //$NON-NLS-1$
591

592         action = new ToggleLogicalStructureAction(this);
593         setAction("ToggleContentProviders", action); //$NON-NLS-1$
594

595         action = new CollapseAllAction((TreeViewer)getViewer());
596         setAction("CollapseAll", action); //$NON-NLS-1$
597

598         action = new ChangeVariableValueAction(this);
599         action.setEnabled(false);
600         setAction("ChangeVariableValue", action); //$NON-NLS-1$
601

602         action= new VirtualFindAction(getVariablesViewer());
603         setAction(VARIABLES_FIND_ELEMENT_ACTION, action);
604     }
605     
606     /* (non-Javadoc)
607      *
608      * Save the copy action so we can restore it on focus lost/gain
609      *
610      * @see org.eclipse.debug.ui.AbstractDebugView#createContextMenu(org.eclipse.swt.widgets.Control)
611      */

612     protected void createContextMenu(Control menuControl) {
613         super.createContextMenu(menuControl);
614         setAction(VARIABLES_COPY_ACTION, getAction(COPY_ACTION));
615     }
616
617     /**
618      * Creates the actions that allow the orientation of the detail pane to be changed.
619      *
620      * @param viewer
621      */

622     private void createOrientationActions(TreeModelViewer viewer) {
623         IActionBars actionBars = getViewSite().getActionBars();
624         IMenuManager viewMenu = actionBars.getMenuManager();
625         
626         fToggleDetailPaneActions = new ToggleDetailPaneAction[3];
627         fToggleDetailPaneActions[0] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_UNDERNEATH, null);
628         fToggleDetailPaneActions[1] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_RIGHT, null);
629         fToggleDetailPaneActions[2] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN, getToggleActionLabel());
630         viewMenu.add(new Separator());
631         final MenuManager layoutSubMenu = new MenuManager(VariablesViewMessages.VariablesView_40);
632         layoutSubMenu.setRemoveAllWhenShown(true);
633         layoutSubMenu.add(fToggleDetailPaneActions[0]);
634         layoutSubMenu.add(fToggleDetailPaneActions[1]);
635         layoutSubMenu.add(fToggleDetailPaneActions[2]);
636         viewMenu.add(layoutSubMenu);
637         viewMenu.add(new Separator());
638         
639         fConfigureColumnsAction = new ConfigureColumnsAction(viewer);
640         setAction("ToggleColmns", new ToggleShowColumnsAction(viewer)); //$NON-NLS-1$
641

642         layoutSubMenu.addMenuListener(new IMenuListener() {
643             public void menuAboutToShow(IMenuManager manager) {
644                 layoutSubMenu.add(fToggleDetailPaneActions[0]);
645                 layoutSubMenu.add(fToggleDetailPaneActions[1]);
646                 layoutSubMenu.add(fToggleDetailPaneActions[2]);
647                 IAction action = getAction("ToggleColmns"); //$NON-NLS-1$
648
((IUpdate)action).update();
649                 if (action.isEnabled()) {
650                     layoutSubMenu.add(action);
651                 }
652                 fConfigureColumnsAction.update();
653                 if (fConfigureColumnsAction.isEnabled()) {
654                     layoutSubMenu.add(fConfigureColumnsAction);
655                 }
656             }
657         });
658     }
659     
660     /**
661      * Returns the label to use for the action that toggles the view layout to be the tree viewer only (detail pane is hidden).
662      * Should be of the style '[view name] View Only'.
663      *
664      * @return action label for toggling the view layout to tree viewer only
665      */

666     protected String JavaDoc getToggleActionLabel(){
667         return VariablesViewMessages.VariablesView_41;
668     }
669     
670     /**
671      * Configures the toolBar.
672      *
673      * @param tbm The toolbar that will be configured
674      */

675     protected void configureToolBar(IToolBarManager tbm) {
676         tbm.add(new Separator(this.getClass().getName()));
677         tbm.add(new Separator(IDebugUIConstants.RENDER_GROUP));
678         tbm.add(getAction("ShowTypeNames")); //$NON-NLS-1$
679
tbm.add(getAction("ToggleContentProviders")); //$NON-NLS-1$
680
tbm.add(getAction("CollapseAll")); //$NON-NLS-1$
681
}
682
683    /**
684     * Adds items to the tree viewer's context menu including any extension defined
685     * actions.
686     *
687     * @param menu The menu to add the item to.
688     */

689     protected void fillContextMenu(IMenuManager menu) {
690
691         menu.add(new Separator(IDebugUIConstants.EMPTY_VARIABLE_GROUP));
692         menu.add(new Separator(IDebugUIConstants.VARIABLE_GROUP));
693         menu.add(getAction(VARIABLES_FIND_ELEMENT_ACTION));
694         menu.add(getAction("ChangeVariableValue")); //$NON-NLS-1$
695
menu.add(new Separator());
696         IAction action = new AvailableLogicalStructuresAction(this);
697         if (action.isEnabled()) {
698             menu.add(action);
699         }
700         action = new AvailableDetailPanesAction(this);
701         if (isDetailPaneVisible() && action.isEnabled()) {
702             menu.add(action);
703         }
704         menu.add(new Separator(IDebugUIConstants.EMPTY_RENDER_GROUP));
705         menu.add(new Separator(IDebugUIConstants.EMPTY_NAVIGATION_GROUP));
706         menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
707     }
708     
709    /**
710      * Lazily instantiate and return a selection listener that populates the detail pane,
711      * but only if the detail is currently visible.
712      */

713     protected ISelectionChangedListener getTreeSelectionChangedListener() {
714         if (fTreeSelectionChangedListener == null) {
715             fTreeSelectionChangedListener = new ISelectionChangedListener() {
716                 public void selectionChanged(final SelectionChangedEvent event) {
717                     if (event.getSelectionProvider().equals(getViewer())) {
718                         clearStatusLine();
719                         // if the detail pane is not visible, don't waste time retrieving details
720
if (fSashForm.getMaximizedControl() == getViewer().getControl()) {
721                             return;
722                         }
723                         refreshDetailPaneContents();
724                         treeSelectionChanged(event);
725                     }
726                 }
727             };
728         }
729         return fTreeSelectionChangedListener;
730     }
731     
732     /**
733      * Selection in the variable tree changed. Perform any updates.
734      *
735      * @param event
736      */

737     protected void treeSelectionChanged(SelectionChangedEvent event) {}
738
739     /* (non-Javadoc)
740      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentPaneID()
741      */

742     public String JavaDoc getCurrentPaneID() {
743         return fDetailPane.getCurrentPaneID();
744     }
745
746     /* (non-Javadoc)
747      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentSelection()
748      */

749     public IStructuredSelection getCurrentSelection() {
750         if (getViewer() != null){
751             return (IStructuredSelection)getViewer().getSelection();
752         }
753         return null;
754     }
755
756     /* (non-Javadoc)
757      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getParentComposite()
758      */

759     public Composite getParentComposite() {
760         return fSashForm;
761     }
762
763     /* (non-Javadoc)
764      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getWorkbenchPartSite()
765      */

766     public IWorkbenchPartSite getWorkbenchPartSite() {
767         return getSite();
768     }
769     
770     /* (non-Javadoc)
771      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#refreshDetailPaneContents()
772      */

773     public void refreshDetailPaneContents() {
774         fDetailPane.display(getCurrentSelection());
775     }
776
777     /* (non-Javadoc)
778      * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#paneChanged(java.lang.String)
779      */

780     public void paneChanged(String JavaDoc newPaneID) {
781         if (fDetailPaneActivatedListener == null){
782             fDetailPaneActivatedListener = new Listener() {
783                 public void handleEvent(Event event) {
784                     fTreeHasFocus = false;
785                 }
786             };
787         }
788         fDetailPane.getCurrentControl().addListener(SWT.Activate, fDetailPaneActivatedListener);
789     }
790     
791     /**
792      * @return the model presentation to be used for this view
793      */

794     protected IDebugModelPresentation getModelPresentation() {
795         if (fModelPresentation == null) {
796             fModelPresentation = new VariablesViewModelPresentation();
797         }
798         return fModelPresentation;
799     }
800     
801     /* (non-Javadoc)
802      * @see org.eclipse.ui.part.WorkbenchPart#getAdapter(Class)
803      */

804     public Object JavaDoc getAdapter(Class JavaDoc required) {
805         if (IDebugModelPresentation.class.equals(required)) {
806             return getModelPresentation();
807         }
808         else if (fDetailPane != null){
809             Object JavaDoc adapter = fDetailPane.getAdapter(required);
810             if (adapter != null) return adapter;
811         }
812         return super.getAdapter(required);
813     }
814
815     /**
816      * If possible, calls the update method of the action associated with the given ID.
817      *
818      * @param actionId the ID of the action to update
819      */

820     protected void updateAction(String JavaDoc actionId) {
821         IAction action= getAction(actionId);
822         if (action instanceof IUpdate) {
823             ((IUpdate) action).update();
824         }
825     }
826     
827     /**
828      * @return whether the detail pane is visible to the user
829      */

830     protected boolean isDetailPaneVisible() {
831         return !fToggleDetailPaneActions[2].isChecked();
832     }
833     
834     /* (non-Javadoc)
835      * @see org.eclipse.debug.ui.AbstractDebugView#getDefaultControl()
836      */

837     protected Control getDefaultControl() {
838         return fSashForm;
839     }
840     
841     /* (non-Javadoc)
842      * @see org.eclipse.debug.internal.ui.views.IDebugExceptionHandler#handleException(org.eclipse.debug.core.DebugException)
843      */

844     public void handleException(DebugException e) {
845         showMessage(e.getMessage());
846     }
847     
848     /* (non-Javadoc)
849      * @see org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener#contextEvent(org.eclipse.debug.internal.ui.contexts.provisional.DebugContextEvent)
850      */

851     public void debugContextChanged(DebugContextEvent event) {
852         if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) {
853             contextActivated(event.getContext());
854         }
855     }
856
857     /**
858      * Updates actions and sets the viewer input when a context is activated.
859      * @param selection
860      */

861     protected void contextActivated(ISelection selection) {
862         if (!isAvailable() || !isVisible()) {
863             return;
864         }
865         
866         if (selection instanceof IStructuredSelection) {
867             setViewerInput(((IStructuredSelection)selection).getFirstElement());
868         }
869         showViewer();
870         
871         updateAction(VARIABLES_FIND_ELEMENT_ACTION);
872         updateAction(FIND_ACTION);
873     }
874         
875     /**
876      * Delegate to the <code>DOUBLE_CLICK_ACTION</code>,
877      * if any.
878      *
879      * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(DoubleClickEvent)
880      */

881     public void doubleClick(DoubleClickEvent event) {
882         IAction action = getAction(DOUBLE_CLICK_ACTION);
883         if (action != null && action.isEnabled()) {
884             action.run();
885         }
886     }
887
888     /* (non-Javadoc)
889      * @see org.eclipse.debug.ui.IDebugView#getPresentation(String)
890      */

891     public IDebugModelPresentation getPresentation(String JavaDoc id) {
892         if (getViewer() instanceof StructuredViewer) {
893             IDebugModelPresentation lp = getModelPresentation();
894             if (lp instanceof DelegatingModelPresentation) {
895                 return ((DelegatingModelPresentation)lp).getPresentation(id);
896             }
897             if (lp instanceof LazyModelPresentation) {
898                 if (((LazyModelPresentation)lp).getDebugModelIdentifier().equals(id)) {
899                     return lp;
900                 }
901             }
902         }
903         return null;
904     }
905
906     /* (non-Javadoc)
907      * @see org.eclipse.debug.ui.IDetailSite#isMainViewerAvailable()
908      */

909     public boolean isMainViewerAvailable() {
910         return isAvailable();
911     }
912     
913     /**
914      * @return the presentation context of the viewer
915      */

916     protected IPresentationContext getPresentationContext() {
917         return getVariablesViewer().getPresentationContext();
918     }
919     
920     /**
921      * Sets whether logical structures are being displayed
922      */

923     public void setShowLogicalStructure(boolean flag) {
924         getPresentationContext().setProperty(PRESENTATION_SHOW_LOGICAL_STRUCTURES, Boolean.valueOf(flag));
925     }
926     
927     /**
928      * Returns whether logical structures are being displayed
929      */

930     public boolean isShowLogicalStructure() {
931         Boolean JavaDoc show = (Boolean JavaDoc) getPresentationContext().getProperty(PRESENTATION_SHOW_LOGICAL_STRUCTURES);
932         return show != null && show.booleanValue();
933     }
934
935     /* (non-Javadoc)
936      * @see org.eclipse.debug.ui.AbstractDebugView#becomesHidden()
937      */

938     protected void becomesHidden() {
939         setViewerInput(null);
940         super.becomesHidden();
941     }
942
943     /* (non-Javadoc)
944      * @see org.eclipse.debug.ui.AbstractDebugView#becomesVisible()
945      */

946     protected void becomesVisible() {
947         super.becomesVisible();
948         ISelection selection = DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).getActiveContext();
949         contextActivated(selection);
950     }
951
952     /**
953      * @return the tree model viewer displaying variables
954      */

955     protected TreeModelViewer getVariablesViewer() {
956         return (TreeModelViewer) getViewer();
957     }
958     
959     /**
960      * Clears the status line of all messages and errors
961      */

962     protected void clearStatusLine() {
963         IStatusLineManager manager = getViewSite().getActionBars().getStatusLineManager();
964         manager.setErrorMessage(null);
965         manager.setMessage(null);
966     }
967
968     /* (non-Javadoc)
969      * @see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor)
970      */

971     public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {}
972
973     /* (non-Javadoc)
974      * @see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, java.lang.String)
975      */

976     public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String JavaDoc changeId) {
977         if(changeId.equals(IWorkbenchPage.CHANGE_RESET)) {
978             setLastSashWeights(DEFAULT_SASH_WEIGHTS);
979             fSashForm.setWeights(DEFAULT_SASH_WEIGHTS);
980         }
981     }
982
983     /* (non-Javadoc)
984      * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta)
985      */

986     public void modelChanged(IModelDelta delta, IModelProxy proxy) {
987         fVisitor.reset();
988         delta.accept(fVisitor);
989     }
990
991     /* (non-Javadoc)
992      * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#updateComplete(org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousRequestMonitor)
993      */

994     public void updateComplete(IViewerUpdate update) {
995         IStatus status = update.getStatus();
996         if (!update.isCanceled()) {
997             if (status != null && status.getCode() != IStatus.OK) {
998                 showMessage(status.getMessage());
999             } else {
1000                showViewer();
1001            }
1002        }
1003    }
1004
1005    /* (non-Javadoc)
1006     * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#updateStarted(org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousRequestMonitor)
1007     */

1008    public void updateStarted(IViewerUpdate update) {
1009    }
1010
1011    /* (non-Javadoc)
1012     * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#viewerUpdatesBegin()
1013     */

1014    public synchronized void viewerUpdatesBegin() {
1015        fTriggerDetailsJob.cancel();
1016    }
1017
1018    /* (non-Javadoc)
1019     * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#viewerUpdatesComplete()
1020     */

1021    public synchronized void viewerUpdatesComplete() {
1022        if (fVisitor.isTriggerDetails()) {
1023            fTriggerDetailsJob.schedule();
1024        }
1025    }
1026    
1027    /**
1028     * @see org.eclipse.ui.IWorkbenchPart#setFocus()
1029     */

1030    public void setFocus() {
1031        boolean success = false;
1032        if (!fTreeHasFocus && fDetailPane != null){
1033            success = fDetailPane.setFocus();
1034        }
1035        // Unless the detail pane successfully set focus to a control, set focus to the variables tree
1036
if (!success && getViewer() != null){
1037            getViewer().getControl().setFocus();
1038        }
1039    }
1040}
1041
Popular Tags