// 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.util;
import com.google.collide.json.shared.JsonArray;
import com.google.collide.mvp.HasView;
import com.google.collide.shared.util.JsonCollections;
import elemental.html.Element;
/**
* Encapsulates a list of dom elements that are to be reused during rendering. This controller will
* automatically create new ones when the list grows and remove old ones when it shrinks. It is
* particularly efficient if rendering happens often.
*
* @param <P> A presenter which has a view
*/
public class ViewListController<P extends HasView<?>> {
public static <P extends HasView<?>> ViewListController<P> create(
Element container, Factory<P> factory) {
return new ViewListController<P>(container, JsonCollections.<P>createArray(), factory);
}
/**
* A factory which can return a new presenter with its view.
*
* @param <P> The presenter type
*/
public interface Factory<P extends HasView<?>> {
/**
* Creates a new presenter and appends its view to the specified container.
*/
public P create(Element container);
}
private int index = 0;
private final JsonArray<P> list;
private final Factory<P> factory;
private final Element container;
public ViewListController(Element container, JsonArray<P> list, Factory<P> factory) {
this.list = list;
this.container = container;
this.factory = factory;
}
/**
* Resets the list to element index 0.
*/
public void reset() {
index = 0;
}
/**
* Retrieves the next presenter to be used (potentially creating a new one).
*/
public P next() {
int elementIndex = index++;
if (elementIndex >= list.size()) {
P presenter = factory.create(container);
list.add(presenter);
}
return list.get(elementIndex);
}
/**
* @return the number of elements current in the list.
*/
public int size() {
return list.size();
}
/**
* Removes any remaining elements still attached to the DOM.
*/
public void prune() {
if (index >= list.size()) {
return;
}
JsonArray<P> elementsToRemove = list.splice(index, list.size() - index);
for (int i = 0; i < elementsToRemove.size(); i++) {
elementsToRemove.get(i).getView().getElement().removeFromParent();
}
}
}