/*
* Ext GWT - Ext for GWT
* Copyright(c) 2007-2009, Ext JS, LLC.
* licensing@extjs.com
*
* http://extjs.com/license
*/
package com.extjs.gxt.ui.client.data;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Default implementation of the <code>TreeModel</code> interface.
*/
public class BaseTreeModel extends BaseModel implements TreeModel {
/**
* The model's parent.
*/
protected TreeModel parent;
/**
* The model's children.
*/
protected List<ModelData> children;
/**
* Creates a new model instance.
*/
public BaseTreeModel() {
children = new ArrayList<ModelData>();
}
/**
* Creates a new model instance with the specified properties.
*
* @param properties the initial properties
*/
public BaseTreeModel(Map<String, Object> properties) {
super(properties);
children = new ArrayList<ModelData>();
}
/**
* Creates a new model instance.
*
* @param parent the parent
*/
public BaseTreeModel(TreeModel parent) {
this();
parent.add(this);
}
/**
* Adds a child to the model and fires an {@link ChangeEventSource#Add} event.
*
* @param child the child to be added
*/
public void add(ModelData child) {
insert(child, getChildCount());
}
/**
* Returns the child at the given index or <code>null</code> if the index is
* out of range.
*
* @param index the index to be retrieved
* @return the model at the index
*/
public ModelData getChild(int index) {
if ((index < 0) || (index >= children.size())) return null;
return children.get(index);
}
/**
* Returns the number of children.
*
* @return the number of children
*/
public int getChildCount() {
return children.size();
}
/**
* Returns the model's children.
*
* @return the children
*/
public List<ModelData> getChildren() {
return children;
}
/**
* Returns the model's parent or <code>null</code> if no parent.
*
* @return the parent
*/
public TreeModel getParent() {
return parent;
}
public int indexOf(ModelData child) {
return children.indexOf(child);
}
/**
* Inserts a child to the model and fires an {@link ChangeEventSource#Add}
* event.
*
* @param child the child to be inserted
* @param index the location to insert the child
*/
public void insert(ModelData child, int index) {
adopt(child);
children.add(index, child);
ChangeEvent evt = new ChangeEvent(Add, this);
evt.setParent(this);
evt.setItem(child);
evt.setIndex(index);
notify(evt);
}
public boolean isLeaf() {
return children.size() == 0;
}
@Override
public void notify(ChangeEvent evt) {
super.notify(evt);
if (parent != null && parent instanceof ChangeEventSource) {
evt.setSource(parent);
((ChangeEventSource) parent).notify(evt);
}
}
/**
* Removes the child at the given index.
*
* @param index the child index
*/
public void remove(int index) {
if (index >= 0 && index < getChildCount()) {
remove(getChild(index));
}
}
/**
* Removes the child from the model and fires a
* {@link ChangeEventSource#Remove} event.
*
* @param child the child to be removed
*/
public void remove(ModelData child) {
orphan(child);
children.remove(child);
ChangeEvent evt = new ChangeEvent(Remove, this);
evt.setParent(this);
evt.setItem(child);
notify(evt);
}
public void removeAll() {
for (int i = children.size() - 1; i >= 0; i--) {
remove(getChild(i));
}
}
/**
* Sets the model's children. All existing children are first removed.
*
* @param children the children to be set
*/
public void setChildren(List<ModelData> children) {
removeAll();
if (children != null) {
for (ModelData child : children) {
add(child);
}
}
}
public void setParent(TreeModel parent) {
this.parent = parent;
}
private void setParentInternal(ModelData child) {
if (child instanceof TreeModel) {
TreeModel treeChild = (TreeModel) child;
treeChild.setParent(this);
} else {
child.set("gxt-parent", child);
}
}
private TreeModel getParentInternal(ModelData child) {
if (child instanceof TreeModel) {
TreeModel treeChild = (TreeModel) child;
return treeChild.getParent();
} else {
return (TreeModel) child.get("gxt-parent");
}
}
private void adopt(ModelData child) {
TreeModel p = getParentInternal(child);
if (p != null && p != this) {
p.remove(child);
}
setParentInternal(child);
}
private void orphan(ModelData child) {
if (child instanceof TreeModel) {
TreeModel treeChild = (TreeModel) child;
treeChild.setParent(null);
} else {
child.remove("gxt-parent");
}
}
}