1 /*******************************************************************************
2  * Copyright (c) 2000, 2015 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.ui.internal;
15 
16 import org.eclipse.ui.IPageListener;
17 import org.eclipse.ui.IWorkbenchPage;
18 import org.eclipse.ui.IWorkbenchWindow;
19 import org.eclipse.ui.actions.ActionFactory;
20 import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
21 import org.eclipse.ui.actions.PartEventAction;
22 
23 /**
24  * The abstract superclass for actions that listen to page activation and
25  * open/close events. This implementation tracks the active page (see
26  * <code>getActivePage</code>) and provides a convenient place to monitor page
27  * lifecycle events that could affect the availability of the action.
28  * <p>
29  * Subclasses must implement the following <code>IAction</code> method:
30  * </p>
31  * <ul>
32  * <li><code>run</code> - to do the action's work</li>
33  * </ul>
34  * <p>
35  * Subclasses may extend any of the <code>IPartListener</code> methods if the
36  * action availablity needs to be recalculated:
37  * </p>
38  * <ul>
39  * <li><code>partActivated</code></li>
40  * <li><code>partDeactivated</code></li>
41  * <li><code>partOpened</code></li>
42  * <li><code>partClosed</code></li>
43  * <li><code>partBroughtToTop</code></li>
44  * </ul>
45  * <p>
46  * Subclasses may extend any of the <code>IPageListener</code> methods if the
47  * action availability needs to be recalculated:
48  * </p>
49  * <ul>
50  * <li><code>pageActivated</code></li>
51  * <li><code>pageClosed</code></li>
52  * <li><code>pageOpened</code></li>
53  * </ul>
54  * <p>
55  * This method implements the <code>IPartListener</code> and
56  * <code>IPageListener</code>interfaces, and automatically registers listeners
57  * so that it can keep its enablement state up to date. Ordinarily, the window's
58  * references to these listeners will be dropped automatically when the window
59  * closes. However, if the client needs to get rid of an action while the window
60  * is still open, the client must call {@link IWorkbenchAction#dispose dispose}
61  * to give the action an opportunity to deregister its listeners and to perform
62  * any other cleanup.
63  * </p>
64  */
65 public abstract class PageEventAction extends PartEventAction implements IPageListener, ActionFactory.IWorkbenchAction {
66 	/**
67 	 * The active page, or <code>null</code> if none.
68 	 */
69 	private IWorkbenchPage activePage;
70 
71 	/**
72 	 * The workbench window this action is registered with.
73 	 */
74 	private IWorkbenchWindow workbenchWindow;
75 
76 	/**
77 	 * Creates a new action with the given text. Register this action with the
78 	 * workbench window for page lifecycle events.
79 	 *
80 	 * @param text   the string used as the text for the action, or
81 	 *               <code>null</code> if there is no text
82 	 * @param window the workbench window this action is registered with
83 	 */
PageEventAction(String text, IWorkbenchWindow window)84 	protected PageEventAction(String text, IWorkbenchWindow window) {
85 		super(text);
86 		if (window == null) {
87 			throw new IllegalArgumentException();
88 		}
89 		this.workbenchWindow = window;
90 		this.activePage = window.getActivePage();
91 		this.workbenchWindow.addPageListener(this);
92 		this.workbenchWindow.getPartService().addPartListener(this);
93 	}
94 
95 	/**
96 	 * Returns the currently active page in the workbench window.
97 	 *
98 	 * @return currently active page in the workbench window, or <code>null</code>
99 	 *         in none
100 	 */
getActivePage()101 	public final IWorkbenchPage getActivePage() {
102 		return activePage;
103 	}
104 
105 	/**
106 	 * Returns the workbench window this action applies to.
107 	 *
108 	 * @return the workbench window, or <code>null</code> if this action has been
109 	 *         disposed
110 	 */
getWorkbenchWindow()111 	public final IWorkbenchWindow getWorkbenchWindow() {
112 		return workbenchWindow;
113 	}
114 
115 	/**
116 	 * The <code>PageEventAction</code> implementation of this
117 	 * <code>IPageListener</code> method records that the given page is active.
118 	 * Subclasses may extend this method if action availability has to be
119 	 * recalculated.
120 	 */
121 	@Override
pageActivated(IWorkbenchPage page)122 	public void pageActivated(IWorkbenchPage page) {
123 		this.activePage = page;
124 	}
125 
126 	/**
127 	 * The <code>PageEventAction</code> implementation of this
128 	 * <code>IPageListener</code> method clears the active page if it just closed.
129 	 * Subclasses may extend this method if action availability has to be
130 	 * recalculated.
131 	 */
132 	@Override
pageClosed(IWorkbenchPage page)133 	public void pageClosed(IWorkbenchPage page) {
134 		if (page == activePage) {
135 			activePage = null;
136 		}
137 	}
138 
139 	/**
140 	 * The <code>PageEventAction</code> implementation of this
141 	 * <code>IPageListener</code> method does nothing. Subclasses should extend this
142 	 * method if action availability has to be recalculated.
143 	 */
144 	@Override
pageOpened(IWorkbenchPage page)145 	public void pageOpened(IWorkbenchPage page) {
146 		// do nothing
147 	}
148 
149 	/**
150 	 * The <code>PageEventAction</code> implementation of this
151 	 * <code>ActionFactory.IWorkbenchAction</code> method deregisters the part and
152 	 * page listener adding by the constructor. Subclasses should extend this method
153 	 * to do additional cleanup.
154 	 *
155 	 * @since 3.0
156 	 */
157 	@Override
dispose()158 	public void dispose() {
159 		if (workbenchWindow == null) {
160 			// action has already been disposed
161 			return;
162 		}
163 		super.partDeactivated(null);
164 		workbenchWindow.removePageListener(this);
165 		workbenchWindow.getPartService().removePartListener(this);
166 		workbenchWindow = null;
167 	}
168 }
169