| /* |
| * 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.editor.client.adapters; |
| |
| import com.google.gwt.editor.client.CompositeEditor; |
| import com.google.gwt.editor.client.Editor; |
| import com.google.gwt.editor.client.EditorDelegate; |
| |
| import java.util.Collections; |
| import java.util.List; |
| |
| /** |
| * Manages a list of objects and their associated Editors. |
| * <p> |
| * The ListEditor will have no backing list until {@link #setValue(List)} is |
| * called with a non-null value. |
| * |
| * @param <T> The type of data being managed |
| * @param <E> The type of Editor |
| */ |
| public class ListEditor<T, E extends Editor<T>> implements |
| CompositeEditor<List<T>, T, E> { |
| |
| /** |
| * Create a ListEditor backed by an EditorSource. |
| * |
| * @param <T> The type of data being managed |
| * @param <E> The type of Editor |
| * @param source the EditorSource which will create sub-Editors |
| * @return a new instance of ListEditor |
| */ |
| public static <T, E extends Editor<T>> ListEditor<T, E> of( |
| EditorSource<E> source) { |
| return new ListEditor<T, E>(source); |
| } |
| |
| private CompositeEditor.EditorChain<T, E> chain; |
| private EditorSource<E> editorSource; |
| private ListEditorWrapper<T, E> list; |
| |
| /** |
| * Create a ListEditor backed by an EditorSource. |
| * |
| * @param source the EditorSource which will create sub-Editors |
| */ |
| protected ListEditor(EditorSource<E> source) { |
| this.editorSource = source; |
| } |
| |
| /** |
| * Creates a temporary sub-Editor to use for traversal. |
| * |
| * @return an {@link Editor} of type E |
| */ |
| public E createEditorForTraversal() { |
| E toReturn = editorSource.create(0); |
| editorSource.dispose(toReturn); |
| return toReturn; |
| } |
| |
| public void flush() { |
| if (list != null) { |
| list.flush(); |
| } |
| } |
| |
| /** |
| * Returns an unmodifiable, live view of the Editors managed by the |
| * ListEditor. |
| * <p> |
| * The returned list will be live until the next call to {@link #setValue(List)} |
| * and shouldn't be used after that. Editors might (or might not) be reused |
| * after a call to {@link #setValue(List)}. |
| * <p> |
| * If there is no backing list, an empty list will be returned. |
| * |
| * @return a List of {@link Editor Editors} of type E |
| */ |
| public List<E> getEditors() { |
| if (list == null) { |
| return Collections.emptyList(); |
| } |
| return Collections.unmodifiableList(list.getEditors()); |
| } |
| |
| /** |
| * Returns a live view of the ListEditor's backing data. |
| * <p> |
| * The structure of the List may be mutated arbitrarily, subject to the |
| * limitations of the backing List, but the elements themselves should not |
| * be mutated except through {@link #getEditors()} to avoid data |
| * inconsistency. |
| * <p> |
| * Returns null if there is no backing list, and edits cannot be made. |
| * |
| * <pre> |
| * ListEditor<Foo, MyFooEditor> listEditor = ListEditor.of(...); |
| * listEditor.setValue(listOfFoo); // Usually called by EditorDriver |
| * listEditor.getList().set(1, new Foo()); |
| * listEditor.getEditors().get(1).getFooFieldEditor().setValue(....); |
| * </pre> |
| * |
| * @return a live view of the ListEditor's backing data, or <code>null</code> |
| * if there is no backing list. |
| */ |
| public List<T> getList() { |
| return list; |
| } |
| |
| public String getPathElement(E subEditor) { |
| return "[" + list.getEditors().indexOf(subEditor) + "]"; |
| } |
| |
| public void onPropertyChange(String... paths) { |
| } |
| |
| public void setDelegate(EditorDelegate<List<T>> delegate) { |
| } |
| |
| public void setEditorChain(CompositeEditor.EditorChain<T, E> chain) { |
| this.chain = chain; |
| } |
| |
| /** |
| * Sets the ListEditor's backing data. |
| * <p> |
| * If a null is passed in, the ListEditor will have no backing list and edits |
| * cannot be made. |
| * |
| * @param value a List of data objects of type T |
| */ |
| public void setValue(List<T> value) { |
| if (list == null && value == null) { |
| // fast exit |
| return; |
| } |
| if (list != null && list.isSameValue(value)) { |
| // setting the same value as the one being edited |
| list.refresh(); |
| return; |
| } |
| |
| if (list != null) { |
| // Having entire value reset, so dump the wrapper gracefully |
| list.detach(); |
| } |
| if (value == null) { |
| list = null; |
| } else { |
| list = new ListEditorWrapper<T, E>(value, chain, editorSource); |
| list.attach(); |
| } |
| } |
| } |