package edu.washington.cs.oneswarm.ui.gwt.client;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;
import com.google.gwt.user.client.ui.TreeListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.OneSwarmCss;
import edu.washington.cs.oneswarm.ui.gwt.rpc.FileTree;
import edu.washington.cs.oneswarm.ui.gwt.rpc.OneSwarmUIServiceAsync;
public class FileTreePanel extends VerticalPanel {
public Tree t;
public final Label loadingLabel = new Label("Loading, please wait...");
public FileTreePanel(String path) {
t = new Tree();
add(loadingLabel);
OneSwarmUIServiceAsync service = OneSwarmRPCClient.getService();
service.getFiles(OneSwarmRPCClient.getSessionID(), path, new AsyncCallback<FileTree>() {
public void onFailure(Throwable caught) {
System.out.print("failed:" + caught.getMessage());
loadingLabel.setText("error: " + caught.getMessage());
}
public void onSuccess(FileTree result) {
root = new CheckBoxTreeItem(result);
update();
t.addTreeListener(treeExpander);
}
});
}
private String filter = null;
private CheckBoxTreeItem root;
private HorizontalPanel bottomButtons;
private TreeListener treeExpander = new TreeListener() {
public void onTreeItemSelected(TreeItem item) {
}
public void onTreeItemStateChanged(TreeItem item) {
if (item.getState() == true) {
final CheckBoxTreeItem checkBoxTreeItem = (CheckBoxTreeItem) item;
checkBoxTreeItem.addChildren(1, null);
bottomButtons.setVisible(root.getTotalChildCount() > 15);
}
}
};
private void update() {
this.clear();
root.addChildren(1, filter);
loadingLabel.setVisible(false);
t.addItem(root);
recursiveInitialCheck(root, filter);
this.add(createButtons(root, true));
this.add(t);
bottomButtons = createButtons(root, false);
bottomButtons.setVisible(false);
this.add(bottomButtons);
}
private HorizontalPanel createButtons(final CheckBoxTreeItem root, boolean top) {
/*
* buttons for easy sharing
*/
final ListBox level = new ListBox();
HorizontalPanel buttonPanel = new HorizontalPanel();
Button selectAllButton = new Button("Check level: ");
selectAllButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
selectAllButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent sender) {
uncheckAll();
checkLevel(root, 0, level.getSelectedIndex());
}
});
buttonPanel.add(selectAllButton);
// level.addStyleName(SaveLocationPanel.CSS_SMALL_BUTTON);
for (int i = 0; i < 6; i++) {
level.addItem("" + i);
}
level.setSelectedIndex(1);
buttonPanel.add(level);
Button noneButton = new Button("Select none");
noneButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
noneButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent sender) {
uncheckAll();
}
});
buttonPanel.add(noneButton);
Button autoButton = new Button("Auto Grouping");
autoButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
autoButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent sender) {
recursiveInitialCheck(root, null);
}
});
buttonPanel.add(autoButton);
if (top && false) {
final TextBox filterBox = new TextBox();
buttonPanel.add(filterBox);
Button filterButton = new Button("Filter");
buttonPanel.add(filterButton);
filterButton.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
filter = filterBox.getText();
update();
}
});
filterBox.addKeyUpHandler(new KeyUpHandler() {
public void onKeyUp(KeyUpEvent event) {
if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) {
filter = filterBox.getText();
update();
}
}
});
}
return buttonPanel;
}
public void checkLevel(CheckBoxTreeItem item, int currentLevel, int levelToCheck) {
if (item == null) {
return;
} else if (currentLevel > levelToCheck) {
return;
} else if (levelToCheck == currentLevel) {
TreeItem parent = item.getParentItem();
if (parent != null) {
parent.setState(true);
}
item.setValue(true);
item.updateChildren(true);
} else {
for (CheckBoxTreeItem kid : item.getChildList()) {
kid.addChildren(1, null);
checkLevel(kid, currentLevel + 1, levelToCheck);
}
}
}
public void uncheckAll() {
((CheckBoxTreeItem) t.getItem(0)).unCheckedRecursive();
((CheckBoxTreeItem) t.getItem(0)).setState(true);
}
public void recursiveInitialCheck(CheckBoxTreeItem curr, String filter) {
if (curr.fileTree.getMagicCheck()) {
curr.setState(false);
curr.setValue(true);
curr.updateChildren(true);
} else if (curr.fileTree.getCheckedChild()) {
curr.setState(true);
curr.addChildren(1, filter);
for (CheckBoxTreeItem kid : curr.getChildList())
recursiveInitialCheck(kid, filter);
} else {
curr.setState(false);
curr.setValue(false);
curr.updateChildren(false);
}
}
public ArrayList<String> getSelected() {
ArrayList<String> sel = new ArrayList<String>();
LinkedList<CheckBoxTreeItem> itemsToCheck = new LinkedList<CheckBoxTreeItem>();
itemsToCheck.addFirst((CheckBoxTreeItem) t.getItem(0));
while (itemsToCheck.size() > 0) {
CheckBoxTreeItem currItem = itemsToCheck.removeFirst();
if (currItem.isFirstSelected()) {
System.out.println("adding " + currItem.getFilePath());
sel.add(currItem.getFilePath());
} else {
itemsToCheck.addAll(0, currItem.getChildList());
}
}
return sel;
}
class CheckBoxTreeItem extends TreeItem {
private final FileTree fileTree;
private final CheckBox checkBox;
public boolean isFirstSelected() {
return checkBox.getValue() && checkBox.isEnabled();
}
public CheckBoxTreeItem(FileTree fileTree) {
checkBox = new CheckBox(fileTree.getName());
this.setWidget(checkBox);
this.fileTree = fileTree;
checkBox.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
boolean checked = ((CheckBox) event.getSource()).getValue();
updateChildren(checked);
}
});
checkBox.setValue(fileTree.getMagicCheck());
this.setState(fileTree.getCheckedChild());
}
public String getFilePath() {
return fileTree.getFullpath();
}
public int getTotalChildCount() {
int count = 0;
final Collection<CheckBoxTreeItem> children = getChildList();
for (CheckBoxTreeItem c : children) {
count += c.getTotalChildCount();
}
return count;
}
public void setState(boolean state) {
if (state == true) {
super.setState(true);
TreeItem parent = getParentItem();
if (parent != null) {
parent.setState(true);
}
} else {
super.setState(false);
}
}
public void unCheckedRecursive() {
checkBox.setEnabled(true);
checkBox.setValue(false);
this.setState(false);
int childNum = this.getChildCount();
for (int i = 0; i < childNum; i++) {
CheckBoxTreeItem child = this.getChild(i);
child.unCheckedRecursive();
}
}
public Collection<CheckBoxTreeItem> getChildList() {
List<CheckBoxTreeItem> c = new LinkedList<CheckBoxTreeItem>();
int childNum = this.getChildCount();
for (int i = 0; i < childNum; i++) {
CheckBoxTreeItem child = this.getChild(i);
c.add(child);
}
return c;
}
public void setValue(boolean checked) {
checkBox.setValue(checked);
}
public void setEnabled(boolean enabled) {
checkBox.setEnabled(enabled);
}
public void updateChildren(boolean checked) {
int cNum = CheckBoxTreeItem.this.getChildCount();
for (int i = 0; i < cNum; i++) {
CheckBoxTreeItem child = CheckBoxTreeItem.this.getChild(i);
child.setValue(checked);
child.setEnabled(!checked);
child.updateChildren(checked);
}
}
public void addChildren(int depth, String filter) {
// first, check if we need to add the child items
if (this.getChildCount() == 0) {
if (fileTree.getChildren() != null) {
for (FileTree child : fileTree.getChildren()) {
if (child.matches(filter)) {
CheckBoxTreeItem childItem = new CheckBoxTreeItem(child);
childItem.setValue(checkBox.getValue());
childItem.setEnabled(checkBox.isEnabled());
this.addItem(childItem);
}
}
}
}
// then add the grand kids
int childNum = this.getChildCount();
for (int i = 0; i < childNum; i++) {
CheckBoxTreeItem childItem = this.getChild(i);
if (depth > 0) {
if (childItem.fileTree.matches(filter)) {
childItem.addChildren(depth - 1, filter);
}
}
}
}
public CheckBoxTreeItem getChild(int index) {
return (CheckBoxTreeItem) super.getChild(index);
}
}
}