| /******************************************************************************* |
| * Copyright (c) 2000, 2010 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| * QNX Software Systems - Mikhail Khodjaiants - Registers View (Bug 53640) |
| * Wind River - Pawel Piech - Drag/Drop to Expressions View (Bug 184057) |
| * Wind River - Pawel Piech - Busy status while updates in progress (Bug 206822) |
| * Wind River - Pawel Piech - NPE when closing the Variables view (Bug 213719) |
| * Wind River - Pawel Piech - Fix viewer input race condition (Bug 234908) |
| * Wind River - Anton Leherbauer - Fix selection provider (Bug 254442) |
| * Patrick Chuong (Texas Instruments) - Improve usability of the breakpoint view (Bug 238956) |
| *******************************************************************************/ |
| package org.eclipse.debug.internal.ui.views.variables; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.OutputStreamWriter; |
| |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.ListenerList; |
| import org.eclipse.core.runtime.Status; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.debug.core.DebugException; |
| import org.eclipse.debug.internal.ui.DebugUIPlugin; |
| import org.eclipse.debug.internal.ui.DelegatingModelPresentation; |
| import org.eclipse.debug.internal.ui.IDebugHelpContextIds; |
| import org.eclipse.debug.internal.ui.LazyModelPresentation; |
| import org.eclipse.debug.internal.ui.SWTFactory; |
| import org.eclipse.debug.internal.ui.VariablesViewModelPresentation; |
| import org.eclipse.debug.internal.ui.actions.CollapseAllAction; |
| import org.eclipse.debug.internal.ui.actions.ConfigureColumnsAction; |
| import org.eclipse.debug.internal.ui.actions.variables.ChangeVariableValueAction; |
| import org.eclipse.debug.internal.ui.actions.variables.ShowTypesAction; |
| import org.eclipse.debug.internal.ui.actions.variables.ToggleDetailPaneAction; |
| import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants; |
| import org.eclipse.debug.internal.ui.viewers.model.VirtualFindAction; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelChangedListener; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDelta; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelDeltaVisitor; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IModelProxy; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputRequestor; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerInputUpdate; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdate; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.IViewerUpdateListener; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; |
| import org.eclipse.debug.internal.ui.viewers.model.provisional.ViewerInputService; |
| import org.eclipse.debug.internal.ui.views.DebugModelPresentationContext; |
| import org.eclipse.debug.internal.ui.views.IDebugExceptionHandler; |
| import org.eclipse.debug.internal.ui.views.variables.details.AvailableDetailPanesAction; |
| import org.eclipse.debug.internal.ui.views.variables.details.DetailPaneProxy; |
| import org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer2; |
| import org.eclipse.debug.ui.AbstractDebugView; |
| import org.eclipse.debug.ui.DebugUITools; |
| import org.eclipse.debug.ui.IDebugModelPresentation; |
| import org.eclipse.debug.ui.IDebugUIConstants; |
| import org.eclipse.debug.ui.contexts.DebugContextEvent; |
| import org.eclipse.debug.ui.contexts.IDebugContextListener; |
| import org.eclipse.jface.action.IAction; |
| import org.eclipse.jface.action.IMenuListener; |
| import org.eclipse.jface.action.IMenuManager; |
| import org.eclipse.jface.action.IStatusLineManager; |
| import org.eclipse.jface.action.IToolBarManager; |
| import org.eclipse.jface.action.MenuManager; |
| import org.eclipse.jface.action.Separator; |
| import org.eclipse.jface.commands.ActionHandler; |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.resource.JFaceResources; |
| import org.eclipse.jface.util.IPropertyChangeListener; |
| import org.eclipse.jface.util.LocalSelectionTransfer; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.jface.viewers.DoubleClickEvent; |
| import org.eclipse.jface.viewers.ISelection; |
| import org.eclipse.jface.viewers.ISelectionChangedListener; |
| import org.eclipse.jface.viewers.ISelectionProvider; |
| import org.eclipse.jface.viewers.IStructuredSelection; |
| import org.eclipse.jface.viewers.SelectionChangedEvent; |
| import org.eclipse.jface.viewers.StructuredSelection; |
| import org.eclipse.jface.viewers.StructuredViewer; |
| import org.eclipse.jface.viewers.TreeSelection; |
| import org.eclipse.jface.viewers.TreeViewer; |
| import org.eclipse.jface.viewers.Viewer; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.custom.SashForm; |
| import org.eclipse.swt.dnd.DND; |
| import org.eclipse.swt.dnd.Transfer; |
| import org.eclipse.swt.events.ControlEvent; |
| import org.eclipse.swt.events.ControlListener; |
| import org.eclipse.swt.events.FocusAdapter; |
| import org.eclipse.swt.events.FocusEvent; |
| import org.eclipse.swt.graphics.Point; |
| import org.eclipse.swt.layout.GridData; |
| import org.eclipse.swt.layout.GridLayout; |
| import org.eclipse.swt.widgets.Composite; |
| import org.eclipse.swt.widgets.Control; |
| import org.eclipse.swt.widgets.Event; |
| import org.eclipse.swt.widgets.Label; |
| import org.eclipse.swt.widgets.Listener; |
| import org.eclipse.swt.widgets.TreeItem; |
| import org.eclipse.swt.widgets.Widget; |
| import org.eclipse.ui.IActionBars; |
| import org.eclipse.ui.IMemento; |
| import org.eclipse.ui.IPerspectiveDescriptor; |
| import org.eclipse.ui.IPerspectiveListener; |
| import org.eclipse.ui.IPropertyListener; |
| import org.eclipse.ui.ISaveablePart; |
| import org.eclipse.ui.IViewSite; |
| import org.eclipse.ui.IWorkbenchActionConstants; |
| import org.eclipse.ui.IWorkbenchPage; |
| import org.eclipse.ui.IWorkbenchPart; |
| import org.eclipse.ui.IWorkbenchPartSite; |
| import org.eclipse.ui.PartInitException; |
| import org.eclipse.ui.WorkbenchException; |
| import org.eclipse.ui.XMLMemento; |
| import org.eclipse.ui.handlers.CollapseAllHandler; |
| import org.eclipse.ui.handlers.IHandlerService; |
| import org.eclipse.ui.progress.IWorkbenchSiteProgressService; |
| import org.eclipse.ui.progress.UIJob; |
| import org.eclipse.ui.texteditor.IUpdate; |
| |
| /** |
| * This view shows variables and their values for a particular stack frame |
| */ |
| public class VariablesView extends AbstractDebugView implements IDebugContextListener, |
| IPropertyChangeListener, IDebugExceptionHandler, |
| IPerspectiveListener, IModelChangedListener, |
| IViewerUpdateListener, IDetailPaneContainer2, ISaveablePart { |
| |
| /** |
| * Selection provider wrapping an exchangeable active selection provider. |
| * Sends out a selection changed event when the active selection provider changes. |
| * Forwards all selection changed events of the active selection provider. |
| */ |
| private static class SelectionProviderWrapper implements ISelectionProvider { |
| private final ListenerList fListenerList = new ListenerList(ListenerList.IDENTITY); |
| private final ISelectionChangedListener fListener = new ISelectionChangedListener() { |
| public void selectionChanged(SelectionChangedEvent event) { |
| fireSelectionChanged(event); |
| } |
| }; |
| private ISelectionProvider fActiveProvider; |
| |
| private SelectionProviderWrapper(ISelectionProvider provider) { |
| setActiveProvider(provider); |
| } |
| |
| private void setActiveProvider(ISelectionProvider provider) { |
| if (fActiveProvider == provider || this == provider) { |
| return; |
| } |
| if (fActiveProvider != null) { |
| fActiveProvider.removeSelectionChangedListener(fListener); |
| } |
| if (provider != null) { |
| provider.addSelectionChangedListener(fListener); |
| } |
| fActiveProvider = provider; |
| fireSelectionChanged(new SelectionChangedEvent(this, getSelection())); |
| } |
| |
| private void dispose() { |
| fListenerList.clear(); |
| setActiveProvider(null); |
| } |
| |
| private void fireSelectionChanged(SelectionChangedEvent event) { |
| Object[] listeners = fListenerList.getListeners(); |
| for (int i = 0; i < listeners.length; i++) { |
| ISelectionChangedListener listener = (ISelectionChangedListener) listeners[i]; |
| listener.selectionChanged(event); |
| } |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) |
| */ |
| public void addSelectionChangedListener(ISelectionChangedListener listener) { |
| fListenerList.add(listener); |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() |
| */ |
| public ISelection getSelection() { |
| if (fActiveProvider != null) { |
| return fActiveProvider.getSelection(); |
| } |
| return StructuredSelection.EMPTY; |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) |
| */ |
| public void removeSelectionChangedListener(ISelectionChangedListener listener) { |
| fListenerList.remove(listener); |
| } |
| |
| /* |
| * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection) |
| */ |
| public void setSelection(ISelection selection) { |
| if (fActiveProvider != null) { |
| fActiveProvider.setSelection(selection); |
| } |
| } |
| } |
| |
| /** |
| * The model presentation used as the label provider for the tree viewer, |
| * and also as the detail information provider for the detail pane. |
| */ |
| protected VariablesViewModelPresentation fModelPresentation; |
| |
| /** |
| * The UI construct that provides a sliding sash between the variables tree |
| * and the detail pane. |
| */ |
| private SashForm fSashForm; |
| |
| /** |
| * Composite that holds the details pane and always remains |
| */ |
| private Composite fDetailsAnchor; |
| |
| /** |
| * Composite that holds the separator container and detail pane control. |
| * Gets disposed/created as the layout changes. |
| */ |
| private Composite fDetailsComposiste; |
| |
| /** |
| * Separator used when detail pane background colors of tree/detail pane are different. |
| */ |
| private Label fSepearator; |
| |
| /** |
| * Parent of the viewer, used to detect re-sizing for automatic layout |
| */ |
| private Composite fParent; |
| |
| /** |
| * Whether the detail pane has been built yet. |
| */ |
| private boolean fPaneBuilt = false; |
| |
| /** |
| * The detail pane that displays detailed information about the current selection |
| * @since 3.3 |
| */ |
| private DetailPaneProxy fDetailPane; |
| |
| /** |
| * Stores whether the tree viewer was the last control to have focus in the |
| * view. Used to give focus to the correct component if the user leaves the view. |
| * @since 3.3 |
| */ |
| private boolean fTreeHasFocus = true; |
| |
| /** |
| * Various listeners used to update the enabled state of actions and also to |
| * populate the detail pane. |
| */ |
| private ISelectionChangedListener fTreeSelectionChangedListener; |
| |
| /** |
| * Listener added to the control of the detail pane, allows view to keep track of which |
| * part last had focus, the tree or the detail pane. |
| */ |
| private Listener fDetailPaneActivatedListener; |
| |
| /** |
| * Viewer input service used to translate active debug context to viewer input. |
| */ |
| private ViewerInputService fInputService; |
| |
| /** |
| * Viewer input requester used to update the viewer once the viewer input has been |
| * resolved. |
| */ |
| private IViewerInputRequestor fRequester = new IViewerInputRequestor() { |
| public void viewerInputComplete(IViewerInputUpdate update) { |
| if (!update.isCanceled()) { |
| viewerInputUpdateComplete(update); |
| } |
| } |
| }; |
| |
| /** |
| * These are used to initialize and persist the position of the sash that |
| * separates the tree viewer from the detail pane. |
| */ |
| private static final int[] DEFAULT_SASH_WEIGHTS = {13, 6}; |
| private int[] fLastSashWeights; |
| private boolean fToggledDetailOnce; |
| private String fCurrentDetailPaneOrientation = IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN; |
| private ToggleDetailPaneAction[] fToggleDetailPaneActions; |
| private ConfigureColumnsAction fConfigureColumnsAction; |
| |
| protected String PREF_STATE_MEMENTO = "pref_state_memento."; //$NON-NLS-1$ |
| |
| public static final String LOGICAL_STRUCTURE_TYPE_PREFIX = "VAR_LS_"; //$NON-NLS-1$ |
| |
| /** |
| * Presentation context property. |
| * TODO: make API |
| * @since 3.3 |
| */ |
| public static final String PRESENTATION_SHOW_LOGICAL_STRUCTURES = "PRESENTATION_SHOW_LOGICAL_STRUCTURES"; //$NON-NLS-1$ |
| |
| /** |
| * the preference name for the view part of the sash form |
| * @since 3.2 |
| */ |
| protected static final String SASH_VIEW_PART = DebugUIPlugin.getUniqueIdentifier() + ".SASH_VIEW_PART"; //$NON-NLS-1$ |
| /** |
| * the preference name for the details part of the sash form |
| * @since 3.2 |
| */ |
| protected static final String SASH_DETAILS_PART = DebugUIPlugin.getUniqueIdentifier() + ".SASH_DETAILS_PART"; //$NON-NLS-1$ |
| |
| /** |
| * Sash weights for a specific detail pane type |
| */ |
| protected static final String DETAIL_PANE_TYPE = "DETAIL_PANE_TYPE"; //$NON-NLS-1$ |
| |
| /** |
| * Key for "Find..." action. |
| */ |
| protected static final String VARIABLES_FIND_ELEMENT_ACTION = FIND_ACTION + ".Variables"; //$NON-NLS-1$ |
| |
| /** |
| * Key for "Select All" action. |
| */ |
| protected static final String VARIABLES_SELECT_ALL_ACTION = SELECT_ALL_ACTION + ".Variables"; //$NON-NLS-1$ |
| |
| /** |
| * Key for "Copy" action. |
| */ |
| protected static final String VARIABLES_COPY_ACTION = COPY_ACTION + ".Variables"; //$NON-NLS-1$ |
| |
| /** |
| * Key for "Paste" action. |
| */ |
| protected static final String VARIABLES_PASTE_ACTION = PASTE_ACTION + ".Variables"; //$NON-NLS-1$ |
| |
| /** |
| * Visits deltas to determine if details should be displayed |
| */ |
| class Visitor implements IModelDeltaVisitor { |
| /** |
| * Whether to trigger details display. |
| * |
| * @since 3.3 |
| */ |
| private boolean fTriggerDetails = false; |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelDeltaVisitor#visit(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta, int) |
| */ |
| public boolean visit(IModelDelta delta, int depth) { |
| if ((delta.getFlags() & IModelDelta.CONTENT) > 0) { |
| fTriggerDetails = true; |
| return false; |
| } |
| return true; |
| } |
| |
| public void reset() { |
| fTriggerDetails = false; |
| } |
| |
| public boolean isTriggerDetails() { |
| return fTriggerDetails; |
| } |
| |
| } |
| /** |
| * Delta visitor |
| */ |
| private Visitor fVisitor = new Visitor(); |
| |
| /** |
| * Job to update details in the UI thread. |
| */ |
| private Job fTriggerDetailsJob = new UIJob("trigger details") { //$NON-NLS-1$ |
| |
| public IStatus runInUIThread(IProgressMonitor monitor) { |
| if (monitor.isCanceled()) { |
| return Status.CANCEL_STATUS; |
| } |
| refreshDetailPaneContents(); |
| return Status.OK_STATUS; |
| } |
| }; |
| |
| /** |
| * Selection provider registered with the view site. |
| */ |
| private SelectionProviderWrapper fSelectionProvider; |
| |
| /** |
| * Presentation context for this view. |
| */ |
| private IPresentationContext fPresentationContext; |
| |
| /** |
| * Remove myself as a selection listener |
| * and preference change listener. |
| * |
| * @see IWorkbenchPart#dispose() |
| */ |
| public void dispose() { |
| |
| DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).removeDebugContextListener(this); |
| getSite().getWorkbenchWindow().removePerspectiveListener(this); |
| DebugUIPlugin.getDefault().getPreferenceStore().removePropertyChangeListener(this); |
| JFaceResources.getFontRegistry().removeListener(this); |
| TreeModelViewer viewer = getVariablesViewer(); |
| if (viewer != null) { |
| viewer.removeModelChangedListener(this); |
| viewer.removeViewerUpdateListener(this); |
| } |
| if (fPresentationContext != null) { |
| fPresentationContext.dispose(); |
| fPresentationContext = null; |
| } |
| if (fDetailPane != null) fDetailPane.dispose(); |
| fInputService.dispose(); |
| fSelectionProvider.dispose(); |
| super.dispose(); |
| } |
| |
| /** |
| * Called when the viewer input update is completed. Unlike |
| * {@link #setViewerInput(Object)}, it allows overriding classes |
| * to examine the context for which the update was calculated. |
| * |
| * @param update Completed viewer input update. |
| */ |
| protected void viewerInputUpdateComplete(IViewerInputUpdate update) { |
| setViewerInput(update.getInputElement()); |
| updateAction(VARIABLES_FIND_ELEMENT_ACTION); |
| updateAction(FIND_ACTION); |
| } |
| |
| /** |
| * Sets the input to the viewer |
| * @param context the object context |
| */ |
| protected void setViewerInput(Object context) { |
| if (context == null) { |
| // Clear the detail pane |
| refreshDetailPaneContents(); |
| } |
| |
| Object current = getViewer().getInput(); |
| |
| if (current == null && context == null) { |
| return; |
| } |
| |
| if (current != null && current.equals(context)) { |
| return; |
| } |
| |
| showViewer(); |
| getViewer().setInput(context); |
| } |
| |
| /** |
| * @see IPropertyChangeListener#propertyChange(PropertyChangeEvent) |
| */ |
| public void propertyChange(PropertyChangeEvent event) { |
| String propertyName= event.getProperty(); |
| if (propertyName.equals(IDebugUIConstants.PREF_CHANGED_DEBUG_ELEMENT_COLOR) || |
| propertyName.equals(IDebugUIConstants.PREF_CHANGED_VALUE_BACKGROUND) || |
| propertyName.equals(IDebugUIConstants.PREF_VARIABLE_TEXT_FONT)) { |
| getViewer().refresh(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#createViewer(Composite) |
| */ |
| public Viewer createViewer(Composite parent) { |
| addResizeListener(parent); |
| fParent = parent; |
| fTriggerDetailsJob.setSystem(true); |
| |
| // create the sash form that will contain the tree viewer & text viewer |
| fSashForm = new SashForm(parent, SWT.NONE); |
| |
| getModelPresentation(); |
| DebugUIPlugin.getDefault().getPreferenceStore().addPropertyChangeListener(this); |
| JFaceResources.getFontRegistry().addListener(this); |
| |
| TreeModelViewer variablesViewer = createTreeViewer(fSashForm); |
| fInputService = new ViewerInputService(variablesViewer, fRequester); |
| |
| fSashForm.setMaximizedControl(variablesViewer.getControl()); |
| fDetailsAnchor = SWTFactory.createComposite(fSashForm, parent.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0); |
| fSashForm.setWeights(getLastSashWeights()); |
| |
| fSelectionProvider = new SelectionProviderWrapper(variablesViewer); |
| getSite().setSelectionProvider(fSelectionProvider); |
| |
| createOrientationActions(variablesViewer); |
| IPreferenceStore prefStore = DebugUIPlugin.getDefault().getPreferenceStore(); |
| String orientation = prefStore.getString(getDetailPanePreferenceKey()); |
| for (int i = 0; i < fToggleDetailPaneActions.length; i++) { |
| fToggleDetailPaneActions[i].setChecked(fToggleDetailPaneActions[i].getOrientation().equals(orientation)); |
| } |
| |
| fDetailPane = new DetailPaneProxy(this); |
| fDetailPane.addProperyListener(new IPropertyListener() { |
| public void propertyChanged(Object source, int propId) { |
| firePropertyChange(propId); |
| } |
| }); |
| setDetailPaneOrientation(orientation); |
| |
| IMemento memento = getMemento(); |
| if (memento != null) { |
| variablesViewer.initState(memento); |
| } |
| |
| variablesViewer.addModelChangedListener(this); |
| variablesViewer.addViewerUpdateListener(this); |
| |
| initDragAndDrop(variablesViewer); |
| |
| return variablesViewer; |
| } |
| |
| /** |
| * Initializes the drag and/or drop adapters for this view. Called from createViewer(). |
| * |
| * @param viewer the viewer to add drag/drop support to. |
| * @since 3.4 |
| */ |
| protected void initDragAndDrop(TreeModelViewer viewer) { |
| // Drag only |
| viewer.addDragSupport(DND.DROP_COPY, new Transfer[] {LocalSelectionTransfer.getTransfer()}, new SelectionDragAdapter(viewer)); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.IViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento) |
| */ |
| public void init(IViewSite site, IMemento memento) throws PartInitException { |
| super.init(site, memento); |
| PREF_STATE_MEMENTO = PREF_STATE_MEMENTO + site.getId(); |
| IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore(); |
| String string = store.getString(PREF_STATE_MEMENTO); |
| if(string.length() > 0) { |
| ByteArrayInputStream bin = new ByteArrayInputStream(string.getBytes()); |
| InputStreamReader reader = new InputStreamReader(bin); |
| try { |
| XMLMemento stateMemento = XMLMemento.createReadRoot(reader); |
| setMemento(stateMemento); |
| } catch (WorkbenchException e) { |
| } finally { |
| try { |
| reader.close(); |
| bin.close(); |
| } catch (IOException e){} |
| } |
| } |
| IMemento mem = getMemento(); |
| // check the weights to makes sure they are valid -- bug 154025 |
| setLastSashWeights(DEFAULT_SASH_WEIGHTS); |
| if (mem != null) { |
| int[] weights = getWeights(mem); |
| if (weights != null) { |
| setLastSashWeights(weights); |
| } |
| } |
| site.getWorkbenchWindow().addPerspectiveListener(this); |
| } |
| |
| /** |
| * Returns sash weights stored in the given memento or <code>null</code> if none. |
| * |
| * @param memento |
| * @return sash weights or <code>null</code> |
| */ |
| private int[] getWeights(IMemento memento) { |
| Integer sw = memento.getInteger(SASH_VIEW_PART); |
| if(sw != null) { |
| int view = sw.intValue(); |
| sw = memento.getInteger(SASH_DETAILS_PART); |
| if(sw != null) { |
| int details = sw.intValue(); |
| if(view > -1 & details > -1) { |
| return new int[] {view, details}; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.part.PageBookView#partDeactivated(org.eclipse.ui.IWorkbenchPart) |
| */ |
| public void partDeactivated(IWorkbenchPart part) { |
| String id = part.getSite().getId(); |
| if (id.equals(getSite().getId())) { |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(); |
| OutputStreamWriter writer = new OutputStreamWriter(bout); |
| |
| try { |
| XMLMemento memento = XMLMemento.createWriteRoot("VariablesViewMemento"); //$NON-NLS-1$ |
| saveViewerState(memento); |
| memento.save(writer); |
| |
| IPreferenceStore store = DebugUIPlugin.getDefault().getPreferenceStore(); |
| String xmlString = bout.toString(); |
| store.putValue(PREF_STATE_MEMENTO, xmlString); |
| } catch (IOException e) { |
| } finally { |
| try { |
| writer.close(); |
| bout.close(); |
| } catch (IOException e) { |
| } |
| } |
| } |
| super.partDeactivated(part); |
| } |
| |
| /** |
| * Saves the current state of the viewer |
| * @param memento the memento to write the viewer state into |
| */ |
| public void saveViewerState(IMemento memento) { |
| if (fSashForm != null && !fSashForm.isDisposed()) { |
| int[] weights = fSashForm.getWeights(); |
| memento.putInteger(SASH_VIEW_PART, weights[0]); |
| memento.putInteger(SASH_DETAILS_PART, weights[1]); |
| } |
| getVariablesViewer().saveState(memento); |
| } |
| |
| /** |
| * @return the pref key for the variables view details pane |
| */ |
| protected String getDetailPanePreferenceKey() { |
| return IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_ORIENTATION; |
| } |
| |
| /** |
| * Create and return the main tree viewer that displays variable. |
| */ |
| protected TreeModelViewer createTreeViewer(Composite parent) { |
| |
| int style = getViewerStyle(); |
| fPresentationContext = new DebugModelPresentationContext(getPresentationContextId(), this, fModelPresentation); |
| final TreeModelViewer variablesViewer = new TreeModelViewer(parent, style, fPresentationContext); |
| |
| variablesViewer.getControl().addFocusListener(new FocusAdapter() { |
| public void focusGained(FocusEvent e) { |
| fTreeHasFocus = true; |
| fSelectionProvider.setActiveProvider(variablesViewer); |
| setAction(SELECT_ALL_ACTION, getAction(VARIABLES_SELECT_ALL_ACTION)); |
| setAction(COPY_ACTION, getAction(VARIABLES_COPY_ACTION)); |
| setAction(PASTE_ACTION, getAction(VARIABLES_PASTE_ACTION)); |
| setAction(FIND_ACTION, getAction(VARIABLES_FIND_ELEMENT_ACTION)); |
| getViewSite().getActionBars().updateActionBars(); |
| } |
| |
| public void focusLost(FocusEvent e){ |
| fSelectionProvider.setActiveProvider(null); |
| setAction(SELECT_ALL_ACTION, null); |
| setAction(COPY_ACTION,null); |
| setAction(FIND_ACTION, null); |
| setAction(PASTE_ACTION, null); |
| getViewSite().getActionBars().updateActionBars(); |
| } |
| }); |
| variablesViewer.getPresentationContext().addPropertyChangeListener( |
| new IPropertyChangeListener() { |
| public void propertyChange(PropertyChangeEvent event) { |
| if (IPresentationContext.PROPERTY_COLUMNS.equals(event.getProperty())) { |
| IAction action = getAction("ShowTypeNames"); //$NON-NLS-1$ |
| if (action != null) { |
| action.setEnabled(event.getNewValue() == null); |
| } |
| } |
| } |
| }); |
| |
| variablesViewer.addPostSelectionChangedListener(getTreeSelectionChangedListener()); |
| DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).addDebugContextListener(this); |
| return variablesViewer; |
| } |
| |
| /** |
| * Returns the presentation context id for this view. |
| * |
| * @return context id |
| */ |
| protected String getPresentationContextId() { |
| return IDebugUIConstants.ID_VARIABLE_VIEW; |
| } |
| |
| /** |
| * Returns the style bits for the viewer. |
| * |
| * @return SWT style |
| */ |
| protected int getViewerStyle() { |
| return SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.VIRTUAL | SWT.FULL_SELECTION; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#getHelpContextId() |
| */ |
| protected String getHelpContextId() { |
| return IDebugHelpContextIds.VARIABLE_VIEW; |
| } |
| |
| private void addResizeListener(Composite parent) { |
| parent.addControlListener(new ControlListener() { |
| public void controlMoved(ControlEvent e) { |
| } |
| public void controlResized(ControlEvent e) { |
| if (IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_AUTO.equals(fCurrentDetailPaneOrientation)) { |
| setDetailPaneOrientation(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_AUTO); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Returns vertical or horizontal based on view size. |
| * |
| * @return vertical or horizontal |
| */ |
| int computeOrientation() { |
| Point size= fParent.getSize(); |
| if (size.x != 0 && size.y != 0) { |
| if ((size.x / 3)> size.y) |
| return SWT.HORIZONTAL; |
| else |
| return SWT.VERTICAL; |
| } |
| return SWT.HORIZONTAL; |
| } |
| |
| /** |
| * Set the orientation of the details pane so that is one of: |
| * - underneath the main tree view |
| * - to the right of the main tree view |
| * - not visible |
| */ |
| public void setDetailPaneOrientation(String orientation) { |
| if (!IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_AUTO.equals(orientation) && orientation.equals(fCurrentDetailPaneOrientation)) { |
| return; |
| } |
| fCurrentDetailPaneOrientation = orientation; |
| DebugUIPlugin.getDefault().getPreferenceStore().setValue(getDetailPanePreferenceKey(), orientation); |
| if (orientation.equals(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN)) { |
| hideDetailPane(); |
| } else { |
| int vertOrHoriz = -1; |
| if (orientation.equals(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_AUTO)) { |
| vertOrHoriz = computeOrientation(); |
| if (fPaneBuilt && fSashForm.getOrientation() == vertOrHoriz) { |
| return; |
| } |
| } else { |
| vertOrHoriz = orientation.equals(IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_UNDERNEATH) ? SWT.VERTICAL : SWT.HORIZONTAL; |
| |
| } |
| buildDetailPane(vertOrHoriz); |
| } |
| } |
| |
| private void buildDetailPane(int orientation) { |
| try { |
| fDetailsAnchor.setRedraw(false); |
| if (fDetailsComposiste != null) { |
| fDetailPane.dispose(); |
| fDetailsComposiste.dispose(); |
| } |
| fSashForm.setOrientation(orientation); |
| if (orientation == SWT.VERTICAL) { |
| fDetailsComposiste = SWTFactory.createComposite(fDetailsAnchor, fDetailsAnchor.getFont(), 1, 1, GridData.FILL_BOTH, 0, 0); |
| GridLayout layout = (GridLayout) fDetailsComposiste.getLayout(); |
| layout.verticalSpacing = 0; |
| fSepearator = new Label(fDetailsComposiste, SWT.SEPARATOR| SWT.HORIZONTAL); |
| fSepearator.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); |
| } else { |
| fDetailsComposiste = SWTFactory.createComposite(fDetailsAnchor, fDetailsAnchor.getFont(), 2, 1, GridData.FILL_BOTH, 0, 0); |
| GridLayout layout = (GridLayout) fDetailsComposiste.getLayout(); |
| layout.horizontalSpacing = 0; |
| fSepearator= new Label(fDetailsComposiste, SWT.SEPARATOR | SWT.VERTICAL); |
| fSepearator.setLayoutData(new GridData(SWT.TOP, SWT.FILL, false, true)); |
| } |
| // force update so detail pane can adapt to orientation change |
| showDetailPane(); |
| } finally { |
| fDetailsAnchor.layout(true); |
| fDetailsAnchor.setRedraw(true); |
| fPaneBuilt = true; |
| } |
| } |
| |
| /** |
| * Hides the details pane |
| */ |
| private void hideDetailPane() { |
| if (fToggledDetailOnce) { |
| setLastSashWeights(fSashForm.getWeights()); |
| } |
| fSashForm.setMaximizedControl(getViewer().getControl()); |
| } |
| |
| /** |
| * Shows the details pane |
| */ |
| private void showDetailPane() { |
| fSashForm.setMaximizedControl(null); |
| fSashForm.setWeights(getLastSashWeights()); |
| refreshDetailPaneContents(); |
| revealTreeSelection(); |
| fToggledDetailOnce = true; |
| } |
| |
| /** |
| * Make sure the currently selected item in the tree is visible. |
| */ |
| protected void revealTreeSelection() { |
| StructuredViewer viewer = (StructuredViewer) getViewer(); |
| if (viewer != null) { |
| ISelection selection = viewer.getSelection(); |
| if (selection instanceof IStructuredSelection) { |
| Object selected = ((IStructuredSelection)selection).getFirstElement(); |
| if (selected != null) { |
| viewer.reveal(selected); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Return the relative weights that were in effect the last time both panes were |
| * visible in the sash form, or the default weights if: |
| * <ul> |
| * <li> both panes have not yet been made visible</li> |
| * <li> one of the values persisted before is an invalid value</li> |
| * </ul> |
| */ |
| protected int[] getLastSashWeights() { |
| if (fLastSashWeights == null) { |
| fLastSashWeights = DEFAULT_SASH_WEIGHTS; |
| } |
| //check the weights to makes sure they are valid -- bug 154025 |
| else if(fLastSashWeights[0] < 0 || fLastSashWeights[1] < 0) { |
| fLastSashWeights = DEFAULT_SASH_WEIGHTS; |
| } |
| return fLastSashWeights; |
| } |
| |
| /** |
| * Set the current relative weights of the controls in the sash form, so that |
| * the sash form can be reset to this layout at a later time. |
| */ |
| protected void setLastSashWeights(int[] weights) { |
| fLastSashWeights = weights; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#createActions() |
| */ |
| protected void createActions() { |
| IAction action = new ShowTypesAction(this); |
| setAction("ShowTypeNames",action); //$NON-NLS-1$ |
| |
| action = new ToggleLogicalStructureAction(this); |
| setAction("ToggleContentProviders", action); //$NON-NLS-1$ |
| |
| action = new CollapseAllAction((TreeViewer)getViewer()); |
| setAction("CollapseAll", action); //$NON-NLS-1$ |
| IHandlerService hs = (IHandlerService) getSite().getService(IHandlerService.class); |
| if (hs != null) { |
| hs.activateHandler(CollapseAllHandler.COMMAND_ID, new ActionHandler(action)); |
| } |
| |
| action = new ChangeVariableValueAction(this); |
| action.setEnabled(false); |
| setAction("ChangeVariableValue", action); //$NON-NLS-1$ |
| |
| action= new VirtualFindAction(getVariablesViewer()); |
| setAction(VARIABLES_FIND_ELEMENT_ACTION, action); |
| } |
| |
| /* (non-Javadoc) |
| * |
| * Save the copy action so we can restore it on focus lost/gain |
| * |
| * @see org.eclipse.debug.ui.AbstractDebugView#createContextMenu(org.eclipse.swt.widgets.Control) |
| */ |
| protected void createContextMenu(Control menuControl) { |
| super.createContextMenu(menuControl); |
| setAction(VARIABLES_COPY_ACTION, getAction(COPY_ACTION)); |
| setAction(VARIABLES_PASTE_ACTION, getAction(PASTE_ACTION)); |
| } |
| |
| /** |
| * Creates the actions that allow the orientation of the detail pane to be changed. |
| * |
| * @param viewer |
| */ |
| private void createOrientationActions(TreeModelViewer viewer) { |
| IActionBars actionBars = getViewSite().getActionBars(); |
| IMenuManager viewMenu = actionBars.getMenuManager(); |
| |
| fToggleDetailPaneActions = new ToggleDetailPaneAction[4]; |
| fToggleDetailPaneActions[0] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_UNDERNEATH, null); |
| fToggleDetailPaneActions[1] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_RIGHT, null); |
| fToggleDetailPaneActions[2] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_AUTO, null); |
| fToggleDetailPaneActions[3] = new ToggleDetailPaneAction(this, IDebugPreferenceConstants.VARIABLES_DETAIL_PANE_HIDDEN, getToggleActionLabel()); |
| viewMenu.add(new Separator()); |
| final MenuManager layoutSubMenu = new MenuManager(VariablesViewMessages.VariablesView_40); |
| layoutSubMenu.setRemoveAllWhenShown(true); |
| layoutSubMenu.add(fToggleDetailPaneActions[0]); |
| layoutSubMenu.add(fToggleDetailPaneActions[1]); |
| layoutSubMenu.add(fToggleDetailPaneActions[2]); |
| layoutSubMenu.add(fToggleDetailPaneActions[3]); |
| viewMenu.add(layoutSubMenu); |
| viewMenu.add(new Separator()); |
| |
| fConfigureColumnsAction = new ConfigureColumnsAction(viewer); |
| setAction("ToggleColmns", new ToggleShowColumnsAction(viewer)); //$NON-NLS-1$ |
| |
| layoutSubMenu.addMenuListener(new IMenuListener() { |
| public void menuAboutToShow(IMenuManager manager) { |
| layoutSubMenu.add(fToggleDetailPaneActions[0]); |
| layoutSubMenu.add(fToggleDetailPaneActions[1]); |
| layoutSubMenu.add(fToggleDetailPaneActions[2]); |
| layoutSubMenu.add(fToggleDetailPaneActions[3]); |
| IAction action = getAction("ToggleColmns"); //$NON-NLS-1$ |
| ((IUpdate)action).update(); |
| if (action.isEnabled()) { |
| layoutSubMenu.add(action); |
| } |
| fConfigureColumnsAction.update(); |
| if (fConfigureColumnsAction.isEnabled()) { |
| layoutSubMenu.add(fConfigureColumnsAction); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * Returns the label to use for the action that toggles the view layout to be the tree viewer only (detail pane is hidden). |
| * Should be of the style '[view name] View Only'. |
| * |
| * @return action label for toggling the view layout to tree viewer only |
| */ |
| protected String getToggleActionLabel(){ |
| return VariablesViewMessages.VariablesView_41; |
| } |
| |
| /** |
| * Configures the toolBar. |
| * |
| * @param tbm The toolbar that will be configured |
| */ |
| protected void configureToolBar(IToolBarManager tbm) { |
| tbm.add(new Separator(this.getClass().getName())); |
| tbm.add(new Separator(IDebugUIConstants.RENDER_GROUP)); |
| tbm.add(getAction("ShowTypeNames")); //$NON-NLS-1$ |
| tbm.add(getAction("ToggleContentProviders")); //$NON-NLS-1$ |
| tbm.add(getAction("CollapseAll")); //$NON-NLS-1$ |
| } |
| |
| /** |
| * Adds items to the tree viewer's context menu including any extension defined |
| * actions. |
| * |
| * @param menu The menu to add the item to. |
| */ |
| protected void fillContextMenu(IMenuManager menu) { |
| |
| menu.add(new Separator(IDebugUIConstants.EMPTY_VARIABLE_GROUP)); |
| menu.add(new Separator(IDebugUIConstants.VARIABLE_GROUP)); |
| menu.add(getAction(VARIABLES_FIND_ELEMENT_ACTION)); |
| ChangeVariableValueAction changeValueAction = (ChangeVariableValueAction)getAction("ChangeVariableValue"); //$NON-NLS-1$ |
| if (changeValueAction.isApplicable()) { |
| menu.add(changeValueAction); |
| } |
| menu.add(new Separator()); |
| IAction action = new AvailableLogicalStructuresAction(this); |
| if (action.isEnabled()) { |
| menu.add(action); |
| } |
| action = new AvailableDetailPanesAction(this); |
| if (isDetailPaneVisible() && action.isEnabled()) { |
| menu.add(action); |
| } |
| menu.add(new Separator(IDebugUIConstants.EMPTY_RENDER_GROUP)); |
| menu.add(new Separator(IDebugUIConstants.EMPTY_NAVIGATION_GROUP)); |
| menu.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS)); |
| } |
| |
| /** |
| * Lazily instantiate and return a selection listener that populates the detail pane, |
| * but only if the detail is currently visible. |
| */ |
| protected ISelectionChangedListener getTreeSelectionChangedListener() { |
| if (fTreeSelectionChangedListener == null) { |
| fTreeSelectionChangedListener = new ISelectionChangedListener() { |
| public void selectionChanged(final SelectionChangedEvent event) { |
| if (event.getSelectionProvider().equals(getViewer())) { |
| clearStatusLine(); |
| // if the detail pane is not visible, don't waste time retrieving details |
| if (fSashForm.getMaximizedControl() == getViewer().getControl()) { |
| return; |
| } |
| refreshDetailPaneContents(); |
| treeSelectionChanged(event); |
| } |
| } |
| }; |
| } |
| return fTreeSelectionChangedListener; |
| } |
| |
| /** |
| * Selection in the variable tree changed. Perform any updates. |
| * |
| * @param event |
| */ |
| protected void treeSelectionChanged(SelectionChangedEvent event) {} |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentPaneID() |
| */ |
| public String getCurrentPaneID() { |
| return fDetailPane.getCurrentPaneID(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getCurrentSelection() |
| */ |
| public IStructuredSelection getCurrentSelection() { |
| if (getViewer() != null){ |
| return (IStructuredSelection)getViewer().getSelection(); |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getParentComposite() |
| */ |
| public Composite getParentComposite() { |
| return fDetailsComposiste; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#getWorkbenchPartSite() |
| */ |
| public IWorkbenchPartSite getWorkbenchPartSite() { |
| return getSite(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#refreshDetailPaneContents() |
| */ |
| public void refreshDetailPaneContents() { |
| if (isDetailPaneVisible()) { |
| String currentPaneID = getCurrentPaneID(); |
| if (currentPaneID != null) { |
| fLastSashWeights = fSashForm.getWeights(); |
| } |
| fDetailPane.display(getCurrentSelection()); |
| // Adjust sash background color settings and separator based on detail pane background color: |
| // When the backgrounds are the same, the sash should have a default background, else it should be |
| // invisible and the label separator should appear with the same background color as the detail pane |
| Control control = fDetailPane.getCurrentControl(); |
| if (control.getBackground().equals(fDetailsAnchor.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND))) { |
| // don't show the label separator |
| if (!fSepearator.isDisposed()) { |
| getDefaultControl().setBackground(fDetailsAnchor.getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); |
| fSepearator.dispose(); |
| fDetailsComposiste.layout(true); |
| } |
| } else { |
| // show the label separator and make sash invisible |
| if (fSepearator.isDisposed()) { |
| // re-build the detail pane with the separator |
| buildDetailPane(fSashForm.getOrientation()); |
| return; |
| } |
| getDefaultControl().setBackground(fDetailsAnchor.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND)); |
| fSepearator.setBackground(control.getBackground()); |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer#paneChanged(java.lang.String) |
| */ |
| public void paneChanged(String newPaneID) { |
| if (fDetailPaneActivatedListener == null){ |
| fDetailPaneActivatedListener = new Listener() { |
| public void handleEvent(Event event) { |
| fTreeHasFocus = false; |
| } |
| }; |
| } |
| fDetailPane.getCurrentControl().addListener(SWT.Activate, fDetailPaneActivatedListener); |
| } |
| |
| /** |
| * @return the model presentation to be used for this view |
| */ |
| protected IDebugModelPresentation getModelPresentation() { |
| if (fModelPresentation == null) { |
| fModelPresentation = new VariablesViewModelPresentation(); |
| } |
| return fModelPresentation; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.part.WorkbenchPart#getAdapter(Class) |
| */ |
| public Object getAdapter(Class required) { |
| if (IDebugModelPresentation.class.equals(required)) { |
| return getModelPresentation(); |
| } |
| else if (fDetailPane != null){ |
| Object adapter = fDetailPane.getAdapter(required); |
| if (adapter != null) return adapter; |
| } |
| return super.getAdapter(required); |
| } |
| |
| /** |
| * If possible, calls the update method of the action associated with the given ID. |
| * |
| * @param actionId the ID of the action to update |
| */ |
| protected void updateAction(String actionId) { |
| IAction action= getAction(actionId); |
| if (action instanceof IUpdate) { |
| ((IUpdate) action).update(); |
| } |
| } |
| |
| /** |
| * @return whether the detail pane is visible to the user |
| */ |
| protected boolean isDetailPaneVisible() { |
| return !fToggleDetailPaneActions[3].isChecked(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#getDefaultControl() |
| */ |
| protected Control getDefaultControl() { |
| return fSashForm; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.views.IDebugExceptionHandler#handleException(org.eclipse.debug.core.DebugException) |
| */ |
| public void handleException(DebugException e) { |
| showMessage(e.getMessage()); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.contexts.provisional.IDebugContextListener#contextEvent(org.eclipse.debug.internal.ui.contexts.provisional.DebugContextEvent) |
| */ |
| public void debugContextChanged(DebugContextEvent event) { |
| if ((event.getFlags() & DebugContextEvent.ACTIVATED) > 0) { |
| contextActivated(event.getContext()); |
| } |
| } |
| |
| /** |
| * Updates actions and sets the viewer input when a context is activated. |
| * @param selection |
| */ |
| protected void contextActivated(ISelection selection) { |
| if (!isAvailable() || !isVisible()) { |
| return; |
| } |
| if (selection instanceof IStructuredSelection) { |
| Object source = ((IStructuredSelection)selection).getFirstElement(); |
| fInputService.resolveViewerInput(source); |
| } |
| } |
| |
| /** |
| * Delegate to the <code>DOUBLE_CLICK_ACTION</code>, |
| * if any. |
| * |
| * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(DoubleClickEvent) |
| */ |
| public void doubleClick(DoubleClickEvent event) { |
| IAction action = getAction(DOUBLE_CLICK_ACTION); |
| if (action != null && action.isEnabled()) { |
| action.run(); |
| } else { |
| ISelection selection = getVariablesViewer().getSelection(); |
| if (selection instanceof TreeSelection) { |
| TreeSelection ss = (TreeSelection) selection; |
| if (ss.size() == 1) { |
| Widget item = getVariablesViewer().findItem(ss.getPaths()[0]); |
| if (item instanceof TreeItem) { |
| TreeItem ti = (TreeItem) item; |
| if (ti.getExpanded()) { |
| ti.setExpanded(false); |
| } else { |
| // need to trigger proper children updates when expanding |
| getVariablesViewer().expandToLevel(ss.getPaths()[0], 1); |
| } |
| } |
| |
| } |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.IDebugView#getPresentation(String) |
| */ |
| public IDebugModelPresentation getPresentation(String id) { |
| if (getViewer() instanceof StructuredViewer) { |
| IDebugModelPresentation lp = getModelPresentation(); |
| if (lp instanceof DelegatingModelPresentation) { |
| return ((DelegatingModelPresentation)lp).getPresentation(id); |
| } |
| if (lp instanceof LazyModelPresentation) { |
| if (((LazyModelPresentation)lp).getDebugModelIdentifier().equals(id)) { |
| return lp; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.IDetailSite#isMainViewerAvailable() |
| */ |
| public boolean isMainViewerAvailable() { |
| return isAvailable(); |
| } |
| |
| /** |
| * @return the presentation context of the viewer |
| */ |
| protected IPresentationContext getPresentationContext() { |
| return getVariablesViewer().getPresentationContext(); |
| } |
| |
| /** |
| * Sets whether logical structures are being displayed |
| */ |
| public void setShowLogicalStructure(boolean flag) { |
| getPresentationContext().setProperty(PRESENTATION_SHOW_LOGICAL_STRUCTURES, Boolean.valueOf(flag)); |
| } |
| |
| /** |
| * Returns whether logical structures are being displayed |
| */ |
| public boolean isShowLogicalStructure() { |
| Boolean show = (Boolean) getPresentationContext().getProperty(PRESENTATION_SHOW_LOGICAL_STRUCTURES); |
| return show != null && show.booleanValue(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#becomesHidden() |
| */ |
| protected void becomesHidden() { |
| fInputService.resolveViewerInput(ViewerInputService.NULL_INPUT); |
| super.becomesHidden(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.ui.AbstractDebugView#becomesVisible() |
| */ |
| protected void becomesVisible() { |
| super.becomesVisible(); |
| ISelection selection = DebugUITools.getDebugContextManager().getContextService(getSite().getWorkbenchWindow()).getActiveContext(); |
| contextActivated(selection); |
| } |
| |
| /** |
| * @return the tree model viewer displaying variables |
| */ |
| protected TreeModelViewer getVariablesViewer() { |
| return (TreeModelViewer) getViewer(); |
| } |
| |
| /** |
| * Clears the status line of all messages and errors |
| */ |
| protected void clearStatusLine() { |
| IStatusLineManager manager = getViewSite().getActionBars().getStatusLineManager(); |
| manager.setErrorMessage(null); |
| manager.setMessage(null); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.IPerspectiveListener#perspectiveActivated(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor) |
| */ |
| public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {} |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.IPerspectiveListener#perspectiveChanged(org.eclipse.ui.IWorkbenchPage, org.eclipse.ui.IPerspectiveDescriptor, java.lang.String) |
| */ |
| public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) { |
| if(changeId.equals(IWorkbenchPage.CHANGE_RESET)) { |
| setLastSashWeights(DEFAULT_SASH_WEIGHTS); |
| fSashForm.setWeights(DEFAULT_SASH_WEIGHTS); |
| fSashForm.layout(true); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.provisional.IModelChangedListener#modelChanged(org.eclipse.debug.internal.ui.viewers.provisional.IModelDelta) |
| */ |
| public void modelChanged(IModelDelta delta, IModelProxy proxy) { |
| fVisitor.reset(); |
| delta.accept(fVisitor); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#updateComplete(org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousRequestMonitor) |
| */ |
| public void updateComplete(IViewerUpdate update) { |
| IStatus status = update.getStatus(); |
| if (!update.isCanceled()) { |
| if (status != null && !status.isOK()) { |
| showMessage(status.getMessage()); |
| } else { |
| showViewer(); |
| } |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#updateStarted(org.eclipse.debug.internal.ui.viewers.provisional.IAsynchronousRequestMonitor) |
| */ |
| public void updateStarted(IViewerUpdate update) { |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#viewerUpdatesBegin() |
| */ |
| public synchronized void viewerUpdatesBegin() { |
| fTriggerDetailsJob.cancel(); |
| IWorkbenchSiteProgressService progressService = |
| (IWorkbenchSiteProgressService)getSite().getAdapter(IWorkbenchSiteProgressService.class); |
| if (progressService != null) { |
| progressService.incrementBusy(); |
| } |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.debug.internal.ui.viewers.model.provisional.viewers.IViewerUpdateListener#viewerUpdatesComplete() |
| */ |
| public synchronized void viewerUpdatesComplete() { |
| if (fVisitor.isTriggerDetails()) { |
| fTriggerDetailsJob.schedule(); |
| } |
| IWorkbenchSiteProgressService progressService = |
| (IWorkbenchSiteProgressService)getSite().getAdapter(IWorkbenchSiteProgressService.class); |
| if (progressService != null) { |
| progressService.decrementBusy(); |
| } |
| } |
| |
| /** |
| * @see org.eclipse.ui.IWorkbenchPart#setFocus() |
| */ |
| public void setFocus() { |
| boolean success = false; |
| if (!fTreeHasFocus && fDetailPane != null){ |
| success = fDetailPane.setFocus(); |
| } |
| // Unless the detail pane successfully set focus to a control, set focus to the variables tree |
| if (!success && getViewer() != null){ |
| getViewer().getControl().setFocus(); |
| } |
| } |
| |
| protected ToggleDetailPaneAction getToggleDetailPaneAction(String orientation) |
| { |
| for (int i=0; i<fToggleDetailPaneActions.length; i++) |
| if (fToggleDetailPaneActions[i].getOrientation().equals(orientation)) |
| return fToggleDetailPaneActions[i]; |
| |
| return null; |
| } |
| |
| /* |
| * @see org.eclipse.debug.internal.ui.views.variables.details.IDetailPaneContainer2#setSelectionProvider(org.eclipse.jface.viewers.ISelectionProvider) |
| */ |
| public void setSelectionProvider(ISelectionProvider provider) { |
| // Workaround for legacy detail pane implementations (bug 254442) |
| // set selection provider wrapper again in case it got overridden by detail pane |
| getSite().setSelectionProvider(fSelectionProvider); |
| // change active provider |
| fSelectionProvider.setActiveProvider(provider); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISaveablePart#doSave(org.eclipse.core.runtime.IProgressMonitor) |
| */ |
| public void doSave(IProgressMonitor monitor) { |
| fDetailPane.doSave(monitor); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISaveablePart#doSaveAs() |
| */ |
| public void doSaveAs() { |
| fDetailPane.doSaveAs(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISaveablePart#isDirty() |
| */ |
| public boolean isDirty() { |
| return fDetailPane.isDirty(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed() |
| */ |
| public boolean isSaveAsAllowed() { |
| return fDetailPane.isSaveAsAllowed(); |
| } |
| |
| /* (non-Javadoc) |
| * @see org.eclipse.ui.ISaveablePart#isSaveOnCloseNeeded() |
| */ |
| public boolean isSaveOnCloseNeeded() { |
| return fDetailPane.isSaveOnCloseNeeded(); |
| } |
| } |