# 5

## JCList and JCMultiColumnList

Introduction · Sample Program Code · Enabling Multiple Selections

Setting Row Height and Spacing · Row and Column Visibility

Setting Selection Colors · Scrollbar Display · Column Settings

Events · Property Listing · Example Programs

### Introduction

List boxes are standard Graphical User Interface (GUI) components common to most windowing systems. List boxes enable users to view and choose from a series of selectable options. If the list is large, a scrollbar can be added to conserve space. To the user, list boxes operate in essentially the same manner as a collection of checkboxes or radio buttons, but list boxes are inherently dynamic--changes made in one list can be immediately reflected in another list component, providing a convenient way of managing large numbers of options.

A multi-column list is a list display containing multiple columns and column labels. Multi-column lists also enable the user to arrange the information contained within the entire list by clicking on a column label. In addition, column widths can be resized by dragging the boundary between the column labels. Multi-column lists provide a convenient way of displaying and managing large amounts of information.

While a list box component are incorporated within the Java Development Kit (JDK), it does not have a multi-column list component. Unlike AWT list boxes, `JCList` (and `JCMultiColumnList`) can incorporate images and text through the use of JCStrings. They can also incorporate objects. Both `JCList` and `JCMultiColumnList` have the standard Windows 95 "look and feel" and behavior.

#### Behavior:

`JCList` behaves in the following manner:

- if an item is clicked (or the SPACE BAR is hit) with no other key pressed, the item is selected if it was previously unselected, or unselected if it was previously selected. Previously selected items are unselected.
- if an item is clicked (or the space key is hit) with the SHIFT key down, the current selection is extended from the current anchor to the item if `AllowMultipleSelections` is `true`.
- if the anchor item (the last selected or unselected item) is selected, the selection will be selected; if the anchor item is unselected, the selection will be unselected
- if an item is clicked (or the space key is hit) with the CONTROL key down, the current selection is toggled if `AllowMultipleSelections` is `true`, and the item becomes the new anchor. If the mouse is dragged across items, they are selected if `AllowMultipleSelections` is `true`.
- hitting the up or down arrow keys moves the focus item, which is shown as a 2-pixel rectangle drawn around the item. The list will scroll if necessary to display the focus item.

`JCMultiColumnList` behaves in the following manner:

- the column labels may be created as labels or buttons. Clicking on a column's button causes the column to be sorted
- columns can be resized interactively by dragging them.

#### Keyboard traversal

Items can be individually selected within a `JCList` by clicking them with the cursor. Once a `JCList` has focus, a continuous range of items can be selected by, clicking an item, holding down the SHIFT key, and then clicking the item at the end of the desired range. To select multiple items, click each item while holding down the CTRL key. When an item in a list is selected, the cursor keys will move focus in the direction of the cursor key. To select a single item, click the SPACE BAR. To select multiple items, click ENTER over individual items.

Items can be individually selected within a `JCMultiColumnList` by clicking them with the cursor. Once a `JCMultiColumnList` has focus, the cursor keys will move focus in the direction of the cursor key. To select an item, click SPACE BAR or ENTER.

### Sample Program Code

The following code fragment shows how several different `JCList`s can be created:

    package jclass.bwt.examples;
    import jclass.bwt.BWTEnum;
    import jclass.bwt.JCList;
    import jclass.contrib.ContribFrame;
    import jclass.util.JCString;
    import java.awt.*;
    public class lists extends java.applet.Applet {

    static int font_style_values[] = {
    	Font.PLAIN, Font.BOLD, Font.ITALIC,
    };

    static String font_style_names[] = {
    	"plain", "bold", "italic",
    };

    static String font_size_names[] = {
    	"12", "14", "15", "20"
    };

    static String item_strings[] = {
    	"check mark",
    	"copy",
    	"cut",
    	"info",
    	"x",
    };

    static String item_images[] = {
    	"check16.gif",
    	"copy16.gif",
    	"cut16.gif",
    	"info16.gif",
    	"x16.gif",
    };

    static String color_names[] = {
        "red",
        "pink",
        "orange",
        "yellow",
        "green",
        "magenta",
        "cyan",
        "blue",
    };

    static Color color_values[] = {
        Color.red,
        Color.pink,
        Color.orange,
        Color.yellow,
        Color.green,
        Color.magenta,
        Color.cyan,
        Color.blue,
    };

    public void init() {
    	JCList list = new JCList();
    	setBackground(Color.lightGray);
        String font_names[] = getToolkit().getFontList();

    	/*
    	 * Image list
    	 */
    	list.setSpacing(5);
    	list.setAllowMultipleSelections(true);
    	for (int i=0; i < item_strings.length; i++) {
    		String str = "[IMG=../images/" + item_images[i] + "]"
    			+ "[HORIZ_SPACE=10][ALIGN=MIDDLE]"
    			+ item_strings[i];
    		list.addItem(JCString.parse(this, str));
    	}
    	add(list);

    	/*
    	 * Font list
    	 */
    	JCList font_window = new JCList(7, true);
    	for (int i=0; i < font_names.length; i++) {
    		for (int k=0; k < font_style_names.length; k++) {
    			Font font = new Font(font_names[i], font_style_values[k], 14);
    			JCString s = new JCString();
    			s.add(font);
    			s.add(font_names[i] + "-" + font_style_names[k] + "-" + 14);
    			font_window.addItem(s);
    		}
    	}
    	add(font_window);

    	/*
    	 * Color list
    	 */
    	list = new JCList();
    	list.setFont(new Font("Dialog", Font.BOLD, 14));
    	list.setBackground(Color.black);
    	list.setSelectedBackground(Color.white);
    	list.setAllowMultipleSelections(true);
    	list.getList().setHighlightColor(Color.white);
    	for (int i=0; i < color_names.length; i++) {
    		JCString s = new JCString();
    		s.add(color_values[i]);
    		s.add(color_names[i]);
    		list.addItem(s);
    	}
    	add(list);
    }

    public static void main(String args[]) {
    	ContribFrame frame = new ContribFrame("Lists");

    	lists l = new lists();
    	l.init();

    	fontChooser chooser = new fontChooser();
    	chooser.init();
    	l.add(chooser);

    	frame.add(l);
    	frame.pack();
    	frame.show();
    	chooser.start();
    }
    }

This program creates the following display:

#####

##### Three sample JCLists

The image list displays how images can be inserted using JCStrings, the font list displays how a list can be associated with a scrollable window, and the color list is an example of how JCStrings can be used to set color values. (For more information on JCStrings, see Appendix B: JCString Properties).

The following code fragment shows how a `JCMultiColumnList` can be created:

    package jclass.bwt.examples;
    import jclass.bwt.BWTEnum;
    import jclass.bwt.JCMultiColumnList;
    import jclass.contrib.ContribFrame;
    import java.awt.*;
    import java.applet.Applet;
    public class multiColumnList extends java.applet.Applet {
    final static String[] column_labels = {
    ...
    [multiple string values added here]
    ...
    JCMultiColumnList list = new JCMultiColumnList();
    public void init() {
    	// Force list to be same size as applet
    	setLayout(new GridLayout(1,1));
    	setBackground(Color.lightGray);
    	list.getList().setBackground(Color.white);
    	list.getList().setFont(new Font("Dialog", Font.PLAIN, 10));
    	list.setVisibleRows(15);
    	list.setSpacing(10);
    	list.setRowHeight(BWTEnum.VARIABLE);
    	for (int i=0; i < data.length; i++)
    		list.addItem(data[i], '|');
    	list.setColumnButtons(column_labels);
    	list.setColumnAlignments(alignments);
    	list.getHeader().setColumnAlignments(alignments);
    	add(list);
    }
    public Insets insets() {
    	return new Insets(5,5,5,5);
    }
    public static void main(String args[]) {
    	ContribFrame frame = new ContribFrame("MultiColumnList");
    	multiColumnList l = new multiColumnList();
    	l.init();
    	frame.add(l);
    	frame.pack();
    	frame.show();
    }
    }

String values can be easily added to this code, as the following fragment demonstrates:

    final static String[] column_labels = {
            "Title", "Author", "Price", "Pages", "Publisher"
    };
    final static int[] alignments = {
            LEFT, LEFT, RIGHT, RIGHT, LEFT,
    };
    final static String[] data = {
    "Active Java|"+
    "Adam Freeman\n"+
    "Darrel Ince|"+
    "$25.95|"+
    "235|"+
    "Addison-Wesley",
    JCMultiColumnList list = new JCMultiColumnList();

When a number of string values are added to the above code, it creates a display similar to the following:

#####

##### A sample program incorporating JCMultiColumnList

The code samples used in this section are incorporated into the example files lists.class and multiColumnList.class provided with JClass BWT. For information on how to run these program, see the "Example Programs" section at the end of this chapter.

### Enabling Multiple Selections

One of the chief advantages of using a list component is that it enables the user a wide variety of options to choose from. There are cases where it is desirable to offer the user the ability to choose multiple items from the list, and when only a single option can be chosen. Use the `AllowMultipleSelections` property in `JCList` or `JCMultiColumnList` to set whether a user can select more than one item from the list. It takes a boolean value, and when set to `true`, the list allows multiple selections.

### Setting Row Height and Spacing

By default, the height of a row in a `JCList` or `JCMultiColumnList` is set by the height of the font contained within a row. This action is set by `RowHeight`, whose default value is `FONT_HEIGHT`. `RowHeight` can also take a specific pixel value as the height value for each row.

A list component can also be set to automatically size rows and columns to fit the contents of the row by setting `RowHeight` to `VARIABLE`. If an application changes a lists' attributes affecting the cells' contents, this setting will resize the rows accordingly.

The spacing between rows is set by the `Spacing` property (default: 0).

### Row and Column Visibility

The `VisibleRows` property sets the number of rows that are visible in a `JCList` or `JCMultiColumnList`. If set to 0 (default), the list will attempt to resize itself so that four items are visible. If it is set to another value, only the number of row specified will be displayed. `VisibleRows` only works if the list is made visible beforehand.

Column visibility in `JCMultiColumnList` is set using the `NumColumns` property. If set to `VARIABLE` (default), all columns are displayed.

### Setting Selection Colors

The color values for selected items can be set explicitly within a `JCList` or `JCMultiColumnList`. Both the background and foreground (text) colors can be set in this manner. The `SelectedBackground` property sets the background selected color for a `JCList`, and `SelectedForeground` to set the selected text color.

For a list of available color values, see Appendix A: Colors and Fonts.

### Scrollbar Display

Scrollbar display for both `JCList` and `JCMultiColumnList` is controlled by two methods: `ScrollbarDisplay` and `ScrollbarOffset`. The `ScrollbarDisplay` property is used to specify when scrollbars are to be displayed. `ScrollbarDisplay` has five different, self-explanitory values: `DISPLAY_ALWAYS`, `DISPLAY_AS_NEEDED` (default), `DISPLAY_VERTICAL_ONLY`, `DISPLAY_HORIZONTAL_ONLY`, `DISPLAY_NONE`.

`ScrollbarOffset` is used to set the distance in pixels between the scrollbars and the viewport (default: 0).

### Column Settings

`JCMultiColumnList` provides a number of property to enable the programmer to modify various column characteristics.

The `ColumnAlignments` property enables the programmer to explicitly set the alignment for the text, images and other items that appear in a list. It can have one of nine values: `TOPLEFT`, `TOPCENTER`, `TOPRIGHT`, `MIDDLELEFT`, `MIDDLECENTER` , `MIDDLERIGHT`, `BOTTOMLEFT` `BOTTOMCENTER` and `BOTTOMRIGHT`. By default, `ColumnAlignments` is set to `MIDDLELEFT`.

Column margins can be explicitly set with the `ColumnRightMargin` and the `ColumnLeftMargin` properties. Both set the margin value in pixels for the text, images or other items that appear in a column (default: 5 pixels).

Column width can be set using the `ColumnWidths` property. It can take a list value, or a specific value for a particular column. If a column value is set to `VARIABLE`, the width is set to the item of the widest value within the column.

To sets a header for the window with the specified labels, use the `ColumnLabels` property. Each label can take a string or a JCString.

There are many cases where it desirable to allow the user to sort the information contained within a multi-column list. The `ColumnLabelSort` property is used to specify whether a column is sorted when its button is clicked (default: `true`). If true, `sortByColumn()` is called. When `sortByColumn()` is called, it sorts the rows in the list based on the specified column, based on the numerical or string values contained within the column. The optional `sort_if` parameter can be used with `sortByColumn()` to enable the programmer to provide a mechanism to specify their own sorting scheme.

`ColumnLabelSortMethod` sets the method to be called during sorting. `ColumnLabelSortMethod` can take the parameter `method`, which is an interface whose "compare" method is called during sorting, in order to provide a mechanism for the application to specify whether one object is greater than another. It works in a similar fashion to `qsort`'s `compare` function. By default `ColumnLabelSortMethod` is set to `null`, which sorts the the column through either a numerical or string comparison as applicable.

### Events

A class can be notified when the user presses the ENTER key or double-clicks an item within a `JCList` by implementing the `JCActionListener` interface and registering itself with the list via `addActionListener`, as the following code demonstrates:

    public interface JCActionListener {
            public void actionPerformed(JCActionEvent e);
    }
    public class JCActionEvent {
            // Returns the component where the event originated.
            public Object getSource()
            // Returns the event type: ACTION_PERFORMED.
            public int getId()
    }

A class can be notified when the user selects an item in the list by implementing the `JCItemListener` interface and registering itself with the list via `addItemListener`:

    public interface JCItemListener {
            public void itemStateChanged(JCItemEvent e);
    }
    public class JCItemEvent {
            // Returns the component where the event originated.
            public Object getSource()
            // Returns the event type: ITEM_STATE_CHANGED.
            public int getId()
            // Returns the item where the event occurred.
            public Object getItem()
            // Returns the state change type which generated the event: SELECTED or DESELECTED
            public int getStateChange()

To receive additional information, a class can implement the `JCListListener` interface, and register itself with the list via `addItemListener`:

    public interface JCListListener extends JCItemListener {
            // Invoked before an item is selected. The event's values can be modified via its setXXX methods.
            public void listItemSelectBegin(JCListEvent e);
            // Invoked after an item is selected. Any changes made to the event are ignored.
            public void listItemSelectEnd(JCListEvent e);
    }

It is then passed onto `JCListEvents` using the following code:

    public class JCListEvent extends JCItemEvent {
            // Gets the last item selected.
            public int getRow()
            // Gets the selection type: INITIAL, MODIFICATION or ADDITION
            public int getType()
            // Gets the current AllowSelection value.
            public boolean getAllowSelection()
            // Determines whether the selection should be allowed (default: true)
            public void setAllowSelection(boolean v)
            // Gets the originating event (null if selection was not interactive)
            public Event getSourceEvent()
    }

### Property Listing

The following is a listing of available properties for `JCList` and `JCMultiColumnList`.

#### jclass.bwt.JCList

#####

Name | Method | Inherited from
--- | --- | ---
`AllowMultipleSelections` | `setAllowMultipleSelections` | `jclass.bwt.JCList`
`AutoSelect` | `setAutoSelect` | `jclass.bwt.JCList`
`Background` | `setBackground` | `jclass.bwt.JCContainer`
`Font` | `setFont` | `jclass.bwt.JCContainer`
`Foreground` | `setForeground` | `jclass.bwt.JCContainer`
`Insets` | `setInsets` | `jclass.bwt.JCContainer`
`Items` | `setItems` | `jclass.bwt.JCList`
`PreferredSize` | `setPreferredSize` | `jclass.bwt.JCContainer`
`RowHeight` | `setRowHeight` | `jclass.bwt.JCList`
`ScrollbarDisplay` | `setScrollbarDisplay` | `jclass.bwt.JCScrolledWindow`
`ScrollbarOffset` | `setScrollbarOffset` | `jclass.bwt.JCScrolledWindow`
`SelectedBackground` | `setSelectedBackground` | `jclass.bwt.JCList`
`SelectedForeground` | `setSelectedForeground` | `jclass.bwt.JCList`
`Spacing` | `setSpacing` | `jclass.bwt.JCList`
`UserData` | `setUserData` | `jclass.bwt.JCContainer`
`VisibleRows` | `setVisibleRows` | `jclass.bwt.JCList`

#### jclass.bwt.JCMultiColumnList

#####

Name | Method | Inherited from
--- | --- | ---
`AllowMultipleSelections` | `setAllowMultipleSelections` | `jclass.bwt.JCMultiColumnList`
`AutoSelect` | `setAutoSelect` | `jclass.bwt.JCMultiColumnList`
`Background` | `setBackground` | `jclass.bwt.JCContainer`
`ColumnAlignments` | `setColumnAlignments` | `jclass.bwt.JCMultiColumnWindow`
`ColumnLabels` | `setColumnLabels` | `jclass.bwt.JCMultiColumnWindow`
`ColumnLabelSort` | `setColumnLabelSort` | `jclass.bwt.JCMultiColumnList`
`ColumnLabelSortMethod` | `setColumnLabelSortMethod` | `jclass.bwt.JCMultiColumnList`
`ColumnLeftMargin` | `setColumnLeftMargin` | `jclass.bwt.JCMultiColumnWindow`
`ColumnRightMargin` | `setColumnRightMargin` | `jclass.bwt.JCMultiColumnWindow`
`ColumnWidths` | `setColumnWidths` | `jclass.bwt.JCMultiColumnWindow`
`Font` | `setFont` | `jclass.bwt.JCContainer`
`Foreground` | `setForeground` | `jclass.bwt.JCContainer`
`Insets` | `setInsets` | `jclass.bwt.JCContainer`
`Items` | `setItems` | `jclass.bwt.JCMultiColumnList`
`NumColumns` | `setNumColumns` | `jclass.bwt.JCMultiColumnWindow`
`PreferredSize` | `setPreferredSize` | `jclass.bwt.JCContainer`
`RowHeight` | `setRowHeight` | `jclass.bwt.JCMultiColumnList`
`ScrollbarDisplay` | `setScrollbarDisplay` | `jclass.bwt.JCScrolledWindow`
`ScrollbarOffset` | `setScrollbarOffset` | `jclass.bwt.JCScrolledWindow`
`SelectedBackground` | `setSelectedBackground` | `jclass.bwt.JCMultiColumnList`
`SelectedForeground` | `setSelectedForeground` | `jclass.bwt.JCMultiColumnList`
`Spacing` | `setSpacing` | `jclass.bwt.JCMultiColumnList`
`UserData` | `setUserData` | `jclass.bwt.JCContainer`
`VisibleRows` | `setVisibleRows` | `jclass.bwt.JCMultiColumnList`

### Example Programs

Demonstration programs and example code containing `JCList`s and `JCMultiColumnList`s come with JClass BWT. The examples can be viewed in applet form by launching index.html within the /jclass/bwt/examples directory. lists.class and multiColumnLists.class can also be run as stand-alone Java applications from the command prompt by typing:

         java jclass.bwt.examples.lists

and

         java jclass.bwt.examples.multiColumnList