All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.swing.etable.ColumnSelectionPanel Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 1997-2010 Oracle and/or its affiliates. All rights reserved.
 *
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
 * Other names may be trademarks of their respective owners.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common
 * Development and Distribution License("CDDL") (collectively, the
 * "License"). You may not use this file except in compliance with the
 * License. You can obtain a copy of the License at
 * http://www.netbeans.org/cddl-gplv2.html
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
 * specific language governing permissions and limitations under the
 * License.  When distributing the software, include this License Header
 * Notice in each file and include the License file at
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the GPL Version 2 section of the License file that
 * accompanied this code. If applicable, add the following below the
 * License Header, with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Contributor(s):
 *
 * The Original Software is NetBeans. The Initial Developer of the Original
 * Software is Sun Microsystems, Inc. Portions Copyright 1997-2009 Sun
 * Microsystems, Inc. All Rights Reserved.
 *
 * If you wish your version of this file to be governed by only the CDDL
 * or only the GPL Version 2, indicate your decision by adding
 * "[Contributor] elects to include this software in this distribution
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
 * single choice of license, a recipient has the option to distribute
 * your version of this file under either the CDDL, the GPL Version 2 or
 * to extend the choice of license to its licensees as provided above.
 * However, if you add GPL Version 2 code and therefore, elected the GPL
 * Version 2 license, then the option applies only if the new code is
 * made subject to such option by the copyright holder.
 */
package org.netbeans.swing.etable;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GraphicsConfiguration;
import java.awt.GraphicsEnvironment;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.KeyboardFocusManager;
import java.awt.Rectangle;
import java.awt.Window;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.swing.JCheckBox;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;

/**
 * Panel containing checkboxes for selecting visible columns
 * of a table.
 * @author David Strupl
 */
class ColumnSelectionPanel extends JPanel {

    private static final String COLUMNS_SELECTOR_HINT = "ColumnsSelectorHint"; // NOI18N

    /**
     * Map: ETableColumn --> JCheckBox
     */
    private Map checkBoxes = new HashMap();
    
    /**
     * Model allowing to show/hide columns.
     */
    private ETableColumnModel columnModel;
    
    /** Creates a new instance of ColumnSelectionPanel */
    public ColumnSelectionPanel(ETable table) {
        TableColumnModel colModel = table.getColumnModel();
        if (! (colModel instanceof ETableColumnModel)) {
            return;
        }

        ETableColumnModel etcm = (ETableColumnModel)colModel;
        this.columnModel = etcm;
        List columns = etcm.getAllColumns();
        Collections.sort(columns, ETableColumnComparator.DEFAULT );
        int width = 1; // columns.size() / 10 + 1;

        JPanel p = layoutPanel(columns, width, table);
        Dimension prefSize = p.getPreferredSize();
        final Rectangle screenBounds = getUsableScreenBounds(getCurrentGraphicsConfiguration());
        JScrollPane currentScrollPane;
        JComponent toAdd = null;

        if (prefSize.width > screenBounds.width - 100
            || prefSize.height > screenBounds.height- 100
            ) {
            currentScrollPane = new JScrollPane() {
                @Override
                public Dimension getPreferredSize() {
                    Dimension sz = new Dimension(super.getPreferredSize());
                    if (sz.width > screenBounds.width - 100) {
                        sz.width = screenBounds.width * 3 / 4;
                    }
                    if (sz.height > screenBounds.height - 100)
                        sz.height = screenBounds.height * 3 / 4;
                    return sz;
                }
            };
            currentScrollPane.setViewportView(p);
            toAdd = currentScrollPane;
        } else {
            toAdd = p;
        }

        add(toAdd);
    }
    
    /**
     * Adds checkbox for each ETableColumn contained in the columns parameter.
     */
    @SuppressWarnings("unchecked")
    private JPanel layoutPanel(List columns, int width, ETable table) {
        JPanel toAdd = new JPanel(new GridBagLayout());
        Map displayNameToCheckBox = new HashMap();
        ArrayList displayNames = new ArrayList();
        for (int col = 0; col < columns.size (); col++) {
            ETableColumn etc = (ETableColumn) columns.get (col);
            JCheckBox checkBox = new JCheckBox();
            Object transformed = table.transformValue (etc);
            String dName;
            if (transformed == etc || transformed == null) {
                dName = etc.getHeaderValue ().toString ();
            } else {
                dName = transformed.toString ();
            }
            checkBox.setText(dName);
            JCheckBox transfCheckBox = (JCheckBox) table.transformValue(checkBox);
            if (transfCheckBox != null) {
                checkBox = transfCheckBox;
            }
            checkBoxes.put(etc, checkBox);
            checkBox.setSelected(! columnModel.isColumnHidden(etc));
            checkBox.setEnabled(etc.isHidingAllowed());
            if (! displayNames.contains(dName)) {
                // the expected case
                displayNameToCheckBox.put(dName, checkBox);
            } else {
                // the same display name is used for more columns - fuj
                ArrayList al = null;
                Object theFirstOne = displayNameToCheckBox.get(dName);
                if (theFirstOne instanceof JCheckBox) {
                    JCheckBox firstCheckBox = (JCheckBox)theFirstOne;
                    al = new ArrayList();
                    al.add(firstCheckBox);
                } else {
                    // already a list there
                    if (theFirstOne instanceof ArrayList) {
                        al = (ArrayList)theFirstOne;
                    } else {
                        throw new IllegalStateException("Wrong object theFirstOne is " + theFirstOne);
                    }
                }
                al.add(checkBox);
                displayNameToCheckBox.put(dName, al);
            }
            displayNames.add(dName);
        }
        String first = displayNames.remove (0);
        Collections.sort(displayNames, Collator.getInstance());
        displayNames.add (0, first);
        int i = 0;
        int j = 0;
        int index = 0;
        int rows = columns.size() / width;
        Object hint = table.transformValue (COLUMNS_SELECTOR_HINT);
        if (hint != null) {
            GridBagConstraints gridBagConstraints = new GridBagConstraints();
            gridBagConstraints.gridx = 0;
            gridBagConstraints.gridy = 0;
            gridBagConstraints.insets = new java.awt.Insets(5, 12, 12, 12);
            gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
            toAdd.add (new JLabel (hint.toString ()), gridBagConstraints);
        }
        for (Iterator it = displayNames.iterator(); it.hasNext(); i++) {
            if (i >= rows) {
                i = 0;
                j++;
            }
            String displayName = it.next();
            Object obj = displayNameToCheckBox.get(displayName);
            JCheckBox checkBox = null;
            if (obj instanceof JCheckBox) {
                checkBox = (JCheckBox)obj;
            } else {
                // in case there are duplicate names we store ArrayLists
                // of JCheckBoxes
                if (obj instanceof ArrayList) {
                    ArrayList al = (ArrayList)obj;
                    if (index >= al.size()) {
                        index = 0;
                    }
                    checkBox = al.get(index++);
                } else {
                    throw new IllegalStateException("Wrong object obj is " + obj);
                }
            }
            GridBagConstraints gridBagConstraints = new GridBagConstraints();
            gridBagConstraints.gridx = j;
            gridBagConstraints.gridy = i + (hint == null ? i : i + 1);
            gridBagConstraints.insets = new java.awt.Insets(0, 12, 0, 12);
            gridBagConstraints.anchor = GridBagConstraints.NORTHWEST;
            gridBagConstraints.weightx = 1;
            toAdd.add(checkBox, gridBagConstraints);
        }
        return toAdd;
    }
    
    /**
     * After the user clicks Ok this method will hide/un-hide the
     * columns according to the selected checkboxes.
     */
    public void changeColumnVisibility() {
        if (columnModel == null) {
            return;
        }
        for (Iterator it = checkBoxes.keySet().iterator(); it.hasNext(); ) {
            ETableColumn etc = (ETableColumn) it.next();
            JCheckBox checkBox = checkBoxes.get (etc);
            columnModel.setColumnHidden(etc,! checkBox.isSelected());
        }
    }
    
    static void showColumnSelectionPopupOrDialog(Component c, final ETable table) {
        if (table.isPopupUsedFromTheCorner()) {
            showColumnSelectionPopup(c, table);
        } else {
            showColumnSelectionDialog(table);
        }
    }
    
    /**
     * Shows the popup allowing to show/hide columns.
     */
    static void showColumnSelectionPopup(Component c, final ETable table) {
        showColumnSelectionPopup(c, 8, 8, table);
    }
    
    /**
     * Shows the popup allowing to show/hide columns.
     */
    @SuppressWarnings("unchecked")
    static void showColumnSelectionPopup(Component c, int posx, int posy, final ETable table) {
        if( !table.isColumnHidingAllowed() )
            return;
        
        JPopupMenu popup = new JPopupMenu();
        TableColumnModel columnModel = table.getColumnModel();
        if (! (columnModel instanceof ETableColumnModel)) {
            return;
        }
        TableColumnSelector tcs = table.getColumnSelector();
        if (tcs != null && !table.isPopupUsedFromTheCorner()) {
            JMenuItem selector = new JMenuItem(table.getSelectVisibleColumnsLabel());
            selector.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showColumnSelectionDialog(table);
                }
            });
            popup.add(selector);
        } else {
            final ETableColumnModel etcm = (ETableColumnModel)columnModel;
            List columns = etcm.getAllColumns();
            Collections.sort(columns, ETableColumnComparator.DEFAULT);
            Map displayNameToCheckBox = new HashMap();
            ArrayList displayNames = new ArrayList();
            for (Iterator it = columns.iterator(); it.hasNext(); ) {
                final ETableColumn etc = (ETableColumn)it.next();
                JCheckBoxMenuItem checkBox = new JCheckBoxMenuItem();
                Object transformed = table.transformValue (etc);
                String dName;
                if (transformed == etc || transformed == null) {
                    dName = etc.getHeaderValue ().toString ();
                } else {
                    dName = transformed.toString ();
                }
                checkBox.setText(dName);
                checkBox = (JCheckBoxMenuItem) table.transformValue (checkBox);
                checkBox.setSelected(! etcm.isColumnHidden(etc));
                checkBox.setEnabled(etc.isHidingAllowed());
                final JCheckBoxMenuItem finalChB = checkBox;
                checkBox.addActionListener(new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent evt) {
                        etcm.setColumnHidden(etc,! finalChB.isSelected());
                        table.updateColumnSelectionMouseListener();
                    }
                });
                if (! displayNames.contains(dName)) {
                    // the expected case
                    displayNameToCheckBox.put(dName, checkBox);
                } else {
                    // the same display name is used for more columns - fuj
                    ArrayList al = null;
                    Object theFirstOne = displayNameToCheckBox.get(dName);
                    if (theFirstOne instanceof JCheckBoxMenuItem) {
                        JCheckBoxMenuItem firstCheckBox = (JCheckBoxMenuItem)theFirstOne;
                        al = new ArrayList();
                        al.add(firstCheckBox);
                    } else {
                        // already a list there
                        if (theFirstOne instanceof ArrayList) {
                            al = (ArrayList)theFirstOne;
                        } else {
                            throw new IllegalStateException("Wrong object theFirstOne is " + theFirstOne);
                        }
                    }
                    al.add(checkBox);
                    displayNameToCheckBox.put(dName, al);
                }
                displayNames.add(dName);
            }
            Collections.sort(displayNames, Collator.getInstance());
            int index = 0;
            for (Iterator it = displayNames.iterator(); it.hasNext(); ) {
                String displayName = it.next();
                Object obj = displayNameToCheckBox.get(displayName);
                JCheckBoxMenuItem checkBox = null;
                if (obj instanceof JCheckBoxMenuItem) {
                    checkBox = (JCheckBoxMenuItem)obj;
                } else {
                    // in case there are duplicate names we store ArrayLists
                    // of JCheckBoxes
                    if (obj instanceof ArrayList) {
                        ArrayList al = (ArrayList)obj;
                        if (index >= al.size()) {
                            index = 0;
                        }
                        checkBox = al.get(index++);
                    } else {
                        throw new IllegalStateException("Wrong object obj is " + obj);
                    }
                }
                popup.add(checkBox);
            }
        }
        popup.show(c, posx, posy);
    }
    
    /**
     * Shows dialog allowing to show/hide columns.
     */
    static void showColumnSelectionDialog(ETable table) {
        if( !table.isColumnHidingAllowed() )
            return;
        TableColumnSelector tcs = table.getColumnSelector();
        if (tcs != null) {
            ETableColumnModel etcm = (ETableColumnModel)table.getColumnModel();
            TableColumnSelector.TreeNode root = etcm.getColumnHierarchyRoot();
            if (root != null) {
                String[] origVisible = getAvailableColumnNames(table, true);
                String[] visibleColumns = tcs.selectVisibleColumns(root, origVisible);
                makeVisibleColumns(table, visibleColumns);
            } else {
                String[] availableColumns = getAvailableColumnNames(table, false);
                String[] origVisible = getAvailableColumnNames(table, true);
                String[] visibleColumns = tcs.selectVisibleColumns(availableColumns, origVisible);
                makeVisibleColumns(table, visibleColumns);
            }
            return;
        }
        // The default behaviour:
        ColumnSelectionPanel panel = new ColumnSelectionPanel(table);
        int res = JOptionPane.showConfirmDialog(null, panel, table.getSelectVisibleColumnsLabel(), JOptionPane.OK_CANCEL_OPTION);
        if (res == JOptionPane.OK_OPTION) {
            panel.changeColumnVisibility();
            table.updateColumnSelectionMouseListener();
        }
    }

    /**
     * This method is called after the user made a selection. Applies the
     * changes to the visible column for the given table.
     */
    private static void makeVisibleColumns(ETable table, String[] visibleColumns) {
        HashSet visible = new HashSet(Arrays.asList(visibleColumns));
        TableColumnModel columnModel = table.getColumnModel();
        if (! (columnModel instanceof ETableColumnModel)) {
            return;
        }
        final ETableColumnModel etcm = (ETableColumnModel)columnModel;
        List columns = etcm.getAllColumns();
        Collections.sort(columns, ETableColumnComparator.DEFAULT);
        Map nameToColumn = new HashMap();
        for (Iterator it = columns.iterator(); it.hasNext(); ) {
            final ETableColumn etc = (ETableColumn)it.next();
            String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
            etcm.setColumnHidden(etc, !visible.contains(dName));
            nameToColumn.put(dName, etc);
        }
        for (int i = 0; i < visibleColumns.length; i++) {
            ETableColumn etc = nameToColumn.get(visibleColumns[i]);
            if (etc == null) {
                throw new IllegalStateException("Cannot find column with name " + visibleColumns[i]);
            }
            int currentIndex = etcm.getColumnIndex(etc.getIdentifier());
            etcm.moveColumn(currentIndex, i);
        }
    }

    /**
     * Computes the strings shown to the user in the selection dialog.
     */
    private static String[] getAvailableColumnNames(ETable table, boolean visibleOnly) {
        TableColumnModel columnModel = table.getColumnModel();
        if (! (columnModel instanceof ETableColumnModel)) {
            return new String[0];
        }
        final ETableColumnModel etcm = (ETableColumnModel)columnModel;
        List columns;
        if (visibleOnly) {
            columns = Collections.list(etcm.getColumns());
        } else {
            columns = etcm.getAllColumns();
        }
        Collections.sort(columns, ETableColumnComparator.DEFAULT);
        ArrayList displayNames = new ArrayList();
        for (Iterator it = columns.iterator(); it.hasNext(); ) {
            final ETableColumn etc = (ETableColumn)it.next();
            String dName = table.getColumnDisplayName(etc.getHeaderValue().toString());
            displayNames.add(dName);
        }
        Collections.sort(displayNames, Collator.getInstance());
        return displayNames.toArray(new String[displayNames.size()]);
    }
    
    private static class ETableColumnComparator implements Comparator {
        public static final ETableColumnComparator DEFAULT = new ETableColumnComparator();
        
        @Override
        public int compare(TableColumn o1, TableColumn o2) {
            if( o1 instanceof ETableColumn && o2 instanceof ETableColumn ) {
                ((ETableColumn)o1).compareTo((ETableColumn)o2);
            }
            return 0;
        }
        
    }
    
    private static GraphicsConfiguration getCurrentGraphicsConfiguration() {
	Component focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner();
        if (focusOwner != null) {
            Window w = SwingUtilities.getWindowAncestor(focusOwner);
            if (w != null) {
                return w.getGraphicsConfiguration();
            }
        }

        return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
    }

    private static Rectangle getUsableScreenBounds(GraphicsConfiguration gconf) {
        if (gconf == null) {
            gconf = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
        }

        return new Rectangle(gconf.getBounds());
    }}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy