1/*******************************************************************************
2 * Copyright (c) 2011 Google, Inc.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 *    Google, Inc. - initial API and implementation
10 *******************************************************************************/
11package org.eclipse.wb.internal.core.utils.binding.editors.controls;
12
13import com.google.common.collect.Lists;
14
15import org.eclipse.core.commands.AbstractHandler;
16import org.eclipse.core.commands.ExecutionEvent;
17import org.eclipse.core.commands.ExecutionException;
18import org.eclipse.core.commands.IHandler;
19import org.eclipse.core.expressions.EvaluationResult;
20import org.eclipse.core.expressions.Expression;
21import org.eclipse.core.expressions.ExpressionInfo;
22import org.eclipse.core.expressions.IEvaluationContext;
23import org.eclipse.core.runtime.CoreException;
24import org.eclipse.swt.events.DisposeEvent;
25import org.eclipse.swt.events.DisposeListener;
26import org.eclipse.swt.events.FocusEvent;
27import org.eclipse.swt.events.FocusListener;
28import org.eclipse.swt.widgets.Control;
29import org.eclipse.ui.ISources;
30import org.eclipse.ui.PlatformUI;
31import org.eclipse.ui.handlers.IHandlerActivation;
32import org.eclipse.ui.handlers.IHandlerService;
33import org.eclipse.ui.texteditor.IWorkbenchActionDefinitionIds;
34
35import java.util.List;
36
37/**
38 * Manager for installing/unistalling global handlers for {@link Control} actions commands.
39 *
40 * @author sablin_aa
41 * @author mitin_aa
42 */
43public abstract class AbstractControlActionsManager {
44  @SuppressWarnings("deprecation")
45  protected final Object[] COMMAND_HANDLER_IDS = new Object[]{
46      IWorkbenchActionDefinitionIds.COPY,
47      IWorkbenchActionDefinitionIds.CUT,
48      IWorkbenchActionDefinitionIds.PASTE,
49      IWorkbenchActionDefinitionIds.DELETE,
50      IWorkbenchActionDefinitionIds.SELECT_ALL,
51      IWorkbenchActionDefinitionIds.UNDO,
52      IWorkbenchActionDefinitionIds.REDO};
53  ////////////////////////////////////////////////////////////////////////////
54  //
55  // Constructor
56  //
57  ////////////////////////////////////////////////////////////////////////////
58  protected final Control m_control;
59  private boolean m_active = false;
60
61  public AbstractControlActionsManager(final Control control) {
62    m_control = control;
63    m_control.addFocusListener(new FocusListener() {
64      @Override
65    public void focusGained(FocusEvent e) {
66        activateHandlers();
67        m_active = true;
68      }
69
70      @Override
71    public void focusLost(FocusEvent e) {
72        deactivateHandlers();
73        m_active = false;
74      }
75    });
76    m_control.addDisposeListener(new DisposeListener() {
77      @Override
78    public void widgetDisposed(DisposeEvent e) {
79        if (m_active) {
80          // deactivate on dispose
81          deactivateHandlers();
82        }
83      }
84    });
85  }
86
87  ////////////////////////////////////////////////////////////////////////////
88  //
89  // Handlers
90  //
91  ////////////////////////////////////////////////////////////////////////////
92  protected static final IHandler EMPTY_HANDLER = new AbstractHandler() {
93    @Override
94    public Object execute(ExecutionEvent event) throws ExecutionException {
95      // do nothing
96      return null;
97    }
98
99    @Override
100    public boolean isEnabled() {
101      // of course, it is enabled ;)
102      return true;
103    }
104
105    @Override
106    public boolean isHandled() {
107      // we do not handle the actions; since action not handled, its' underlying SWT event
108      // would not be filtered by workbench, so it get a chance to be handled by SWT code
109      // or to be passed to the OS; see WorkbenchKeyboard.press() method.
110      return false;
111    }
112  };
113
114  /**
115   * @returns the global handler service.
116   */
117  public static IHandlerService getHandlerService() {
118    return (IHandlerService) PlatformUI.getWorkbench().getService(IHandlerService.class);
119  }
120
121  /**
122   * Activates the handlers for list of commands (see COMMAND_HANDLERS) with:<br>
123   * 1. The empty handler (except 'selectAll'), so underlying SWT event wouldn't be filtered by the
124   * workbench;<br>
125   * 2. Highest priority {@link Expression}, so this handler has a chance to be set.
126   */
127  protected void activateHandlers() {
128    IHandlerService service = getHandlerService();
129    for (int i = 0; i < COMMAND_HANDLER_IDS.length; ++i) {
130      String actionName = (String) COMMAND_HANDLER_IDS[i];
131      IHandler handler = getHandlerFor(actionName);
132      activateHandler(actionName, service, handler, new Expression() {
133        @Override
134        public EvaluationResult evaluate(IEvaluationContext context) throws CoreException {
135          return EvaluationResult.TRUE;
136        }
137
138        @Override
139        public void collectExpressionInfo(ExpressionInfo info) {
140          // get the highest priority
141          // note, if someone else has such priority, there will be key-binding conflicts logged.
142          info.markSystemPropertyAccessed();
143          info.markDefaultVariableAccessed();
144          info.addVariableNameAccess(ISources.ACTIVE_MENU_NAME);
145        }
146      });
147    }
148  }
149
150  protected IHandler getHandlerFor(String actionName) {
151    return EMPTY_HANDLER;
152  }
153
154  /**
155   * Activates handler and stores it into a collection for further deactivation.
156   */
157  private final List<IHandlerActivation> m_activations = Lists.newLinkedList();
158
159  private void activateHandler(String actionName,
160      IHandlerService service,
161      IHandler handler,
162      Expression highPriorityExpression) {
163    // activate handler and store it into a collection for further deactivation
164    m_activations.add(service.activateHandler(actionName, handler, highPriorityExpression));
165  }
166
167  /**
168   * Deactivates all handlers and clears handlers collection.
169   */
170  protected void deactivateHandlers() {
171    getHandlerService().deactivateHandlers(m_activations);
172    m_activations.clear();
173  }
174}
175