package edu.washington.cs.oneswarm.ui.gwt.client.newui; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import com.allen_sauer.gwt.dnd.client.DragContext; import com.allen_sauer.gwt.dnd.client.PickupDragController; import com.allen_sauer.gwt.dnd.client.drop.SimpleDropController; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.logical.shared.SelectionEvent; import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.HorizontalSplitPanel; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SimplePanel; import com.google.gwt.user.client.ui.Tree; import com.google.gwt.user.client.ui.TreeItem; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwt.user.client.ui.Widget; import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmDialogBox; import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmRPCClient; import edu.washington.cs.oneswarm.ui.gwt.client.ReportableErrorDialogBox; import edu.washington.cs.oneswarm.ui.gwt.client.newui.SwarmsBrowser.TorrentContainingImage; import edu.washington.cs.oneswarm.ui.gwt.client.newui.settings.SettingsDialog; import edu.washington.cs.oneswarm.ui.gwt.rpc.FileTree; import edu.washington.cs.oneswarm.ui.gwt.rpc.TorrentInfo; public class TagEditorDialog extends OneSwarmDialogBox { public static final int WIDTH = 550; public static final int HEIGHT = 450; Button updateButton = new Button("Update"); Button cancelButton = new Button("Cancel"); private Button addSelectedButton; private Button moveButton; private Label selectLabel; private TorrentInfo[] mTorrents; private VerticalPanel leftVP; private Button addButton; private Button removeButton; private Button clearButton; private Tree mCurrentTagsTree; private Tree mAllTagsTree; private TreeItem mCurrentTagsRoot; private TreeItem mAllTagsRoot; private EntireUIRoot mUIRoot; public TagEditorDialog(EntireUIRoot entireUIRoot, TorrentInfo[] torrents) { super(false, false, true); mUIRoot = entireUIRoot; mTorrents = torrents; this.setText("Edit tags"); VerticalPanel mainPanel = new VerticalPanel(); selectLabel = new Label("Editing tags for " + torrents.length + " selected swarm" + (torrents.length > 1 ? "s" : "")); selectLabel.addStyleName(CSS_DIALOG_HEADER); selectLabel.setWidth(WIDTH + "px"); mainPanel.add(selectLabel); HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(); splitPanel.setLeftWidget(createLeftPanel()); splitPanel.setRightWidget(createRightPanel()); mainPanel.add(splitPanel); splitPanel.setHeight("250px"); HorizontalPanel buttons_hp = new HorizontalPanel(); buttons_hp.add(cancelButton); buttons_hp.add(updateButton); buttons_hp.setSpacing(3); cancelButton.addClickHandler(this); updateButton.addClickHandler(this); com.google.gwt.user.client.ui.Widget hrule = new SimplePanel(); hrule.addStyleName(SettingsDialog.CSS_HRULE); mainPanel.add(hrule); mainPanel.add(buttons_hp); mainPanel.setCellHorizontalAlignment(buttons_hp, HorizontalPanel.ALIGN_RIGHT); this.setWidget(mainPanel); } private Widget createRightPanel() { final VerticalPanel rightVP = new VerticalPanel(); rightVP.add(new HTML("<b>Available tags:</b>")); rightVP.add(new Label("Loading...")); // getAllTags OneSwarmRPCClient.getService().getAllTags(OneSwarmRPCClient.getSessionID(), new AsyncCallback<FileTree>() { public void onFailure(Throwable caught) { caught.printStackTrace(); } public void onSuccess(FileTree result) { rightVP.remove(1); if (result == null) { hide(); new ReportableErrorDialogBox("Couldn't load tag list!", false); } mAllTagsTree = new Tree(); mAllTagsRoot = mAllTagsTree.addItem("All tags"); addChildren(mAllTagsRoot, result.getChildren(), null); expandAll(mAllTagsRoot); mAllTagsRoot.setSelected(true); mAllTagsTree.setSelectedItem(mAllTagsRoot, true); mAllTagsTree.addSelectionHandler(new SelectionHandler<TreeItem>() { public void onSelection(SelectionEvent<TreeItem> event) { boolean enabled = !event.getSelectedItem().equals(mAllTagsRoot); if (addSelectedButton != null) { addSelectedButton.setEnabled(enabled); } } }); HorizontalPanel rightActions = new HorizontalPanel(); addSelectedButton = new Button("Add"); moveButton = new Button("Move"); addSelectedButton.setEnabled(false); addSelectedButton.addStyleName(OneSwarmCss.SMALL_BUTTON); moveButton.addStyleName(OneSwarmCss.SMALL_BUTTON); addSelectedButton.addClickHandler(TagEditorDialog.this); moveButton.addClickHandler(TagEditorDialog.this); rightActions.add(moveButton); rightActions.add(addSelectedButton); rightActions.setSpacing(2); rightVP.add(rightActions); rightVP.add(mAllTagsTree); } }); return rightVP; } class MutableInt { public int v; }; private Widget createLeftPanel() { leftVP = new VerticalPanel(); leftVP.add(new HTML("<b>Current tags:</b>")); leftVP.add(new Label("Loading...")); mCurrentTagsTree = new Tree(); mCurrentTagsRoot = mCurrentTagsTree.addItem("All tags"); mCurrentTagsTree.setSelectedItem(mCurrentTagsRoot, true); mCurrentTagsTree.addSelectionHandler(new SelectionHandler<TreeItem>() { public void onSelection(SelectionEvent<TreeItem> event) { boolean enabled = !event.getSelectedItem().equals(mCurrentTagsRoot); if (removeButton != null) { removeButton.setEnabled(enabled); } } }); final MutableInt done = new MutableInt(); for (TorrentInfo t : mTorrents) { OneSwarmRPCClient.getService().getTags(OneSwarmRPCClient.getSessionID(), t.getTorrentID(), new AsyncCallback<FileTree>() { public void onFailure(Throwable caught) { caught.printStackTrace(); } public void onSuccess(FileTree result) { addChildren(mCurrentTagsRoot, result.getChildren(), null); if ((++done.v) == mTorrents.length) { leftLoadDone(mCurrentTagsTree); expandAll(mCurrentTagsRoot); } } }); } return leftVP; } private void leftLoadDone(Tree finishedTree) { leftVP.remove(1); HorizontalPanel buttonsHP = new HorizontalPanel(); addButton = new Button("Add"); removeButton = new Button("Remove"); removeButton.setEnabled(false); clearButton = new Button("Clear"); buttonsHP.add(addButton); buttonsHP.add(removeButton); buttonsHP.add(clearButton); addButton.addClickHandler(this); removeButton.addClickHandler(this); clearButton.addClickHandler(this); addButton.addStyleName(OneSwarmCss.SMALL_BUTTON); removeButton.addStyleName(OneSwarmCss.SMALL_BUTTON); clearButton.addStyleName(OneSwarmCss.SMALL_BUTTON); buttonsHP.setSpacing(2); leftVP.add(buttonsHP); leftVP.add(finishedTree); } private void commit() { System.out.println("should save here"); List<String> tags = new ArrayList<String>(); for (int kItr = 0; kItr < mCurrentTagsRoot.getChildCount(); kItr++) { for (String tag : getPaths(mCurrentTagsRoot.getChild(kItr))) { tags.add(tag); } } for (String s : tags) { System.out.println("client sending tag: " + s); } String[] rpcArr = null; if (tags.size() > 0) { rpcArr = tags.toArray(new String[0]); } for (TorrentInfo torrent : mTorrents) { OneSwarmRPCClient.getService().setTags(OneSwarmRPCClient.getSessionID(), torrent.getTorrentID(), rpcArr, new AsyncCallback<Void>() { public void onFailure(Throwable caught) { caught.printStackTrace(); } public void onSuccess(Void result) { mUIRoot.refreshSwarms(); } }); } } private static List<String> getPaths(TreeItem curr) { if (curr.getChildCount() == 0) { return Arrays.asList(new String[] { curr.getText() }); } else { List<String> out = new ArrayList<String>(); for (int kItr = 0; kItr < curr.getChildCount(); kItr++) { for (String path : getPaths(curr.getChild(kItr))) { out.add(curr.getText() + "/" + path); } } return out; } } public static void addChildren(TreeItem parent, FileTree[] kids, PickupDragController controller) { if (kids == null) { return; } boolean found = false; for (FileTree kid : kids) { found = false; TreeItem kti = null; String name = kid.getName(); for (int kItr = 0; kItr < parent.getChildCount(); kItr++) { if (parent.getChild(kItr).getText().equals(name)) { found = true; kti = parent.getChild(kItr); break; } } if (!found) { final Label l = new Label(name); kti = new TreeItem(l) { public String getText() { return l.getText(); } public void setSelected(boolean selected) { if (selected) { l.addStyleDependentName("selected"); } else { l.removeStyleDependentName("selected"); } super.setSelected(selected); } }; // kti = parent.addItem(name); parent.addItem(kti); if (controller != null) { controller.registerDropController(new TreeItemDropController(l, kti)); } l.setStylePrimaryName("gwt-TreeItem"); l.setStyleName("gwt-TreeItem"); } addChildren(kti, kid.getChildren(), controller); } } final static class TreeItemDropController extends SimpleDropController { private static final String SELECTED = "selected"; private final TreeItem item; private TreeItemDropController(Label dropTarget, TreeItem item) { super(dropTarget); this.item = item; } public void onDrop(DragContext context) { List<Widget> selectedWidgets = context.selectedWidgets; // Window.alert("got drag and drop"); for (Widget widget : selectedWidgets) { if (widget instanceof TorrentContainingImage) { TorrentInfo torrent = ((TorrentContainingImage) widget).getTorrent(); String path = item.getText(); TreeItem current = item; TreeItem parent; while ((parent = current.getParentItem()) != null && parent.getParentItem() != null) { path = parent.getText() + "/" + path; current = parent; } if (Window .confirm("Set tag for '" + torrent.getName() + "' to '" + path + "'?")) { OneSwarmRPCClient.getService().setTags(OneSwarmRPCClient.getSessionID(), torrent.getTorrentID(), new String[] { path }, new AsyncCallback<Void>() { public void onFailure(Throwable caught) { caught.printStackTrace(); } public void onSuccess(Void result) { EntireUIRoot.getRoot(item.getWidget()).refreshSwarms(); } }); } } } } public void onEnter(DragContext context) { if (!item.isSelected()) { item.addStyleDependentName(SELECTED); if (item.getWidget() != null) { item.getWidget().addStyleDependentName(SELECTED); } } } public void onLeave(DragContext context) { if (!item.isSelected()) { item.removeStyleDependentName(SELECTED); if (item.getWidget() != null) { item.getWidget().removeStyleDependentName(SELECTED); } } } } public static void expandAll(TreeItem curr) { curr.setState(true); for (int kItr = 0; kItr < curr.getChildCount(); kItr++) { expandAll(curr.getChild(kItr)); } } public void onClick(ClickEvent event) { boolean moveIt = false; if (event.getSource().equals(moveButton)) { moveIt = true; // this does the next two actions in order, which is // a move } if (event.getSource().equals(clearButton) || moveIt) { this.mCurrentTagsTree.clear(); mCurrentTagsRoot = mCurrentTagsTree.addItem("All tags"); } if (event.getSource().equals(addSelectedButton) || moveIt) { TreeItem selected = mAllTagsTree.getSelectedItem(); TreeItem added = selected; List<String> toAdd = new ArrayList<String>(); while (added.equals(mAllTagsRoot) == false) { toAdd.add(added.getText()); added = added.getParentItem(); } Collections.reverse(toAdd); TreeItem curr = mCurrentTagsRoot; boolean found = false; for (String s : toAdd) { found = false; for (int kid = 0; kid < curr.getChildCount(); kid++) { if (curr.getChild(kid).getText().equals(s)) { found = true; curr = curr.getChild(kid); break; } } if (!found) { curr = curr.addItem(s); curr.getParentItem().setState(true); } System.out.println("add selected: " + s); } } else if (event.getSource().equals(addButton)) { String name = Window.prompt("Tag name:", ""); if (name == null) { return; } if (name.length() == 0) { return; } name = name.replaceAll("/", "-"); TreeItem selected = mCurrentTagsTree.getSelectedItem(); boolean found = false; // check for duplicates for (int kid = 0; kid < selected.getChildCount(); kid++) { if (selected.getChild(kid).getText().equals(name)) { found = true; } } if (!found) { selected.addItem(name); selected.setState(true); } } else if (event.getSource().equals(removeButton)) { TreeItem selected = mCurrentTagsTree.getSelectedItem(); if (selected.equals(mCurrentTagsRoot)) { System.err.println("Cannot remove root"); } mCurrentTagsTree.setSelectedItem(selected.getParentItem(), true); selected.getParentItem().removeItem(selected); selected.remove(); } else if (event.getSource().equals(clearButton)) { this.mCurrentTagsTree.clear(); mCurrentTagsRoot = mCurrentTagsTree.addItem("All tags"); } else if (event.getSource().equals(updateButton)) { commit(); hide(); } else if (event.getSource().equals(cancelButton)) { hide(); } else { super.onClick(event); } } }