<?xml version="1.0" encoding="UTF-8"?>
<!--
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements.  See the NOTICE file distributed with
this work for additional information regarding copyright ownership.
The ASF licenses this file to you under the Apache License,
Version 2.0 (the "License"); you may not use this file except in
compliance with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<document id="lists">
    <properties>
        <title>Lists</title>
    </properties>

    <body>
        <p>
            List components in Pivot include <tt>ListView</tt> and <tt>ListButton</tt>.
            <tt>ListView</tt> is a (often scrollable) list of items of which one or more may be
            selected. <tt>ListButton</tt> is a popup list of items of which only one may be
            selected at a time. It is often used in place of a group of radio buttons, particularly
            when space is limited.
        </p>

        <p>
            <tt>ListButton</tt> is discussed in the next section. The following example
            demonstrates the <tt>ListView</tt> component. Multiple items may be selected at a time,
            and list selections are reflected in the label to the right.
        </p>

        <application class="org.apache.pivot.wtk.ScriptApplication"
            width="216" height="122">
            <libraries>
                <library>core</library>
                <library>wtk</library>
                <library>wtk-terra</library>
                <library>tutorials</library>
            </libraries>
            <startup-properties>
                <src>/org/apache/pivot/tutorials/lists/list_views.bxml</src>
            </startup-properties>
        </application>

        <p>
            The BXML source for the example follows. Note that the list view is itself contained
            within a <tt>ScrollPane</tt>. List views do not support scrolling internally. This
            allows a UI designer to place a list view within an application and have the list view
            simply grow to accommodate its contents, rather than requiring the designer to specify
            a fixed height for the list in advance. However, if the designer knows that the list
            will be long and that it is likely to scroll, it can be placed in a scroll pane.
            <tt>ScrollPane</tt> is discussed in more detail in the
            <a href="navigation-containers.html">Navigation Containers</a> section.
        </p>

        <p>
            Also note that the list's contents are specified in the BXML document itself, as a JSON
            array of strings in the <tt>listData</tt> attribute. Any type of object can actually be
            used as a list item, provided that the list view has been given a renderer that is
            capable of painting it. However, they are most often specified as strings (as in this
            example) or as instances of <tt>org.apache.pivot.wtk.content.ListItem</tt>, both of
            which the default renderer is capable of presenting.
        </p>

        <source type="xml" location="org/apache/pivot/tutorials/lists/list_views.bxml">
            <![CDATA[
            <lists:ListViews title="List Views" maximized="true"
                xmlns:bxml="http://pivot.apache.org/bxml"
                xmlns:lists="org.apache.pivot.tutorials.lists"
                xmlns="org.apache.pivot.wtk">
                <Border>
                    <BoxPane styles="{padding:4, spacing:4}">
                        <Border styles="{color:10}">
                            <ScrollPane preferredWidth="80" preferredHeight="110"
                                horizontalScrollBarPolicy="fill"
                                verticalScrollBarPolicy="fill_to_capacity">
                                <ListView bxml:id="listView" selectMode="multi"
                                    listData="['One', 'Two', 'Three', 'Four', 'Five',
                                        'Six', 'Seven', 'Eight', 'Nine', 'Ten']"/>
                            </ScrollPane>
                        </Border>
                        <BoxPane orientation="vertical" preferredWidth="120" styles="{fill:true}">
                            <Label text="You selected:"/>
                            <Label bxml:id="selectionLabel" styles="{wrapText:true}"/>
                        </BoxPane>
                    </BoxPane>
                </Border>
            </lists:ListViews>
            ]]>
        </source>

        <p>
            The Java code for the example also uses the list data to populate the label component
            as the list selection changes. A <tt>ListView</tt>'s selection is represented by a
            sorted list of <tt>org.apache.pivot.wtk.Span</tt> objects that contain the currently
            selected ranges; the application retrieves the list of currently selected ranges and
            then constructs the label's text by appending each selected item to the string:
        </p>

        <source type="java" location="org/apache/pivot/tutorials/lists/ListViews.java">
            <![CDATA[
            package org.apache.pivot.tutorials.lists;

            import java.net.URL;

            import org.apache.pivot.beans.Bindable;
            import org.apache.pivot.collections.Map;
            import org.apache.pivot.collections.Sequence;
            import org.apache.pivot.util.Resources;
            import org.apache.pivot.wtk.Label;
            import org.apache.pivot.wtk.ListView;
            import org.apache.pivot.wtk.ListViewSelectionListener;
            import org.apache.pivot.wtk.Span;
            import org.apache.pivot.wtk.Window;
            import org.apache.pivot.wtk.content.ListItem;

            public class ListViews extends Window implements Bindable {
                private Label selectionLabel = null;
                private ListView listView = null;

                @Override
                public void initialize(Map<String, Object> namespace, URL location, Resources resources) {
                    selectionLabel = (Label)namespace.get("selectionLabel");
                    listView = (ListView)namespace.get("listView");

                    listView.getListViewSelectionListeners().add(new ListViewSelectionListener() {
                        @Override
                        public void selectedRangeAdded(ListView listView, int rangeStart, int rangeEnd) {
                            updateSelection(listView);
                        }

                        @Override
                        public void selectedRangeRemoved(ListView listView, int rangeStart, int rangeEnd) {
                            updateSelection(listView);
                        }

                        @Override
                        public void selectedRangesChanged(ListView listView, Sequence<Span> previousSelectedRanges) {
                            if (previousSelectedRanges != null
                                && previousSelectedRanges != listView.getSelectedRanges()) {
                                updateSelection(listView);
                            }
                        }

                        @Override
                        public void selectedItemChanged(ListView listView, Object previousSelectedItem) {
                            // No-op
                        }

                        private void updateSelection(ListView listView) {
                            String selectionText = "";

                            Sequence<Span> selectedRanges = listView.getSelectedRanges();
                            for (int i = 0, n = selectedRanges.getLength(); i < n; i++) {
                                Span selectedRange = selectedRanges.get(i);

                                for (int j = selectedRange.start;
                                    j <= selectedRange.end;
                                    j++) {
                                    if (selectionText.length() > 0) {
                                        selectionText += ", ";
                                    }

                                    Object item = listView.getListData().get(j);
                                    String text;
                                    if (item instanceof ListItem) {  // item is a listItem (for example because it has an image)
                                        text = ((ListItem) item).getText();
                                    } else {  // item is a standard item for listData
                                        text = item.toString();
                                    }
                                    selectionText += text;
                                }
                            }

                            selectionLabel.setText(selectionText);
                        }
                    });
                }
            }
            ]]>
        </source>

<br/>
<br/>

        <p>
            Sample <tt>ListView</tt> containing <tt>ListItem</tt>s, and a renderer to display images for any item.
        </p>

        <application class="org.apache.pivot.wtk.ScriptApplication"
            width="216" height="122">
            <libraries>
                <library>core</library>
                <library>wtk</library>
                <library>wtk-terra</library>
                <library>tutorials</library>
            </libraries>
            <startup-properties>
                <src>/org/apache/pivot/tutorials/lists/list_views_with_images.bxml</src>
            </startup-properties>
        </application>

        <p>
            The BXML source for the example follows.
        </p>

        <p>
            In this case list contents are set using the content namespace,
            they are ListItem instances (not only plain Strings as the previous sample),
            and there is a ListViewItemRenderer set.
            Note that references to images (icon) here are set in a relative path,
            to reuse images already existing just for convenience.
        </p>

        <source type="xml" location="org/apache/pivot/tutorials/lists/list_views_with_images.bxml">
            <![CDATA[
            <lists:ListViews title="List Views with Images" maximized="true"
                xmlns:bxml="http://pivot.apache.org/bxml"
                xmlns:content="org.apache.pivot.wtk.content"
                xmlns:lists="org.apache.pivot.tutorials.lists"
                xmlns="org.apache.pivot.wtk">
                <Border>
                    <BoxPane styles="{padding:4, spacing:4}">
                        <Border styles="{color:10}">
                            <ScrollPane preferredWidth="80" preferredHeight="110"
                                horizontalScrollBarPolicy="fill"
                                verticalScrollBarPolicy="fill_to_capacity">
                                <ListView bxml:id="listView" selectMode="multi"
                                >
                                    <itemRenderer>
                                        <content:ListViewItemRenderer iconWidth="16" iconHeight="16"
                                            showIcon="true"
                                        />
                                    </itemRenderer>

                                    <content:ListItem icon="@../anchor.png" text="Anchor"/>
                                    <content:ListItem icon="@../bell.png" text="Bell"/>
                                    <content:ListItem icon="@../clock.png" text="Clock"/>
                                    <content:ListItem icon="@../cup.png" text="Cup"/>
                                    <content:ListItem icon="@../house.png" text="House"/>
                                    <content:ListItem icon="@../star.png" text="Star"/>
                                </ListView>
                            </ScrollPane>
                        </Border>
                        <BoxPane orientation="vertical" preferredWidth="120" styles="{fill:true}">
                            <Label text="You selected:"/>
                            <Label bxml:id="selectionLabel" styles="{wrapText:true}"/>
                        </BoxPane>
                    </BoxPane>
                </Border>
            </lists:ListViews>
            ]]>
        </source>

        <p>
            The Java code for the example is the same seen in the previous sample.
        </p>

<br/>
<br/>

        <p>
            In case your <tt>ListView</tt> contains a bean instance, for example a <tt>Contact</tt> for any element,
            the default renderer uses (as last option) the toString method on list elements,
            so override it to return whatever you want to display in the ListView,
            or implement your own custom renderer.
        </p>

    </body>
</document>
