/* * 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 java.util.AbstractList; import java.util.ArrayList; import java.util.List; /** * Synchronizes a list of objects and a list of Editors. * * @param <T> the type of data being edited * @param <E> the type of Editor */ class ListEditorWrapper<T, E extends Editor<T>> extends AbstractList<T> { private final List<T> backing; private final CompositeEditor.EditorChain<T, E> chain; private final List<E> editors; private final EditorSource<E> editorSource; private final List<T> workingCopy; public ListEditorWrapper(List<T> backing, CompositeEditor.EditorChain<T, E> chain, EditorSource<E> editorSource) { this.backing = backing; this.chain = chain; this.editorSource = editorSource; editors = new ArrayList<E>(backing.size()); workingCopy = new ArrayList<T>(backing); } @Override public void add(int index, T element) { workingCopy.add(index, element); E subEditor = editorSource.create(index); editors.add(index, subEditor); for (int i = index + 1, j = editors.size(); i < j; i++) { editorSource.setIndex(editors.get(i), i); } chain.attach(element, subEditor); } @Override public T get(int index) { return workingCopy.get(index); } @Override public T remove(int index) { T toReturn = workingCopy.remove(index); E subEditor = editors.remove(index); editorSource.dispose(subEditor); for (int i = index, j = editors.size(); i < j; i++) { editorSource.setIndex(editors.get(i), i); } chain.detach(subEditor); return toReturn; } @Override public T set(int index, T element) { T toReturn = workingCopy.set(index, element); chain.attach(element, editors.get(index)); return toReturn; } @Override public int size() { return workingCopy.size(); } /** * Must be called after construction. This is a two-phase initialization so * that ListEditor can assign its list field before any sub-editors might call * {@link ListEditor#getList()} */ void attach() { editors.addAll(editorSource.create(workingCopy.size(), 0)); for (int i = 0, j = workingCopy.size(); i < j; i++) { chain.attach(workingCopy.get(i), editors.get(i)); } } void detach() { for (int i = 0, j = editors.size(); i < j; i++) { chain.detach(editors.get(i)); editorSource.dispose(editors.get(i)); } } void flush() { for (int i = 0, j = workingCopy.size(); i < j; i++) { E subEditor = editors.get(i); T value = chain.getValue(subEditor); // Use of object-identity intentional if (workingCopy.get(i) != value) { workingCopy.set(i, value); } } backing.clear(); backing.addAll(workingCopy); } /** * For testing only. */ List<? extends E> getEditors() { return editors; } }