com.intellij.openapi.ui.FixedComboBoxEditor.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.openapi.ui.FixedComboBoxEditor.java

Source

/*
 * Copyright 2000-2017 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.openapi.ui;

import com.intellij.openapi.wm.IdeFocusManager;
import com.intellij.ui.Gray;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
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.lang.reflect.Method;

/**
 * Use this editor if you wish your combobox editor to look good on Macs.
 *
 * User: spLeaner
 */
public class FixedComboBoxEditor implements ComboBoxEditor {
    @NotNull
    private final JBTextField myField = UIUtil.isUnderDefaultMacTheme() ? new MacComboBoxTextField()
            : new JBTextField();
    private Object oldValue;

    @NotNull
    public JBTextField getField() {
        return myField;
    }

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

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

    @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", String.class);
                    newValue = method.invoke(oldValue, myField.getText());
                } catch (Exception ex) {
                    // Fail silently and return the newValue (a String object)
                }
            }
        }
        return newValue;
    }

    @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(JComboBox comboBox) {
        ComboBoxUI ui = comboBox.getUI();
        ComboPopup popup = null;
        if (ui instanceof BasicComboBoxUI) {
            popup = ReflectionUtil.getField(BasicComboBoxUI.class, ui, ComboPopup.class, "popup");
        }

        return popup;
    }

    private class MacComboBoxTextField extends JBTextField implements DocumentListener, FocusListener {
        private MacComboBoxTextField() {
            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");

            addFocusListener(this);
        }

        @Override
        public boolean hasFocus() {
            Container parent = getParent();
            if (parent instanceof ComboBox && ((ComboBox) parent).myPaintingNow) {
                return false; // to disable focus painting around combobox button
            }
            return super.hasFocus();
        }

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

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

        private void repaintCombobox() {
            Container parent = getParent();

            if (parent == null || parent instanceof JComponent
                    && Boolean.TRUE == ((JComponent) parent).getClientProperty("JComboBox.isTableCellEditor"))
                return;

            Container grandParent = parent.getParent();
            if (grandParent != null) {
                grandParent.repaint();
            }
        }

        @Override
        public Color getBackground() {
            if (UIUtil.isUnderDefaultMacTheme()) {
                Container parent = getParent();
                if (parent != null && !parent.isEnabled()) {
                    return Gray.xF8;
                }
            }
            return super.getBackground();
        }

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

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

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

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

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

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

            String s = myField.getText();

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