Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 2ca62c65f804df6808b7cfccb74b44f8ca00c546 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
/*******************************************************************************
 * Copyright (c) 2004, 2010 QNX Software Systems 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:
 *     QNX Software Systems - Initial API and implementation
 *     Ericsson             - DSF-GDB version
 *     Nokia                - Made generic to DSF
 *     Wind River Systems   - Adapted to TCF Debug
 *******************************************************************************/
package org.eclipse.tm.internal.tcf.cdt.ui;

import java.util.HashMap;
import java.util.Map;

import org.eclipse.cdt.debug.ui.CDebugUIPlugin;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNode;
import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeExecContext;
import org.eclipse.tm.internal.tcf.debug.ui.model.TCFNodeStackFrame;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.WorkbenchJob;

/**
 * Manages the current evaluation context (stack frame) for evaluation actions.
 * In each page, the selection is tracked in each debug view (if any). When a
 * debug target selection exists, the "debuggerActive" System property is set to
 * true. This property is used to make the "Run To Line", "Resume At Line",
 * "Move To Line" and "Add Watch Expression" actions visible in editors only if
 * there is a running debug session.
 */
public class EvaluationContextManager implements IWindowListener,
        IPageListener, ISelectionListener, IPartListener2 {

    // Must use the same ID as the base CDT since we want to enable
    // actions that are registered by base CDT.
    private final static String DEBUGGER_ACTIVE = CDebugUIPlugin.PLUGIN_ID + ".debuggerActive"; //$NON-NLS-1$

    protected static EvaluationContextManager fgManager;

    private Map<IWorkbenchPage, TCFNode> fContextsByPage = null;

    protected EvaluationContextManager() {
    }

    public static void startup() {
        WorkbenchJob job = new WorkbenchJob("") {
            @Override
            public IStatus runInUIThread(IProgressMonitor monitor) {
                if (fgManager == null) {
                    fgManager = new EvaluationContextManager();
                    IWorkbench workbench = PlatformUI.getWorkbench();
                    IWorkbenchWindow[] windows = workbench.getWorkbenchWindows();
                    for (int i = 0; i < windows.length; i++) {
                        fgManager.windowOpened(windows[i]);
                    }
                    workbench.addWindowListener(fgManager);
                }
                return Status.OK_STATUS;
            }
        };
        job.setPriority(Job.SHORT);
        job.setSystem(true);
        job.schedule();
    }

    public void windowActivated(IWorkbenchWindow window) {
        windowOpened(window);
    }

    public void windowDeactivated(IWorkbenchWindow window) {
    }

    public void windowClosed(IWorkbenchWindow window) {
        window.removePageListener(this);
    }

    public void windowOpened(IWorkbenchWindow window) {
        IWorkbenchPage[] pages = window.getPages();
        for (int i = 0; i < pages.length; i++) {
            window.addPageListener(this);
            pageOpened(pages[i]);
        }
    }

    public void pageActivated(IWorkbenchPage page) {
        pageOpened(page);
    }

    public void pageClosed(IWorkbenchPage page) {
        page.removeSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
        page.removePartListener(this);
    }

    public void pageOpened(IWorkbenchPage page) {
        page.addSelectionListener(IDebugUIConstants.ID_DEBUG_VIEW, this);
        page.addPartListener(this);
        IWorkbenchPartReference ref = page.getActivePartReference();
        if (ref != null) {
            partActivated(ref);
        }
    }

    public void selectionChanged(IWorkbenchPart part, ISelection selection) {
        IWorkbenchPage page = part.getSite().getPage();
        if (selection instanceof IStructuredSelection) {
            IStructuredSelection ss = (IStructuredSelection) selection;
            if (ss.size() == 1) {
                Object element = ss.getFirstElement();
                if (element instanceof TCFNodeExecContext
                        || element instanceof TCFNodeStackFrame) {
                    setContext(page, (TCFNode) element);
                    return;
                }
            }
        }
        // no context in the given view
        removeContext(page);
    }

    public void partActivated(IWorkbenchPartReference partRef) {
    }

    public void partBroughtToTop(IWorkbenchPartReference partRef) {
    }

    public void partClosed(IWorkbenchPartReference partRef) {
        if (IDebugUIConstants.ID_DEBUG_VIEW.equals(partRef.getId())) {
            removeContext(partRef.getPage());
        }
    }

    public void partDeactivated(IWorkbenchPartReference partRef) {
    }

    public void partOpened(IWorkbenchPartReference partRef) {
    }

    public void partHidden(IWorkbenchPartReference partRef) {
    }

    public void partVisible(IWorkbenchPartReference partRef) {
    }

    public void partInputChanged(IWorkbenchPartReference partRef) {
    }

    /**
     * Sets the evaluation context for the given page, and notes that a valid
     * execution context exists.
     *
     * @param page
     * @param target
     */
    private void setContext(IWorkbenchPage page, TCFNode target) {
        if (fContextsByPage == null) {
            fContextsByPage = new HashMap<IWorkbenchPage, TCFNode>();
        }
        fContextsByPage.put(page, target);
        System.setProperty(DEBUGGER_ACTIVE, Boolean.TRUE.toString());
    }

    /**
     * Removes an evaluation context for the given page, and determines if any
     * valid execution context remain.
     *
     * @param page
     */
    private void removeContext(IWorkbenchPage page) {
        if (fContextsByPage != null) {
            fContextsByPage.remove(page);
            if (fContextsByPage.isEmpty()) {
                System.setProperty(DEBUGGER_ACTIVE, Boolean.FALSE.toString());
                fContextsByPage = null;
            }
        }
    }
}

Back to the top