Package com.dci.intellij.dbn.common.ui

Source Code of com.dci.intellij.dbn.common.ui.ValueSelector$ValueSelectorBorder

package com.dci.intellij.dbn.common.ui;

import com.dci.intellij.dbn.common.Icons;
import com.dci.intellij.dbn.common.util.NamingUtil;
import com.intellij.ide.DataManager;
import com.intellij.ide.ui.laf.darcula.DarculaUIUtil;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.ui.GraphicsConfig;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.ListPopup;
import com.intellij.openapi.util.Condition;
import com.intellij.ui.Gray;
import com.intellij.ui.JBColor;
import com.intellij.ui.RoundedLineBorder;
import com.intellij.util.IconUtil;
import com.intellij.util.ui.UIUtil;

import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.SwingConstants;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.LineBorder;
import javax.swing.plaf.InsetsUIResource;
import javax.swing.plaf.UIResource;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.List;

public abstract class ValueSelector<T extends Presentable> extends JPanel{
    public static Color COMBO_BOX_BACKGROUND = UIUtil.getTextFieldBackground();
    private T selectedValue;
    private JLabel label;
    private JPanel innerPanel;
    private Icon icon;
    private String text;
    private boolean isComboBox;
    private boolean isEnabled = true;
    private boolean isActive = false;
    private boolean isShowingPopup = false;

    private Border focusBorder;
    private Border defaultBorder;
    private Border insideBorder;
    private Border insideBorderFocused;

    private List<T> values;


    public ValueSelector(String text, T preselectedValue, boolean isComboBox) {
        this(null, text, preselectedValue, isComboBox);
    }

    public ValueSelector(Icon icon, String text, T preselectedValue, boolean isComboBox) {
        super(new BorderLayout());
        this.icon = icon;
        this.text = text;
        this.isComboBox = isComboBox;

        setBorder(new EmptyBorder(3, 0, 3, 0));

        if (isComboBox) {
            defaultBorder = new ValueSelectorBorder(this);
            focusBorder = defaultBorder;
        } else {
            insideBorder = new EmptyBorder(3, 5, 3, 5);
            insideBorderFocused = new EmptyBorder(2, 4, 2, 4);

            defaultBorder = insideBorder;
            focusBorder = new CompoundBorder(new RoundedLineBorder(new JBColor(Gray._190, Gray._55), 3), insideBorderFocused);
        }

        label = new JLabel(text, cropIcon(icon), SwingConstants.LEFT);
        label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        label.addMouseListener(mouseListener);

        innerPanel = new JPanel(new BorderLayout());
        innerPanel.setBorder(defaultBorder);
        innerPanel.add(label, BorderLayout.WEST);
        innerPanel.addMouseListener(mouseListener);
        innerPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
        add(innerPanel, BorderLayout.CENTER);


        if (isComboBox) {
            selectedValue = preselectedValue;
            if (selectedValue == null) {
                label.setIcon(cropIcon(icon));
                label.setText(text);
            } else {
                label.setIcon(cropIcon(selectedValue.getIcon()));
                label.setText(selectedValue.getName());
            }

            innerPanel.setBackground(COMBO_BOX_BACKGROUND);
            innerPanel.add(new JLabel(Icons.COMMON_ARROW_DOWN), BorderLayout.EAST);

            innerPanel.setFocusable(true);
            innerPanel.addFocusListener(new FocusListener() {
                @Override
                public void focusGained(FocusEvent e) {
                    isActive = true;
                    updateUI();
                }

                @Override
                public void focusLost(FocusEvent e) {
                    if (!isShowingPopup) {
                        isActive = false;
                        updateUI();
                    }
                }
            });

            innerPanel.addKeyListener(new KeyAdapter() {
                @Override
                public void keyPressed(KeyEvent e) {
                    if (e.getKeyCode() == 38) {//UP
                        selectPrevious();
                        e.consume();
                    } else if (e.getKeyCode() == 40) { // DOWN
                        selectNext();
                        e.consume();
                    } else if (e.getKeyCode() == KeyEvent.VK_ENTER ) {
                        showPopup();
                        e.consume();
                    }

                }
            });

        }

        int minWidth = 0;
        FontMetrics fontMetrics = label.getFontMetrics(label.getFont());
        int height = fontMetrics.getHeight();
        for (T presentable : getAllPossibleValues()) {
            int width = fontMetrics.stringWidth(presentable.getName());
            if (presentable.getIcon() != null) {
                width = width + 16;
            }
            minWidth = Math.max(minWidth, width);
        }
        int width = fontMetrics.stringWidth(text);
        if (icon != null) {
            width = width + 16;
        }
        minWidth = Math.max(minWidth, width);
        label.setPreferredSize(new Dimension(minWidth + 6, height));
    }

    private Icon cropIcon(Icon icon) {
        return icon == null ? null : IconUtil.cropIcon(icon, 16, 16);
    }

    public boolean isEnabled() {
        return isEnabled;
    }

    public void setEnabled(boolean isEnabled) {
        this.isEnabled = isEnabled;

        label.setCursor(isEnabled ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR): Cursor.getDefaultCursor());
        innerPanel.setCursor(isEnabled ? Cursor.getPredefinedCursor(Cursor.HAND_CURSOR) : Cursor.getDefaultCursor());

        innerPanel.setBackground(isComboBox && isEnabled ? COMBO_BOX_BACKGROUND : UIUtil.getPanelBackground());
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
    }
    private MouseListener mouseListener = new MouseAdapter() {
        @Override
        public void mouseEntered(MouseEvent e) {
            if (!isShowingPopup && !isComboBox) {
                innerPanel.setBorder(focusBorder);
                innerPanel.setBackground(new JBColor(Gray._210, Gray._75));
                updateUI();
            }
        }

        @Override
        public void mouseExited(MouseEvent e) {
            if (!isShowingPopup && !isComboBox) {
                innerPanel.setBorder(defaultBorder);
                //innerPanel.setBorder(new EmptyBorder(21 - icon.getIconHeight(), 6, 21 - icon.getIconHeight(), 6));
                innerPanel.setBackground(isComboBox ? COMBO_BOX_BACKGROUND : UIUtil.getPanelBackground());
                updateUI();
            }
        }

        @Override
        public void mousePressed(MouseEvent e) {
            if (isEnabled && !isShowingPopup) {
                innerPanel.grabFocus();
                showPopup();
            }
        }

        @Override
        public void mouseMoved(MouseEvent e) {
            super.mouseMoved(e);
        }
    };

    private void showPopup() {
        isShowingPopup = true;
        innerPanel.setCursor(Cursor.getDefaultCursor());
        label.setCursor(Cursor.getDefaultCursor());
        DefaultActionGroup actionGroup = new DefaultActionGroup();
        for (T value : getValues()) {
            actionGroup.add(new SelectValueAction(value));
        }
        ListPopup popup = JBPopupFactory.getInstance().createActionGroupPopup(
                null,
                actionGroup,
                DataManager.getInstance().getDataContext(this),
                false,
                false,
                false,
                new Runnable() {
                    @Override
                    public void run() {
                        isShowingPopup = false;
                        innerPanel.setBorder(defaultBorder);
                        innerPanel.setBackground(isComboBox ? COMBO_BOX_BACKGROUND : UIUtil.getPanelBackground());
                        innerPanel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                        label.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
                        updateUI();
                    }
                }, 10, new Condition<AnAction>() {
                    @Override
                    public boolean value(AnAction anAction) {
                        if (anAction instanceof ValueSelector.SelectValueAction) {
                            SelectValueAction action = (SelectValueAction) anAction;
                            return action.value.equals(selectedValue);
                        }
                        return false;
                    }
                });

        Point locationOnScreen = getLocationOnScreen();
        Point location = new Point(
                (int) (locationOnScreen.getX()),
                (int) locationOnScreen.getY() + getHeight() + 1);
        popup.showInScreenCoordinates(this, location);
        isActive = true;
    }

    public class SelectValueAction extends AnAction {
        private T value;

        public SelectValueAction(T value) {
            super(NamingUtil.enhanceUnderscoresForDisplay(value.getName()), null, value.getIcon());
            this.value = value;
        }

        public void actionPerformed(AnActionEvent e) {
            selectValue(value);
        }

    }

    public T getSelectedValue() {
        return selectedValue;
    }

    public final List<T> getValues() {
        if (values == null) {
            values = loadValues();
        }
        return values;
    }

    protected abstract List<T> loadValues();

    protected List<T> getAllPossibleValues() {
        return getValues();
    }

    public void resetValues() {
        values = null;
    }

    public abstract void valueSelected(T value);

    private void selectValue(T value) {
        if (isComboBox) {
            selectedValue = value;
            if (selectedValue == null) {
                label.setIcon(cropIcon(icon));
                label.setText(text);
            } else {
                label.setIcon(cropIcon(selectedValue.getIcon()));
                label.setText(selectedValue.getName());
            }
        }
        valueSelected(value);
    }

    public void selectNext() {
        if (isComboBox && selectedValue != null) {
            List<T> values = getValues();
            int index = values.indexOf(selectedValue);
            if (index < values.size() - 1) {
                T nextValue = values.get(index + 1);
                selectValue(nextValue);
            }
        }
    }

    public void selectPrevious() {
        if (isComboBox && selectedValue != null) {
            List<T> values = getValues();
            int index = values.indexOf(selectedValue);
            if (index > 0) {
                T previousValue = values.get(index - 1);
                selectValue(previousValue);
            }
        }
    }

    public class ValueSelectorBorder implements Border, UIResource {
        ValueSelector<T> valueSelector;

        public ValueSelectorBorder(ValueSelector<T> valueSelector) {
            this.valueSelector = valueSelector;
        }

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

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

        @Override
        public void paintBorder(Component c, Graphics g2, int x, int y, int width, int height) {
            Graphics2D g = ((Graphics2D)g2);
            final GraphicsConfig config = new GraphicsConfig(g);
            g.translate(x, y);

            if (UIUtil.isUnderDarcula() || UIUtil.isUnderIntelliJLaF()) {
                if (valueSelector.isActive) {
                    DarculaUIUtil.paintFocusRing(g, 2, 2, width - 4, height - 4);
                } else {
                    boolean editable = valueSelector.isEnabled;
                    g.setColor(getBorderColor(c.isEnabled() && editable));
                    g.drawRect(1, 1, width-2, height-2);
                    g.setColor(UIUtil.getPanelBackground());
                    g.drawRect(0, 0, width, height);

                }
            } else {
                Border textFieldBorder = UIUtil.getTextFieldBorder();
                if (textFieldBorder instanceof LineBorder) {
                    LineBorder lineBorder = (LineBorder) textFieldBorder;
                    g.setColor(lineBorder.getLineColor());
                } else {
                    g.setColor(UIUtil.getBorderColor());
                }
                g.drawRect(1, 1, width - 3, height - 3);
                g.setColor(UIUtil.getPanelBackground());
                g.drawRect(0, 0, width-1, height-1);
            }
            g.translate(-x, -y);
            config.restore();

        }

        private Color getBorderColor(boolean enabled) {
            if (UIUtil.isUnderDarcula()) {
                return enabled ? Gray._100 : Gray._83;
            }
            // disabled color is the same as ComboBox's border has
            return enabled ? Gray._100 : Gray._150;
        }
    }
}
TOP

Related Classes of com.dci.intellij.dbn.common.ui.ValueSelector$ValueSelectorBorder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.