Package com.dci.intellij.dbn.data.editor.ui

Source Code of com.dci.intellij.dbn.data.editor.ui.ValuesListPopupProviderForm$ListModel

package com.dci.intellij.dbn.data.editor.ui;

import com.dci.intellij.dbn.common.filter.Filter;
import com.dci.intellij.dbn.common.list.FiltrableList;
import com.dci.intellij.dbn.common.thread.ConditionalLaterInvocator;
import com.dci.intellij.dbn.common.ui.DBNColor;
import com.dci.intellij.dbn.common.util.StringUtil;
import com.intellij.openapi.actionSystem.IdeActions;
import com.intellij.openapi.ui.popup.JBPopup;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.ui.popup.PopupChooserBuilder;
import org.jetbrains.annotations.NotNull;

import javax.swing.AbstractListModel;
import javax.swing.JComponent;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JTextField;
import java.awt.Color;
import java.awt.Rectangle;
import java.awt.event.FocusEvent;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class ValuesListPopupProviderForm extends TextFieldPopupProviderForm {
    public static final DBNColor BACKGROUND_COLOR = new DBNColor(
            new Color(0xEBF4FE),
            new Color(0x3c3f41));
    private ListPopupValuesProvider valuesProvider;
    private List<String> valuesList;
    private ListModel listModel;
    private JList list;
    private JPanel mainPanel;
    private boolean useDynamicFiltering;

    public ValuesListPopupProviderForm(TextFieldWithPopup textField, @NotNull ListPopupValuesProvider valuesProvider, boolean useDynamicFiltering) {
        super(textField, false);
        this.valuesProvider = valuesProvider;
        this.useDynamicFiltering = useDynamicFiltering;
        list.setBackground(BACKGROUND_COLOR);
    }

    public ValuesListPopupProviderForm(TextFieldWithPopup textField, @NotNull List<String> valuesList, boolean useDynamicFiltering) {
        super(textField, false);
        this.valuesList = valuesList;
        this.useDynamicFiltering = useDynamicFiltering;
        list.setBackground(BACKGROUND_COLOR);
    }

    public JComponent getComponent() {
        return mainPanel;
    }

    public JBPopup createPopup() {
        List<String> possibleValues = valuesProvider == null ? valuesList : valuesProvider.getValues();
        if (possibleValues.size() > 0) {
            Collections.sort(possibleValues);
            listModel = useDynamicFiltering ? new ListModel(new DynamicFilter(), possibleValues) : new ListModel(possibleValues);
            list.setModel(listModel);
            list.addMouseListener(mouseListener);
            PopupChooserBuilder popupBuilder = JBPopupFactory.getInstance().createListPopupBuilder(list);
            popupBuilder.setRequestFocus(false);

            String text = getTextField().getText();
            if (StringUtil.isEmptyOrSpaces(text)) {
                list.clearSelection();
                list.scrollRectToVisible(list.getCellBounds(0, 0));
            } else {
                list.setSelectedValue(text, true);
            }
            return popupBuilder.createPopup();
        } else {
            return null;
        }
    }

    public void handleKeyPressedEvent(KeyEvent e) {
        assert isShowingPopup();
        int keyCode = e.getKeyCode();
        if (keyCode == 38) { // UP
            int selectedIndex = list.getSelectedIndex();
            if (selectedIndex > 0) {
                scrollToIndex(selectedIndex - 1);
            }
            e.consume();
        } else if (keyCode == 40) { // DOWN
            int selectedIndex = list.getSelectedIndex();
            if (selectedIndex < list.getModel().getSize() - 1) {
                scrollToIndex(selectedIndex + 1);
            }
            e.consume();
        } else if (keyCode == 33) { // PAGE UP
            int selectedIndex = list.getSelectedIndex();
            if (selectedIndex > 0) {
                int scrollCount = list.getVisibleRowCount() == 0 ? list.getModel().getSize() : list.getVisibleRowCount();
                int newIndex = Math.max(selectedIndex - scrollCount, 0);
                scrollToIndex(newIndex);
            }
            e.consume();
        } else if (keyCode == 34) { // PAGE DOWN
            int selectedIndex = list.getSelectedIndex();
            if (selectedIndex < list.getModel().getSize() - 1) {
                int scrollCount = list.getVisibleRowCount() == 0 ? list.getModel().getSize() : list.getVisibleRowCount();
                int newIndex = Math.min(selectedIndex + scrollCount, list.getModel().getSize() - 1);
                scrollToIndex(newIndex);
            }
            e.consume();
        } else if (keyCode == 37 || keyCode == 39 || keyCode == 35 || keyCode == 36) { // RIGHT or LEFT or END or HOME
            updateList();
        } else if (keyCode == 10 || keyCode == 9) { // ENTER or TAB
            String selectedValue = (String) list.getSelectedValue();
            if (selectedValue != null) {
                hidePopup();
                JTextField textField = getTextField();
                textField.setText(selectedValue);
                textField.requestFocus();
            }
            e.consume();
        } else if (keyCode == 27) { //ESC
            hidePopup();
            e.consume();
        } else {
            updateList();
        }
    }

    public void handleKeyReleasedEvent(KeyEvent e) {
        if (e.getKeyCode() == 36 || e.getKeyCode() == 35) { // HOME or END
            updateList();
        }
    }

    public void handleFocusLostEvent(FocusEvent e) {
        if (getPopup().getContent().getParent().getParent().getParent().getParent() != e.getOppositeComponent()) {
            hidePopup();
        }
    }

    public String getKeyShortcutName() {
        return IdeActions.ACTION_CODE_COMPLETION;
    }

    public String getDescription() {
        return "Possible Values List";
    }

    @Override
    public TextFieldPopupType getPopupType() {
        return TextFieldPopupType.VALUE_LIST;
    }

    private void scrollToIndex(int index) {
        list.setSelectedIndex(index);
        Rectangle rectangle = list.getCellBounds(index, index);
        if (rectangle != null) {
            list.scrollRectToVisible(rectangle);
        }
    }

    private void updateList() {
        new ConditionalLaterInvocator() {
            public void execute() {
                if (listModel.isFiltrable()) {
                    int index = list.getSelectedIndex();
                    listModel.notifyContentChanged();
                    if (index > listModel.getSize() - 1) {
                        scrollToIndex(listModel.getSize() - 1);
                    }
                } else {
                    String text = getTextField().getText();
                    for (int i=0; i<listModel.getElements().size(); i++ ) {
                        String element = listModel.getElements().get(i);
                        if (element.startsWith(text)) {
                            scrollToIndex(i);
                            break;
                        }
                    }

                }
            }
        }.start();
    }

    private class DynamicFilter extends Filter<String> {
        public boolean accepts(String string) {
            if (getEditorComponent().isSelected()) return true;

            JTextField textField = getTextField();
            int caretOffset = textField.getCaretPosition();
            if (caretOffset == 0) {
                return true;
            } else {
                if (caretOffset > string.length()) {
                    return false;
                } else {
                    String textFieldValue = textField.getText().substring(0, caretOffset).toLowerCase();
                    String listValue = string.substring(0, caretOffset).toLowerCase();
                    return textFieldValue.equals(listValue);
                }
            }
        }
    }


    /******************************************************
     *                  MouseListener                     *
     ******************************************************/
    private MouseListener mouseListener = new MouseAdapter() {

        @Override
        public void mousePressed(MouseEvent event) {
            if (!event.isConsumed() && event.getButton() == MouseEvent.BUTTON1) {
                String selectedValue = (String) list.getSelectedValue();
                if (selectedValue != null) {
                    hidePopup();
                    JTextField textField = getTextField();
                    textField.setText(selectedValue);
                    textField.requestFocus();
                    event.consume();
                }

            }
        }

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

        @Override
        public void mouseClicked(MouseEvent event) {
        }

    };

    /******************************************************
     *                    ListModel                       *
     ******************************************************/
    class ListModel extends AbstractListModel {
        List<String> elements;

        ListModel(Filter<String> filter, Collection<String> elements) {
            this.elements = new FiltrableList<String>(filter);
            this.elements.addAll(elements);
        }

        public List<String> getElements() {
            return elements;
        }

        ListModel(Collection<String> elements) {
            this.elements = new ArrayList<String>(elements);
        }

        public boolean isFiltrable() {
            return elements instanceof FiltrableList;
        }

        public int getSize() {
            return elements.size();
        }

        public Object getElementAt(int index) {
            return index == -1 ? null : elements.get(index);
        }

        void setVariants(Collection<String> collection) {
            elements.clear();
            elements.addAll(collection);
            notifyContentChanged();
        }

        void notifyContentChanged() {
            fireContentsChanged(this, 0, elements.size());
        }

        void clear() {
            elements.clear();
        }
    }

    public void dispose() {
        super.dispose();
    }

}
TOP

Related Classes of com.dci.intellij.dbn.data.editor.ui.ValuesListPopupProviderForm$ListModel

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.