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