2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.openapi.actionSystem.impl;
18 import com.intellij.ide.DataManager;
19 import com.intellij.openapi.actionSystem.*;
20 import com.intellij.openapi.actionSystem.ex.ActionButtonLook;
21 import com.intellij.openapi.actionSystem.ex.ActionManagerEx;
22 import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
23 import com.intellij.openapi.actionSystem.ex.ActionUtil;
24 import com.intellij.openapi.util.IconLoader;
25 import com.intellij.util.ui.EmptyIcon;
26 import org.jetbrains.annotations.NonNls;
27 import org.jetbrains.annotations.NotNull;
31 import java.awt.event.MouseEvent;
32 import java.beans.PropertyChangeEvent;
33 import java.beans.PropertyChangeListener;
35 public class ActionButton extends JComponent implements ActionButtonComponent {
36 private static final Insets ICON_INSETS = new Insets(2, 2, 2, 2);
38 private static final Icon ourEmptyIcon = new EmptyIcon(18, 18);
40 private Dimension myMinimumButtonSize;
41 private PropertyChangeListener myActionButtonSynchronizer;
42 private Icon myDisabledIcon;
44 protected final Presentation myPresentation;
45 protected final AnAction myAction;
46 private final String myPlace;
47 private ActionButtonLook myLook = ActionButtonLook.IDEA_LOOK;
48 private boolean myMouseDown;
49 private boolean myRollover;
50 private static boolean ourGlobalMouseDown = false;
52 private static final Icon myDropdownIcon = IconLoader.getIcon("/general/dropdown.png");
54 private boolean myNoIconsInPopup = false;
57 final AnAction action,
58 final Presentation presentation,
60 @NotNull final Dimension minimumSize
62 setMinimumButtonSize(minimumSize);
66 myPresentation = presentation;
69 enableEvents(AWTEvent.MOUSE_EVENT_MASK);
70 myMinimumButtonSize = minimumSize;
73 public void setNoIconsInPopup(boolean noIconsInPopup) {
74 myNoIconsInPopup = noIconsInPopup;
77 public void setMinimumButtonSize(@NotNull Dimension size) {
78 myMinimumButtonSize = size;
81 public void paintChildren(Graphics g) {}
83 public int getPopState() {
84 if (myAction instanceof Toggleable) {
85 Boolean selected = (Boolean)myPresentation.getClientProperty(Toggleable.SELECTED_PROPERTY);
86 boolean flag1 = selected != null && selected.booleanValue();
87 return getPopState(flag1);
90 return getPopState(false);
94 protected boolean isButtonEnabled() {
95 return myPresentation.isEnabled();
98 private void onMousePresenceChanged(boolean setInfo) {
99 ActionMenu.showDescriptionInStatusBar(setInfo, this, myPresentation.getDescription());
102 public void click() {
103 performAction(new MouseEvent(this, MouseEvent.MOUSE_CLICKED, System.currentTimeMillis(), 0, 0, 0, 1, false));
106 private void performAction(MouseEvent e) {
107 AnActionEvent event = new AnActionEvent(
111 ActionManager.getInstance(),
114 if (!ActionUtil.lastUpdateAndCheckDumb(myAction, event, false)) {
118 if (isButtonEnabled()) {
119 final ActionManagerEx manager = ActionManagerEx.getInstanceEx();
120 final DataContext dataContext = event.getDataContext();
121 manager.fireBeforeActionPerformed(myAction, dataContext, event);
122 Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
123 if (component != null && !component.isShowing()) {
126 actionPerfomed(event);
127 manager.queueActionPerformedEvent(myAction, dataContext, event);
131 protected DataContext getDataContext() {
132 return DataManager.getInstance().getDataContext();
135 private void actionPerfomed(final AnActionEvent event) {
136 if (myAction instanceof ActionGroup && !(myAction instanceof CustomComponentAction) && ((ActionGroup)myAction).isPopup()) {
137 final ActionManagerImpl am = (ActionManagerImpl)ActionManager.getInstance();
138 ActionPopupMenu popupMenu = am.createActionPopupMenu(event.getPlace(), (ActionGroup)myAction, new MenuItemPresentationFactory() {
140 protected Presentation processPresentation(Presentation presentation) {
141 if (myNoIconsInPopup) {
142 presentation.setIcon(null);
143 presentation.setHoveredIcon(null);
148 popupMenu.getComponent().show(this, getWidth(), 0);
150 myAction.actionPerformed(event);
154 public void removeNotify() {
155 if (myActionButtonSynchronizer != null) {
156 myPresentation.removePropertyChangeListener(myActionButtonSynchronizer);
157 myActionButtonSynchronizer = null;
159 super.removeNotify();
162 public void addNotify() {
164 if (myActionButtonSynchronizer == null) {
165 myActionButtonSynchronizer = new ActionButtonSynchronizer();
166 myPresentation.addPropertyChangeListener(myActionButtonSynchronizer);
172 public void setToolTipText(String s) {
173 String tooltipText = AnAction.createTooltipText(s, myAction);
174 super.setToolTipText(tooltipText.length() > 0 ? tooltipText : null);
177 public Dimension getPreferredSize() {
178 Icon icon = getIcon();
180 icon.getIconWidth() < myMinimumButtonSize.width &&
181 icon.getIconHeight() < myMinimumButtonSize.height
183 return myMinimumButtonSize;
186 return new Dimension(
187 icon.getIconWidth() + ICON_INSETS.left + ICON_INSETS.right,
188 icon.getIconHeight() + ICON_INSETS.top + ICON_INSETS.bottom
193 public Dimension getMinimumSize() {
194 return getPreferredSize();
198 * @return button's icon. Icon depends on action's state. It means that the method returns
199 * disabled icon if action is disabled. If the action's icon is <code>null</code> then it returns
202 protected Icon getIcon() {
203 Icon icon = isButtonEnabled() ? myIcon : myDisabledIcon;
210 private void updateIcon() {
211 myIcon = myPresentation.getIcon();
212 if (myPresentation.getDisabledIcon() != null) { // set disabled icon if it is specified
213 myDisabledIcon = myPresentation.getDisabledIcon();
216 myDisabledIcon = IconLoader.getDisabledIcon(myIcon);
220 private void setDisabledIcon(Icon icon) {
221 myDisabledIcon = icon;
224 void updateToolTipText() {
225 String text = myPresentation.getText();
226 setToolTipText(text == null ? myPresentation.getDescription() : text);
229 public void paintComponent(Graphics g) {
230 super.paintComponent(g);
234 if (myAction instanceof ActionGroup && ((ActionGroup)myAction).isPopup()) {
239 if (getPopState() == PUSHED) {
244 myDropdownIcon.paintIcon(this, g, x, y);
248 protected void paintButtonLook(Graphics g) {
249 ActionButtonLook look = getButtonLook();
250 look.paintBackground(g, this);
251 look.paintIcon(g, this, getIcon());
252 look.paintBorder(g, this);
255 protected ActionButtonLook getButtonLook() {
259 public void setLook(ActionButtonLook look) {
264 myLook = ActionButtonLook.IDEA_LOOK;
269 protected void processMouseEvent(MouseEvent e) {
270 super.processMouseEvent(e);
271 if (e.isConsumed()) return;
272 boolean skipPress = e.isMetaDown() || e.getButton() != MouseEvent.BUTTON1;
274 case MouseEvent.MOUSE_PRESSED:
275 if (skipPress || !isButtonEnabled()) return;
277 ourGlobalMouseDown = true;
281 case MouseEvent.MOUSE_RELEASED:
282 if (skipPress || !isButtonEnabled()) return;
284 ourGlobalMouseDown = false;
291 case MouseEvent.MOUSE_ENTERED:
292 if (!myMouseDown && ourGlobalMouseDown) break;
295 onMousePresenceChanged(true);
298 case MouseEvent.MOUSE_EXITED:
300 if (!myMouseDown && ourGlobalMouseDown) break;
302 onMousePresenceChanged(false);
307 private int getPopState(boolean isPushed) {
308 if (isPushed || myRollover && myMouseDown && isButtonEnabled()) {
312 return !myRollover || !isButtonEnabled() ? NORMAL : POPPED;
316 public AnAction getAction() {
320 private class ActionButtonSynchronizer implements PropertyChangeListener {
321 @NonNls protected static final String SELECTED_PROPERTY_NAME = "selected";
323 public void propertyChange(PropertyChangeEvent e) {
324 String propertyName = e.getPropertyName();
325 if (Presentation.PROP_TEXT.equals(propertyName)) {
328 else if (Presentation.PROP_ENABLED.equals(propertyName)) {
331 else if (Presentation.PROP_ICON.equals(propertyName)) {
335 else if (Presentation.PROP_DISABLED_ICON.equals(propertyName)) {
336 setDisabledIcon(myPresentation.getDisabledIcon());
339 else if (Presentation.PROP_VISIBLE.equals(propertyName)) {
341 else if (SELECTED_PROPERTY_NAME.equals(propertyName)) {