Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.control;
027
028import javafx.beans.property.ObjectProperty;
029import javafx.beans.property.ObjectPropertyBase;
030import javafx.collections.ListChangeListener;
031import javafx.collections.ObservableList;
032
033/**
034 * An abstract class that extends {@link SelectionModel} to add API to support
035 * multiple selection.
036 * 
037 * @see SelectionModel
038 * @see SelectionMode
039 * @param <T> The type of the item contained in the control that can be selected.
040 */
041public abstract class MultipleSelectionModel<T> extends SelectionModel<T> {
042    
043    /***************************************************************************
044     *                                                                         *
045     * Properties                                                              *
046     *                                                                         *
047     **************************************************************************/     
048    
049    /**
050     * <p>Specifies the selection mode to use in this selection model. The
051     * selection mode specifies how many items in the underlying data model can
052     * be selected at any one time.
053     * 
054     * <p>By default, the selection mode is <code>SelectionMode.SINGLE</code>.
055     */
056    private ObjectProperty<SelectionMode> selectionMode;
057    public final void setSelectionMode(SelectionMode value) {
058        selectionModeProperty().set(value);
059    }
060
061    public final SelectionMode getSelectionMode() {
062        return selectionMode == null ? SelectionMode.SINGLE : selectionMode.get();
063    }
064
065    public final ObjectProperty<SelectionMode> selectionModeProperty() {
066        if (selectionMode == null) {
067            selectionMode = new ObjectPropertyBase<SelectionMode>(SelectionMode.SINGLE) {
068                @Override protected void invalidated() {
069                    if (getSelectionMode() == SelectionMode.SINGLE) {
070                        // we need to pick out just the last selected item, as we've gone
071                        // to single selection
072                        if (! isEmpty()) {
073                            int lastIndex = getSelectedIndex();
074                            clearSelection();
075                            select(lastIndex);
076                        }
077                    }
078                }
079
080                @Override
081                public Object getBean() {
082                    return MultipleSelectionModel.this;
083                }
084
085                @Override
086                public String getName() {
087                    return "selectionMode";
088                }
089            };
090        }
091        return selectionMode;
092    }
093    
094    
095    
096    /***************************************************************************
097     *                                                                         *
098     * Constructor                                                             *
099     *                                                                         *
100     **************************************************************************/  
101    
102    /**
103     * Creates a default MultipleSelectionModel instance.
104     */
105    public MultipleSelectionModel() { }
106    
107    
108    
109    /***************************************************************************
110     *                                                                         *
111     * Public API                                                              *
112     *                                                                         *
113     **************************************************************************/     
114
115    /**
116     * <p>Returns a <b>read-only</b> ObservableList of all selected indices. The
117     * ObservableList will be updated  by the selection model to always reflect
118     * changes in selection. This can be observed by adding a
119     * {@link ListChangeListener} to the returned ObservableList.
120     */
121    public abstract ObservableList<Integer> getSelectedIndices();
122
123    /**
124     * <p>Returns a <b>read-only</b> ObservableList of all selected items. The
125     * ObservableList will be updated further by the selection model to always reflect
126     * changes in selection. This can be observed by adding a
127     * {@link ListChangeListener} to the returned ObservableList.
128     */
129    public abstract ObservableList<T> getSelectedItems();
130
131    /**
132     * <p>This method allows for one or more selections to be set at the same time.
133     * It will ignore any value that is not within the valid range (i.e. greater
134     * than or equal to zero, and less than the total number of items in the
135     * underlying data model). Any duplication of indices will be ignored.
136     *
137     * <p>If there is already one or more indices selected in this model, calling
138     * this method will <b>not</b> clear these selections - to do so it is
139     * necessary to first call clearSelection.
140     *
141     * <p>The last valid value given will become the selected index / selected
142     * item.
143     */
144    public abstract void selectIndices(int index, int... indices);
145
146    /**
147     * <p>Selects all indices from the given start index to the item before the
148     * given end index. This means that the selection is inclusive of the start
149     * index, and exclusive of the end index. This method will work regardless
150     * of whether start < end or start > end: the only constant is that the 
151     * index before the given end index will become the selected index.
152     *
153     * <p>If there is already one or more indices selected in this model, calling
154     * this method will <b>not</b> clear these selections - to do so it is
155     * necessary to first call clearSelection.
156     *
157     * @param start The first index to select - this index will be selected.
158     * @param end The last index of the selection - this index will not be selected.
159     */
160    public void selectRange(final int start, final int end) {
161        if (start == end) return;
162        
163        final boolean asc = start < end;
164        final int low = asc ? start : end;      // Math.min(start, end);
165        final int high = asc ? end : start;     //Math.max(start, end);
166        final int arrayLength = high - low - 1;
167        
168        int[] indices = new int[arrayLength];
169        
170        int startValue = asc ? low : high;
171        int firstVal = asc ? startValue++ : startValue--;
172        for (int i = 0; i < arrayLength; i++) {
173            indices[i] = asc ? startValue++ : startValue--;
174        }
175        selectIndices(firstVal, indices);
176    }
177
178    /**
179     * <p>Convenience method to select all available indices.</p>
180     */
181    public abstract void selectAll();
182
183    /**
184     * <p>This method will attempt to select the first index in the control. If
185     * clearSelection is not called first, this method
186     * will have the result of selecting the first index, whilst retaining
187     * the selection of any other currently selected indices.</p>
188     *
189     * <p>If the first index is already selected, calling this method will have
190     * no result, and no selection event will take place.</p>
191     */
192    @Override public abstract void selectFirst();
193
194    /**
195     * <p>This method will attempt to select the last index in the control. If
196     * clearSelection is not called first, this method
197     * will have the result of selecting the last index, whilst retaining
198     * the selection of any other currently selected indices.</p>
199     *
200     * <p>If the last index is already selected, calling this method will have
201     * no result, and no selection event will take place.</p>
202     */
203    @Override public abstract void selectLast();
204}