package eu.jucy.gui.downloadqueue;
import helpers.IObservable;
import helpers.PrefConverter;
import helpers.SizeEnum;
import helpers.StatusObject;
import helpers.Observable.IObserver;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import logger.LoggerFactory;
import org.apache.log4j.Logger;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceAdapter;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.TextTransfer;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import eu.jucy.gui.Application;
import eu.jucy.gui.GUIPI;
import eu.jucy.gui.IImageKeys;
import eu.jucy.gui.ISearchableEditor;
import eu.jucy.gui.Lang;
import eu.jucy.gui.UCEditor;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQAdded;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQDownloaded;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQErrors;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQExactSize;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQFile;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQPath;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQPriority;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQSize;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQStatus;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQTTHRoot;
import eu.jucy.gui.downloadqueue.DownloadQueueColumns.DQUsers;
import eu.jucy.gui.itemhandler.DownloadQueueHandlers;
import uc.crypto.HashValue;
import uc.files.downloadqueue.DownloadQueue;
import uc.files.downloadqueue.AbstractDownloadQueueEntry;
import uc.files.downloadqueue.DownloadQueueFolder;
import uihelpers.IconManager;
import uihelpers.SUIJob;
import uihelpers.SelectionProviderIntermediate;
import uihelpers.TableViewerAdministrator;
public class DownloadQueueEditor extends UCEditor implements IObserver<StatusObject> , ISearchableEditor {
public static final String ID = "eu.jucy.DownloadQueue";
private static final Logger logger = LoggerFactory.make();
private static final String OverrideFilePrefix = "TARGET:";
private Image showLeftIcon;
private CLabel totalSizeLabel;
private CLabel nrOfFilesLabel;
private CLabel sizeLabel;
private CLabel nrOfSelectedItemsLabel;
private Table table;
private Tree tree;
private Composite composite;
private TreeViewer treeViewer;
private TableViewer tableViewer;
private final AtomicBoolean arInProgress = new AtomicBoolean();
private TableViewerAdministrator<AbstractDownloadQueueEntry> tva;
// private List<Action> actions = new ArrayList<Action>();
// private Action remove;
// private IHandlerActivation handRemove;
// private IHandlerActivation handUp;
// private IHandlerActivation handDown;
private SelectionProviderIntermediate spi = new SelectionProviderIntermediate();
@Override
public void createPartControl(Composite parent) {
final GridLayout gridLayout = new GridLayout();
gridLayout.verticalSpacing = 1;
gridLayout.marginWidth = 2;
gridLayout.marginHeight = 1;
gridLayout.horizontalSpacing = 3;
parent.setLayout(gridLayout);
composite = new Composite(parent, SWT.NONE);
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = 487;
composite.setLayoutData(gridData);
composite.setLayout(new GridLayout());
final SashForm sashForm = new SashForm(composite, SWT.NONE);
sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
tree = new Tree(sashForm, SWT.BORDER);
final TreeColumn newColumnTreeColumn = new TreeColumn(tree, SWT.NONE);
newColumnTreeColumn.setWidth(200);
table = new Table(sashForm, SWT.FULL_SELECTION | SWT.BORDER | SWT.MULTI);
table.setHeaderVisible(true);
sashForm.setWeights(new int[] { 120, 300 });
final Composite composite_1 = new Composite(parent, SWT.BORDER);
composite_1.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
final GridLayout gridLayout_1 = new GridLayout();
gridLayout_1.numColumns = 5;
gridLayout_1.verticalSpacing = 1;
gridLayout_1.marginWidth = 2;
gridLayout_1.marginHeight = 1;
gridLayout_1.horizontalSpacing = 3;
composite_1.setLayout(gridLayout_1);
showLeftIcon = AbstractUIPlugin.imageDescriptorFromPlugin(
Application.PLUGIN_ID, IImageKeys.SHOW_LEFT_SIDEVIEW).createImage();
ToolBar toolBar = new ToolBar (composite_1, SWT.HORIZONTAL | SWT.SHADOW_OUT | SWT.FLAT);
final ToolItem scroll = new ToolItem (toolBar, SWT.CHECK);
scroll.setImage(showLeftIcon);
scroll.addSelectionListener(new SelectionAdapter() {
private int[] sashweights = null;
public void widgetSelected(final SelectionEvent e) {
if (!scroll.getSelection()) {
sashForm.setWeights(sashweights);
tree.setVisible(true);
} else {
sashweights = sashForm.getWeights();
tree.setVisible(false);
sashForm.setWeights(new int[]{0,400});
}
sashForm.layout(true);
}
});
toolBar.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
// Label placeholder = new Label(composite_1,SWT.NONE);
// placeholder.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// final Button showSidebarCheckbox = new Button(composite_1, SWT.CHECK);
// showSidebarCheckbox.addSelectionListener(new SelectionAdapter() {
// private int[] sashweights = null;
// public void widgetSelected(final SelectionEvent e) {
// if (showSidebarCheckbox.getSelection()) {
// sashForm.setWeights(sashweights);
// tree.setVisible(true);
// } else {
// sashweights = sashForm.getWeights();
// tree.setVisible(false);
// sashForm.setWeights(new int[]{0,400});
// }
// sashForm.layout(true);
// }
// });
// showSidebarCheckbox.setSelection(true);
// showSidebarCheckbox.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
// showSidebarCheckbox.setText(Lang.ShowSidebar);
nrOfSelectedItemsLabel = new CLabel(composite_1, SWT.NONE);
final GridData gridData_1 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_1.widthHint = 100;
nrOfSelectedItemsLabel.setLayoutData(gridData_1);
sizeLabel = new CLabel(composite_1, SWT.NONE);
final GridData gridData_2 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_2.widthHint = 100;
sizeLabel.setLayoutData(gridData_2);
nrOfFilesLabel = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_3 = new GridData(SWT.FILL, SWT.CENTER, false, false);
nrOfFilesLabel.setLayoutData(gridData_3);
totalSizeLabel = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_4 = new GridData(SWT.FILL, SWT.CENTER, false, false);
totalSizeLabel.setLayoutData(gridData_4);
treeViewer = new TreeViewer(tree);
DownloadQueueTreeManager dqtp = new DownloadQueueTreeManager();
treeViewer.setContentProvider(dqtp);
treeViewer.setLabelProvider(dqtp);
treeViewer.addFilter(new DownloadQueueFolderFilter());
treeViewer.setComparator(dqtp);
treeViewer.setAutoExpandLevel(2);
DQProgressPainter.addToTable(table,3);
tableViewer = new TableViewer(table);
DownloadQueueTableProvider dqTablep = new DownloadQueueTableProvider();
tableViewer.setContentProvider(dqTablep);
tableViewer.addFilter(new DownloadQueueEntryFilter());
tva = new TableViewerAdministrator<AbstractDownloadQueueEntry>(tableViewer,
Arrays.asList(new DQFile(),new DQStatus(),new DQSize(),
new DQDownloaded(),new DQPriority(),new DQUsers(),
new DQPath(),new DQExactSize(),new DQErrors(),
new DQAdded(), new DQTTHRoot()),
GUIPI.downloadQueueTable,0);
tva.apply();
spi.addViewer(treeViewer);
spi.addViewer(tableViewer);
getSite().setSelectionProvider(spi);
createContextPopup(tableViewer);
createContextPopup(treeViewer);
treeViewer.setInput(getDQ().getRoot());
tableViewer.setInput(getDQ().getRoot());
updateLabels();
addListener();
pack();
setControlsForFontAndColour(treeViewer.getTree(),tableViewer.getTable());
logger.debug("current column width: "+tree.getColumn(0).getWidth());
DragSource ds = new DragSource(table, DND.DROP_MOVE);
ds.setTransfer(new Transfer[] { TextTransfer.getInstance() });
ds.addDragListener(new DragSourceAdapter() {
public void dragSetData(DragSourceEvent event) {
IStructuredSelection isl = (IStructuredSelection)tableViewer.getSelection();
List<String> paths = new ArrayList<String>();
for (Object o: isl.toArray()) {
if (o instanceof AbstractDownloadQueueEntry) {
paths.add(((AbstractDownloadQueueEntry)o).getID().toString());
}
}
event.data = PrefConverter.asString(paths.toArray(new String[]{}));
}
});
DragSource ds2 = new DragSource(tree, DND.DROP_MOVE);
ds2.setTransfer(new Transfer[] { TextTransfer.getInstance() });
ds2.addDragListener(new DragSourceAdapter() {
public void dragSetData(DragSourceEvent event) {
IStructuredSelection isl = (IStructuredSelection)treeViewer.getSelection();
List<String> paths = new ArrayList<String>();
Object o = isl.getFirstElement();
if (o instanceof DownloadQueueFolder) {
DownloadQueueFolder dqf = (DownloadQueueFolder)o;
paths.add(OverrideFilePrefix+dqf.getShownPath().getParent());
for (AbstractDownloadQueueEntry adqe: dqf.getAllDQEChildren()) {
paths.add(adqe.getID().toString());
}
}
event.data = PrefConverter.asString(paths.toArray(new String[]{}));
}
});
DropTarget dt = new DropTarget(tree, DND.DROP_MOVE);
dt.setTransfer(new Transfer[] { TextTransfer.getInstance() });
dt.addDropListener (new DropTargetAdapter() {
public void dragOver(DropTargetEvent event) {
event.feedback = DND.FEEDBACK_EXPAND | DND.FEEDBACK_SCROLL;
if (event.item != null) {
event.feedback |= DND.FEEDBACK_SELECT;
}
}
@Override
public void drop(DropTargetEvent event) {
if (event.data == null) {
event.detail = DND.DROP_NONE;
return;
}
String[] files = PrefConverter.asArray((String)event.data);
File overridePrefix = null;
List<AbstractDownloadQueueEntry> adqeList = new ArrayList<AbstractDownloadQueueEntry>();
for (String s : files) {
if (HashValue.isHash(s)) {
HashValue h = HashValue.createHash(s);
AbstractDownloadQueueEntry adqe = getDQ().get(h);
if (adqe != null) {
adqeList.add(adqe);
}
} else if (s.startsWith(OverrideFilePrefix)) {
overridePrefix = new File(s.substring(OverrideFilePrefix.length()));
}
}
Object o = ((TreeItem)event.item).getData();
if (o instanceof DownloadQueueFolder) {
DownloadQueueFolder dqf = (DownloadQueueFolder)o;
DownloadQueueHandlers.move(dqf, adqeList, overridePrefix);
} else {
event.detail = DND.DROP_NONE;
}
}
});
}
private void updateLabels() {
totalSizeLabel.setText( " "+
String.format(Lang.TotalSize,SizeEnum.getReadableSize(
getDQ().getTotalSize())) +
" ");
nrOfFilesLabel.setText( " " +
String.format(Lang.TotalFiles,getDQ().getTotalNrOfFiles())
+" ");
totalSizeLabel.getParent().layout();
}
private void addListener() {
treeViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event)
{
IStructuredSelection selection =
(IStructuredSelection) event.getSelection();
Object selectedFolder = selection.getFirstElement();
pack();
logger.debug("current column selection width: "+tree.getColumn(0).getWidth());
tableViewer.setInput(selectedFolder);
}
});
treeViewer.addTreeListener(new ITreeViewerListener() {
public void treeCollapsed(TreeExpansionEvent event) {
pack();
logger.debug("current column collapsed width: "+tree.getColumn(0).getWidth());
}
public void treeExpanded(TreeExpansionEvent event) {
pack();
logger.debug("current column expanded width: "+tree.getColumn(0).getWidth());
}
});
getDQ().addObserver(this);
}
private DownloadQueue getDQ() {
return ((DownloadQueueEditorInput)getEditorInput()).getDQ();
}
// private void makeActions() {
// MenuManager tableMenu = new MenuManager();
// MenuManager treeMenu = new MenuManager();
// IWorkbenchWindow window = getEditorSite().getWorkbenchWindow();
// if (!actions.isEmpty()) {
// throw new IllegalStateException();
// }
//
// actions.add(new SearchForAlternatesAction(window,tableViewer,treeViewer));
// actions.add(new CopyTTHToClipboardAction(window,tableViewer,treeViewer));
// actions.add(new CopyMagnetToClipboardAction(window,tableViewer,treeViewer));
// actions.add(new MoveRenameAction(window,tableViewer,treeViewer));
// for (Action a: actions) {
// tableMenu.add(a);
// if (a instanceof AbstractDownloadQueueActions) {
// treeMenu.add(a);
// }
// }
//
// List<? extends Action> prio = SetPriorityAction.getAll(window,tableViewer,treeViewer);
// MenuManager setPrio = new MenuManager(Lang.SetPriority);
// MenuManager setPrioTree = new MenuManager(Lang.SetPriority);
// for (Action a : prio) {
// setPrio.add(a);
// setPrioTree.add(a);
// actions.add(a);
// }
// setPrio.add(new Separator());
// setPrioTree.add(new Separator());
//
// IHandlerService hservice = (IHandlerService) getSite().getService(IHandlerService.class);
// // change priority action
// Action up = new ChangePriorityAction(window,true,tableViewer,treeViewer);
// Action down = new ChangePriorityAction(window,false,tableViewer,treeViewer);
// IHandler hUp = new ActionHandler(up);
// IHandler hDown = new ActionHandler(down);
// handUp = hservice.activateHandler(up.getId(), hUp);
// handDown = hservice.activateHandler(down.getId(), hDown);
//
// setPrio.add(up);
// setPrioTree.add(up);
// setPrio.add(down);
// setPrioTree.add(down);
// actions.add(up);
// actions.add(down);
// //cp end
//
// tableMenu.add(setPrio);
// treeMenu.add(setPrioTree);
//
//
//
// remove = new RemoveAction(window,tableViewer,treeViewer);
// IHandler hRemove = new ActionHandler(remove);
// handRemove = hservice.activateHandler(RemoveAction.ID, hRemove);
//
//
//
// tableMenu.add(remove);
// treeMenu.add(remove);
// actions.add(remove);
//
// tableMenu.add(new Separator());
//
// new DQUserActionMenuListener(tableViewer,window,tableMenu);
//
//
// Menu menu = tableMenu.createContextMenu(tableViewer.getControl());
// Menu menu2 = treeMenu.createContextMenu(treeViewer.getControl());
//
// tableMenu.updateAll(true);
//
// tableViewer.getControl().setMenu(menu);
// treeViewer.getControl().setMenu(menu2);
//
// logger.debug("DQ created");
//
//
// }
private void pack() {
new SUIJob(treeViewer.getTree()) {
public void run() {
Tree tree = treeViewer.getTree();
TreeColumn col = tree.getColumn(0);
col.pack();
if (col.getWidth() < tree.getBounds().width) {
logger.debug("setting new Column width after pack: "+tree.getBounds().width);
col.setWidth(tree.getBounds().width);
}
}
}.schedule();
}
public void setFocus() {
table.setFocus();
}
public void dispose() {
//getEditorSite().getKeyBindingService().unregisterAction(remove);
// IHandlerService hservice = (IHandlerService) getSite().getService(IHandlerService.class);
// hservice.deactivateHandler(handUp);
// hservice.deactivateHandler(handDown);
// hservice.deactivateHandler(handRemove);
//
// for (Action a:actions) {
// ((IWorkbenchAction)a).dispose();
// }
if (showLeftIcon != null) {
showLeftIcon.dispose();
}
getDQ().deleteObserver(this);
super.dispose();
}
public String getTopic() {
return getPartName();
}
public void update(IObservable<StatusObject> o, final StatusObject status) {
switch(status.getType()) {
case ADDED:
case REMOVED:
if (arInProgress.compareAndSet(false, true)) {
new SUIJob(table) {
public void run() {
arInProgress.set(false);
tableViewer.refresh();
treeViewer.refresh();
updateLabels();
}
}.schedule();
}
break;
case CHANGED:
new SUIJob(table) {
public void run() {
tableViewer.update(status.getValue(), null);
}
}.schedule();
break;
}
}
public void next() {}
public void search(String searchstring) {
tableViewer.setInput( getDQ().search(searchstring));
}
public static class DownloadQueueTableProvider implements IStructuredContentProvider {
public DownloadQueueTableProvider(){
}
public Object[] getElements(Object inputElement) {
if (inputElement instanceof DownloadQueueFolder) {
DownloadQueueFolder dqf =(DownloadQueueFolder)inputElement;
if (dqf.oneFolderChildNothingElse() && dqf.getParent() != null) {
return getElements(dqf.getChildren()[0]);
} else {
return dqf.getChildren() ;
}
}
if (inputElement instanceof List<?>) {
return ((List<?>)inputElement).toArray();
}
return new Object[0];
}
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
}
public static class DownloadQueueTreeManager extends ViewerComparator implements ITreeContentProvider , ILabelProvider {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
*/
public Image getImage(Object element) {
return IconManager.get().getFolderIcon();
}
public String getText(Object element) {
DownloadQueueFolder dqf = ((DownloadQueueFolder)element);
if (dqf.oneFolderChildNothingElse() ) {
return dqf.getName()+java.io.File.separator+getText(dqf.getChildren()[0]);
}
return dqf.getName();
}
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
return getText(e1).compareTo(getText(e2));
}
public Object[] getChildren(Object parentElement) {
DownloadQueueFolder dqf= (DownloadQueueFolder)parentElement;
if (dqf.oneFolderChildNothingElse() && dqf.getParent() != null) {
return getChildren(dqf.getChildren()[0]);
} else {
return dqf.getChildren();
}
}
public Object getParent(Object element) {
return null;
}
public boolean hasChildren(Object element) {
DownloadQueueFolder dqf = (DownloadQueueFolder)element;
if (dqf.oneFolderChildNothingElse() && dqf.getParent() != null) {
Object[] children =dqf.getChildren();
if (children.length == 0) { //concurrency problem.. if folder is removed after check above..
return false;
}
return hasChildren(children[0]);
} else {
return dqf.hasChildFolders();
}
}
public Object[] getElements(Object inputElement) {
return getChildren(inputElement);
}
public void addListener(ILabelProviderListener listener) {}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {}
public void dispose() {}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
}
public static class DownloadQueueFolderFilter extends ViewerFilter {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public boolean select(Viewer viewer, Object parentElement, Object element) {
return element instanceof DownloadQueueFolder;
}
}
public static class DownloadQueueEntryFilter extends ViewerFilter {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public boolean select(Viewer viewer, Object parentElement, Object element) {
return element instanceof AbstractDownloadQueueEntry;
}
}
}