// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed 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.
package com.google.collide.client.search.awesomebox;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.shared.util.JsonCollections;
import elemental.html.Element;
/**
* Manages a list of elements which can have selection. Note no guarantees are
* made when a JsonArray operation which affects the underlying list is
* performed. If you do something rash, clearSelection or selectFirst or
* selectLast, to reset into a known state.
*/
public class ManagedSelectionList<T extends ManagedSelectionList.SelectableElement> {
public static <T extends ManagedSelectionList.SelectableElement> ManagedSelectionList<
T> create() {
return new ManagedSelectionList<T>();
}
public interface SelectableElement {
Element getElement();
/**
* @return false if the item doesn't want selection.
*/
boolean onSelected();
void onSelectionCleared();
}
private static final int NO_SELECTION = -1;
private int selectedIndex = NO_SELECTION;
private JsonArray<T> elements;
public ManagedSelectionList() {
elements = JsonCollections.createArray();
}
public T getSelectedElement() {
return hasSelection() ? elements.get(selectedIndex) : null;
}
public boolean selectNext() {
for (int i = selectedIndex + 1; i < elements.size(); i++) {
if (elements.get(i).onSelected()) {
clearSelection();
selectedIndex = i;
return true;
}
}
return false;
}
public boolean selectPrevious() {
for (int i = selectedIndex - 1; i >= 0; i--) {
if (elements.get(i).onSelected()) {
clearSelection();
selectedIndex = i;
return true;
}
}
return false;
}
/**
* @param index of item to select
*/
public void selectIndex(int index) {
clearSelection();
if (index < 0 || index >= elements.size()) {
throw new IndexOutOfBoundsException();
}
selectedIndex = index;
getSelectedElement().onSelected();
}
/**
* Moves the selection either next or previous based on a boolean
*/
public boolean moveSelection(boolean next) {
if (!hasSelection()) {
return next ? selectFirst() : selectLast();
} else {
return next ? selectNext() : selectPrevious();
}
}
public boolean selectFirst() {
selectedIndex = -1;
if (!selectNext()) {
selectedIndex = NO_SELECTION;
}
return selectedIndex != NO_SELECTION;
}
public boolean selectLast() {
selectedIndex = elements.size();
if (!selectPrevious()) {
selectedIndex = NO_SELECTION;
}
return selectedIndex != NO_SELECTION;
}
public void clearSelection() {
if (hasSelection()) {
getSelectedElement().onSelectionCleared();
}
selectedIndex = NO_SELECTION;
}
public boolean hasSelection() {
return selectedIndex >= 0 && selectedIndex < elements.size();
}
public JsonArray<T> asJsonArray() {
return elements;
}
public void add(T value) {
elements.add(value);
}
public T get(int index) {
return elements.get(index);
}
public int size() {
return elements.size();
}
public T remove(int index) {
return elements.remove(index);
}
public void clear() {
elements.clear();
}
}