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