blob: d1c19df6e3ada9d4b0970408fe04985350a03bc9 [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ui;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.ui.awt.RelativePoint;
import com.intellij.util.containers.SmartHashSet;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.Set;
/**
* @author Konstantin Bulenkov
*/
public abstract class AnActionButton extends AnAction implements ShortcutProvider {
private boolean myEnabled = true;
private boolean myVisible = true;
private ShortcutSet myShortcut;
private AnAction myAction = null;
private JComponent myContextComponent;
private Set<AnActionButtonUpdater> myUpdaters;
public AnActionButton(String text) {
super(text);
}
public AnActionButton(String text, String description, @Nullable Icon icon) {
super(text, description, icon);
}
@SuppressWarnings("NullableProblems")
public AnActionButton(String text, Icon icon) {
this(text, null, icon);
}
public AnActionButton() {
}
public static AnActionButton fromAction(final AnAction action) {
final Presentation presentation = action.getTemplatePresentation();
return action instanceof CheckedActionGroup ? new CheckedAnActionButton(presentation, action)
: new AnActionButtonWrapper(presentation, action);
}
public boolean isEnabled() {
return myEnabled;
}
public void setEnabled(boolean enabled) {
myEnabled = enabled;
}
public boolean isVisible() {
return myVisible;
}
public void setVisible(boolean visible) {
myVisible = visible;
}
@Override
public final void update(AnActionEvent e) {
boolean myActionVisible = true;
boolean myActionEnabled = true;
if (myAction != null) {
myAction.update(e);
myActionEnabled = e.getPresentation().isEnabled();
myActionVisible = e.getPresentation().isVisible();
}
boolean enabled = isEnabled() && isContextComponentOk() && myActionEnabled;
if (enabled && myUpdaters != null) {
for (AnActionButtonUpdater updater : myUpdaters) {
if (!updater.isEnabled(e)) {
enabled = false;
break;
}
}
}
e.getPresentation().setEnabled(enabled);
e.getPresentation().setVisible(isVisible() && myActionVisible);
if (enabled) {
updateButton(e);
}
}
public final void addCustomUpdater(@NotNull AnActionButtonUpdater updater) {
if (myUpdaters == null) {
myUpdaters = new SmartHashSet<AnActionButtonUpdater>();
}
myUpdaters.add(updater);
}
public void updateButton(AnActionEvent e) {
final JComponent component = getContextComponent();
e.getPresentation().setEnabled(component != null && component.isShowing() && component.isEnabled());
}
@Override
public ShortcutSet getShortcut() {
return myShortcut;
}
public void setShortcut(ShortcutSet shortcut) {
myShortcut = shortcut;
}
public void setContextComponent(JComponent contextComponent) {
myContextComponent = contextComponent;
}
public JComponent getContextComponent() {
return myContextComponent;
}
public DataContext getDataContext() {
return DataManager.getInstance().getDataContext(getContextComponent());
}
private boolean isContextComponentOk() {
return myContextComponent == null
|| (myContextComponent.isVisible() && UIUtil.getParentOfType(JLayeredPane.class, myContextComponent) != null);
}
public final RelativePoint getPreferredPopupPoint() {
Container c = myContextComponent;
ActionToolbar toolbar = null;
while ((c = c.getParent()) != null) {
if (c instanceof JComponent
&& (toolbar = (ActionToolbar)((JComponent)c).getClientProperty(ActionToolbar.ACTION_TOOLBAR_PROPERTY_KEY)) != null) {
break;
}
}
if (toolbar instanceof JComponent) {
for (Component comp : ((JComponent)toolbar).getComponents()) {
if (comp instanceof ActionButtonComponent) {
if (comp instanceof AnActionHolder) {
if (((AnActionHolder)comp).getAction() == this) {
return new RelativePoint(comp.getParent(), new Point(comp.getX(), comp.getY() + comp.getHeight()));
}
}
}
}
}
return null;
}
public static class CheckedAnActionButton extends AnActionButtonWrapper implements CheckedActionGroup {
private final AnAction myDelegate;
public CheckedAnActionButton(Presentation presentation, AnAction action) {
super(presentation, action);
myDelegate = action;
}
public AnAction getDelegate() {
return myDelegate;
}
}
private static class AnActionButtonWrapper extends AnActionButton {
private final AnAction myAction;
public AnActionButtonWrapper(Presentation presentation, AnAction action) {
super(presentation.getText(), presentation.getDescription(), presentation.getIcon());
myAction = action;
}
@Override
public void actionPerformed(AnActionEvent e) {
myAction.actionPerformed(new AnActionEventWrapper(e, this));
}
@Override
public void updateButton(AnActionEvent e) {
myAction.update(e);
final boolean enabled = e.getPresentation().isEnabled();
final boolean visible = e.getPresentation().isVisible();
if (enabled && visible) {
super.updateButton(e);
}
}
@Override
public boolean isDumbAware() {
return myAction.isDumbAware();
}
}
public static class AnActionEventWrapper extends AnActionEvent {
private final AnActionButton myPeer;
private AnActionEventWrapper(AnActionEvent e, AnActionButton peer) {
super(e.getInputEvent(), e.getDataContext(), e.getPlace(), e.getPresentation(), e.getActionManager(), e.getModifiers());
myPeer = peer;
}
public void showPopup(JBPopup popup) {
popup.show(myPeer.getPreferredPopupPoint());
}
}
}