package edu.washington.cs.oneswarm.ui.gwt.client.newui; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import com.google.gwt.gen2.table.client.FixedWidthFlexTable; import com.google.gwt.gen2.table.client.FixedWidthGrid; import com.google.gwt.gen2.table.client.ScrollTable; import com.google.gwt.gen2.table.client.SelectionGrid.SelectionPolicy; import com.google.gwt.gen2.table.event.client.RowSelectionEvent; import com.google.gwt.gen2.table.event.client.RowSelectionHandler; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Label; import com.google.gwt.user.client.ui.SourcesTableEvents; import com.google.gwt.user.client.ui.TableListener; import com.google.gwt.widgetideas.client.ProgressBar; 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.Updateable; import edu.washington.cs.oneswarm.ui.gwt.client.i18n.OSMessages; import edu.washington.cs.oneswarm.ui.gwt.client.newui.friends.FriendsDetailsTable.HeaderWithWidth; import edu.washington.cs.oneswarm.ui.gwt.rpc.StringTools; import edu.washington.cs.oneswarm.ui.gwt.rpc.TorrentInfo; public class SwarmsListTable extends ScrollTable implements Updateable { FixedWidthGrid mData = null; FixedWidthFlexTable mHeader = null; List<Integer> mFilteredRows = new ArrayList<Integer>(); TorrentInfo[] mSwarms = null; // private SwarmsBrowser mSwarmsBrowser; protected static OSMessages msg = OneSwarmGWT.msg; private static final HeaderWithWidth[] COLUMNS = new HeaderWithWidth[] { new HeaderWithWidth("", 20), new HeaderWithWidth(msg.swarm_browser_sort_name(), 300, true), new HeaderWithWidth(msg.settings_tab_files(), 25), new HeaderWithWidth(msg.swarm_browser_sort_size(), 25), new HeaderWithWidth(msg.add_friends_invite_view_table_status(), 50), new HeaderWithWidth(msg.swarm_browser_sort_date(), 40) }; public SwarmsListTable(TorrentInfo[] swarms, final SwarmsBrowser swarmsBrowser) { super(new FixedWidthGrid(0, COLUMNS.length - 1) { @Override protected int getInputColumnWidth() { return COLUMNS[0].width; } }, new FixedWidthFlexTable()); mSwarms = swarms; // mSwarmsBrowser = swarmsBrowser; mData = getDataTable(); mHeader = getHeaderTable(); /** * We do sorting on the backend via the menu */ this.setSortPolicy(SortPolicy.DISABLED); mData.setSelectionPolicy(SelectionPolicy.CHECKBOX); mData.addTableListener(new TableListener() { public void onCellClicked(SourcesTableEvents sender, int row, int cell) { if (mData.isRowSelected(row)) { mData.deselectRow(row); } else { mData.selectRow(row, false); } swarmsBrowser.refreshHeaderButtons(); swarmsBrowser.propAction(); } }); mData.addRowSelectionHandler(new RowSelectionHandler() { public void onRowSelection(RowSelectionEvent event) { swarmsBrowser.refreshHeaderButtons(); swarmsBrowser.propAction(); } }); setScrollPolicy(ScrollPolicy.DISABLED); setResizePolicy(ResizePolicy.FILL_WIDTH); setupHeader(); addSwarms(); resizeTable(); // Window.addWindowResizeListener(new WindowResizeListener() { // // int lastWindowWidth = Window.getClientWidth(); // // public void onWindowResized(int width, int height) { // System.out.println("this width: " + Window.getClientWidth() + // " last: " + lastWindowWidth); // /** // * For some reason, we need to do this manually. // */ // if (Window.getClientWidth() < lastWindowWidth) { // double factor = (double) Window.getClientWidth() / (double) // lastWindowWidth; // factor *= 0.95; // take care of slop. eventually, this will // // resize anyway to fill width when we // // update. HACK ATTACK! // System.out.println("factor: " + factor); // for (int cItr = 0; cItr < mHeader.getColumnCount(); cItr++) { // mHeader.setColumnWidth(cItr, (int) Math.round((double) // mHeader.getColumnWidth(cItr) * factor)); // mData.setColumnWidth(cItr, (int) Math.round((double) // mData.getColumnWidth(cItr) * factor)); // } // } // lastWindowWidth = Window.getClientWidth(); // } // }); } private void resizeTable() { for (int i = 0; i < COLUMNS.length; i++) { mHeader.setColumnWidth(i, COLUMNS[i].width); if (i < COLUMNS.length - 1) { mData.setColumnWidth(i, COLUMNS[i + 1].width); } } fillWidth(); } public void onAttach() { super.onAttach(); OneSwarmGWT.addToUpdateTask(this); } public void onDetach() { super.onDetach(); OneSwarmGWT.removeFromUpdateTask(this); } class EncapsulatingLabel extends Label { public final static int COLUMN = 0; public TorrentInfo swarm; public ProgressBar progress; public EncapsulatingLabel(TorrentInfo swarm) { super(swarm.getName()); this.swarm = swarm; } } private void addSwarms() { if (mData.getRowCount() != mSwarms.length) { mData.resizeRows(mSwarms.length); } for (int row = 0; row < mSwarms.length; row++) { final TorrentInfo swarm = mSwarms[row]; EncapsulatingLabel encap = new EncapsulatingLabel(swarm); int col = 0; mData.setWidget(row, EncapsulatingLabel.COLUMN, encap); col++; mData.setText(row, col, Integer.toString(swarm.getNumFiles())); col++; mData.setText(row, col, StringTools.formatRate(swarm.getTotalSize())); col++; if (swarm.isF2FOnly()) { mData.setText(row, col, "F2F (" + swarm.getF2F_nick() + ")"); } else if (swarm.getProgress() == 1000) { mData.setText(row, col, "Complete"); } else { encap.progress = new ProgressBar(0, 1000); encap.progress.setTextFormatter(new SwarmRateTextFormatter(swarm)); encap.progress.setProgress(swarm.getProgress()); mData.setWidget(row, col, encap.progress); } col++; mData.setText(row, col, StringTools.formatDateMonthDayYear(new Date(swarm.getAddedDate()))); } } private void setupHeader() { for (int i = 0; i < COLUMNS.length; i++) { mHeader.setText(0, i, COLUMNS[i].name); } } public void update(int count) { ArrayList<String> whichOnes = new ArrayList<String>(); final HashMap<String, TorrentInfo> id_to_swarm = new HashMap<String, TorrentInfo>(); for (TorrentInfo s : mSwarms) { whichOnes.add(s.getTorrentID()); id_to_swarm.put(s.getTorrentID(), s); } OneSwarmRPCClient.getService().pagedTorrentStateRefresh(OneSwarmRPCClient.getSessionID(), whichOnes, new AsyncCallback<TorrentInfo[]>() { public void onFailure(Throwable caught) { caught.printStackTrace(); } public void onSuccess(TorrentInfo[] result) { for (TorrentInfo updated : result) { if (updated == null) { continue; } if (updated.getTorrentID() == null) { System.err.println("torrent ID is null: " + updated.getName()); continue; } TorrentInfo existing = id_to_swarm.get(updated.getTorrentID()); if (existing == null) { System.err .println("SwarmsListTable: couldn't get existing for new swarm info: " + updated.getName()); continue; } existing.setProgress(updated.getProgress()); existing.setUploadRate(updated.getUploadRate()); existing.setDownloadRate(updated.getDownloadRate()); existing.setDownloaded(updated.getDownloaded()); existing.setStatus(updated.getStatus()); } // now refresh UI for (int row = 0; row < mData.getRowCount(); row++) { EncapsulatingLabel encap = ((EncapsulatingLabel) mData.getWidget(row, EncapsulatingLabel.COLUMN)); if (encap.progress != null) { if (encap.swarm.getProgress() == 1000) { encap.progress.removeFromParent(); mData.setText(row, 4, "Complete"); } else { encap.progress.setProgress(((EncapsulatingLabel) mData .getWidget(row, EncapsulatingLabel.COLUMN)).swarm .getProgress()); } } } } }); } public void checkAll(boolean check) { if (check) { mData.selectAllRows(); } else { mData.deselectAllRows(); } } public TorrentInfo[] getSelectedSwarms() { List<TorrentInfo> out = new ArrayList<TorrentInfo>(); for (int row = 0; row < mData.getRowCount(); row++) { EncapsulatingLabel label = ((EncapsulatingLabel) mData.getWidget(row, 0)); if (mData.isRowSelected(row)) { out.add(label.swarm); } } if (out.size() > 0) return out.toArray(new TorrentInfo[0]); else return null; } }