com.android.tools.idea.gradle.editor.ui.GradleEditorComboBoxEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.android.tools.idea.gradle.editor.ui.GradleEditorComboBoxEditor.java

Source

/*
 * Copyright (C) 2015 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.gradle.editor.ui;

import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.FixedComboBoxEditor;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.Gray;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.plaf.ComboBoxUI;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * This is a copy-paste from {@link FixedComboBoxEditor} with the difference that it uses gradle editor background color for painting
 * border ({@link MacComboBoxEditorBorder#paintBorder(Component, Graphics, int, int, int, int)})
 */
public class GradleEditorComboBoxEditor implements ComboBoxEditor {
    public static final Border EDITOR_BORDER = new MacComboBoxEditorBorder(false);
    public static final Border DISABLED_EDITOR_BORDER = new MacComboBoxEditorBorder(true);

    private JTextField myField;
    private Object oldValue;

    public GradleEditorComboBoxEditor() {
        if (SystemInfo.isMac && UIUtil.isUnderAquaLookAndFeel()) {
            myField = new MacComboBoxTextField();
        } else {
            myField = new JTextField();
            myField.setBorder(null);
        }
    }

    protected JTextField getField() {
        return myField;
    }

    @Override
    public Component getEditorComponent() {
        return myField;
    }

    @SuppressWarnings("RedundantArrayCreation")
    @Override
    public Object getItem() {
        Object newValue = myField.getText();
        if (oldValue != null && !(oldValue instanceof String)) {
            // The original value is not a string. Should return the value in it's
            // original type.
            if (newValue.equals(oldValue.toString())) {
                return oldValue;
            } else {
                // Must take the value from the editor and get the value and cast it to the new type.
                Class<?> cls = oldValue.getClass();
                try {
                    Method method = cls.getMethod("valueOf", new Class[] { String.class });
                    newValue = method.invoke(oldValue, new Object[] { myField.getText() });
                } catch (Exception ex) {
                    // Fail silently and return the newValue (a String object)
                }
            }
        }
        return newValue;
    }

    @Override
    public void setItem(Object anObject) {
        if (anObject != null) {
            myField.setText(anObject.toString());
            oldValue = anObject;
        } else {
            myField.setText("");
        }
    }

    @Override
    public void selectAll() {
        myField.selectAll();
        IdeFocusManager.getGlobalInstance().doWhenFocusSettlesDown(() -> {
            IdeFocusManager.getGlobalInstance().requestFocus(myField, true);
        });
    }

    @Override
    public void addActionListener(ActionListener l) {
    }

    @Override
    public void removeActionListener(ActionListener l) {
    }

    @Nullable
    private static ComboPopup getComboboxPopup(final JComboBox comboBox) {
        final ComboBoxUI ui = comboBox.getUI();
        ComboPopup popup = null;
        if (ui instanceof BasicComboBoxUI) {
            try {
                final Field popupField = BasicComboBoxUI.class.getDeclaredField("popup");
                popupField.setAccessible(true);
                popup = (ComboPopup) popupField.get(ui);
            } catch (NoSuchFieldException e1) {
                popup = null;
            } catch (IllegalAccessException e1) {
                popup = null;
            }
        }

        return popup;
    }

    public static class MacComboBoxEditorBorder implements Border {

        private boolean myDisabled;

        public MacComboBoxEditorBorder(final boolean disabled) {
            myDisabled = disabled;
        }

        @Override
        public void paintBorder(final Component c, final Graphics g, final int x, final int y, final int width,
                final int height) {
            Color topColor;
            Color secondTopColor;
            Color leftRightColor;
            Color bottomColor;

            if (myDisabled) {
                topColor = Gray._200;
                secondTopColor = Gray._250;
                leftRightColor = Gray._205;
                bottomColor = Gray._220;
            } else {
                topColor = Gray._150;
                secondTopColor = Gray._230;
                leftRightColor = Gray._175;
                bottomColor = Gray._200;
            }

            int _y = y + MacUIUtil.MAC_COMBO_BORDER_V_OFFSET;

            g.setColor(topColor);
            g.drawLine(x + 3, _y + 3, x + width - 1, _y + 3);

            g.setColor(secondTopColor);
            g.drawLine(x + 3, _y + 4, x + width - 1, _y + 4);

            g.setColor(leftRightColor);
            g.drawLine(x + 3, _y + 4, x + 3, _y + height - 4);
            g.drawLine(x + width - 1, _y + 4, x + width - 1, _y + height - 4);

            g.setColor(bottomColor);
            g.drawLine(x + 4, _y + height - 4, x + width - 2, _y + height - 4);

            g.setColor(GradleEditorUiConstants.BACKGROUND_COLOR);

            g.fillRect(x, y, width, 3 + (SystemInfo.isMacOSLion ? 1 : 0));
            g.fillRect(x, _y, 3, height);
            g.fillRect(x, _y + height - 3, width, 3);
        }

        @Override
        public Insets getBorderInsets(final Component c) {
            return new Insets(6, 6, 4, 3);
        }

        @Override
        public boolean isBorderOpaque() {
            return true;
        }
    }

    private class MacComboBoxTextField extends JTextField implements DocumentListener, FocusListener {
        private MacComboBoxTextField() {
            setBorder(isEnabled() ? EDITOR_BORDER : DISABLED_EDITOR_BORDER);
            //setFont(UIUtil.getListFont());

            final InputMap inputMap = getInputMap();

            inputMap.put(KeyStroke.getKeyStroke("DOWN"), "aquaSelectNext");
            inputMap.put(KeyStroke.getKeyStroke("KP_DOWN"), "aquaSelectNext");
            inputMap.put(KeyStroke.getKeyStroke("UP"), "aquaSelectPrevious");
            inputMap.put(KeyStroke.getKeyStroke("KP_UP"), "aquaSelectPrevious");

            inputMap.put(KeyStroke.getKeyStroke("HOME"), "aquaSelectHome");
            inputMap.put(KeyStroke.getKeyStroke("END"), "aquaSelectEnd");
            inputMap.put(KeyStroke.getKeyStroke("PAGE_UP"), "aquaSelectPageUp");
            inputMap.put(KeyStroke.getKeyStroke("PAGE_DOWN"), "aquaSelectPageDown");

            inputMap.put(KeyStroke.getKeyStroke("ENTER"), "aquaEnterPressed");
            inputMap.put(KeyStroke.getKeyStroke("SPACE"), "aquaSpacePressed");

            //getActionMap().put("macEnterPressed", macEnterPressedAction);
            //getDocument().addDocumentListener(this);

            addPropertyChangeListener(new PropertyChangeListener() {
                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if ("enabled".equals(evt.getPropertyName())) {
                        setBorder(Boolean.TRUE.equals(evt.getNewValue()) ? EDITOR_BORDER : DISABLED_EDITOR_BORDER);
                        repaint();
                    }
                }
            });

            addFocusListener(this);
        }

        @Override
        public boolean hasFocus() {
            final Container parent = getParent();
            if (parent instanceof ComboBox) {
                try {
                    Field field = parent.getClass().getDeclaredField("myPaintingNow");
                    field.setAccessible(true);
                    if (field.get(parent) == Boolean.TRUE) {
                        return false; // to disable focus painting around combobox button
                    }
                } catch (Exception ignore) {
                }
            }
            return super.hasFocus();
        }

        @Override
        public void focusGained(FocusEvent e) {
            repaintCombobox();
        }

        private void repaintCombobox() {
            final Container parent = getParent();
            if (parent == null)
                return;
            if (UIUtil.isClientPropertyTrue(parent, "JComboBox.isTableCellEditor"))
                return;
            final Container grandParent = parent.getParent();
            if (grandParent != null) {
                grandParent.repaint();
            }
        }

        @Override
        public void focusLost(FocusEvent e) {
            repaintCombobox();
        }

        @Override
        public Dimension getMinimumSize() {
            final Dimension minimumSize = super.getMinimumSize();
            return new Dimension(minimumSize.width, minimumSize.height + 2);
        }

        @Override
        public Dimension getPreferredSize() {
            return getMinimumSize();
        }

        @Override
        public void setBounds(final int x, final int y, final int width, final int height) {
            UIUtil.setComboBoxEditorBounds(x, y, width, height, this);
        }

        @Override
        public void insertUpdate(DocumentEvent e) {
            textChanged();
        }

        @Override
        public void removeUpdate(DocumentEvent e) {
            textChanged();
        }

        @Override
        public void changedUpdate(DocumentEvent e) {
            textChanged();
        }

        private void textChanged() {
            final Container ancestor = SwingUtilities.getAncestorOfClass(JComboBox.class, this);
            if (ancestor == null || !ancestor.isVisible())
                return;

            final JComboBox comboBox = (JComboBox) ancestor;
            if (!comboBox.isPopupVisible())
                return;

            final ComboPopup popup = getComboboxPopup(comboBox);
            if (popup == null)
                return;

            String s = myField.getText();

            final ListModel listmodel = comboBox.getModel();
            int i = listmodel.getSize();
            if (s.length() > 0) {
                for (int j = 0; j < i; j++) {
                    Object obj = listmodel.getElementAt(j);
                    if (obj == null)
                        continue;

                    String s1 = obj.toString();
                    if (s1 != null && (s1.startsWith(s) || s1.equals(s))) {
                        popup.getList().setSelectedIndex(j);
                        return;
                    }
                }
            }

            popup.getList().clearSelection();
        }
    }
}