replaced <code></code> with more concise {@code}
[idea/community.git] / platform / editor-ui-api / src / com / intellij / openapi / actionSystem / AnActionEvent.java
1 /*
2  * Copyright 2000-2017 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.actionSystem;
17
18 import com.intellij.ide.DataManager;
19 import com.intellij.openapi.project.Project;
20 import com.intellij.openapi.util.text.StringUtil;
21 import com.intellij.ui.PlaceProvider;
22 import org.intellij.lang.annotations.JdkConstants;
23 import org.jetbrains.annotations.NonNls;
24 import org.jetbrains.annotations.NotNull;
25 import org.jetbrains.annotations.Nullable;
26
27 import java.awt.event.InputEvent;
28 import java.util.HashMap;
29 import java.util.Map;
30
31 /**
32  * Container for the information necessary to execute or update an {@link AnAction}.
33  *
34  * @see AnAction#actionPerformed(AnActionEvent)
35  * @see AnAction#update(AnActionEvent)
36  */
37
38 public class AnActionEvent implements PlaceProvider<String> {
39   private final InputEvent myInputEvent;
40   @NotNull private final ActionManager myActionManager;
41   @NotNull private final DataContext myDataContext;
42   @NotNull private final String myPlace;
43   @NotNull private final Presentation myPresentation;
44   @JdkConstants.InputEventMask private final int myModifiers;
45   private boolean myWorksInInjected;
46   @NonNls private static final String ourInjectedPrefix = "$injected$.";
47   private static final Map<String, String> ourInjectedIds = new HashMap<>();
48   private final boolean myIsContextMenuAction;
49   private final boolean myIsActionToolbar;
50
51   /**
52    * @throws IllegalArgumentException if {@code dataContext} is {@code null} or
53    * {@code place} is {@code null} or {@code presentation} is {@code null}
54    *
55    * @see ActionManager#getInstance()
56    */
57   public AnActionEvent(InputEvent inputEvent,
58                        @NotNull DataContext dataContext,
59                        @NotNull @NonNls String place,
60                        @NotNull Presentation presentation,
61                        @NotNull ActionManager actionManager,
62                        @JdkConstants.InputEventMask int modifiers) {
63     this(inputEvent, dataContext, place, presentation, actionManager, modifiers, false, false);
64   }
65
66   /**
67    * @throws IllegalArgumentException if {@code dataContext} is {@code null} or
68    * {@code place} is {@code null} or {@code presentation} is {@code null}
69    *
70    * @see ActionManager#getInstance()
71    */
72   public AnActionEvent(InputEvent inputEvent,
73                        @NotNull DataContext dataContext,
74                        @NotNull @NonNls String place,
75                        @NotNull Presentation presentation,
76                        @NotNull ActionManager actionManager,
77                        @JdkConstants.InputEventMask int modifiers,
78                        boolean isContextMenuAction,
79                        boolean isActionToolbar) {
80     // TODO[vova,anton] make this constructor package-private. No one is allowed to create AnActionEvents
81     myInputEvent = inputEvent;
82     myActionManager = actionManager;
83     myDataContext = dataContext;
84     myPlace = place;
85     myPresentation = presentation;
86     myModifiers = modifiers;
87     myIsContextMenuAction = isContextMenuAction;
88     myIsActionToolbar = isActionToolbar;
89   }
90
91
92   @Deprecated
93   @NotNull
94   public static AnActionEvent createFromInputEvent(@NotNull AnAction action, @Nullable InputEvent event, @NotNull String place) {
95     DataContext context = event == null ? DataManager.getInstance().getDataContext() : DataManager.getInstance().getDataContext(event.getComponent());
96     return createFromAnAction(action, event, place, context);
97   }
98
99   @NotNull
100   public static AnActionEvent createFromAnAction(@NotNull AnAction action,
101                                                  @Nullable InputEvent event,
102                                                  @NotNull String place,
103                                                  @NotNull DataContext dataContext) {
104     int modifiers = event == null ? 0 : event.getModifiers();
105     Presentation presentation = action.getTemplatePresentation().clone();
106     AnActionEvent anActionEvent = new AnActionEvent(event, dataContext, place, presentation, ActionManager.getInstance(), modifiers);
107     anActionEvent.setInjectedContext(action.isInInjectedContext());
108     return anActionEvent;
109   }
110
111   @NotNull
112   public static AnActionEvent createFromDataContext(@NotNull String place,
113                                                     @Nullable Presentation presentation,
114                                                     @NotNull DataContext dataContext) {
115     return new AnActionEvent(null, dataContext, place, presentation == null ? new Presentation() : presentation, ActionManager.getInstance(), 0);
116   }
117
118
119   @NotNull
120   public static AnActionEvent createFromInputEvent(@Nullable InputEvent event,
121                                                    @NotNull String place,
122                                                    @NotNull Presentation presentation,
123                                                    @NotNull DataContext dataContext) {
124     return createFromInputEvent(event, place, presentation, dataContext, false, false);
125   }
126
127   @NotNull
128   public static AnActionEvent createFromInputEvent(@Nullable InputEvent event,
129                                                    @NotNull String place,
130                                                    @NotNull Presentation presentation,
131                                                    @NotNull DataContext dataContext,
132                                                    boolean isContextMenuAction,
133                                                    boolean isToolbarAction) {
134     return new AnActionEvent(event, dataContext, place, presentation, ActionManager.getInstance(),
135                              event == null ? 0 : event.getModifiers(), isContextMenuAction, isToolbarAction);
136   }
137
138   /**
139    * Returns the {@code InputEvent} which causes invocation of the action. It might be
140    * {@code KeyEvent}, {@code MouseEvent}.
141    * @return the {@code InputEvent} instance.
142    */
143   public InputEvent getInputEvent() {
144     return myInputEvent;
145   }
146
147   /**
148    * @return Project from the context of this event.
149    */
150   @Nullable
151   public Project getProject() {
152     return getData(CommonDataKeys.PROJECT);
153   }
154
155   @NonNls
156   public static String injectedId(String dataId) {
157     synchronized(ourInjectedIds) {
158       String injected = ourInjectedIds.get(dataId);
159       if (injected == null) {
160         injected = ourInjectedPrefix + dataId;
161         ourInjectedIds.put(dataId, injected);
162       }
163       return injected;
164     }
165   }
166
167   @NonNls
168   public static String uninjectedId(@NotNull String dataId) {
169     return StringUtil.trimStart(dataId, ourInjectedPrefix);
170   }
171
172   public static DataContext getInjectedDataContext(final DataContext context) {
173     return new DataContextWrapper(context) {
174       @Nullable
175       @Override
176       public Object getData(@NonNls String dataId) {
177         Object injected = super.getData(injectedId(dataId));
178         if (injected != null) return injected;
179         return super.getData(dataId);
180       }
181     };
182   }
183
184   /**
185    * Returns the context which allows to retrieve information about the state of IDEA related to
186    * the action invocation (active editor, selection and so on).
187    *
188    * @return the data context instance.
189    */
190   @NotNull
191   public DataContext getDataContext() {
192     return myWorksInInjected ? getInjectedDataContext(myDataContext) : myDataContext;
193   }
194
195   @Nullable
196   public <T> T getData(@NotNull DataKey<T> key) {
197     return getDataContext().getData(key);
198   }
199
200   /**
201    * Returns not null data by a data key. This method assumes that data has been checked for null in AnAction#update method.
202    *<br/><br/>
203    * Example of proper usage:
204    *
205    * <pre>
206    *
207    * public class MyAction extends AnAction {
208    *   public void update(AnActionEvent e) {
209    *     //perform action if and only if EDITOR != null
210    *     boolean enabled = e.getData(CommonDataKeys.EDITOR) != null;
211    *     e.getPresentation.setEnabled(enabled);
212    *   }
213    *
214    *   public void actionPerformed(AnActionEvent e) {
215    *     //if we're here then EDITOR != null
216    *     Document doc = e.getRequiredData(CommonDataKeys.EDITOR).getDocument();
217    *     doSomething(doc);
218    *   }
219    * }
220    *
221    * </pre>
222    */
223   @NotNull
224   public <T> T getRequiredData(@NotNull DataKey<T> key) {
225     T data = getData(key);
226     assert data != null;
227     return data;
228   }
229
230   /**
231    * Returns the identifier of the place in the IDEA user interface from where the action is invoked
232    * or updated.
233    *
234    * @return the place identifier
235    * @see ActionPlaces
236    */
237   @Override
238   @NotNull
239   public String getPlace() {
240     return myPlace;
241   }
242
243   public boolean isActionToolbar() {
244     return myIsActionToolbar;
245   }
246
247   public boolean isContextMenu() {
248     return myIsContextMenuAction;
249   }
250
251   /**
252    * Returns the presentation which represents the action in the place from where it is invoked
253    * or updated.
254    *
255    * @return the presentation instance.
256    */
257   @NotNull
258   public Presentation getPresentation() {
259     return myPresentation;
260   }
261
262   /**
263    * Returns the modifier keys held down during this action event.
264    * @return the modifier keys.
265    */
266   @JdkConstants.InputEventMask
267   public int getModifiers() {
268     return myModifiers;
269   }
270
271   @NotNull
272   public ActionManager getActionManager() {
273     return myActionManager;
274   }
275
276   public void setInjectedContext(boolean worksInInjected) {
277     myWorksInInjected = worksInInjected;
278   }
279
280   public boolean isInInjectedContext() {
281     return myWorksInInjected;
282   }
283
284   public void accept(@NotNull AnActionEventVisitor visitor) {
285     visitor.visitEvent(this);
286   }
287 }