/* * Copyright (c) 2012, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.tools.debug.ui.internal.view; import com.google.dart.tools.debug.ui.internal.DartDebugUIPlugin; import com.google.dart.tools.debug.ui.internal.DartUtil; import com.google.dart.tools.ui.DartToolsPlugin; import com.google.dart.tools.ui.internal.util.SWTUtil; import org.eclipse.debug.core.DebugPlugin; import org.eclipse.debug.core.ILaunch; import org.eclipse.debug.core.ILaunchesListener; import org.eclipse.debug.core.model.IDebugTarget; import org.eclipse.debug.internal.ui.viewers.model.provisional.TreeModelViewer; import org.eclipse.debug.internal.ui.views.launch.LaunchView; import org.eclipse.debug.internal.ui.views.variables.ToggleLogicalStructureAction; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.action.Separator; import org.eclipse.jface.action.ToolBarManager; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.layout.GridLayoutFactory; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.Rectangle; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.ToolBar; import org.eclipse.ui.IActionBars; import org.eclipse.ui.IMemento; import org.eclipse.ui.PartInitException; /** * A custom debugger view that combines the stack trace view and the variables view together. */ @SuppressWarnings("restriction") public class DebuggerView extends LaunchView implements ILaunchesListener { public static final String ID = "com.google.dart.tools.debug.debuggerView"; private static final String SASH_WEIGHTS = "sashWeights"; private ToolBar toolbar; private SashForm sashForm; private DartVariablesView variablesView; private static Image CONNECTED_IMAGE; private static Image NOT_CONNECTED_IMAGE; private ShowBreakpointsAction showBreakpointsAction; private ShowInspectorAction showInspectorAction; private ShowExpressionsAction showExpressionsAction; private TreeModelViewer treeViewer; private IPreferenceStore preferences; private IPropertyChangeListener propertyChangeListener = new IPropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent event) { doPropertyChange(event); } }; /** * Create a new DebuggerView instance. */ public DebuggerView() { } @Override public void createPartControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); GridLayoutFactory.fillDefaults().spacing(0, 0).applyTo(composite); toolbar = new ToolBar(composite, SWT.HORIZONTAL); GridDataFactory.fillDefaults().grab(true, false).applyTo(toolbar); Label separator = new Label(composite, SWT.SEPARATOR | SWT.HORIZONTAL); GridDataFactory.fillDefaults().grab(true, false).applyTo(separator); sashForm = new SashForm(composite, SWT.VERTICAL); GridDataFactory.fillDefaults().grab(true, true).applyTo(sashForm); super.createPartControl(sashForm); ISelectionProvider selProvider = getViewSite().getSelectionProvider(); variablesView = new DartVariablesView(); try { variablesView.init(getViewSite()); } catch (PartInitException ex) { DartUtil.logError(ex); } variablesView.createPartControl(sashForm); if (getViewSite().getSelectionProvider() != selProvider) { getViewSite().setSelectionProvider(selProvider); } variablesView.becomesVisible(); showInspectorAction.setSelectionProvider(variablesView); restoreSashWeights(getMemento()); updateSashOrientation(sashForm); sashForm.addControlListener(new ControlAdapter() { @Override public void controlResized(ControlEvent e) { updateSashOrientation(sashForm); } }); IActionBars actionBars = getViewSite().getActionBars(); actionBars.getMenuManager().removeAll(); configureViewToolBar(actionBars.getToolBarManager()); DebugPlugin.getDefault().getLaunchManager().addLaunchListener(this); if (CONNECTED_IMAGE == null) { NOT_CONNECTED_IMAGE = DartDebugUIPlugin.getImage("obj16/debug_exc.gif"); CONNECTED_IMAGE = DartDebugUIPlugin.getImage(new DecorationOverlayIcon( NOT_CONNECTED_IMAGE, DartDebugUIPlugin.getImageDescriptor("ovr16/play.png"), IDecoration.BOTTOM_RIGHT)); } updateConnectionStatus(); } @Override public void dispose() { DebugPlugin.getDefault().getLaunchManager().removeLaunchListener(this); variablesView.dispose(); if (propertyChangeListener != null) { getPreferences().removePropertyChangeListener(propertyChangeListener); propertyChangeListener = null; } super.dispose(); } @Override public void launchesAdded(ILaunch[] launches) { updateConnectionStatusAsync(); } @Override public void launchesChanged(ILaunch[] launches) { updateConnectionStatusAsync(); } @Override public void launchesRemoved(ILaunch[] launches) { updateConnectionStatusAsync(); } @Override public void saveViewerState(IMemento memento) { super.saveViewerState(memento); // Save the sash weights. int[] weights = sashForm.getWeights(); memento.putString(SASH_WEIGHTS, weights[0] + "," + weights[1]); } @Override protected void configureToolBar(IToolBarManager viewToolBarManager) { ToolBarManager manager = new ToolBarManager(toolbar); manager.add(getAction("resume")); manager.add(getAction("suspend")); manager.add(new BlankSeparator()); manager.add(getAction("step_into")); manager.add(getAction("step_over")); manager.add(getAction("step_return")); manager.add(new BlankSeparator()); manager.add(getAction("terminate")); manager.update(true); toolbar.pack(); toolbar.getParent().layout(true); } protected void configureViewToolBar(IToolBarManager manager) { manager.removeAll(); manager.add(showBreakpointsAction); manager.add(showInspectorAction); manager.add(showExpressionsAction); manager.add(new Separator()); manager.add(new ToggleLogicalStructureAction(variablesView)); manager.add(new ToggleUseSourceMapsAction(this)); manager.update(true); } @Override protected void createActions() { super.createActions(); showBreakpointsAction = new ShowBreakpointsAction(); setAction("showBreakpointsAction", showBreakpointsAction); showInspectorAction = new ShowInspectorAction(); setAction("showInspectorAction", showInspectorAction); showExpressionsAction = new ShowExpressionsAction(); setAction("showExpressionsAction", showExpressionsAction); } @Override protected TreeModelViewer createViewer(Composite parent) { preferences = DartToolsPlugin.getDefault().getCombinedPreferenceStore(); final TreeModelViewer treeViewer = (TreeModelViewer) super.createViewer(parent); this.treeViewer = treeViewer; treeViewer.getTree().setBackgroundMode(SWT.INHERIT_FORCE); treeViewer.getTree().addListener(SWT.EraseItem, new Listener() { @Override public void handleEvent(Event event) { SWTUtil.eraseSelection(event, treeViewer.getTree(), getPreferences()); } }); SWTUtil.bindJFaceResourcesFontToControl(treeViewer.getTree()); updateColors(); return treeViewer; } /** * This method is overridden to remove the context menu for the Debugger view. */ @Override protected void fillContextMenu(IMenuManager menu) { } protected void updateColors() { SWTUtil.setColors(treeViewer.getTree(), getPreferences()); } void updateSashOrientation(SashForm sash) { Rectangle r = sash.getBounds(); int orientation = (r.height * 1.25) >= r.width ? SWT.VERTICAL : SWT.HORIZONTAL; if (sash.getOrientation() != orientation) { sash.setOrientation(orientation); } } private void doPropertyChange(PropertyChangeEvent event) { SWTUtil.runUI(new Runnable() { @Override public void run() { updateColors(); treeViewer.refresh(false); } }); } private IPreferenceStore getPreferences() { return preferences; } private boolean isConnected() { for (IDebugTarget debugTarget : DebugPlugin.getDefault().getLaunchManager().getDebugTargets()) { if (!debugTarget.isTerminated()) { return true; } } return false; } private void restoreSashWeights(IMemento memento) { if (memento != null && memento.getString(SASH_WEIGHTS) != null) { String[] strs = memento.getString(SASH_WEIGHTS).split(","); if (strs.length == 2) { try { sashForm.setWeights(new int[] {Integer.parseInt(strs[0]), Integer.parseInt(strs[1])}); return; } catch (NumberFormatException ex) { DartUtil.logError(ex); } } } sashForm.setWeights(new int[] {40, 60}); } private void updateConnectionStatus() { if (isConnected()) { setTitleImage(CONNECTED_IMAGE); } else { setTitleImage(NOT_CONNECTED_IMAGE); } } private void updateConnectionStatusAsync() { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { updateConnectionStatus(); } }); } }