| /* |
| * Copyright 2010 Google Inc. |
| * |
| * 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.gwt.view.client; |
| |
| import com.google.gwt.view.client.SelectionModel.AbstractSelectionModel; |
| |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| /** |
| * A simple selection model that allows only one item to be selected a a time. |
| * |
| * @param <T> the record data type |
| */ |
| public class SingleSelectionModel<T> extends AbstractSelectionModel<T> |
| implements SetSelectionModel<T> { |
| |
| private Object curKey; |
| private T curSelection; |
| |
| // Pending selection change |
| private boolean newSelected; |
| private T newSelectedItem = null; |
| private boolean newSelectedPending; |
| |
| /** |
| * Constructs a SingleSelectionModel without a key provider. |
| */ |
| public SingleSelectionModel() { |
| super(null); |
| } |
| |
| /** |
| * Constructs a SingleSelectionModel with the given key provider. |
| * |
| * @param keyProvider an instance of ProvidesKey<T>, or null if the item |
| * should act as its own key |
| */ |
| public SingleSelectionModel(ProvidesKey<T> keyProvider) { |
| super(keyProvider); |
| } |
| |
| @Override |
| public void clear() { |
| setSelected(getSelectedObject(), false); |
| } |
| |
| /** |
| * Gets the currently-selected item. |
| * |
| * @return the selected item |
| */ |
| public T getSelectedObject() { |
| resolveChanges(); |
| return curSelection; |
| } |
| |
| @Override |
| public Set<T> getSelectedSet() { |
| Set<T> set = new HashSet<T>(); |
| T item = getSelectedObject(); |
| if (item != null) { |
| set.add(item); |
| } |
| return set; |
| } |
| |
| @Override |
| public boolean isSelected(T item) { |
| resolveChanges(); |
| if (curSelection == null || curKey == null || item == null) { |
| return false; |
| } |
| return curKey.equals(getKey(item)); |
| } |
| |
| @Override |
| public void setSelected(T item, boolean selected) { |
| // If we are deselecting an item that isn't actually selected, ignore it. |
| if (!selected) { |
| Object oldKey = newSelectedPending ? getKey(newSelectedItem) : curKey; |
| Object newKey = getKey(item); |
| if (!equalsOrBothNull(oldKey, newKey)) { |
| return; |
| } |
| } |
| newSelectedItem = item; |
| newSelected = selected; |
| newSelectedPending = true; |
| scheduleSelectionChangeEvent(); |
| } |
| |
| @Override |
| protected void fireSelectionChangeEvent() { |
| if (isEventScheduled()) { |
| setEventCancelled(true); |
| } |
| resolveChanges(); |
| } |
| |
| private boolean equalsOrBothNull(Object a, Object b) { |
| return (a == null) ? (b == null) : a.equals(b); |
| } |
| |
| private void resolveChanges() { |
| if (!newSelectedPending) { |
| return; |
| } |
| |
| Object key = getKey(newSelectedItem); |
| boolean sameKey = equalsOrBothNull(curKey, key); |
| boolean changed = false; |
| if (newSelected) { |
| changed = !sameKey; |
| curSelection = newSelectedItem; |
| curKey = key; |
| } else if (sameKey) { |
| changed = true; |
| curSelection = null; |
| curKey = null; |
| } |
| |
| newSelectedItem = null; |
| newSelectedPending = false; |
| |
| // Fire a selection change event. |
| if (changed) { |
| SelectionChangeEvent.fire(this); |
| } |
| } |
| } |