blob: 0e66bb65fc8341b7b4a9c6cc2f285d3013a1efe5 [file] [log] [blame]
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.android.tools.idea.configurations;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.*;
import com.intellij.openapi.actionSystem.ex.CustomComponentAction;
import com.intellij.openapi.keymap.KeymapUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.ColorUtil;
import com.intellij.ui.IdeBorderFactory;
import com.intellij.util.ui.GraphicsUtil;
import com.intellij.util.ui.UIUtil;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import static java.awt.GridBagConstraints.BOTH;
import static java.awt.GridBagConstraints.CENTER;
/**
* Simplified version of {@link FlatComboAction}, which works as a push button
* rather than a combo button. This is needed such that this button looks and
* behaves similar to the {@link FlatComboAction} buttons in the same toolbar;
* in particular, same text font (which is not the case for the default IntelliJ
* toolbar action ({@link com.intellij.openapi.actionSystem.impl.ActionButtonWithText})
* when you show both icons and text), same roll over gradient, same border,
* same baseline alignment, etc.
*/
public abstract class FlatAction extends AnAction implements CustomComponentAction {
private DataContext myDataContext;
protected FlatAction() {
}
@Override
public JComponent createCustomComponent(Presentation presentation) {
JPanel panel = new JPanel(new GridBagLayout());
FlatButton button = createComboBoxButton(presentation);
panel.add(button, new GridBagConstraints(0, 0, 1, 1, 1, 1, CENTER, BOTH, new Insets(0, 0, 0, 0), 0, 0));
return panel;
}
protected FlatButton createComboBoxButton(Presentation presentation) {
return new FlatButton(presentation);
}
@Override
public void update(AnActionEvent e) {
super.update(e);
myDataContext = e.getDataContext();
}
protected class FlatButton extends JButton {
private final Presentation myPresentation;
private PropertyChangeListener myButtonSynchronizer;
private boolean myMouseInside = false;
public FlatButton(Presentation presentation) {
myPresentation = presentation;
setModel(new DefaultButtonModel());
setHorizontalAlignment(LEFT);
setFocusable(false);
Insets margins = getMargin();
setMargin(new Insets(margins.top, 2, margins.bottom, 2));
setBorder(IdeBorderFactory.createEmptyBorder(0, 2, 0, 2));
if (!UIUtil.isUnderGTKLookAndFeel()) {
setFont(UIUtil.getLabelFont().deriveFont(11.0f));
}
addActionListener(new ActionListener() {
@Override
public void actionPerformed(final ActionEvent e) {
IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(new Runnable() {
@Override
public void run() {
AnActionEvent event = AnActionEvent.createFromInputEvent(FlatAction.this, null, ActionPlaces.EDITOR_TOOLBAR);
FlatAction.this.actionPerformed(event);
}
});
}
});
addMouseListener(new MouseAdapter() {
@Override
public void mouseEntered(MouseEvent e) {
myMouseInside = true;
repaint();
}
@Override
public void mouseExited(MouseEvent e) {
myMouseInside = false;
repaint();
}
@Override
public void mousePressed(final MouseEvent e) {
if (SwingUtilities.isLeftMouseButton(e)) {
e.consume();
doClick();
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
});
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(MouseEvent e) {
mouseMoved(
new MouseEvent(e.getComponent(), MouseEvent.MOUSE_MOVED, e.getWhen(), e.getModifiers(), e.getX(), e.getY(), e.getClickCount(),
e.isPopupTrigger(), e.getButton()));
}
@Override
public void mouseMoved(MouseEvent e) {
}
});
}
protected DataContext getDataContext() {
return myDataContext == null ? DataManager.getInstance().getDataContext(this) : myDataContext;
}
@Override
public void removeNotify() {
if (myButtonSynchronizer != null) {
myPresentation.removePropertyChangeListener(myButtonSynchronizer);
myButtonSynchronizer = null;
}
super.removeNotify();
}
@Override
public void addNotify() {
super.addNotify();
if (myButtonSynchronizer == null) {
myButtonSynchronizer = new MyButtonSynchronizer();
myPresentation.addPropertyChangeListener(myButtonSynchronizer);
}
initButton();
}
private void initButton() {
setIcon(myPresentation.getIcon());
setEnabled(myPresentation.isEnabled());
setText(myPresentation.getText());
updateTooltipText(myPresentation.getDescription());
updateButtonSize();
}
private void updateTooltipText(String description) {
String tooltip = KeymapUtil.createTooltipText(description, FlatAction.this);
setToolTipText(!tooltip.isEmpty() ? tooltip : null);
}
@Override
public void updateUI() {
super.updateUI();
if (!UIUtil.isUnderGTKLookAndFeel()) {
setBorder(UIUtil.getButtonBorder());
}
}
private class MyButtonSynchronizer implements PropertyChangeListener {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String propertyName = evt.getPropertyName();
if (Presentation.PROP_TEXT.equals(propertyName)) {
setText((String)evt.getNewValue());
updateButtonSize();
}
else if (Presentation.PROP_DESCRIPTION.equals(propertyName)) {
updateTooltipText((String)evt.getNewValue());
}
else if (Presentation.PROP_ICON.equals(propertyName)) {
setIcon((Icon)evt.getNewValue());
updateButtonSize();
}
else if (Presentation.PROP_ENABLED.equals(propertyName)) {
setEnabled(((Boolean)evt.getNewValue()).booleanValue());
}
}
}
@Override
public Insets getInsets() {
final Insets insets = super.getInsets();
return new Insets(insets.top, insets.left, insets.bottom, insets.right);
}
@Override
public boolean isOpaque() {
return false;
}
@Override
public Dimension getPreferredSize() {
final boolean isEmpty = getIcon() == null && StringUtil.isEmpty(getText());
int width = isEmpty ? 10 : super.getPreferredSize().width;
// See ActionToolBarImpl: For a horizontal toolbar, the preferred height is 24
return new Dimension(width, 24);
}
@Override
public void paint(Graphics g) {
GraphicsUtil.setupAntialiasing(g);
boolean textEmpty = StringUtil.isEmpty(getText());
final Dimension size = getSize();
{
final Graphics2D g2 = (Graphics2D)g;
Color controlColor = UIUtil.getControlColor();
if (UIUtil.isUnderIntelliJLaF()) {
controlColor = getParent().getBackground();
}
g2.setColor(controlColor);
final int w = getWidth();
final int h = getHeight();
if (getModel().isArmed() && getModel().isPressed()) {
g2.setPaint(new GradientPaint(0, 0, controlColor, 0, h, ColorUtil.shift(controlColor, 0.8)));
}
else {
if (myMouseInside) {
g2.setPaint(new GradientPaint(0, 0, ColorUtil.shift(controlColor, 1.1), 0, h,
ColorUtil.shift(controlColor, 0.9)));
}
}
g2.fillRect(1, 1, w - 2, h - 2);
GraphicsUtil.setupAntialiasing(g2);
if (myMouseInside) {
if (!UIUtil.isUnderDarcula()) {
g2.setPaint(new GradientPaint(0, 0, UIUtil.getBorderColor().darker(), 0, h, UIUtil.getBorderColor().darker().darker()));
}
else {
g2.setPaint(new GradientPaint(0, 0, ColorUtil.shift(controlColor, 1.4), 0, h,
ColorUtil.shift(controlColor, 1.5)));
}
g2.drawRect(0, 0, w - 1, h - 1);
}
final Icon icon = getIcon();
int x = 2;
if (icon != null) {
icon.paintIcon(null, g, x, (size.height - icon.getIconHeight()) / 2 - 1);
x += icon.getIconWidth() + 1;
}
if (!textEmpty) {
final Font font = getFont();
g2.setFont(font);
g2.setColor(UIManager.getColor("Panel.foreground"));
g2.drawString(getText(), x, (size.height + font.getSize()) / 2 - 1);
}
}
g.setPaintMode();
}
protected void updateButtonSize() {
invalidate();
repaint();
}
}
}