cc.arduino.contributions.ui.InstallerJDialog.java Source code

Java tutorial

Introduction

Here is the source code for cc.arduino.contributions.ui.InstallerJDialog.java

Source

/*
 * This file is part of Arduino.
 *
 * Copyright 2015 Arduino LLC (http://www.arduino.cc/)
 *
 * Arduino is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 * As a special exception, you may use this file as part of a free software
 * library without restriction.  Specifically, if other files instantiate
 * templates or use macros or inline functions from this file, or you compile
 * this file and link it with other files to produce an executable, this
 * file does not by itself cause the resulting executable to be covered by
 * the GNU General Public License.  This exception does not however
 * invalidate any other reasons why the executable file might be covered by
 * the GNU General Public License.
 */
package cc.arduino.contributions.ui;

import cc.arduino.contributions.packages.ui.ContributionIndexTableModel;
import cc.arduino.contributions.ui.listeners.AbstractKeyListener;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Collections2;
import processing.app.Base;
import processing.app.Theme;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.WindowEvent;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;

import static cc.arduino.contributions.packages.ui.ContributionIndexTableModel.DESCRIPTION_COL;
import static processing.app.I18n._;

public abstract class InstallerJDialog<T> extends JDialog {

    // Toolbar on top of the window:
    // - Categories drop-down menu
    protected final JComboBox categoryChooser;
    // - Search text-field
    protected final FilterJTextField filterField;
    protected final JPanel filtersContainer;
    // Currently selected category and filters
    protected Predicate<T> categoryFilter;
    protected String[] filters;
    protected final String noConnectionErrorMessage;

    // Real contribution table
    protected JTable contribTable;
    // Model behind the table
    protected FilteredAbstractTableModel<T> contribModel;

    abstract protected FilteredAbstractTableModel createContribModel();

    abstract protected InstallerTableCell createCellRenderer();

    abstract protected InstallerTableCell createCellEditor();

    // Bottom:
    // - Progress bar
    protected final ProgressJProgressBar progressBar;
    protected final Box progressBox;
    protected final Box errorMessageBox;
    private final JLabel errorMessage;

    public InstallerJDialog(Frame parent, String title, ModalityType applicationModal,
            String noConnectionErrorMessage) {
        super(parent, title, applicationModal);
        this.noConnectionErrorMessage = noConnectionErrorMessage;

        setResizable(true);

        Container pane = getContentPane();
        pane.setLayout(new BorderLayout());

        {
            categoryChooser = new JComboBox();
            categoryChooser.setMaximumRowCount(20);
            categoryChooser.setEnabled(false);

            filterField = new FilterJTextField(_("Filter your search...")) {
                @Override
                protected void onFilter(String[] _filters) {
                    filters = _filters;
                    if (contribTable.getCellEditor() != null) {
                        contribTable.getCellEditor().stopCellEditing();
                    }
                    updateIndexFilter(filters, categoryFilter);
                }
            };

            filtersContainer = new JPanel();
            filtersContainer.setLayout(new BoxLayout(filtersContainer, BoxLayout.X_AXIS));
            filtersContainer.add(Box.createHorizontalStrut(5));
            filtersContainer.add(new JLabel(_("Type")));
            filtersContainer.add(Box.createHorizontalStrut(5));
            filtersContainer.add(categoryChooser);
            filtersContainer.add(Box.createHorizontalStrut(5));
            filtersContainer.add(filterField);
            filtersContainer.setBorder(new EmptyBorder(7, 7, 7, 7));
            pane.add(filtersContainer, BorderLayout.NORTH);
        }

        contribModel = createContribModel();
        contribTable = new JTable(contribModel);
        contribTable.setTableHeader(null);
        contribTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        contribTable.setColumnSelectionAllowed(false);
        contribTable.setDragEnabled(false);
        contribTable.setIntercellSpacing(new Dimension(0, 1));
        contribTable.setShowVerticalLines(false);
        contribTable.setSelectionBackground(Theme.getColor("status.notice.bgcolor"));
        contribTable.addKeyListener(new AbstractKeyListener() {

            @Override
            public void keyReleased(KeyEvent keyEvent) {
                if (keyEvent.getKeyCode() != KeyEvent.VK_DOWN && keyEvent.getKeyCode() != KeyEvent.VK_UP) {
                    return;
                }

                if (!contribTable.isEnabled()) {
                    return;
                }

                contribTable.editCellAt(contribTable.getSelectedRow(), contribTable.getSelectedColumn());
            }
        });

        {
            TableColumnModel tcm = contribTable.getColumnModel();
            TableColumn col = tcm.getColumn(DESCRIPTION_COL);
            col.setCellRenderer(createCellRenderer());
            col.setCellEditor(createCellEditor());
            col.setResizable(true);
        }

        {
            JScrollPane scrollPane = new JScrollPane();
            scrollPane.setViewportView(contribTable);
            scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
            scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            scrollPane.getVerticalScrollBar().setUnitIncrement(7);
            pane.add(scrollPane, BorderLayout.CENTER);
        }

        pane.add(Box.createHorizontalStrut(10), BorderLayout.WEST);
        pane.add(Box.createHorizontalStrut(10), BorderLayout.EAST);

        progressBar = new ProgressJProgressBar();
        progressBar.setStringPainted(true);
        progressBar.setString(" ");
        progressBar.setVisible(true);

        errorMessage = new JLabel("");
        errorMessage.setForeground(Color.RED);

        {
            JButton cancelButton = new JButton(_("Cancel"));
            cancelButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    onCancelPressed();
                }
            });

            progressBox = Box.createHorizontalBox();
            progressBox.add(progressBar);
            progressBox.add(Box.createHorizontalStrut(5));
            progressBox.add(cancelButton);

            JButton dismissErrorMessageButton = new JButton(_("OK"));
            dismissErrorMessageButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent arg0) {
                    clearErrorMessage();
                }
            });

            errorMessageBox = Box.createHorizontalBox();
            errorMessageBox.add(Box.createHorizontalGlue());
            errorMessageBox.add(errorMessage);
            errorMessageBox.add(Box.createHorizontalGlue());
            errorMessageBox.add(dismissErrorMessageButton);
            errorMessageBox.setVisible(false);
        }

        {
            JPanel progressPanel = new JPanel();
            progressPanel.setBorder(new EmptyBorder(7, 7, 7, 7));
            progressPanel.setLayout(new BoxLayout(progressPanel, BoxLayout.Y_AXIS));
            progressPanel.add(progressBox);
            progressPanel.add(errorMessageBox);
            pane.add(progressPanel, BorderLayout.SOUTH);
        }
        setProgressVisible(false, "");

        setMinimumSize(new Dimension(800, 450));

        setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);

        Base.registerWindowCloseKeys(getRootPane(), new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                InstallerJDialog.this
                        .dispatchEvent(new WindowEvent(InstallerJDialog.this, WindowEvent.WINDOW_CLOSING));
            }
        });

        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                onUpdatePressed();
            }
        });
    }

    public void updateIndexFilter(String[] filters, Predicate<T>... additionalFilters) {
        Collection<Predicate<T>> notNullAdditionalFilters = Collections2.filter(Arrays.asList(additionalFilters),
                Predicates.notNull());
        contribModel.updateIndexFilter(filters,
                notNullAdditionalFilters.toArray(new Predicate[notNullAdditionalFilters.size()]));
    }

    public void setErrorMessage(String message) {
        errorMessage.setText("<html><body>" + message + "</body></html>");
        errorMessageBox.setVisible(true);
    }

    public void clearErrorMessage() {
        errorMessage.setText("");
        errorMessageBox.setVisible(false);
    }

    public void setProgressVisible(boolean visible, String status) {
        if (visible) {
            setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
        } else {
            setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        }
        progressBox.setVisible(visible);

        filterField.setEnabled(!visible);
        categoryChooser.setEnabled(!visible);
        contribTable.setEnabled(!visible);
        errorMessageBox.setVisible(false);
        if (contribTable.getCellEditor() != null) {
            ((InstallerTableCell) contribTable.getCellEditor()).setEnabled(!visible);
            ((InstallerTableCell) contribTable.getCellEditor()).setStatus(status);
        }
    }

    protected final ActionListener categoryChooserActionListener = new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent event) {
            DropdownItem<T> selected = (DropdownItem<T>) categoryChooser.getSelectedItem();
            if (categoryFilter == null || !categoryFilter.equals(selected)) {
                categoryFilter = selected.getFilterPredicate();
                if (contribTable.getCellEditor() != null) {
                    contribTable.getCellEditor().stopCellEditing();
                }
                updateIndexFilter(filters, categoryFilter);
            }
        }
    };

    /**
     * Action performed when the Cancel button is pressed.
     */
    protected void onCancelPressed() {
        clearErrorMessage();
    }

    /**
     * Action performed when the "Update List" button is pressed.
     */
    protected void onUpdatePressed() {
        clearErrorMessage();
    }

}