001: /*******************************************************************************
002: * Copyright (c) 2005, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.application;
011:
012: import java.util.HashMap;
013: import java.util.Iterator;
014: import java.util.Map;
015:
016: import org.eclipse.core.runtime.Assert;
017: import org.eclipse.core.runtime.IStatus;
018: import org.eclipse.core.runtime.Status;
019: import org.eclipse.jface.action.IAction;
020: import org.eclipse.jface.action.ICoolBarManager;
021: import org.eclipse.jface.action.IMenuManager;
022: import org.eclipse.jface.action.IStatusLineManager;
023: import org.eclipse.ui.IMemento;
024: import org.eclipse.ui.IWorkbenchWindow;
025: import org.eclipse.ui.PlatformUI;
026: import org.eclipse.ui.actions.ActionFactory;
027:
028: /**
029: * Public base class for configuring the action bars of a workbench window.
030: * <p>
031: * An application should declare a subclass of <code>ActionBarAdvisor</code>
032: * and override methods to configure a window's action bars to suit the needs of the
033: * particular application.
034: * </p>
035: * <p>
036: * The following advisor methods are called at strategic points in the
037: * workbench's lifecycle (all occur within the dynamic scope of the call
038: * to {@link PlatformUI#createAndRunWorkbench PlatformUI.createAndRunWorkbench}):
039: * <ul>
040: * <li><code>fillActionBars</code> - called after <code>WorkbenchWindowAdvisor.preWindowOpen</code>
041: * to configure a window's action bars</li>
042: * </ul>
043: * </p>
044: *
045: * @see WorkbenchWindowAdvisor#createActionBarAdvisor(IActionBarConfigurer)
046: *
047: * @since 3.1
048: */
049: public class ActionBarAdvisor {
050:
051: /**
052: * Bit flag for {@link #fillActionBars fillActionBars} indicating that the
053: * operation is not filling the action bars of an actual workbench window,
054: * but rather a proxy (used for perspective customization).
055: */
056: public static final int FILL_PROXY = 0x01;
057:
058: /**
059: * Bit flag for {@link #fillActionBars fillActionBars} indicating that the
060: * operation is supposed to fill (or describe) the workbench window's menu
061: * bar.
062: */
063: public static final int FILL_MENU_BAR = 0x02;
064:
065: /**
066: * Bit flag for {@link #fillActionBars fillActionBars} indicating that the
067: * operation is supposed to fill (or describe) the workbench window's cool
068: * bar.
069: */
070: public static final int FILL_COOL_BAR = 0x04;
071:
072: /**
073: * Bit flag for {@link #fillActionBars fillActionBars} indicating that the
074: * operation is supposed to fill (or describe) the workbench window's status
075: * line.
076: */
077: public static final int FILL_STATUS_LINE = 0x08;
078:
079: private IActionBarConfigurer actionBarConfigurer;
080:
081: private Map actions = new HashMap();
082:
083: /**
084: * Creates a new action bar advisor to configure a workbench
085: * window's action bars via the given action bar configurer.
086: *
087: * @param configurer the action bar configurer
088: */
089: public ActionBarAdvisor(IActionBarConfigurer configurer) {
090: Assert.isNotNull(configurer);
091: actionBarConfigurer = configurer;
092: }
093:
094: /**
095: * Returns the action bar configurer.
096: *
097: * @return the action bar configurer
098: */
099: protected IActionBarConfigurer getActionBarConfigurer() {
100: return actionBarConfigurer;
101: }
102:
103: /**
104: * Configures the action bars using the given action bar configurer.
105: * Under normal circumstances, <code>flags</code> does not include
106: * <code>FILL_PROXY</code>, meaning this is a request to fill the action
107: * bars of the corresponding workbench window; the
108: * remaining flags indicate which combination of
109: * the menu bar (<code>FILL_MENU_BAR</code>),
110: * the tool bar (<code>FILL_COOL_BAR</code>),
111: * and the status line (<code>FILL_STATUS_LINE</code>) are to be filled.
112: * <p>
113: * If <code>flags</code> does include <code>FILL_PROXY</code>, then this
114: * is a request to describe the actions bars of the given workbench window
115: * (which will already have been filled);
116: * again, the remaining flags indicate which combination of the menu bar,
117: * the tool bar, and the status line are to be described.
118: * The actions included in the proxy action bars can be the same instances
119: * as in the actual window's action bars. Calling <code>ActionFactory</code>
120: * to create new action instances is not recommended, because these
121: * actions internally register listeners with the window and there is no
122: * opportunity to dispose of these actions.
123: * </p>
124: * <p>
125: * This method is called just after {@link WorkbenchWindowAdvisor#preWindowOpen()}.
126: * Clients must not call this method directly (although super calls are okay).
127: * The default implementation calls <code>makeActions</code> if
128: * <code>FILL_PROXY</code> is specified, then calls <code>fillMenuBar</code>,
129: * <code>fillCoolBar</code>, and <code>fillStatusLine</code>
130: * if the corresponding flags are specified.
131: * </p>
132: * <p>
133: * Subclasses may override, but it is recommended that they override the
134: * methods mentioned above instead.
135: * </p>
136: *
137: * @param flags bit mask composed from the constants
138: * {@link #FILL_MENU_BAR FILL_MENU_BAR},
139: * {@link #FILL_COOL_BAR FILL_COOL_BAR},
140: * {@link #FILL_STATUS_LINE FILL_STATUS_LINE},
141: * and {@link #FILL_PROXY FILL_PROXY}
142: */
143: public void fillActionBars(int flags) {
144: if ((flags & FILL_PROXY) == 0) {
145: makeActions(actionBarConfigurer.getWindowConfigurer()
146: .getWindow());
147: }
148: if ((flags & FILL_MENU_BAR) != 0) {
149: fillMenuBar(actionBarConfigurer.getMenuManager());
150: }
151: if ((flags & FILL_COOL_BAR) != 0) {
152: fillCoolBar(actionBarConfigurer.getCoolBarManager());
153: }
154: if ((flags & FILL_STATUS_LINE) != 0) {
155: fillStatusLine(actionBarConfigurer.getStatusLineManager());
156: }
157: }
158:
159: /**
160: * Instantiates the actions used in the fill methods.
161: * Use {@link #register(IAction)} to register the action with the key binding service
162: * and add it to the list of actions to be disposed when the window is closed.
163: *
164: * @param window the window containing the action bars
165: */
166: protected void makeActions(IWorkbenchWindow window) {
167: // do nothing
168: }
169:
170: /**
171: * Registers the given action with the key binding service
172: * (by calling {@link IActionBarConfigurer#registerGlobalAction(IAction)}),
173: * and adds it to the list of actions to be disposed when the window is closed.
174: * <p>
175: * In order to participate in key bindings, the action must have an action
176: * definition id (aka command id), and a corresponding command extension.
177: * See the <code>org.eclipse.ui.commands</code> extension point documentation
178: * for more details.
179: * </p>
180: *
181: * @param action the action to register
182: *
183: * @see IAction#setActionDefinitionId(String)
184: * @see #disposeAction(IAction)
185: */
186: protected void register(IAction action) {
187: String id = action.getId();
188: Assert.isNotNull(id, "Action must not have null id"); //$NON-NLS-1$
189: getActionBarConfigurer().registerGlobalAction(action);
190: actions.put(id, action);
191: }
192:
193: /**
194: * Returns the action with the given id, or <code>null</code> if not found.
195: *
196: * @param id the action id
197: * @return the action with the given id, or <code>null</code> if not found
198: * @see IAction#getId()
199: */
200: protected IAction getAction(String id) {
201: return (IAction) actions.get(id);
202: }
203:
204: /**
205: * Fills the menu bar with the main menus for the window.
206: * <p>
207: * The default implementation does nothing.
208: * Subclasses may override.
209: * </p>
210: *
211: * @param menuBar the menu manager for the menu bar
212: */
213: protected void fillMenuBar(IMenuManager menuBar) {
214: // do nothing
215: }
216:
217: /**
218: * Fills the cool bar with the main toolbars for the window.
219: * <p>
220: * The default implementation does nothing.
221: * Subclasses may override.
222: * </p>
223: *
224: * @param coolBar the cool bar manager
225: */
226: protected void fillCoolBar(ICoolBarManager coolBar) {
227: // do nothing
228: }
229:
230: /**
231: * Fills the status line with the main status line contributions
232: * for the window.
233: * <p>
234: * The default implementation does nothing.
235: * Subclasses may override.
236: * </p>
237: *
238: * @param statusLine the status line manager
239: */
240: protected void fillStatusLine(IStatusLineManager statusLine) {
241: // do nothing
242: }
243:
244: /**
245: * Returns whether the menu with the given id is an application menu of the
246: * given window. This is used during OLE "in place" editing. Application
247: * menus should be preserved during menu merging. All other menus may be
248: * removed from the window.
249: * <p>
250: * The default implementation returns false. Subclasses may override.
251: * </p>
252: *
253: * @param menuId the menu id
254: * @return <code>true</code> for application menus, and <code>false</code>
255: * for part-specific menus
256: */
257: public boolean isApplicationMenu(String menuId) {
258: // default: not an application menu
259: return false;
260: }
261:
262: /**
263: * Disposes this action bar advisor.
264: * Called when the window is being closed.
265: * This should dispose any allocated resources and remove any added listeners.
266: * <p>
267: * The default implementation calls <code>disposeActions()</code>.
268: * Subclasses may extend.
269: * </p>
270: */
271: public void dispose() {
272: disposeActions();
273: }
274:
275: /**
276: * Disposes all actions added via <code>register(IAction)</code>
277: * using <code>disposeAction(IAction)</code>.
278: */
279: protected void disposeActions() {
280: for (Iterator i = actions.values().iterator(); i.hasNext();) {
281: IAction action = (IAction) i.next();
282: disposeAction(action);
283: }
284: actions.clear();
285: }
286:
287: /**
288: * Disposes the given action.
289: * <p>
290: * The default implementation checks whether the action is an instance
291: * of <code>ActionFactory.IWorkbenchAction</code> and calls its
292: * <code>dispose()</code> method if so.
293: * Subclasses may extend.
294: * </p>
295: *
296: * @param action the action to dispose
297: */
298: protected void disposeAction(IAction action) {
299: if (action instanceof ActionFactory.IWorkbenchAction) {
300: ((ActionFactory.IWorkbenchAction) action).dispose();
301: }
302: }
303:
304: /**
305: * Saves arbitrary application-specific state information
306: * for this action bar advisor.
307: * <p>
308: * The default implementation simply returns an OK status.
309: * Subclasses may extend or override.
310: * </p>
311: *
312: * @param memento the memento in which to save the advisor's state
313: * @return a status object indicating whether the save was successful
314: * @since 3.1
315: */
316: public IStatus saveState(IMemento memento) {
317: return Status.OK_STATUS;
318: }
319:
320: /**
321: * Restores arbitrary application-specific state information
322: * for this action bar advisor.
323: * <p>
324: * The default implementation simply returns an OK status.
325: * Subclasses may extend or override.
326: * </p>
327: *
328: * @param memento the memento from which to restore the advisor's state
329: * @return a status object indicating whether the restore was successful
330: * @since 3.1
331: */
332: public IStatus restoreState(IMemento memento) {
333: return Status.OK_STATUS;
334: }
335:
336: }
|