package edu.washington.cs.oneswarm.ui.gwt.client.newui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import com.allen_sauer.gwt.dnd.client.PickupDragController;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Command;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.ChangeListener;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.DockPanel;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Hyperlink;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.MenuBar;
import com.google.gwt.user.client.ui.MenuItem;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.ScrollPanel;
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.TreeListener;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
import com.google.gwt.widgetideas.client.ProgressBar;
import com.google.gwt.widgetideas.graphics.client.Color;
import com.google.gwt.widgetideas.graphics.client.GWTCanvas;
import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmDialogBox;
import edu.washington.cs.oneswarm.ui.gwt.client.OneSwarmGWT;
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.Updateable;
import edu.washington.cs.oneswarm.ui.gwt.client.fileDialog.FileBrowser;
import edu.washington.cs.oneswarm.ui.gwt.client.filebrowser.TorrentDownloaderDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.filebrowser.UpdateSkippedFilesDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.i18n.OSMessages;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.creation.CreateSwarmDialogBox;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.debug.DebugDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.friends.FriendsDetailsListPanel;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.permissions.SwarmPermissionsDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.publish.PublishSwarmsDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.settings.SettingsDialog;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.settings.UISettingsPanel;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.transfer_details.TransferDetailsPanel;
import edu.washington.cs.oneswarm.ui.gwt.client.newui.transfer_details.TransferDetailsTable;
import edu.washington.cs.oneswarm.ui.gwt.rpc.BackendErrorReport;
import edu.washington.cs.oneswarm.ui.gwt.rpc.FileTree;
import edu.washington.cs.oneswarm.ui.gwt.rpc.FriendInfoLite;
import edu.washington.cs.oneswarm.ui.gwt.rpc.OneSwarmConstants;
import edu.washington.cs.oneswarm.ui.gwt.rpc.PagedTorrentInfo;
import edu.washington.cs.oneswarm.ui.gwt.rpc.PermissionsGroup;
import edu.washington.cs.oneswarm.ui.gwt.rpc.ReportableException;
import edu.washington.cs.oneswarm.ui.gwt.rpc.StringTools;
import edu.washington.cs.oneswarm.ui.gwt.rpc.TorrentInfo;
public class SwarmsBrowser extends VerticalPanel implements Updateable {
class PreviewPanel extends SimplePanel {
};
private static OSMessages msg = OneSwarmGWT.msg;
public static final int ICON_WIDTH = 128;
public static final int ICON_HEIGHT = 128;
public static final int CELL_WIDTH = 150; // also need to change this in
// the CSS...
public static final int DIRECTORY_SCROLL_WIDTH = 150;
public static final String CSS_VIDEO_BROWSER = "os-video_browser";
private static final String CSS_FILE_HIGHLIGHT = "os-file_highlighted";
private static final String CSS_F2F_LABEL = "os-f2f_label";
private static final String CSS_BROWSER_HEADER = "os-browser_header_buttons";
private static final String CSS_FILE_ICON = "os-file_icon";
private static final String CSS_VIDEO_PREVIEW_BG = "os-video_preview_bg";
private static final String CSS_PREVIEW_TRANSFERRING = "os-transferring";
private static final String CSS_FILTERED_COUNT = "os-filtered_count_label";
private static final String COOKIE_SWARMS_PER_PAGE_INDEX = "swarmsPerPage";
private static final String COOKIE_SWARMS_VIEW = "oneswarmView";
private static final String COOKIE_SHOW_FRIENDS_SWARMS = "showFriendsSwarms";
private static final int FNAME_BUFFER = 20;
protected static final String ROOT_TAG_LABEL = msg.swarm_browser_tags_root();
private int mSwarmsPerPage = 5;
private long mNextWarningCheck = 0;
private boolean mShowingFriends = false;
/**
* UI widgets and widgets reflecting data
*/
List<GWTCanvas[]> mHighlighted = new ArrayList<GWTCanvas[]>();
// private GWTCanvas[] mCurrentHighlights = new GWTCanvas[2];
TransferDetailsTable transferDetailsTable = null;
HTML allFilesFiltered = new HTML("<div id=\"" + OneSwarmCss.CSS_NOTHING_SHOWING + "\">"
+ msg.swarm_browser_no_files_search_friends_HMTL("") + "</a></div>");
HTML noFilesHTML = new HTML("<div id=\"" + OneSwarmCss.CSS_NOTHING_SHOWING + "\">"
+ Strings.get(Strings.NO_FILES_MESSAGE) + "</div>");
HTML noFriendsFilesHTML = new HTML("<div id=\"" + OneSwarmCss.CSS_NOTHING_SHOWING + "\">"
+ msg.swarm_browser_no_files_shared() + "</div>");
Widget welcomePanel = new NewUserSetupPanel(this);
/**
* This is a total hack to compensate for the fact that GWT-FX RC2 doesn't
* have any way to remove effects on a panel (or clear them) without a
* reference to the Effect object itself.
*/
Map<VerticalPanel, PreviewPanel> filePanel_to_fade = new HashMap<VerticalPanel, PreviewPanel>();
final List<Button> headerButtons = new ArrayList<Button>(4);
final FlowPanel filesFlowPanel = new FlowPanel();
final Label filteredCount = new Label();
final ListBox moreActions = new ListBox();
final CheckBox mShowFriendsCheckbox = new CheckBox(msg.swarm_browser_show_friends_swarms());
// We may need to change the text on this to reflect whether or not we can
// actually play it
Button playButton = null;
Button debugButton = null;
boolean mShowingTransfers = false;
private int mPreviousFullRefreshTotalSwarmsCount;
private TorrentInfo[] mSwarmsOrderedByDisplay = null;
private final Tree mDirectoryTree = new Tree();
private ScrollPanel mDirectoryScroll = null; // so we can hide/show this
private HorizontalPanel mFoldersAndFiles = null;
private TreeItem mRootTreeItem = null;
/**
* Actual data
*/
// TorrentList mTorrents = new TorrentList();
List<TorrentInfo> mTransferringSwarms = new ArrayList<TorrentInfo>();
List<ProgressBar> mProgressBars = new ArrayList<ProgressBar>();
enum DoubleClickAction {
BrowserPlay(Strings.SWARM_BROWSER_PLAY), SystemPlay(Strings.SWARM_DEFAULT_PLAY), OpenFolder(
Strings.SWARM_REVEAL);
String action;
DoubleClickAction(String inAction) {
action = inAction;
}
public String getAction() {
return action;
}
};
DoubleClickAction mDoubleClickAction = DoubleClickAction.BrowserPlay;
/**
* Glue
*/
// Maintained by addFile() / removeFile()
HashMap<TorrentInfo, PreviewPanel> torrent_to_panel = new HashMap<TorrentInfo, PreviewPanel>();
// List<EffectPanel> mCurrentlyFiltered = new ArrayList<EffectPanel>();
String mFilterPattern = "";
final SwarmsBrowser this_shadow = this;
long mLastFileRefresh = 0;
/**
* The TorrentInfo associated with the swarm most recently moused over. This
* is distinct from the selected swarm since we need to support the popup
* menu.
*/
// TorrentInfo mMouseOverSwarm = null;
// The TorrentInfo associated with the currently selected swarm
List<TorrentInfo> mSelectedSwarms = new ArrayList<TorrentInfo>();
private HorizontalPanel mPagingPanel;
private ListBox swarmsPerPagePopup;
private HorizontalPanel mSwarmsPerPagePanel;
private boolean mUsingIconView = true;
private boolean useDebug = false;
private SimplePanel mTagsFilesSeparator;
public SwarmsBrowser(boolean useDebug) {
this.useDebug = useDebug;
addStyleName(CSS_VIDEO_BROWSER);
this.add(createHeaderButtons());
mPagingPanel = createPagingNavigationPanel();
this.add(mPagingPanel);
// setWidth("100%");
mFoldersAndFiles = new HorizontalPanel();
mFoldersAndFiles.setWidth("100%");
mDirectoryScroll = new ScrollPanel();
// mDirectoryScroll.addStyleName(CSS_TAGS_TREE_SCROLL);
mDirectoryScroll.setWidth(DIRECTORY_SCROLL_WIDTH + "px");
mDirectoryScroll.add(mDirectoryTree);
mFoldersAndFiles.add(mDirectoryScroll);
mFoldersAndFiles.setCellWidth(mDirectoryScroll, DIRECTORY_SCROLL_WIDTH + "px");
/**
* Hack attack.
*/
mTagsFilesSeparator = new SimplePanel();
mTagsFilesSeparator.setWidth("1px");
mFoldersAndFiles.add(mTagsFilesSeparator);
com.google.gwt.user.client.Element td = DOM.getParent(mTagsFilesSeparator.getElement());
DOM.setStyleAttribute(td, "borderRight", "1px solid #d2d2d2");
/********/
mFoldersAndFiles.add(filesFlowPanel);
mDirectoryTree.addTreeListener(new TreeListener() {
@Override
public void onTreeItemSelected(TreeItem item) {
refreshActive(true);
}
@Override
public void onTreeItemStateChanged(TreeItem item) {
}
});
// this.add(filesFlowPanel);
this.add(mFoldersAndFiles);
filteredCount.addStyleName(CSS_FILTERED_COUNT);
updateFilteredCount(0);
this.add(filteredCount);
mSwarmsPerPagePanel = new HorizontalPanel();
mSwarmsPerPagePanel.setSpacing(3);
Label sppLabel = new Label(msg.swarm_browser_swarms_per_page());
mSwarmsPerPagePanel.add(sppLabel);
swarmsPerPagePopup = new ListBox();
for (int i : new int[] { 10, 20, 35, 50, 100, 200, 500 }) {
swarmsPerPagePopup.addItem(Integer.toString(i));
}
mSwarmsPerPagePanel.setCellVerticalAlignment(sppLabel, VerticalPanel.ALIGN_MIDDLE);
mSwarmsPerPagePanel
.setCellVerticalAlignment(swarmsPerPagePopup, VerticalPanel.ALIGN_MIDDLE);
try {
int spp = Integer.parseInt(Cookies.getCookie(COOKIE_SWARMS_PER_PAGE_INDEX));
if (spp > 0 && spp < swarmsPerPagePopup.getItemCount()) {
swarmsPerPagePopup.setSelectedIndex(spp);
}
} catch (Exception e) {
swarmsPerPagePopup.setSelectedIndex(1);
}
try {
if (Cookies.getCookie(COOKIE_SWARMS_VIEW).equals("list")) {
mUsingIconView = false;
}
} catch (Exception e) {
mUsingIconView = true;
}
mSwarmsPerPage = Integer.parseInt(swarmsPerPagePopup.getItemText(swarmsPerPagePopup
.getSelectedIndex()));
swarmsPerPagePopup.addChangeListener(new ChangeListener() {
@Override
public void onChange(Widget sender) {
mSwarmsPerPage = Integer.parseInt(swarmsPerPagePopup.getItemText(swarmsPerPagePopup
.getSelectedIndex()));
Cookies.setCookie(COOKIE_SWARMS_PER_PAGE_INDEX,
swarmsPerPagePopup.getSelectedIndex() + "",
OneSwarmConstants.TEN_YEARS_FROM_NOW);
pageZero();
changeFilter(mCurrentFileTypeFilter, true);
}
});
mSwarmsPerPagePanel.add(swarmsPerPagePopup);
this.add(mSwarmsPerPagePanel);
this.setCellHorizontalAlignment(mSwarmsPerPagePanel, HorizontalPanel.ALIGN_CENTER);
/*
* save the "show friends swarms" state
*/
try {
boolean show = Boolean.parseBoolean(Cookies.getCookie(COOKIE_SHOW_FRIENDS_SWARMS));
mShowFriendsCheckbox.setValue(show);
} catch (Exception e) {
mShowFriendsCheckbox.setValue(false);
}
this.add(mShowFriendsCheckbox);
mShowFriendsCheckbox.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Cookies.setCookie(COOKIE_SHOW_FRIENDS_SWARMS, mShowFriendsCheckbox.getValue() + "",
OneSwarmConstants.TEN_YEARS_FROM_NOW);
refreshActive(true);
}
});
sync_settings();
/*
* add click listener to noFriendsFilesLabel
*/
allFilesFiltered.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (mFilterPattern.trim().length() < NavigationFilterBar.MIN_SEARCH_LENGTH) {
Window.alert(msg
.swarm_browser_warning_short_search(NavigationFilterBar.MIN_SEARCH_LENGTH));
return;
}
mEntireUIRoot.displaySearch(mFilterPattern);
}
});
this.setCellHorizontalAlignment(mShowFriendsCheckbox, HorizontalPanel.ALIGN_CENTER);
refreshActive(false);
OneSwarmGWT.addToUpdateTask(this);
}
@Override
protected void onAttach() {
super.onAttach();
mEntireUIRoot = EntireUIRoot.getRoot(this);
}
ListBox mSortByList = new ListBox();
ListBox mJumpList = new ListBox();
Label mShowingLabel = new Label();
public final static String SORT_BY_NAME = msg.swarm_browser_sort_name();
public final static String SORT_BY_DATE = msg.swarm_browser_sort_date();
public final static String SORT_BY_SIZE = msg.swarm_browser_sort_size();
public final static int SORT_BY_NAME_ID = 0;
public final static int SORT_BY_DATE_ID = 1;
public final static int SORT_BY_SIZE_ID = 2;
public static final long DOUBLE_CLICK_THRESHOLD = 750;
private int mSortingMetric = SORT_BY_DATE_ID;
private final ChangeListener mJumpChangeListener = new ChangeListener() {
@Override
public void onChange(Widget sender) {
System.out.println("change listener, mJumpList.getSelectedIndex: "
+ mJumpList.getSelectedIndex());
changeFilter(SwarmsBrowser.this.mCurrentFileTypeFilter, true);
updateShowingLabel();
}
};
private ClickHandler nextPreviousPageLinkListener;
private Hyperlink prevLink;
private Hyperlink nextLink;
private HTML mChatHTML;
private HorizontalPanel createPagingNavigationPanel() {
HorizontalPanel hp = new HorizontalPanel();
HorizontalPanel lhs = new HorizontalPanel(), rhs = new HorizontalPanel(), center = new HorizontalPanel();
hp.add(lhs);
hp.add(center);
hp.add(rhs);
hp.setCellHorizontalAlignment(lhs, HorizontalPanel.ALIGN_LEFT);
hp.setCellHorizontalAlignment(rhs, HorizontalPanel.ALIGN_RIGHT);
hp.setCellHorizontalAlignment(center, HorizontalPanel.ALIGN_CENTER);
hp.setCellVerticalAlignment(rhs, HorizontalPanel.ALIGN_MIDDLE);
hp.setCellVerticalAlignment(lhs, HorizontalPanel.ALIGN_MIDDLE);
hp.setCellVerticalAlignment(center, HorizontalPanel.ALIGN_MIDDLE);
mSortByList.addItem(SORT_BY_DATE, "" + SORT_BY_DATE_ID);
mSortByList.addItem(SORT_BY_NAME, "" + SORT_BY_NAME_ID);
mSortByList.addItem(SORT_BY_SIZE, "" + SORT_BY_SIZE_ID);
mSortByList.addChangeListener(new ChangeListener() {
@Override
public void onChange(Widget sender) {
int oldMetric = mSortingMetric;
mSortingMetric = Integer.parseInt(mSortByList.getValue(mSortByList
.getSelectedIndex()));
System.out.println("sorting metric: " + mSortingMetric);
if (mSortingMetric == oldMetric == false) {
System.out.println("changeFilter()");
pageZero(); // this calls changeFilter()
mJumpChangeListener.onChange(mJumpList); // force
// refiltering,
// etc.
// changeFilter(mCurrentFileTypeFilter, true); // this will
// resort
}
}
});
String which = Cookies.getCookie(COOKIE_SWARMS_VIEW);
if (which == null) {
which = "icons";
} else if (!(which.equals("icons") || which.equals("list"))) {
which = "icons";
}
final Hyperlink viewLink = new Hyperlink(
which.equals("icons") ? Strings.get(Strings.LIST_VIEW)
: Strings.get(Strings.ICON_VIEW), "");
viewLink.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (viewLink.getText().equals(Strings.get(Strings.LIST_VIEW))) {
viewLink.setText(Strings.get(Strings.ICON_VIEW));
mUsingIconView = false;
Cookies.setCookie(COOKIE_SWARMS_VIEW, "list",
OneSwarmConstants.TEN_YEARS_FROM_NOW);
refreshActive(false);
} else {
viewLink.setText(Strings.get(Strings.LIST_VIEW));
mUsingIconView = true;
Cookies.setCookie(COOKIE_SWARMS_VIEW, "icons",
OneSwarmConstants.TEN_YEARS_FROM_NOW);
refreshActive(false);
}
}
});
mChatHTML = new HTML("| <a href=\"#\">" + msg.swarm_browser_chat() + "</a>");
mChatHTML.setVisible(false);
mChatHTML.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
mEntireUIRoot.startChat(mEntireUIRoot.getSelectedFriend());
}
});
Label sortLabel = new Label(msg.swarm_browser_sort());
lhs.add(sortLabel);
lhs.add(mSortByList);
Image spacer = new Image(GWT.getModuleBaseURL() + "images/spacer.png");
spacer.setWidth("3px");
spacer.setHeight("3px");
lhs.add(spacer);
lhs.add(viewLink);
lhs.add(spacer);
lhs.add(mChatHTML);
// lhs.add(iconView);
// lhs.add(listView);
lhs.setCellVerticalAlignment(sortLabel, VerticalPanel.ALIGN_MIDDLE);
lhs.setCellVerticalAlignment(mSortByList, VerticalPanel.ALIGN_MIDDLE);
lhs.setCellVerticalAlignment(viewLink, VerticalPanel.ALIGN_MIDDLE);
lhs.setCellVerticalAlignment(mChatHTML, VerticalPanel.ALIGN_MIDDLE);
center.add(mShowingLabel);
prevLink = new Hyperlink(msg.swarm_browser_show_prev_swarms(), "prevfiles");
nextLink = new Hyperlink(msg.swarm_browser_show_next_swarms(), "morefiles");
nextPreviousPageLinkListener = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
int incDec = 0;
Object sender = event.getSource();
if (sender.equals(prevLink)) {
if (mJumpList.getSelectedIndex() - 1 < 0)
return;
incDec = -1;
} else if (sender.equals(nextLink)) {
if (mJumpList.getSelectedIndex() + 1 >= mJumpList.getItemCount())
return;
incDec = 1;
} else {
System.err.println("unknown next/prev widget, shouldn't happen");
incDec = 0;
}
mJumpList.setSelectedIndex(mJumpList.getSelectedIndex() + incDec);
System.out.println("selectedIndex: " + mJumpList.getSelectedIndex());
changeFilter(SwarmsBrowser.this.mCurrentFileTypeFilter, true);
}
};
prevLink.addClickHandler(nextPreviousPageLinkListener);
nextLink.addClickHandler(nextPreviousPageLinkListener);
rhs.add(prevLink);
Label divideLabel = new Label("|");
rhs.add(divideLabel);
rhs.add(nextLink);
rhs.setSpacing(3);
rhs.add(mJumpList);
rhs.setCellVerticalAlignment(nextLink, VerticalPanel.ALIGN_MIDDLE);
rhs.setCellVerticalAlignment(prevLink, VerticalPanel.ALIGN_MIDDLE);
rhs.setCellVerticalAlignment(divideLabel, VerticalPanel.ALIGN_MIDDLE);
rhs.setCellVerticalAlignment(mJumpList, VerticalPanel.ALIGN_MIDDLE);
hp.setWidth("100%");
updateNavigationPanel();
mJumpList.addChangeListener(mJumpChangeListener);
return hp;
}
/**
* changes the pages count in response to events (e.g. filtering changes)
*/
private void updateNavigationPanel() {
int current = Math.max(mJumpList.getSelectedIndex(), 0); // /
// math.max
// for
// corner
// case of
// nothing
// selected
// at start
int count = (int) Math.max(1,
Math.ceil((double) mTotalSwarmsForFilterType / (double) mSwarmsPerPage));
if (mJumpList.getItemCount() != count) {
mJumpList.clear();
for (int i = 0; i < count; i++) {
mJumpList.addItem(Integer.toString(i));
}
mJumpList.setSelectedIndex(Math.min(current, mJumpList.getItemCount() - 1));
}
updateShowingLabel();
}
private void updateShowingLabel() {
int curr = mJumpList.getSelectedIndex() * mSwarmsPerPage;
String extra = "";
if (mTotalSwarmSizeForFilterType != null) {
extra += " (" + mTotalSwarmSizeForFilterType + ")";
}
mShowingLabel.setText(msg.swarm_browser_showing_swarms(curr,
Math.min(curr + mSwarmsPerPage, mTotalSwarmsForFilterType),
(mTotalSwarmsForFilterType)) + extra);
}
private void updateFilteredCount(int count) {
filteredCount.setText(count + " filtered");
if (count == 0) {
DOM.setStyleAttribute(filteredCount.getElement(), "visibility", "hidden");
DOM.setStyleAttribute(filteredCount.getElement(), "height", "0pt");
} else {
DOM.setStyleAttribute(filteredCount.getElement(), "visibility", "visible");
DOM.setStyleAttribute(filteredCount.getElement(), "height", "10pt");
}
}
EntireUIRoot mEntireUIRoot = null;
/**
* a hack to prevent using MouseListener on a FocusWidget on the
* EntireUIRoot (which can use a lot of CPU)
*/
public void propAction() {
if (mEntireUIRoot == null) {
mEntireUIRoot = mEntireUIRoot;
}
if (mEntireUIRoot != null) {
mEntireUIRoot.actionOccurred();
}
}
public void dispatchSwarmAction(String inActionKey, TorrentInfo[] inTorrents) {
propAction();
System.out.println("got swarm action: " + inActionKey);
if (inActionKey.equals(Strings.SWARM_BROWSER_PLAY)) {
System.out.println("got play action");
if (inTorrents[0].isF2FOnly() == false) {
boolean goForIt = true;
if (inTorrents[0].getProgress() < 1000) {
if (inTorrents[0].getDownloadRate() == 0
|| (inTorrents[0].getSeeders() + inTorrents[0].getLeechers() == 0)) {
goForIt = Window.confirm(msg.swarm_browser_warning_stalled_swarm());
} else if (inTorrents[0].getDownloadRate() < 50
&& inTorrents[0].getProgress() < 900) {
goForIt = Window.confirm(msg.swarm_browser_warning_slow_swarm());
}
}
if (goForIt) {
startBrowserPlayer(inTorrents[0]);
}
} else {
for (TorrentInfo inTorrent : inTorrents) {
TorrentDownloaderDialog dlg = new TorrentDownloaderDialog(mEntireUIRoot, null,
inTorrent.getF2F_ID(), inTorrent.getFileListLiteRepresentation(), true);
dlg.everythingChecked();
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() + 125);
dlg.setVisible(true);
}
}
} else if (inActionKey.equals(Strings.SWARM_DETAILS)) {
for (TorrentInfo inTorrent : inTorrents) {
UpdateSkippedFilesDialog dlg = new UpdateSkippedFilesDialog(mEntireUIRoot,
inTorrent);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() + 125);
dlg.setVisible(true);
}
} else if (inActionKey.equals(Strings.SWARM_PUBLISH)) {
TorrentInfo[] infos = getSelectedSwarms();
if (infos != null && infos.length >= 1) {
PublishSwarmsDialog dlg = new PublishSwarmsDialog(mEntireUIRoot, infos);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() + 125);
dlg.setVisible(true);
}
} else if (inActionKey.equals(Strings.SWARM_COPY_MAGNET)) {
TorrentInfo[] infos = getSelectedSwarms();
if (infos != null && infos.length >= 1) {
OneSwarmRPCClient.getService().copyTorrentInfoToMagnetLink(
OneSwarmRPCClient.getSessionID(), new String[] { infos[0].getTorrentID() },
new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
OneSwarmGWT.log("Error: " + caught.getMessage());
}
@Override
public void onSuccess(String success) {
System.out.println("copy success: " + success);
if (OneSwarmGWT.isRemoteAccess()) {
Window.alert("Link: " + success);
}
}
});
}
} else if (inActionKey.equals(Strings.ADD_SWARM_FILE)) {
FileBrowser dialog = new FileBrowser(OneSwarmRPCClient.getSessionID(),
false, new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(String result) {
if (result == null) {
return; // cancelled
}
/**
* We enable everything here since it's pretty
* likely that what is being opened is a public
* torrent. (Even if it is an F2F torrent, it will
* have an invalid tracker URL)
*/
ArrayList<PermissionsGroup> permitted = new ArrayList<PermissionsGroup>();
permitted.add(new PermissionsGroup(PermissionsGroup.ALL_FRIENDS));
permitted.add(new PermissionsGroup(PermissionsGroup.PUBLIC_INTERNET));
OneSwarmRPCClient.getService()
.addDownloadFromLocalTorrentDefaultSaveLocation(
OneSwarmRPCClient.getSessionID(), result, permitted,
new AsyncCallback<Void>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
// new
// ReportableErrorDialogBox(caught.getMessage(),
// false);
Window.alert(msg
.swarm_browser_warning_invalid_torrent());
}
@Override
public void onSuccess(Void result) {
; // success
}
});
}
});
dialog.show();
} else if (inActionKey.equals(Strings.SWARM_DELETE)) {
// keyboard shortcut doesn't check for this
if (deleteButton.isEnabled() == false) {
return;
}
/**
* We ask for confirmation
*/
DeleteTorrentDialog dlg = new DeleteTorrentDialog(getSelectedSwarms(), mEntireUIRoot);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
} else if (inActionKey.equals(Strings.SWARM_REVEAL)) {
/*
* check if remote access,
*/
if (OneSwarmGWT.isRemoteAccess()) {
/*
* open a new window and redirect to /files/hash/
*/
TorrentInfo[] swarms = getSelectedSwarms();
for (TorrentInfo swarm : swarms) {
Window.open("/files/" + swarm.getTorrentID().replace("urn_btih_", "") + "/",
"_blank", "status=0,toolbar=0,menubar=0,location=0,resizable=0");
}
} else {
/*
* otherwise open the normal folder view
*/
OneSwarmRPCClient.getService().revealSwarmInFinder(
OneSwarmRPCClient.getSessionID(), getSelectedSwarms(),
new AsyncCallback<ReportableException>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(ReportableException result) {
if (result != null) {
new ReportableErrorDialogBox(result, false);
}
}
});
}
} else if (inActionKey.equals(Strings.SWARM_DEFAULT_PLAY)) {
System.out.println("got default play event");
OneSwarmRPCClient.getService().openFileDefaultApp(OneSwarmRPCClient.getSessionID(),
getSelectedSwarms(), new AsyncCallback<ReportableException>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(ReportableException result) {
if (result != null) {
new ReportableErrorDialogBox(result, false);
}
}
});
} else if (inActionKey.equals(Strings.MANAGE_PERMS)) {
// SwarmDetailsDialog dlg = new
// SwarmDetailsDialog(EntireUIRoot.getRoot(this),
// torrent_to_panel.keySet().toArray(new TorrentInfo[0]));
if (mPreviousFullRefreshTotalSwarmsCount == 0) {
Window.alert(msg.swarm_browser_warning_no_visibility_with_no_swarms());
} else {
OneSwarmRPCClient.getService().getPagedAndFilteredSwarms(0, Integer.MAX_VALUE, "",
SORT_BY_NAME_ID, "all", false, Integer.MIN_VALUE, null,
new AsyncCallback<PagedTorrentInfo>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(PagedTorrentInfo result) {
TorrentInfo[] selectedarr = getSelectedSwarms();
TorrentInfo selected = null;
if (selectedarr != null) {
if (selectedarr.length > 0) {
selected = selectedarr[0];
}
}
SwarmPermissionsDialog dlg = new SwarmPermissionsDialog(
result.swarms, selected);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(),
Window.getScrollTop() + 100);
dlg.setVisible(true);
}
});
}
}
// else if (inActionKey.equals(Strings.SEARCH_FRIENDS)) {
// SearchDialog dlg = new SearchDialog(EntireUIRoot.getRoot(this),
// null);
// dlg.show();
// dlg.setVisible(false);
// dlg.center();
// dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() +
// 100);
// dlg.setVisible(true);
// }
else if (inActionKey.equals(Strings.DEBUG)) {
DebugDialog dlg = new DebugDialog();
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() + 20);
dlg.setVisible(true);
} else if (inActionKey.equals(Strings.SWARM_STARTSTOP)) {
System.out.println("stopstart action");
TorrentInfo[] selected = getSelectedSwarms();
final String[] selected_ids = new String[selected.length];
if (selected[0].isStarted()) {
for (int i = 0; i < selected.length; i++) {
selected[i].setStatus(TorrentInfo.ST_STOPPED);
selected_ids[i] = selected[i].getTorrentID();
}
OneSwarmRPCClient.getService().stopTorrent(OneSwarmRPCClient.getSessionID(),
selected_ids, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(Boolean result) {
System.out.println("stopped torrents: " + selected_ids.length);
}
});
} else {
for (int i = 0; i < selected.length; i++) {
selected[i].setStatus(TorrentInfo.ST_STOPPED);
selected_ids[i] = selected[i].getTorrentID();
}
OneSwarmRPCClient.getService().startTorrent(OneSwarmRPCClient.getSessionID(),
selected_ids, new AsyncCallback<Boolean>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(Boolean result) {
System.out.println("started torrents: " + selected_ids.length);
}
});
}
} // swarm_startstop
}
long mLastClickTime = 0;
private void selectSwarm(TorrentInfo inTorrent) {
selectSwarm(inTorrent, false);
}
private void selectSwarm(TorrentInfo inTorrent, boolean fromClick) {
selectSwarm(inTorrent, fromClick, false);
}
private void selectSwarm(TorrentInfo inTorrent, boolean fromClick, boolean shiftDown) {
if (inTorrent != null) {
if (mSelectedSwarms.size() > 0) {
if (mSelectedSwarms.contains(inTorrent) && fromClick == true
&& (System.currentTimeMillis() - mLastClickTime) < DOUBLE_CLICK_THRESHOLD) {
if (inTorrent.isF2FOnly()) {
// really: download
dispatchSwarmAction(Strings.SWARM_BROWSER_PLAY, getSelectedSwarms());
} else {
doubleClick();
}
return;
}
}
mLastClickTime = System.currentTimeMillis();
}
/**
* If we aren't adding to the selection, remove all selections...
*/
if ((shiftDown == false) && mHighlighted.size() > 0) {
for (GWTCanvas[] highlight : mHighlighted) {
if (highlight[0].getParent() != null) {
if (highlight[0].getParent().getParent() != null) {
highlight[0].getParent().getParent().removeStyleName(CSS_FILE_HIGHLIGHT);
}
}
for (GWTCanvas c : highlight) {
c.removeFromParent();
}
}
mHighlighted.clear();
mSelectedSwarms.clear();
}
if (inTorrent != null) {
propAction();
/**
* This is brittle.
*/
VerticalPanel fnamePanel = (VerticalPanel) torrent_to_panel.get(inTorrent).getWidget(); // this
// is
// icon_with_name
// verticalpanel
AbsolutePanel fnameAbsolute = (AbsolutePanel) fnamePanel.getWidget(1);
Label fnameLabel = (Label) fnameAbsolute.getWidget(0);
int height = ((MaxHeightWithTorrentInfoLabel) fnameLabel).getActualHeight();
int width = fnameLabel.getOffsetWidth();
GWTCanvas canvas = new GWTCanvas(width, height);
Color fillColor = new Color(56, 117, 215);
canvas.setFillStyle(fillColor);
if (OneSwarmGWT.isIE()) {
canvas.setBackgroundColor(fillColor);
}
canvas.setStrokeStyle(new Color(0, 255, 0));
canvas.arc(5, height - 5, 5, (float) (Math.PI / 2), (float) (Math.PI), false);
canvas.lineTo(0, 5);
canvas.arc(5, 5, 5, (float) (Math.PI), (float) (3 * Math.PI / 2), false);
canvas.lineTo(width - 5, 0);
canvas.arc(width - 5, 5, 5, (float) (3 * Math.PI / 2), (float) (2 * Math.PI), false);
canvas.lineTo(width, height - 5);
canvas.arc(width - 5, height - 5, 5, (float) (2 * Math.PI), (float) (5 * Math.PI / 2),
false);
canvas.lineTo(0, height);
canvas.fill();
fnameAbsolute.add(canvas, 0, 0);
DOM.setStyleAttribute(canvas.getElement(), "zIndex", "-1");
GWTCanvas[] highlight = new GWTCanvas[2];
highlight[0] = canvas;
highlight[0].getParent().getParent().addStyleName(CSS_FILE_HIGHLIGHT);
/**
* Next, for the background for the icon
*/
height = ICON_HEIGHT;
width = ICON_WIDTH + FNAME_BUFFER;
canvas = new GWTCanvas(width, height);
fillColor = new Color(172, 172, 172);
canvas.setFillStyle(fillColor);
if (OneSwarmGWT.isIE()) {
canvas.setBackgroundColor(fillColor);
}
canvas.arc(5, height - 5, 5, (float) (Math.PI / 2), (float) (Math.PI), false);
canvas.lineTo(0, 5);
canvas.arc(5, 5, 5, (float) (Math.PI), (float) (3 * Math.PI / 2), false);
canvas.lineTo(width - 5, 0);
canvas.arc(width - 5, 5, 5, (float) (3 * Math.PI / 2), (float) (2 * Math.PI), false);
canvas.lineTo(width, height - 5);
canvas.arc(width - 5, height - 5, 5, (float) (2 * Math.PI), (float) (5 * Math.PI / 2),
false);
canvas.lineTo(0, height);
canvas.fill();
AbsolutePanel overlay = (AbsolutePanel) fnamePanel.getWidget(0);
overlay.add(canvas, 0, 0);
DOM.setStyleAttribute(canvas.getElement(), "zIndex", "-1");
highlight[1] = canvas;
mHighlighted.add(highlight);
if (currentMoveIcon != null) {
currentMoveIcon.setVisible(false);
}
if (mHighlighted.size() == 1 && !inTorrent.isF2FOnly()) {
for (int i = 0; i < overlay.getWidgetCount(); i++) {
Widget w = overlay.getWidget(i);
if (w instanceof Image && !w.isVisible()) {
w.setVisible(true);
currentMoveIcon = (Image) w;
break;
}
}
}
}
if (inTorrent != null) {
mSelectedSwarms.add(inTorrent);
} else {
mSelectedSwarms.clear();
}
refreshHeaderButtons();
}
public void startBrowserPlayer(TorrentInfo inTorrent) {
OneSwarmDialogBox dlg = new VideoDialog(inTorrent.getTorrentID(),
inTorrent.getProgress() != 1000, "", inTorrent.getNumFiles(), mEntireUIRoot);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getAbsoluteLeft(), Window.getScrollTop() + 100);
dlg.setVisible(true);
}
private FileTypeFilter mCurrentFileTypeFilter = FileTypeFilter.All;
private long mNextPagedUpdate;
private long mNextErrorPoll = 0;
private int mTotalSwarmsForFilterType;
private String mTotalSwarmSizeForFilterType = null;
private Button deleteButton;
private Button tagButton;
protected void refreshActive(boolean pageZero) {
if (pageZero) {
mJumpList.setSelectedIndex(0);
}
mLastFileRefresh = System.currentTimeMillis();
boolean showAllFriendsFiles = mShowFriendsCheckbox.getValue();
// filesFlowPanel.clear();
// torrent_to_panel.clear();
FileTypeFilter fileType = mCurrentFileTypeFilter;
int selectedFriendID = Integer.MIN_VALUE;
EntireUIRoot root = mEntireUIRoot;
if (root != null) {
FriendInfoLite friend = mEntireUIRoot.getSelectedFriend();
if (friend != null) {
selectedFriendID = friend.getConnectionId();
showAllFriendsFiles = false;
fileType = FileTypeFilter.All;
if (friend.isSupportsChat() && friend.isAllowChat()) {
mChatHTML.setVisible(true);
} else {
mChatHTML.setVisible(false);
}
} else {
mChatHTML.setVisible(false);
}
} else {
// during the first refreshActive() this will be null since we are
// not embedded. at this point, however, there's nothing selected
// anyway
}
// System.out.println("paged and filtered call. selected friend id: " +
// selectedFriendID);
final int selected_shadow = selectedFriendID;
OneSwarmRPCClient.getService().getPagedAndFilteredSwarms(
mJumpList.getSelectedIndex(),
Integer.parseInt(swarmsPerPagePopup.getItemText(swarmsPerPagePopup
.getSelectedIndex())), mFilterPattern, mSortingMetric, fileType.name(),
showAllFriendsFiles, selectedFriendID, getSelectedTagPath(),
new AsyncCallback<PagedTorrentInfo>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(PagedTorrentInfo result) {
/**
* Out of order RPC.
*/
if (SwarmsBrowser.this.mShowingFriends
|| SwarmsBrowser.this.mShowingTransfers) {
return;
}
filesFlowPanel.clear();
torrent_to_panel.clear();
mProgressBars.clear();
mTransferringSwarms.clear();
updateTags(result.tags, result.truncated_tags);
mTotalSwarmsForFilterType = result.total_swarms;
mPreviousFullRefreshTotalSwarmsCount = result.total_swarms;
mTotalSwarmSizeForFilterType = result.total_size;
mSwarmsOrderedByDisplay = result.swarms;
updateFilteredCount(result.filtered_count);
updateNavigationPanel();
boolean reselected = false;
if (mUsingIconView == false) {
final SwarmsListTable st = new SwarmsListTable(result.swarms,
SwarmsBrowser.this);
filesFlowPanel.add(st);
final Button selectAllButton = new Button(msg.button_select_all());
selectAllButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
final Button selectNoneButton = new Button(msg.button_select_none());
selectNoneButton.addStyleName(OneSwarmCss.SMALL_BUTTON);
filesFlowPanel.add(selectAllButton);
filesFlowPanel.add(selectNoneButton);
ClickHandler cl = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Object w = event.getSource();
if (w.equals(selectAllButton)) {
st.checkAll(true);
refreshHeaderButtons();
} else {
st.checkAll(false);
refreshHeaderButtons();
}
}
};
selectAllButton.addClickHandler(cl);
selectNoneButton.addClickHandler(cl);
refreshHeaderButtons();
} else {
for (TorrentInfo t : result.swarms) {
if (mSelectedSwarms.contains(t)) {
reselected = true;
}
addFileIcon(t, true);
}
if (!reselected) {
selectSwarm(null);
}
}
boolean filterEnabled = false;
if (mFilterPattern != null && mFilterPattern.length() > 0) {
filterEnabled = true;
allFilesFiltered.setHTML("<div id=\""
+ OneSwarmCss.CSS_NOTHING_SHOWING
+ "\">"
+ msg.swarm_browser_no_files_search_friends_HMTL(mFilterPattern)
+ "</a></div>");
}
if (result.total_swarms == 0 && result.by_type_count == 0
&& mCurrentFileTypeFilter.equals(FileTypeFilter.All)
&& selected_shadow == Integer.MIN_VALUE) {
if (filterEnabled) {
filesFlowPanel.add(allFilesFiltered);
} else {
filesFlowPanel.add(welcomePanel);
}
} else if (result.total_swarms == 0 && selected_shadow == Integer.MIN_VALUE) {
if (filterEnabled) {
filesFlowPanel.add(allFilesFiltered);
} else {
filesFlowPanel.add(noFilesHTML);
}
} else if (result.total_swarms == 0 && selected_shadow != Integer.MIN_VALUE) {
if (filterEnabled) {
filesFlowPanel.add(allFilesFiltered);
} else {
filesFlowPanel.add(noFriendsFilesHTML);
}
}
// System.out.println("got paged torrent result: total: "
// +
// mTotalSwarmsForFilterType + " / " +
// result.total_swarms + " "
// + result.filtered_count + " filtered bytype: " +
// result.by_type_count);
}
});
}
private String getSelectedTagPath() {
TreeItem selected = mDirectoryTree.getSelectedItem();
if (selected == null) {
return null;
}
String path = reverse(selected, 0);
return path;
}
protected void updateTags(FileTree tags, boolean truncated_tags) {
TreeItem root = mRootTreeItem;
/**
* We need to do this carefully to avoid changing the expansion /
* selection status of entries
*/
List<String> expandedPaths = null;
String selectedPath = null;
if (root != null) {
/**
* to eliminate firefox flicker, check to make sure if the current
* hierarchy is the same and only do the .clear() and repopulate if
* changes occurred. (no changes is by far the common case)
*/
if (changed(root, tags, 0) == false) {
// System.out.println("no change, skipping tree update");
return;
}
expandedPaths = getExpandedPaths(root);
selectedPath = null;
TreeItem selected = mDirectoryTree.getSelectedItem();
if (selected != null) {
selectedPath = ROOT_TAG_LABEL + "/" + reverse(selected, 0);
}
for (String expanded : expandedPaths) {
System.out.println("expanded: " + expanded);
}
System.out.println("selected: " + selectedPath);
}
mDirectoryTree.clear();
HTML rootTagLabel = new HTML(ROOT_TAG_LABEL);
root = mDirectoryTree.addItem(ROOT_TAG_LABEL);
if (truncated_tags) {
rootTagLabel.setHTML(ROOT_TAG_LABEL + "<a href=\"#\" >(!)</a>");
rootTagLabel.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
Window.alert(msg.swarm_browser_warning_tags_are_hidden());
}
});
}
mRootTreeItem = root;
if (tags != null) {
TagEditorDialog
.addChildren(root, tags.getChildren(), mEntireUIRoot.getDragController());
} else {
System.err.println("null tags!");
}
mRootTreeItem.setState(true);
TreeItem curr = mRootTreeItem;
if (expandedPaths != null) {
for (String path : expandedPaths) {
String[] toks = path.split("/");
if (toks.length == 0) {
System.err.println("no toks on path! " + path);
continue;
}
if (toks[0].equals(curr.getText())) {
curr.setState(true);
}
for (int tokItr = 1; tokItr < toks.length; tokItr++) {
for (int cItr = 0; cItr < curr.getChildCount(); cItr++) {
if (toks[tokItr].equals(curr.getChild(cItr).getText())) {
curr = curr.getChild(cItr);
curr.setState(true);
break;
}
}
}
} // for over expandedPaths
} else { // if( expandedPaths != null )
// expand first level
mRootTreeItem.setState(true);
}
if (selectedPath != null) {
System.out.println("selected is: " + selectedPath);
String[] toks = selectedPath.split("/");
curr = mRootTreeItem;
// corner case
if (selectedPath.equals(mRootTreeItem.getText() + "/")) {
mDirectoryTree.setSelectedItem(mRootTreeItem, false);
} else {
boolean good = false;
for (int level = 1; level < toks.length; level++) {
good = false;
for (int cItr = 0; cItr < curr.getChildCount(); cItr++) {
if (curr.getChild(cItr).getText().equals(toks[level])) {
curr = curr.getChild(cItr);
good = true;
}
}
if (good == false) {
break;
}
}
if (good) {
mDirectoryTree.setSelectedItem(curr, false);
} else {
refreshActive(true);
}
}
}
checkTagsPanelAttchment();
}
private void checkTagsPanelAttchment() {
if (mRootTreeItem != null && mDirectoryTree != null) {
if (mDirectoryTree.isAttached() && mRootTreeItem.getChildCount() == 0) {
detachDirectoryScrollPanel();
} else if (mRootTreeItem.getChildCount() > 0 && mDirectoryTree.isAttached() == false) {
reattachDirectoryScrollPanel();
}
}
}
private boolean changed(TreeItem ti, FileTree ft, int level) {
if (ti.getChildCount() != ft.getChildren().length) {
return true;
}
if (level != 0) { // don't check name at level 0, just count
if (ti.getText().equals(ft.getName()) == false) {
return true;
}
}
for (int i = 0; i < ti.getChildCount(); i++) {
if (changed(ti.getChild(i), ft.getChildren()[i], level + 1)) {
return true;
}
}
return false;
}
private String reverse(TreeItem curr, int depth) {
if (curr.getParentItem() == null) {
return ""; // don't count the root item in the path
} else {
return reverse(curr.getParentItem(), depth + 1) + curr.getText()
+ (depth > 0 ? "/" : "");
}
}
protected void showSettings(int tab) {
SettingsDialog dlg = new SettingsDialog(mEntireUIRoot, SwarmsBrowser.this, tab);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
}
private List<String> getExpandedPaths(TreeItem curr) {
/**
* If curr is visible, check
*/
List<String> partial = new ArrayList<String>();
if (curr.getState()) {
for (int i = 0; i < curr.getChildCount(); i++) {
for (String path : getExpandedPaths(curr.getChild(i))) {
partial.add(curr.getText() + "/" + path);
}
}
if (partial.size() == 0) {
partial.add(curr.getText());
}
}
return partial;
}
final Label computerNameLabel = new Label();
final private ClickHandler statusImageClickListener = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
if (event.getSource() instanceof TorrentContainingImage) {
TorrentInfo source = ((TorrentContainingImage) event.getSource()).getTorrent();
new TorrentErrorDialogBox(source, mEntireUIRoot);
} else {
System.err.println("********* Got a click event without a TorrentContainingImage");
}
}
};
public Panel createHeaderButtons() {
/**
* We use a dock panel here so we can group some buttons on the left for
* nondestructive actions (play, etc), and keep destructive actions on
* the other side (delete).
*
* DockPanel is much easier to use for this than tables
*/
DockPanel panel = new DockPanel();
panel.addStyleName(CSS_BROWSER_HEADER);
panel.setWidth("100%");
Button createSwarmButton = new Button(Strings.get(Strings.CREATE_SWARM));
if (OneSwarmGWT.isRemoteAccess()) {
createSwarmButton.setEnabled(false);
}
createSwarmButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
new CreateSwarmDialogBox(mEntireUIRoot);
}
});
Button addDownloadButton = new Button(Strings.get(Strings.ADD_SWARM_URL));
addDownloadButton.getElement().setId("addUrlLink");
DOM.setStyleAttribute(addDownloadButton.getElement(), "whiteSpace", "nowrap");
playButton = new Button(Strings.get(Strings.SWARM_BROWSER_PLAY));
deleteButton = new Button(Strings.get(Strings.SWARM_DELETE));
tagButton = new Button(Strings.get(Strings.SWARM_TAGS));
if (useDebug) {
debugButton = new Button(msg.swarm_browser_button_debug());
debugButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
dispatchSwarmAction(Strings.DEBUG, null);
}
});
}
addDownloadButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String url = Window.prompt(msg.swarm_browser_add_enter_url(), "");
if (url == null) { // cancel
return;
}
if (url.toLowerCase().startsWith("magnet:")
|| url.toLowerCase().startsWith("oneswarm:")) {
int pos = url.indexOf('?');
if (pos == -1) {
Window.alert(msg.swarm_browser_add_warning_bad_magnet());
return;
}
String query = url.substring(url.indexOf('?'));
if (query.length() < 10) {
Window.alert(msg.swarm_browser_add_warning_bad_magnet());
return;
}
String[] toks = query.substring(1).split("&");
String base32hash = null;
for (String param : toks) {
String[] kv = param.split("=");
if (kv.length == 2) {
if (kv[0].equals("xt") && kv[1].startsWith("urn:osih:")) {
base32hash = kv[1].substring("urn:osih:".length());
}
}
}
OneSwarmRPCClient.getService().getBase64HashesForBase32s(
OneSwarmRPCClient.getSessionID(), new String[] { base32hash },
new AsyncCallback<String[]>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
OneSwarmGWT.log("Error: " + caught.getMessage());
new ReportableErrorDialogBox(caught.getMessage(), false);
}
@Override
public void onSuccess(String[] result) {
if (result == null) {
return;
}
if (result[0] == null) {
return;
}
for (String s : result) {
History.newItem(EntireUIRoot.SEARCH_HISTORY_TOKEN + "id:"
+ s);
}
}
});
} else {
OneSwarmRPCClient.getService().downloadTorrent(
OneSwarmRPCClient.getSessionID(), url, new AsyncCallback<Integer>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(Integer result) {
if (result == -1) {
Window.alert(msg.swarm_browser_add_download_error());
return;
}
TorrentDownloaderDialog dlg = new TorrentDownloaderDialog(
mEntireUIRoot, result);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
}
});
}
}
});
tagButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
TagEditorDialog dlg = new TagEditorDialog(mEntireUIRoot, SwarmsBrowser.this
.getSelectedSwarms());
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
}
});
/**
* We need to keep track of these so we can disable / enable them in the
* highlighting click listeners
*/
headerButtons.add(playButton);
headerButtons.add(deleteButton);
headerButtons.add(tagButton);
playButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
String btext = playButton.getText();
if (btext.equals(Strings.get(Strings.SWARM_BROWSER_PLAY))
|| btext.equals(msg.swarm_browser_button_download()))
dispatchSwarmAction(Strings.SWARM_BROWSER_PLAY, getSelectedSwarms());
else
dispatchSwarmAction(Strings.SWARM_DEFAULT_PLAY, getSelectedSwarms());
}
});
deleteButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
dispatchSwarmAction(Strings.SWARM_DELETE, getSelectedSwarms());
}
});
Button settingsButton = new Button(Strings.get(Strings.SETTINGS));
settingsButton.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
showSettings(0);
}
});
/**
* Binding things directly to east/west seems to not pack as tightly as
* I want, but wrapping each in a panel works.
*/
HorizontalPanel lhs = new HorizontalPanel();
lhs.add(createSwarmButton);
lhs.add(addDownloadButton);
lhs.add(playButton);
lhs.add(deleteButton);
lhs.add(tagButton);
lhs.add(settingsButton);
if (useDebug) {
lhs.add(debugButton);
}
moreActions.setVisibleItemCount(1);
moreActions.addItem(msg.swarm_browser_more_actions());
// immediately by a call to
// refresh header buttons
moreActions.addChangeListener(new ChangeListener() {
@Override
public void onChange(Widget sender) {
String selected = moreActions.getItemText(moreActions.getSelectedIndex());
System.out.println("selected: " + selected);
if (selected.equals(msg.swarm_browser_more_actions_start_swarm())
|| selected.equals(msg.swarm_browser_more_actions_stop_swarm())) {
dispatchSwarmAction(Strings.SWARM_STARTSTOP, getSelectedSwarms());
String swapped = msg.swarm_browser_more_actions_stop_swarm();
if (selected.equals(msg.swarm_browser_more_actions_stop_swarm())) {
swapped = msg.swarm_browser_more_actions_start_swarm();
}
moreActions.setItemText(moreActions.getSelectedIndex(), swapped);
} else {
for (String action : Strings.SWARM_MORE_ACTIONS_NOSELECTION) {
if (selected.equals(Strings.get(action))) {
dispatchSwarmAction(action, getSelectedSwarms());
moreActions.setSelectedIndex(0);
return;
}
}
for (String action : Strings.SWARM_MORE_ACTIONS_SELECTED) {
if (selected.equals(Strings.get(action))) {
dispatchSwarmAction(action, getSelectedSwarms());
moreActions.setSelectedIndex(0);
return;
}
}
}
moreActions.setSelectedIndex(0);
}
});
lhs.add(moreActions);
lhs.setCellVerticalAlignment(moreActions, VerticalPanel.ALIGN_MIDDLE);
BackendTaskReporter backendReporter = new BackendTaskReporter();
add(backendReporter);
this.setCellHorizontalAlignment(backendReporter, HorizontalPanel.ALIGN_LEFT);
lhs.add(backendReporter);
lhs.setCellVerticalAlignment(backendReporter, VerticalPanel.ALIGN_MIDDLE);
lhs.setSpacing(3);
panel.add(lhs, DockPanel.WEST);
panel.setCellHorizontalAlignment(lhs, HorizontalPanel.ALIGN_LEFT);
panel.setCellVerticalAlignment(lhs, VerticalPanel.ALIGN_MIDDLE);
HorizontalPanel rhs = new HorizontalPanel();
rhs.setSpacing(3);
// Label nameLabel = new Label("Computer: ");
// rhs.add(nameLabel);
rhs.add(computerNameLabel);
updateComputerName();
HTML nameEditAnchor = new HTML("(<a href='#'>" + msg.swarm_browser_change_nick_name()
+ "</a>)");
nameEditAnchor.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
ComputerNameDialog dlg = new ComputerNameDialog(computerNameLabel.getText(), true,
new ComputerNameDialog.NameSetCallback() {
@Override
public void setName(String newName) {
computerNameLabel.setText(newName);
}
});
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setPopupPosition(dlg.getPopupLeft(), Window.getScrollTop() + 125);
dlg.setVisible(true);
}
});
rhs.add(nameEditAnchor);
panel.add(rhs, DockPanel.EAST);
panel.setCellHorizontalAlignment(rhs, HorizontalPanel.ALIGN_RIGHT);
panel.setCellVerticalAlignment(rhs, VerticalPanel.ALIGN_MIDDLE);
refreshHeaderButtons();
return panel;
}
private void updateComputerName() {
OneSwarmRPCClient.getService().getComputerName(OneSwarmRPCClient.getSessionID(),
new AsyncCallback<String>() {
@Override
public void onFailure(Throwable caught) {
}
@Override
public void onSuccess(String result) {
computerNameLabel.setText(result);
}
});
}
public void refreshHeaderButtons() {
boolean isEnabled = true;
TorrentInfo[] selected = getSelectedSwarms();
boolean anyF2F = false;
if (selected != null) {
for (TorrentInfo t : selected) {
if (t.isF2FOnly()) {
anyF2F = true;
break;
}
}
}
if (selected == null)
isEnabled = false;
for (Button b : headerButtons) {
b.setEnabled(isEnabled);
}
/**
* We build up a set of new menu items and then compare it to the
* existing list (updating if necessary). We used to just clear the menu
* and rebuild, but because this function is called periodically,
* Firefox would reset the selected menu in a visually annoying way
* periodically while selected.
*
* ====================================================================
* =================================================
*/
List<String> newActions = new ArrayList<String>();
// moreActions.clear();
// moreActions.addItem("More actions...");
newActions.add(msg.swarm_browser_more_actions());
for (String action : Strings.SWARM_MORE_ACTIONS_NOSELECTION) {
/**
* Things we can't do when accessing remotely.
*/
if (action.equals(Strings.ADD_SWARM_FILE) && OneSwarmGWT.isRemoteAccess()) {
continue;
}
// moreActions.addItem(Strings.get(action));
newActions.add(Strings.get(action));
}
if (selected != null) {
if (anyF2F == false) {
for (String action : Strings.SWARM_MORE_ACTIONS_SELECTED) {
/**
* Things we can't do when accessing remotely.
*/
if (action.equals(Strings.SWARM_DEFAULT_PLAY) && OneSwarmGWT.isRemoteAccess()) {
continue;
}
if (action.equals(Strings.SWARM_STARTSTOP) == false) {
// moreActions.addItem(Strings.get(action));
newActions.add(Strings.get(action));
} else {
// moreActions.addItem(selected[0].isStarted() ?
// "Stop swarm" : "Start swarm");
newActions.add(selected[0].isStarted() ? msg
.swarm_browser_more_actions_stop_swarm() : msg
.swarm_browser_more_actions_start_swarm());
}
}
} // if local
else {
// something is selected, but it's an f2f swarm. In this case,
// only copy link is valid
newActions.add(Strings.get(Strings.SWARM_COPY_MAGNET));
}
}
boolean update = newActions.size() != moreActions.getItemCount();
for (int i = 0; i < newActions.size() && update == false; i++) {
update = !newActions.get(i).equals(moreActions.getItemText(i));
}
if (update) {
moreActions.clear();
for (int i = 0; i < newActions.size(); i++) {
moreActions.addItem(newActions.get(i));
}
}
/**
* end menu updating
* ====================================================
* =================================================================
*/
if (selected != null) {
boolean canPlay = false;
FileTypeFilter type = FileTypeFilter.match(selected[0].getDefaultMovieName());
if (type.equals(FileTypeFilter.Videos) && selected[0].getProgress() > 5) // lets
// pretend
// 0.5
// %
// is
// enough
// (
// basically
// ,
// has
// downloading
// started
// ?
// )
{
canPlay = true;
} else if (type.equals(FileTypeFilter.Audio)
&& selected[0].getProgress() * selected[0].getTotalSize() >= 4096 * 100) // lets
// pretend
// 4
// MB
// is
// enough
// else if( type.equals(FileTypeFilter.Audio) &&
// mSelectedSwarm.getProgress() == 1000 )
{
canPlay = true;
} else if (anyF2F) {
canPlay = true; // play == download
}
if (anyF2F) {
playButton.setText(msg.swarm_browser_button_download());
} else {
playButton.setText(msg.swarm_browser_button_play());
}
if (canPlay) {
// can play
playButton.setEnabled(true);
if (!anyF2F) {
playButton.setText(msg.swarm_browser_button_play());
}
} else {
// can't play
playButton.setEnabled(false);
}
if (anyF2F) {
deleteButton.setEnabled(false);
tagButton.setEnabled(false);
}
}
}
public void removeFile(final TorrentInfo inTorrent) {
// mMouseOverSwarm = null;
selectSwarm(null);
refreshHeaderButtons();
if (inTorrent.getProgress() < 1000) {
int i = mTransferringSwarms.indexOf(inTorrent);
if (i != -1) {
mTransferringSwarms.remove(inTorrent);
mProgressBars.remove(i);
} else {
System.err
.println("torrent had progress < 1000 but no progress bar. not updated somewhere?"
+ inTorrent.getTorrentID());
}
}
VerticalPanel icon_with_name = (VerticalPanel) torrent_to_panel.get(inTorrent).getWidget();
torrent_to_panel.remove(inTorrent);
final PreviewPanel effectPanel = (PreviewPanel) icon_with_name.getParent();
// Fade fade = filePanel_to_fade.get(icon_with_name);
// fade.getProperties().setStartOpacity(100);
// fade.getProperties().setEndOpacity(0);
// effectPanel.beginEffects();
// (new Timer() {
// public void run() {
filesFlowPanel.remove(effectPanel);
// }
// }).schedule((int) (FADE_TIME_SECS * 1000));
}
class MaxHeightWithTorrentInfoLabel extends Label {
int mActualHeight = 0;
TorrentInfo mTorrent = null;
public MaxHeightWithTorrentInfoLabel(String fname, TorrentInfo inTorrent) {
super(fname);
mTorrent = inTorrent;
if (inTorrent.isF2FOnly()) {
this.addStyleName(CSS_F2F_LABEL);
}
}
public int getActualHeight() {
return mActualHeight == 0 ? 45 : mActualHeight;
}
public TorrentInfo getSwarm() {
return mTorrent;
}
@Override
protected void onLoad() {
super.onLoad();
/**
* == 0 check since we don't want to do this twice (e.g. when we
* change filters)
*/
if (mActualHeight == 0) {
mActualHeight = Math.min(45, getOffsetHeight());
setHeight("45px"); // so layout draws correctly, but we'll use
// getActualHeight for GWTCanvas highlight
}
}
}
private static class RightClickablePanel extends VerticalPanel {
List<RightClickHandler> handlers = new LinkedList<RightClickHandler>();
public RightClickablePanel() {
super();
sinkEvents(Event.ONMOUSEUP | Event.ONDBLCLICK | Event.ONCONTEXTMENU);
}
@Override
public void onBrowserEvent(Event event) {
GWT.log("onBrowserEvent", null);
event.stopPropagation();
event.preventDefault();
switch (DOM.eventGetType(event)) {
case Event.ONMOUSEUP:
if (DOM.eventGetButton(event) == Event.BUTTON_RIGHT) {
for (RightClickHandler h : handlers) {
h.onRightClick(event);
}
}
break;
case Event.ONDBLCLICK:
break;
case Event.ONCONTEXTMENU:
GWT.log("Event.ONCONTEXTMENU", null);
break;
default:
break; // Do nothing
}// end switch
}
public void addRightClickHandler(RightClickHandler handler) {
handlers.add(handler);
}
}
private static interface RightClickHandler {
void onRightClick(Event event);
}
private class RightClickMenu extends PopupPanel {
public RightClickMenu() {
super(true, false);
setStyleName("rightclick_menu");
MenuBar popupMenuBar = new MenuBar(true);
final TorrentInfo[] selected = getSelectedSwarms();
boolean anyF2F = false;
boolean anyCompleted = false;
if (selected != null) {
for (TorrentInfo t : selected) {
if (t.isF2FOnly()) {
anyF2F = true;
}
if (t.getProgress() == 1000) {
anyCompleted = true;
}
}
}
if (anyF2F) {
MenuItem downloadItem = new MenuItem(msg.swarm_browser_button_download(), true,
new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_BROWSER_PLAY, selected);
}
});
downloadItem.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(downloadItem);
} else {
if (playButton.isEnabled()) {
MenuItem playItem = new MenuItem(msg.swarm_browser_button_play(), true,
new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_BROWSER_PLAY,
getSelectedSwarms());
hide();
}
});
playItem.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(playItem);
}
MenuItem defaultPlayItem = new MenuItem(
msg.swarm_browser_more_actions_default_app(), true, new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_DEFAULT_PLAY, getSelectedSwarms());
hide();
}
});
defaultPlayItem.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(defaultPlayItem);
MenuItem showInFinder = new MenuItem(msg.swarm_browser_more_actions_reveal(), true,
new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_REVEAL, getSelectedSwarms());
hide();
}
});
showInFinder.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(showInFinder);
popupMenuBar.addSeparator();
if (!anyCompleted) {
MenuItem startStop = new MenuItem(msg.swarm_browser_right_click_start_stop(),
true, new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_STARTSTOP,
getSelectedSwarms());
hide();
}
});
startStop.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(startStop);
}
MenuItem showDetails = new MenuItem(msg.swarm_browser_more_actions_swarm_details(),
true, new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_DETAILS, getSelectedSwarms());
hide();
}
});
showDetails.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(showDetails);
MenuItem copyLink = new MenuItem(msg.swarm_browser_more_actions_copy_magnet(),
true, new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_COPY_MAGNET, getSelectedSwarms());
hide();
}
});
copyLink.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(copyLink);
MenuItem managePerms = new MenuItem(
msg.swarm_browser_more_actions_manage_visibility(), true, new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.MANAGE_PERMS, getSelectedSwarms());
hide();
}
});
managePerms.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(managePerms);
popupMenuBar.addSeparator();
MenuItem delete = new MenuItem(msg.swarm_browser_button_delete(), true,
new Command() {
@Override
public void execute() {
dispatchSwarmAction(Strings.SWARM_DELETE, getSelectedSwarms());
hide();
}
});
delete.addStyleName("rightclick_menu-item");
popupMenuBar.addItem(delete);
}
popupMenuBar.setVisible(true);
add(popupMenuBar);
}
}
static class TorrentContainingImage extends Image {
private final TorrentInfo torrent;
public TorrentContainingImage(String url, TorrentInfo torrent) {
super(url);
this.torrent = torrent;
}
public TorrentInfo getTorrent() {
return torrent;
}
}
public void addFileIcon(final TorrentInfo inTorrent, boolean force_show) {
String fname = inTorrent.getName();
String lineWrapped = fname;
int MAX_LINE_LEN = 20;
// int MIN_LINE_LEN = MAX_LINE_LEN - 6;
int MAX_TOTAL_LEN = 60;
if (lineWrapped.length() > MAX_LINE_LEN) {
// cap at 45 char
lineWrapped = lineWrapped.substring(0, Math.min(lineWrapped.length(), MAX_TOTAL_LEN));
// hack until FF supports css word-wrap=break-word
String firstLine = lineWrapped.substring(0, MAX_LINE_LEN);
if (!firstLine.contains(" ")) {
lineWrapped = firstLine + " " + lineWrapped.substring(MAX_LINE_LEN);
}
// }
}
VerticalPanel icon_panel_scratch = null;
String disableRightClickCookie = Cookies
.getCookie(UISettingsPanel.COOKIE_DISABLE_RIGHT_CLICK);
if (disableRightClickCookie == null || "1".equals(disableRightClickCookie)) {
icon_panel_scratch = new VerticalPanel();
} else {
icon_panel_scratch = new RightClickablePanel();
((RightClickablePanel) icon_panel_scratch)
.addRightClickHandler(new RightClickHandler() {
@Override
public void onRightClick(final Event event) {
selectSwarm(inTorrent, false, false);
refreshHeaderButtons();
final RightClickMenu menu = new RightClickMenu();
menu.setPopupPositionAndShow(new PositionCallback() {
@Override
public void setPosition(int offsetWidth, int offsetHeight) {
menu.setPopupPosition(event.getClientX(), event.getClientY());
}
});
}
});
}
final VerticalPanel icon_with_name = icon_panel_scratch;
icon_with_name.setWidth(ICON_WIDTH + "px");
final Label fnameLabel = new MaxHeightWithTorrentInfoLabel(lineWrapped, inTorrent);
String tooltipText = fname;
tooltipText += " Size: " + StringTools.formatRate(inTorrent.getTotalSize());
if (inTorrent.isF2FOnly()) {
tooltipText += " From friend: " + inTorrent.getF2F_nick();
}
fnameLabel.setTitle(tooltipText);
fnameLabel.setHorizontalAlignment(HorizontalPanel.ALIGN_CENTER);
fnameLabel.setWidth((ICON_WIDTH + FNAME_BUFFER) + "px");
// /fnameLabel.setWidth(ICON_WIDTH+"px");
// fnameLabel.setWidth("30px");
final AbsolutePanel fnameAbsolute = new AbsolutePanel();
fnameAbsolute.add(fnameLabel);
DOM.setStyleAttribute(fnameLabel.getElement(), "zIndex", "10");
Image videoPreviewImage = null;
String hint = "";
if (inTorrent.isF2FOnly() && inTorrent.getDefaultMovieName() != null) {
if (FileTypeFilter.match(inTorrent.getDefaultMovieName(), FileTypeFilter.Audio)) {
hint = "audio";
} else if (FileTypeFilter.match(inTorrent.getDefaultMovieName(), FileTypeFilter.Videos)) {
hint = "video";
}
}
videoPreviewImage = new TorrentContainingImage(GWT.getModuleBaseURL() + "image?infohash="
+ inTorrent.getTorrentID() + "&type=" + hint, inTorrent);
videoPreviewImage.setWidth("128px");
videoPreviewImage.setHeight("128px");
if (inTorrent.isF2FOnly()) {
videoPreviewImage.addStyleName(CSS_PREVIEW_TRANSFERRING);
}
final AbsolutePanel overlay = new AbsolutePanel();
overlay.addStyleName(CSS_VIDEO_PREVIEW_BG);
overlay.setWidth(ICON_WIDTH + FNAME_BUFFER + "px");
overlay.setHeight(ICON_HEIGHT + "px");
overlay.add(videoPreviewImage, FNAME_BUFFER / 2, 0);
Image statusImage = new TorrentContainingImage(
inTorrent.getErrorState() == 0 ? ImageConstants.ICON_STARTED
: ImageConstants.ICON_WARNING, inTorrent);
statusImage.addClickHandler(statusImageClickListener);
statusImage.setWidth("16px");
statusImage.setHeight("16px");
/**
* now always leaving this invisible unless stopped. looks too much like
* a play icon. confusing. note, we use the DOM method instead of
* setVisible since the latter interferes with the selection code's use
* of zIndex, whereas visibility hidden always hides, regardless of
* zIndex.
*/
if (inTorrent.getErrorState() == 0) {
DOM.setStyleAttribute(statusImage.getElement(), "visibility", "hidden");
}
overlay.add(statusImage, 0, ICON_HEIGHT - 16);
statusImage.setTitle("Swarm started");
// ClickListener selectListener = new ClickListener() {
// public void onClick(Widget sender) {
// selectSwarm(inTorrent, true);
// refreshHeaderButtons();
// }
// };
ClickHandler selectHandler = new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
selectSwarm(inTorrent, true, event.getNativeEvent().getShiftKey());
refreshHeaderButtons();
}
};
fnameLabel.addClickHandler(selectHandler);
videoPreviewImage.addClickHandler(selectHandler);
if (inTorrent.getProgress() < 1000) {
overlay.addStyleName(CSS_PREVIEW_TRANSFERRING);
mTransferringSwarms.add(inTorrent);
// Label progressBar = new Label("0");
// fnameAbsolute.add(progressBar, 0, 0);
ProgressBar pb = new ProgressBar(0.0, 1000.0, inTorrent.getProgress());
pb.setTextFormatter(new SwarmRateTextFormatter(inTorrent));
int pb_width = (ICON_WIDTH - (ICON_WIDTH / 5));
pb.setWidth(pb_width + "px");
pb.setHeight("15px");
DOM.setStyleAttribute(pb.getElement(), "zIndex", "100");
overlay.add(pb, (CELL_WIDTH - pb_width) / 2, ICON_HEIGHT - 20);
// add(pb);
mProgressBars.add(pb);
}
icon_with_name.add(overlay);
icon_with_name.add(fnameAbsolute);
icon_with_name.setSpacing(3);
icon_with_name.addStyleName(CSS_FILE_ICON);
PreviewPanel fadePanel = new PreviewPanel();
fadePanel.add(icon_with_name);
// Fade fade = new Fade();
// fade.getProperties().setEffectLength(FADE_TIME_SECS);
// fade.getProperties().setStartOpacity(0);
// fade.getProperties().setEndOpacity(100);
// fadePanel.addEffect(fade);
/**
* So we can link UI elements with torrent data
*/
torrent_to_panel.put(inTorrent, fadePanel);
// filePanel_to_fade.put(icon_with_name, fade);
// filesFlowPanel.add(fadePanel);
// we can't do this if showing transfers -- will crash 8)
if (force_show) {
if (mShowingTransfers == false) {
// sortedFilesPanelInsert(fadePanel);
filesFlowPanel.add(fadePanel);
// filesFlowPanel.add(icon_with_name);
}
// fadePanel.beginEffects();
}
PickupDragController dragController = mEntireUIRoot.getDragController();
if (dragController != null
&& "0".equals(Cookies.getCookie(UISettingsPanel.COOKIE_DISABLE_DRAG_AND_DROP))) {
Image moveImage = new Image("images/move_arrow_16x16.png");
overlay.add(moveImage, overlay.getOffsetWidth() - 16, 0);
dragController.makeDraggable(videoPreviewImage, moveImage);
moveImage.setVisible(false);
}
if (mSelectedSwarms.contains(inTorrent)) {
selectSwarm(inTorrent);
}
}
private Image currentMoveIcon = null;
@Override
public void update(int count) {
// testing explicit signaling to remove polling
// refreshActive();
// if( mNextTransferringSwarmsUpdate < System.currentTimeMillis() ) {
// mNextTransferringSwarmsUpdate = Long.MAX_VALUE;
// refreshTransferringSwarms();
// }
// if( mNextStateSyncUpdate < System.currentTimeMillis() ) {
// mNextStateSyncUpdate = Long.MAX_VALUE;
// synchronizeSwarmStateValues();
// }
if (mNextPagedUpdate < System.currentTimeMillis()) {
mNextPagedUpdate = System.currentTimeMillis() + 20 * 1000; // ensure
// we
// _eventually_
// do
// something
// again
// !
if (mUsingIconView) // the list view will take care of this
// internally.
{
pagedSwarmRefresh();
}
}
if (mNextWarningCheck < System.currentTimeMillis()) {
OneSwarmRPCClient.getService().checkIfWarning(OneSwarmRPCClient.getSessionID(),
new AsyncCallback<String[]>() {
@Override
public void onSuccess(String[] result) {
for (int j = 0; j < 4; j++) {
if (result[4 + (j * 8)].equals("true")) {
StoppedUserDialog dlg = new StoppedUserDialog(mEntireUIRoot,
result[5 + (j * 8)], result[6 + (j * 8)],
result[7 + (j * 8)]);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
} else if (result[(j * 8)].equals("true")) {
WarnUserDialog dlg = new WarnUserDialog(mEntireUIRoot,
result[1 + (j * 8)], result[2 + (j * 8)],
result[3 + (j * 8)]);
dlg.show();
dlg.setVisible(false);
dlg.center();
dlg.setVisible(true);
}
}
}
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
});
mNextWarningCheck = System.currentTimeMillis() + 30 * 1000;
}
if ((count % 5) == 0) {
lightweight_refresh_check();
}
if (mNextErrorPoll < System.currentTimeMillis()) {
mNextErrorPoll = System.currentTimeMillis() + 120 * 1000;
OneSwarmRPCClient.getService().getBackendErrors(OneSwarmRPCClient.getSessionID(),
new AsyncCallback<ArrayList<BackendErrorReport>>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(ArrayList<BackendErrorReport> result) {
if (result.size() > 0) {
OneSwarmGWT.log("Got " + result.size() + " backend errors");
}
// most recent first
Collections.reverse(result);
mNextErrorPoll = System.currentTimeMillis() + (5 * 1000);
if (result.size() == 0) {
return;
}
StringBuffer concat = new StringBuffer();
boolean show_report = false;
for (BackendErrorReport r : result) {
concat.append(r.getMessage() + "\n");
if (r.isShowReportText()) {
show_report = true;
}
}
new ReportableErrorDialogBox(concat.toString(), false, show_report);
}
});
}
updateComputerName();
}
/**
* This checks only the _number_ of download managers as a prelude to decide
* whether or not we need to do a full refreshActive(). Even though the UI
* is explicitly notified of most refreshes, watch directories sometimes
* mean that swarms will be added without UI knowledge
*/
private void lightweight_refresh_check() {
OneSwarmRPCClient.getService().getDownloadManagersCount(OneSwarmRPCClient.getSessionID(),
new AsyncCallback<Integer>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(Integer result) {
if (result.intValue() != mPreviousFullRefreshTotalSwarmsCount) {
System.out
.println("download manager count doesn't match mPreviousFullRefreshTotalSwarmsCount, refreshing ("
+ result + " / " + mPreviousFullRefreshTotalSwarmsCount);
if (mShowingTransfers == false || mShowingFriends) {
SwarmsBrowser.this.refreshActive(false);
}
} else {
// System.out.println("lightweight refresh: " +
// result);
}
}
});
}
private void pagedSwarmRefresh() {
ArrayList<String> whichOnes = new ArrayList<String>();
for (int i = 0; i < filesFlowPanel.getWidgetCount(); i++) {
if (filesFlowPanel.getWidget(i) instanceof PreviewPanel) {
PreviewPanel p = (PreviewPanel) filesFlowPanel.getWidget(i);
VerticalPanel fnamePanel = (VerticalPanel) p.getWidget(); // this
AbsolutePanel fnameAbsolute = (AbsolutePanel) fnamePanel.getWidget(1);
MaxHeightWithTorrentInfoLabel fnameLabel = (MaxHeightWithTorrentInfoLabel) fnameAbsolute
.getWidget(0);
whichOnes.add(fnameLabel.getSwarm().getTorrentID());
}
}
OneSwarmRPCClient.getService().pagedTorrentStateRefresh(OneSwarmRPCClient.getSessionID(),
whichOnes, new AsyncCallback<TorrentInfo[]>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(TorrentInfo[] result) {
/**
* begin by synchronizing the state
*/
Map<String, TorrentInfo> id_to_torrent = new HashMap<String, TorrentInfo>();
for (TorrentInfo t : torrent_to_panel.keySet()) {
id_to_torrent.put(t.getTorrentID(), t);
}
for (TorrentInfo t : result) {
if (t == null)
continue;
if (id_to_torrent.get(t.getTorrentID()) != null) {
id_to_torrent.get(t.getTorrentID()).setStatus(t.getStatus());
id_to_torrent.get(t.getTorrentID()).setProgress(t.getProgress());
id_to_torrent.get(t.getTorrentID()).setDownloadRate(
t.getDownloadRate());
id_to_torrent.get(t.getTorrentID())
.setDownloaded(t.getDownloaded());
id_to_torrent.get(t.getTorrentID()).setSeeders(t.getSeeders());
id_to_torrent.get(t.getTorrentID()).setLeechers(t.getLeechers());
id_to_torrent.get(t.getTorrentID())
.setErrorState(t.getErrorState());
/**
* In case the play button now needs enabled
*/
if (mSelectedSwarms.size() == 1) {
if (mSelectedSwarms.get(0).getTorrentID()
.equals(t.getTorrentID()))
refreshHeaderButtons();
}
}
}
/**
* then progress...
*/
gotRefreshOfTransferring(result);
mNextPagedUpdate = System.currentTimeMillis() + 1000;
}
});
}
private void gotRefreshOfTransferring(TorrentInfo[] swarms) {
// System.out.println("got refresh of: " + swarms.length +
// " currently visible swarms.");
Map<String, TorrentInfo> idToInfo = new HashMap<String, TorrentInfo>();
for (TorrentInfo info : swarms) {
if (info != null) {
idToInfo.put(info.getTorrentID(), info);
}
}
// for (int i = 0; i < mTransferringSwarms.size(); i++) {
for (int swarmsIndex = 0; swarmsIndex < swarms.length; swarmsIndex++) {
// TorrentInfo info = mTransferringSwarms.get(i);
TorrentInfo info = swarms[swarmsIndex];
if (info == null) {
// not refresh
continue;
}
int i = mTransferringSwarms.indexOf(info);
if (i > -1) {
ProgressBar progressBar = mProgressBars.get(i);
/**
* This is brittle (and used somewhere else) -- TODO: should
* wrap this?
*/
final VerticalPanel fnamePanel = (VerticalPanel) torrent_to_panel.get(info)
.getWidget(); // this
// is
// icon_with_name
// verticalpanel
AbsolutePanel fnameAbsolute = (AbsolutePanel) fnamePanel.getWidget(1);
// Label fnameLabel = (Label) fnameAbsolute.getWidget(0);
// System.out.println("attempting refresh of: " + info);
// fnameAbsolute.setWidgetPosition(progressBar, 0,
// -fnameLabel.getOffsetHeight());
TorrentInfo latest = idToInfo.get(info.getTorrentID());
if (latest != null) {
progressBar.setProgress(latest.getProgress());
info.setProgress(latest.getProgress());
// System.out.println("progress of: " + latest.getName() +
// " " +
// latest.getProgress());
if (latest.getProgress() == 1000) {
// done, remove progress bar and make opaque.
int pbi = mTransferringSwarms.indexOf(latest);
mTransferringSwarms.remove(latest);
ProgressBar pb = mProgressBars.get(pbi);
pb.removeFromParent();
fnameAbsolute.removeStyleName(CSS_PREVIEW_TRANSFERRING);
mProgressBars.remove(pbi);
/**
* We may also now be able to generate a preview image,
* so give that a shot
*/
Image previewImage = (Image) ((AbsolutePanel) fnamePanel.getWidget(0))
.getWidget(0);
previewImage.setUrl(previewImage.getUrl() + "&refresh");
System.out.println("attempting image refresh...: " + previewImage.getUrl());
/**
* Also, since it might now be playable (and selected)
*/
refreshHeaderButtons();
}
} else {
// something finished or was removed --> more
// heavyweight
System.out.println("something finished or was removed, refreshing active");
refreshActive(false);
}
}
// this is not transferring, just update start/stop
TorrentInfo latest = idToInfo.get(info.getTorrentID());
info.setStatus(latest.getStatus());
Image statusImage = getStartStopImageFromEffectPanel(torrent_to_panel.get(info));
if (statusImage != null) {
if (info.getErrorState() == 0) {
boolean startImage = statusImage.getUrl().endsWith(ImageConstants.ICON_STARTED);
if (info.isStarted() && !startImage) {
statusImage.setUrl(ImageConstants.ICON_STARTED);
DOM.setStyleAttribute(statusImage.getElement(), "visibility", "hidden");
} else if (!info.isStarted() && startImage) {
statusImage.setUrl(ImageConstants.ICON_STOPPED);
DOM.setStyleAttribute(statusImage.getElement(), "visibility", "visible");
}
} else {
statusImage.setUrl(ImageConstants.ICON_WARNING);
DOM.setStyleAttribute(statusImage.getElement(), "visibility", "visible");
}
// no need to show these if downloads are complete
if (info.getProgress() == 1000 && info.getErrorState() == 0) {
DOM.setStyleAttribute(statusImage.getElement(), "visibility", "hidden");
}
}
}
}
private Image getStartStopImageFromEffectPanel(PreviewPanel effectPanel) {
if (effectPanel == null) {
System.err.println("null effectpanel in startstop image get");
return null;
}
VerticalPanel w = ((VerticalPanel) effectPanel.getWidget());
if (w == null) {
System.err.println("null verticalpanel in startstop image get");
return null;
}
AbsolutePanel imageAbsolute = (AbsolutePanel) w.getWidget(0);
return (Image) imageAbsolute.getWidget(1);
}
public void changeFilter(FileTypeFilter filter, boolean just_a_refresh) {
if (just_a_refresh == false) {
mFilterPattern = "";
}
boolean needReshowControls = mShowingTransfers || mShowingFriends;
mShowingTransfers = false;
mShowingFriends = false;
if (mCurrentFileTypeFilter.equals(filter) == false) {
System.out.println("changing file filter type, going back to jump zero");
mJumpList.setSelectedIndex(0); // go back to first page
}
mCurrentFileTypeFilter = filter;
mTotalSwarmsForFilterType = 0;
if (needReshowControls) {
DOM.setStyleAttribute(mPagingPanel.getElement(), "display", null);
// DOM.setStyleAttribute(mPagingPanel.getElement(), "height",
// mPagingTableOldHeight);
checkTagsPanelAttchment();
DOM.setStyleAttribute(mSwarmsPerPagePanel.getElement(), "visibility", "visible");
DOM.setStyleAttribute(mShowFriendsCheckbox.getElement(), "visibility", "visible");
}
transferDetailsTable = null;
System.out.println("change filter: refreshActive()");
refreshActive(false); // we checked this above
// filterDisplayed(mFilterPattern);
// updateNavigationPanel();
}
private void detachDirectoryScrollPanel() {
this.mDirectoryScroll.removeFromParent();
this.mTagsFilesSeparator.removeFromParent();
}
private void reattachDirectoryScrollPanel() {
mFoldersAndFiles.insert(mDirectoryScroll, 0);
mFoldersAndFiles.insert(mTagsFilesSeparator, 1);
mFoldersAndFiles.setCellWidth(mDirectoryScroll, DIRECTORY_SCROLL_WIDTH + "px");
mFoldersAndFiles.setCellWidth(mTagsFilesSeparator, "1px");
com.google.gwt.user.client.Element td = DOM.getParent(mTagsFilesSeparator.getElement());
DOM.setStyleAttribute(td, "borderRight", "1px solid #d2d2d2");
}
// String mPagingTableOldHeight = null;
protected void showFriends() {
mShowingFriends = true;
// mPagingTableOldHeight =
// DOM.getStyleAttribute(mPagingPanel.getElement(), "height");
DOM.setStyleAttribute(mPagingPanel.getElement(), "display", "none");
// DOM.setStyleAttribute(mPagingPanel.getElement(), "height", "0pt");
if (mDirectoryScroll.isAttached()) {
mDirectoryScroll.removeFromParent();
}
DOM.setStyleAttribute(mSwarmsPerPagePanel.getElement(), "visibility", "hidden");
DOM.setStyleAttribute(mShowFriendsCheckbox.getElement(), "visibility", "hidden");
filesFlowPanel.clear();
selectSwarm(null);
filesFlowPanel.add(new FriendsDetailsListPanel(SwarmsBrowser.this));
}
public void showTransfers() {
mShowingTransfers = true;
// mPagingTableOldHeight =
// DOM.getStyleAttribute(mPagingPanel.getElement(), "height");
DOM.setStyleAttribute(mPagingPanel.getElement(), "display", "none");
// DOM.setStyleAttribute(mPagingPanel.getElement(), "height", "0pt");
if (mDirectoryScroll.isAttached()) {
detachDirectoryScrollPanel();
}
DOM.setStyleAttribute(mSwarmsPerPagePanel.getElement(), "visibility", "hidden");
DOM.setStyleAttribute(mShowFriendsCheckbox.getElement(), "visibility", "hidden");
filesFlowPanel.clear();
/**
* We don't want the transfers panel to persist unless its visible since
* it requires polling updates.
*/
// tableSelectedSwarmChanged(null);
selectSwarm(null);
TransferDetailsPanel detailsPanel = new TransferDetailsPanel();
transferDetailsTable = detailsPanel.getPublicDetailsTable();
filesFlowPanel.add(detailsPanel);
// filterDisplayed(mFilterPattern);
transferDetailsTable.filterDisplayed(mFilterPattern);
}
/**
* This is called by the transfer details table. We need this callback
* because the filtered count depends on an RPC
*/
public void updateFilteredCountFromTransferDetails(int count) {
updateFilteredCount(count);
}
// public void tableSelectedSwarmChanged(TorrentInfo inSwarm) {
// mSelectedSwarm = inSwarm;
// refreshHeaderButtons();
// }
public void refreshFromFilterText(String text) {
mFilterPattern = text;
if (mShowingTransfers == false || mShowingFriends) {
System.out.println("filtering swarms...");
mJumpList.setSelectedIndex(0);
changeFilter(mCurrentFileTypeFilter, true);
} else {
System.out.println("filtering transfers...");
transferDetailsTable.filterDisplayed(mFilterPattern);
}
}
public void pageZero() {
mDirectoryTree.setSelectedItem(null);
mDirectoryScroll.scrollToLeft();
mDirectoryScroll.scrollToTop();
mJumpList.setSelectedIndex(0);
}
public void sync_settings() {
System.out.println("sync settings");
OneSwarmRPCClient.getService().getIntegerParameterValue(OneSwarmRPCClient.getSessionID(),
"OneSwarm.ui.double.click", new AsyncCallback<Integer>() {
@Override
public void onFailure(Throwable caught) {
caught.printStackTrace();
}
@Override
public void onSuccess(Integer result) {
System.out.println("doubleclick action: " + result);
if (result >= 0 && result < 3) {
mDoubleClickAction = DoubleClickAction.values()[result];
System.out.println("doubleclick action str: "
+ mDoubleClickAction.getAction());
}
}
});
// in case we enabled/disabled tags
refreshActive(false);
}
public TorrentInfo[] getSelectedSwarms() {
if (mUsingIconView) {
if (mSelectedSwarms.size() > 0)
return mSelectedSwarms.toArray(new TorrentInfo[0]);
else
return null;
} else if (mShowingTransfers == false && mShowingFriends == false) {
return ((SwarmsListTable) filesFlowPanel.getWidget(0)).getSelectedSwarms();
} else {
return null;
}
}
public void selectPreviousSwarm() {
if (mUsingIconView == false) {
return;
}
if (mSelectedSwarms.size() == 0) {
if (mSwarmsOrderedByDisplay.length > 0) {
selectSwarm(mSwarmsOrderedByDisplay[mSwarmsOrderedByDisplay.length - 1]);
}
}
TorrentInfo which = mSelectedSwarms.get(0);
for (int i = 0; i < mSwarmsOrderedByDisplay.length; i++) {
if (which.equals(mSwarmsOrderedByDisplay[i])) {
if (i == 0) {
previousPage();
} else {
selectSwarm(mSwarmsOrderedByDisplay[i - 1]);
}
}
}
}
public void selectNextSwarm() {
if (mUsingIconView == false) {
return;
}
if (mSelectedSwarms.size() == 0) {
if (mSwarmsOrderedByDisplay.length > 0) {
selectSwarm(mSwarmsOrderedByDisplay[0]);
}
}
TorrentInfo which = mSelectedSwarms.get(0);
for (int i = 0; i < mSwarmsOrderedByDisplay.length; i++) {
if (which.equals(mSwarmsOrderedByDisplay[i])) {
if (i == mSwarmsOrderedByDisplay.length - 1) {
nextPage();
} else {
selectSwarm(mSwarmsOrderedByDisplay[i + 1]);
}
}
}
}
public void nextPage() {
nextPreviousPageLinkListener.onClick(new ClickEvent() {
@Override
public Object getSource() {
return nextLink;
}
});
}
public void previousPage() {
nextPreviousPageLinkListener.onClick(new ClickEvent() {
@Override
public Object getSource() {
return prevLink;
}
});
}
public void doubleClick() {
if (this.getSelectedSwarms() == null) {
return;
}
if (getSelectedSwarms().length == 0) {
return;
}
if (OneSwarmGWT.isRemoteAccess() == false) {
if (mDoubleClickAction.getAction().equals(Strings.SWARM_BROWSER_PLAY)
&& playButton.isEnabled() == false) {
dispatchSwarmAction(Strings.SWARM_DEFAULT_PLAY, getSelectedSwarms());
} else {
dispatchSwarmAction(mDoubleClickAction.getAction(), getSelectedSwarms());
}
} else if (playButton.isEnabled()) {
/**
* other actions don't make sense when connected remotely
*/
dispatchSwarmAction(Strings.SWARM_BROWSER_PLAY, getSelectedSwarms());
}
}
}