/* * 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(); } } }