2316acea6651f78d9bcef6366700665b94c5ce9b
[idea/community.git] / platform / editor-ui-api / src / com / intellij / openapi / actionSystem / ActionGroup.java
1 /*
2  * Copyright 2000-2015 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.util.ReflectionUtil;
19 import org.jetbrains.annotations.NonNls;
20 import org.jetbrains.annotations.NotNull;
21 import org.jetbrains.annotations.Nullable;
22
23 import javax.swing.*;
24 import java.beans.PropertyChangeListener;
25 import java.beans.PropertyChangeSupport;
26 import java.util.HashSet;
27 import java.util.Set;
28
29 /**
30  * Represents a group of actions.
31  *
32  * @see com.intellij.openapi.actionSystem.DefaultActionGroup
33  * @see com.intellij.openapi.actionSystem.ComputableActionGroup
34  */
35 public abstract class ActionGroup extends AnAction {
36   private boolean myPopup;
37   private final PropertyChangeSupport myChangeSupport = new PropertyChangeSupport(this);
38   public static final ActionGroup EMPTY_GROUP = new ActionGroup() {
39     @NotNull
40     @Override
41     public AnAction[] getChildren(@Nullable AnActionEvent e) {
42       return EMPTY_ARRAY;
43     }
44   };
45
46   private Set<AnAction> mySecondaryActions;
47
48   /**
49    * The actual value is a Boolean.
50    */
51   @NonNls public static final String PROP_POPUP = "popup";
52
53   private Boolean myDumbAware;
54
55   /**
56    * Creates a new <code>ActionGroup</code> with shortName set to <code>null</code> and
57    * popup set to false.
58    */
59   public ActionGroup(){
60     this(null, false);
61   }
62
63   /**
64    * Creates a new <code>ActionGroup</code> with the specified shortName
65    * and popup.
66    *
67    * @param shortName Text that represents a short name for this action group
68    *
69    * @param popup <code>true</code> if this group is a popup, <code>false</code>
70    *  otherwise
71    */
72   public ActionGroup(String shortName, boolean popup){
73     super(shortName);
74     setPopup(popup);
75   }
76
77   public ActionGroup(String text, String description, Icon icon) {
78     super(text, description, icon);
79   }
80
81   /**
82    * This method can be called in popup menus if {@link #canBePerformed(DataContext)} is true
83    */
84   @Override
85   public void actionPerformed(AnActionEvent e){
86   }
87
88   /**
89    * @return true if {@link #actionPerformed(AnActionEvent)} should be called
90    */
91   public boolean canBePerformed(DataContext context) {
92     return false;
93   }
94
95   /**
96    * Returns the type of the group.
97    *
98    * @return <code>true</code> if the group is a popup, <code>false</code> otherwise
99    */
100   public boolean isPopup(){
101     return myPopup;
102   }
103
104   /**
105    * Sets the type of the group.
106    *
107    * @param popup If <code>true</code> the group will be shown as a popup in menus
108    */
109   public final void setPopup(boolean popup){
110     boolean oldPopup = myPopup;
111     myPopup = popup;
112     firePropertyChange(PROP_POPUP, oldPopup?Boolean.TRUE:Boolean.FALSE, myPopup?Boolean.TRUE:Boolean.FALSE);
113   }
114
115   public final void addPropertyChangeListener(PropertyChangeListener l){
116     myChangeSupport.addPropertyChangeListener(l);
117   }
118
119   public final void removePropertyChangeListener(PropertyChangeListener l){
120     myChangeSupport.removePropertyChangeListener(l);
121   }
122
123   protected final void firePropertyChange(String propertyName, Object oldValue, Object newValue){
124     myChangeSupport.firePropertyChange(propertyName, oldValue, newValue);
125   }
126
127   /**
128    * Returns the children of the group.
129    *
130    * @return An array representing children of this group. All returned children must be not <code>null</code>.
131    */
132   @NotNull
133   public abstract AnAction[] getChildren(@Nullable AnActionEvent e);
134
135   final void setAsPrimary(AnAction action, boolean isPrimary) {
136     if (isPrimary) {
137       if (mySecondaryActions != null) {
138         mySecondaryActions.remove(action);
139       }
140     } else {
141       if (mySecondaryActions == null) {
142         mySecondaryActions = new HashSet<>();
143       }
144
145       mySecondaryActions.add(action);
146     }
147   }
148
149   public final boolean isPrimary(AnAction action) {
150     return mySecondaryActions == null || !mySecondaryActions.contains(action);
151   }
152
153   protected final void replace(AnAction originalAction, AnAction newAction) {
154     if (mySecondaryActions != null) {
155       if (mySecondaryActions.contains(originalAction)) {
156         mySecondaryActions.remove(originalAction);
157         mySecondaryActions.add(newAction);
158       }
159     }
160   }
161
162   @Override
163   public boolean isDumbAware() {
164     if (myDumbAware != null) {
165       return myDumbAware;
166     }
167
168     boolean dumbAware = super.isDumbAware();
169     if (dumbAware) {
170       myDumbAware = Boolean.TRUE;
171     } else {
172       if (myDumbAware == null) {
173         Class<?> declaringClass = ReflectionUtil.getMethodDeclaringClass(getClass(), "update", AnActionEvent.class);
174         myDumbAware = AnAction.class.equals(declaringClass) || ActionGroup.class.equals(declaringClass);
175       }
176     }
177
178     return myDumbAware;
179   }
180
181   public boolean hideIfNoVisibleChildren() {
182     return false;
183   }
184
185   public boolean disableIfNoVisibleChildren() {
186     return true;
187   }
188 }