Jan
20
2009

Java: CheckBoxList



Comments available as RSS 2.0

I’ve been working a lot with ASP.NET recently, and the one thing .NET does miles better than Java is data-binding. In .NET if you want to show a collection as a list of checkboxes, you databind the collection to a CheckBoxList. Unfortunately, Swing doesn’t contain a CheckBoxList class but creating one didn’t take too long.

The class below provides a list of items. Use a LinkedHashMap<T, Boolean> of items to populate the list, where T, the key, is any type which can be represented by calling it’s toString() method and value is a boolean indicating the initial check state of the item.

package com.lime49.lockcrypt;
 
import java.awt.*;
import java.awt.event.*;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import javax.swing.*;
import javax.swing.border.*;
 
/**
 * A list of checkboxes which maintains a list of custom objects
 * http://www.lime49.com/
 * Copyright 2009 by Harry Jennerway
 * All rights reserved.
 */
public class CheckBoxList<T> extends JList {
    protected static Border noFocusBorder = new EmptyBorder(1, 4, 1, 4);
    private CheckBoxListModel<T> model;
 
    /**
     * Initializes a new CheckBoxList with the specified object collection
     * @param items The items to add to the list
     */
    public CheckBoxList(LinkedHashMap<T, Boolean> items) {
        model = new CheckBoxListModel<T>(items);
        setModel(model);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int index = locationToIndex(e.getPoint());
                if(index != -1) {
                    ListItem<T> item = (ListItem<T>)model.getElementAt(index);
                    item.selected = !item.selected;
                    revalidate();
                    repaint();
                }
            }
        });
        setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        setCellRenderer(new CellRenderer());
    }
    ...
}

Download CheckBoxList.java

package com.lime49.lockcrypt;
 
import java.awt.*;
import java.awt.event.*;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import javax.swing.*;
import javax.swing.border.*;
 
/**
 * A list of checkboxes which maintains a list of custom objects
 * http://www.lime49.com/
 * Copyright 2009 by Harry Jennerway
 * All rights reserved.
 */
public class CheckBoxList<T> extends JList {
    protected static Border noFocusBorder = new EmptyBorder(1, 4, 1, 4);
    private CheckBoxListModel<T> model;
 
    /**
     * Initializes a new CheckBoxList with the specified object collection
     * @param items The items to add to the list
     */
    public CheckBoxList(LinkedHashMap<T, Boolean> items) {
        model = new CheckBoxListModel<T>(items);
        setModel(model);
        addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {
                int index = locationToIndex(e.getPoint());
                if(index != -1) {
                    ListItem<T> item = (ListItem<T>)model.getElementAt(index);
                    item.selected = !item.selected;
                    revalidate();
                    repaint();
                }
            }
        });
        setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        setCellRenderer(new CellRenderer());
    }
 
    /**
     * Selects all items in the list
     */
    public void selectAll() {
        model.selectAll();
        revalidate();
        repaint();
    }
 
    /**
     * Deselects all items in the list
     */
    public void selectNone() {
        model.selectNone();
        revalidate();
        repaint();
    }
 
    @Override
    public String getToolTipText(MouseEvent evt) {
        int index = locationToIndex(evt.getPoint());
        if(index == -1) {
            return &quot;&quot;;
        } else {
            ListItem<T> item = (ListItem<T>)model.getElementAt(index);
            return item.dataItem.toString();
        }
    }
 
    /**
     * Renders ListItems as JCheckBoxes whose text is set by the .toString() method of the dataItem in the Item
     */
    protected class CellRenderer implements ListCellRenderer {
        private JCheckBox checkBox;
        private Box containerBox;
        public Component getListCellRendererComponent(JList list, Object value, int index,
                                                    boolean isSelected, boolean cellHasFocus) {
            if(containerBox == null) {
                containerBox = Box.createHorizontalBox();
                checkBox = new JCheckBox();
                checkBox.setEnabled(isEnabled());
                checkBox.setFont(getFont());
                checkBox.setFocusPainted(false);
                checkBox.setBorderPainted(true);
                checkBox.setBorder(isSelected ? UIManager.getBorder(&quot;List.focusCellHighlightBorder&quot;) : noFocusBorder);
                containerBox.add(checkBox);
            }
            checkBox.setBackground(isSelected ? getSelectionBackground() : getBackground());
            checkBox.setForeground(isSelected ? getSelectionForeground() : getForeground());
            if(value != null) {
                ListItem item = (ListItem)value;
                checkBox.setText(item.dataItem.toString());
                checkBox.setSelected(item.selected);
            }
            return containerBox;
        }
    }
 
    /**
     * Returns the list of items in the CheckBoxList
     * @return The list of items in the CheckBoxList
     */
    public LinkedHashMap<T, Boolean> getItems() {
        return model.getItems();
    }
 
    /**
     * Maintains a sorted list of ListItems for rendering a CheckBoxList
     * @param <T> The type of objects in the list
     */
    class CheckBoxListModel<T> extends AbstractListModel {
        private LinkedList<ListItem<T>> items = new LinkedList<ListItem<T>>(); // damn Java for lacking an indexOf method in LinkedHashMap
 
        /**
         * Initializes a new CheckBoxListModel
         * @param items The items to add to the list
         */
        public CheckBoxListModel(LinkedHashMap<T, Boolean> items) {
            Iterator<T> iter = items.keySet().iterator();
            while(iter.hasNext()) {
                T acc = iter.next();
                this.items.add(new ListItem<T>(acc, items.get(acc)));
            }
        }
 
        /**
         * Returns the size of the list
         * @return The size of the list
         */
        public int getSize() {
            return items.size();
        }
 
        /**
         * Returns the ListItem at the specified index
         * @param index The index of the item to find
         * @return The ListItem at the specified index
         */
        public ListItem<T> getElementAt(int index) {
            return items.get(index);
        }
 
        /**
         * Returns the collection of items in the list
         * @return The collection of items in the list
         */
        private LinkedHashMap<T, Boolean> getItems() {
            LinkedHashMap<T, Boolean> map = new LinkedHashMap<T, Boolean>();
            for(ListItem<T> item : items) {
                map.put(item.dataItem, item.selected);
            }
            return map;
        }
 
        /**
         * Selects all items in the list
         */
        public void selectAll() {
            for(ListItem<T> item : items) {
                item.selected = true;
            }
        }
 
        /**
         * Deselects all items in the list
         */
        public void selectNone() {
            for(ListItem<T> item : items) {
                item.selected = false;
            }
        }
    }
 
    /**
     * Holds an item of the specified type and a value indicating whether or not it is selected
     * @param <T> The type of the item
     */
    class ListItem<T> {
        public T dataItem;
        public boolean selected;
 
        /**
         * Initializes a new ListItem
         * @param dataItem The item to display
         * @param selected <c>true</c> if the item is selected, otherwise <c>false</c>
         */
        public ListItem(T dataItem, boolean selected) {
            this.dataItem = dataItem;
            this.selected = selected;
        }
    }
}

Comments

Leave a Comment

Login using OpenID or enter your details below to leave a comment.

OpenID
Anonymous


Comment