/*
* Copyright 2010 The gwtquery plugins team.
*
* 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 gwtquery.plugins.droppable.client.gwt;
import static com.google.gwt.query.client.GQuery.$;
import java.util.List;
import com.google.gwt.dom.client.Element;
import com.google.gwt.query.client.Function;
import com.google.gwt.user.cellview.client.CellTree.CellTreeMessages;
import com.google.gwt.user.cellview.client.CellTreeNodeView;
import com.google.gwt.view.client.SelectionModel;
import com.google.gwt.view.client.TreeViewModel.NodeInfo;
/**
* A view of a tree node awith drag and drop support.
*
* @param <T> the type that this view contains
*/
class DragAndDropCellTreeNodeView<T> extends CellTreeNodeView<T> {
/**
* The {@link com.google.gwt.view.client.HasData} used to show children. This
* class is intentionally static because we might move it to a new
* {@link DragAndDropCellTreeNodeView}, and we don't want non-static
* references to the old {@link DragAndDropCellTreeNodeView}.
*
* @param <C> the child item type
*/
protected static class DragAndDropNodeCellList<C> extends NodeCellList<C> {
/**
* The view used by the NodeCellList.
*/
protected class View extends NodeCellList<C>.View {
private final Element childContainer;
public View(Element childContainer) {
super(childContainer);
this.childContainer = childContainer;
}
@Override
public void replaceAllChildren(List<C> values, SelectionModel<? super C> selectionModel, boolean
stealFocus) {
// first clean all cell
cleanAllCell();
super.replaceAllChildren(values, selectionModel, stealFocus);
// add drag and drop behaviour
addDragAndDropBehaviour(values, 0);
}
@Override
public void replaceChildren(List<C> values, int start, SelectionModel<? super C> selectionModel, boolean
stealFocus) {
// clean cell before they are replaced
int end = start + values.size();
for (int rowIndex = start; rowIndex < end; rowIndex++) {
Element oldCell = getRowElement(rowIndex);
DragAndDropCellWidgetUtils.get().cleanCell(oldCell);
}
super.replaceChildren(values, start, selectionModel, stealFocus);
// add drag and drop behaviour
addDragAndDropBehaviour(values, start);
}
@SuppressWarnings("unchecked")
protected void addDragAndDropBehaviour(List<C> values, int start) {
int end = start + values.size();
for (int rowIndex = start; rowIndex < end; rowIndex++) {
C value = values.get(rowIndex - start);
Element newCell = getRowElement(rowIndex);
if (!(getNodeInfo() instanceof DragAndDropNodeInfo<?>)) {
continue;
}
final DragAndDropNodeInfo<C> dndNodeInfo = (DragAndDropNodeInfo<C>) getNodeInfo();
DragAndDropCellWidgetUtils.get().maybeMakeDraggableOrDroppable(newCell, value, dndNodeInfo
.getCellDragAndDropBehaviour(), dndNodeInfo.getDraggableOptions(), dndNodeInfo
.getDroppableOptions(), ((DragAndDropCellTreeNodeView) getNodeView()).getTree()
.ensureDragAndDropHandlers());
}
}
protected void cleanAllCell() {
$(childContainer).children().each(new Function() {
@Override
public void f(Element div) {
DragAndDropCellWidgetUtils.get().cleanCell((Element) div.getChild(0).cast());
}
});
}
private Element getRowElement(int indexOnPage) {
if (indexOnPage >= 0 && childContainer.getChildCount() > indexOnPage) {
return childContainer.getChild(indexOnPage).getChild(0).cast();
}
return null;
}
}
// keep the view to clean it during the cleanup
private View view;
public DragAndDropNodeCellList(final NodeInfo<C> nodeInfo, final CellTreeNodeView<?> nodeView, int pageSize) {
super(nodeInfo, nodeView, pageSize);
}
/**
* Cleanup this node view.
*/
public void cleanup() {
super.cleanup();
view.cleanAllCell();
}
@Override
protected NodeCellList<C>.View createView() {
if (view == null) {
view = new View(getNodeView().ensureChildContainer());
}
return view;
}
}
private DragAndDropCellTree tree;
private CellTreeMessages messages;
/**
* Construct a {@link DragAndDropCellTreeNodeView}.
*
* @param tree the parent {@link DragAndDropCellTreeNodeView}
* @param parent the parent {@link DragAndDropCellTreeNodeView}
* @param parentNodeInfo the {@link NodeInfo} of the parent
* @param elem the outer element of this {@link DragAndDropCellTreeNodeView}
* @param value the value of this node
*/
public DragAndDropCellTreeNodeView(final DragAndDropCellTree tree, final CellTreeNodeView<?> parent, NodeInfo<T>
parentNodeInfo, Element elem, T value, CellTreeMessages messages) {
super(tree, parent, parentNodeInfo, elem, value, messages);
this.messages = messages;
this.tree = tree;
}
protected <C> CellTreeNodeView<C> createTreeNodeView(NodeInfo<C> nodeInfo, Element childElem, C childValue,
Object viewData) {
return new DragAndDropCellTreeNodeView<C>(tree, this, nodeInfo, childElem, childValue, messages);
}
protected DragAndDropCellTree getTree() {
return tree;
}
@Override
protected <C> NodeCellList<C> createNodeCellList(NodeInfo<C> nodeInfo) {
return new DragAndDropNodeCellList<C>(nodeInfo, this, tree.getDefaultNodeSize());
}
}