package eu.jucy.gui.filelist;
import helpers.IObservable;
import helpers.SizeEnum;
import helpers.StatusObject;
import helpers.Observable.IObserver;
import java.text.Collator;
import java.util.Arrays;
import java.util.List;
import logger.LoggerFactory;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import eu.jucy.gui.FindHandler;
import eu.jucy.gui.GUIPI;
import eu.jucy.gui.ISearchableEditor;
import eu.jucy.gui.Lang;
import eu.jucy.gui.UCEditor;
import eu.jucy.gui.DownloadableColumn.ExactSize;
import eu.jucy.gui.DownloadableColumn.FileColumn;
import eu.jucy.gui.DownloadableColumn.Path;
import eu.jucy.gui.DownloadableColumn.Size;
import eu.jucy.gui.DownloadableColumn.TTHRoot;
import eu.jucy.gui.DownloadableColumn.Type;
import eu.jucy.gui.itemhandler.DownloadableHandlers.DownloadHandler;
import uc.files.IDownloadable;
import uc.files.IDownloadable.IDownloadableFile;
import uc.files.filelist.FileList;
import uc.files.filelist.FileListFile;
import uc.files.filelist.FileListFolder;
import uc.files.filelist.IFileListItem;
import uihelpers.DelayedTableUpdater;
import uihelpers.DelayedTreeUpdater;
import uihelpers.IconManager;
import uihelpers.SUIJob;
import uihelpers.SelectionProviderIntermediate;
import uihelpers.TableViewerAdministrator;
public class FilelistEditor extends UCEditor implements ISearchableEditor , IObserver<StatusObject> {
private static final Logger logger = LoggerFactory.make(Level.DEBUG);
private static final int MAX_OPEN_EDITORS = 10;
public static boolean isAnotherEditorPossible() {
return OPEN_FILELIST_EDITORS < MAX_OPEN_EDITORS;
}
public static boolean isAnotherEditorOpen() {
return OPEN_FILELIST_EDITORS > 0;
}
private static volatile int OPEN_FILELIST_EDITORS = 0;
private CLabel containedSize;
private CLabel containedFiles;
public static final String ID = "eu.jucy.Filelist";
private volatile FileList fileList;
private String lastSearch;
private int searchIndex = -1;
private List<IFileListItem> found;
private DelayedTableUpdater<IFileListItem> tableUpdater;
private DelayedTreeUpdater<FileListFolder> treeUpdater;
private Table table;
private Tree tree;
private TreeViewer treeViewer;
private TableViewer tableViewer;
private Composite composite;
private CLabel totalsize;
private CLabel totalFiles;
private TableViewerAdministrator<IDownloadable> tva;
private final SelectionProviderIntermediate spi = new SelectionProviderIntermediate();
public FilelistEditor() {
OPEN_FILELIST_EDITORS++;
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl(Composite parent) {
final GridLayout gridLayout = new GridLayout();
gridLayout.verticalSpacing = 0;
gridLayout.marginWidth = 0;
gridLayout.marginHeight = 0;
gridLayout.horizontalSpacing = 0;
parent.setLayout(gridLayout);
composite = new Composite(parent, SWT.NONE);
final SashForm sashForm = new SashForm(composite, SWT.NONE);
sashForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
tree = new Tree(sashForm, SWT.BORDER);
table = new Table(sashForm, SWT.BORDER|SWT.FULL_SELECTION | SWT.MULTI);
table.setHeaderVisible(true);
sashForm.setWeights(new int[] {168, 329 });
final GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
gridData.widthHint = 487;
composite.setLayoutData(gridData);
composite.setLayout(new GridLayout());
final Composite composite_1 = new Composite(parent, SWT.BORDER);
final GridLayout gridLayout_1 = new GridLayout();
gridLayout_1.verticalSpacing = 0;
gridLayout_1.marginWidth = 0;
gridLayout_1.marginHeight = 0;
gridLayout_1.horizontalSpacing = 1;
gridLayout_1.numColumns = 7;
// RowLayout rowLayout = new RowLayout();
// rowLayout.wrap = false;
composite_1.setLayout(gridLayout_1);
final GridData gridData_1 = new GridData(SWT.FILL, SWT.FILL, true, false);
composite_1.setLayoutData(gridData_1);
final CLabel label = new CLabel(composite_1, SWT.BORDER);
label.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
// label.setLayoutData(new RowData());
label.setText(getList().getGenerator());
// final CLabel label_1 = new CLabel(composite_1, SWT.BORDER);
// final GridData gridData_2 = new GridData(SWT.FILL, SWT.FILL, false, false);
// gridData_2.widthHint = 100;
// label_1.setLayoutData(gridData_2);
int labelWidth= 100;
GC gc = new GC(composite_1);
int cWidth = gc.getFontMetrics().getAverageCharWidth();
gc.dispose();
labelWidth = (int)(Math.max(Lang.Size.length()+10, Lang.Files.length()+8)*cWidth*1.05d);
totalFiles = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_5 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_5.widthHint = labelWidth;
totalFiles.setLayoutData(gridData_5);
totalsize = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_4 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_4.widthHint = labelWidth;
totalsize.setLayoutData(gridData_4);
containedFiles = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_3 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_3.widthHint = labelWidth;
containedFiles.setLayoutData(gridData_3);
containedSize = new CLabel(composite_1, SWT.BORDER);
final GridData gridData_6 = new GridData(SWT.FILL, SWT.CENTER, false, false);
gridData_6.widthHint = labelWidth;
containedSize.setLayoutData(gridData_6);
final Button findButton = new Button(composite_1, SWT.NONE);
findButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
executeCommand(FindHandler.ID);
}
});
findButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
findButton.setText(Lang.Find);
final Button nextButton = new Button(composite_1, SWT.NONE);
nextButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
next();
}
});
nextButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
nextButton.setText(Lang.Next);
createColumns();
treeViewer = new TreeViewer(tree);
FilelistTreeProvider ftrp = new FilelistTreeProvider();
treeViewer.setContentProvider(ftrp);
treeViewer.setLabelProvider(ftrp);
treeViewer.addFilter(new FolderFilter() ); //filter that shows only the folders..
treeViewer.setSorter(new ViewerSorter() {
private final Collator col = Collator.getInstance();
@Override
public int compare(Viewer viewer, Object e1, Object e2) {
return col.compare(((FileListFolder)e1).getName(),
((FileListFolder)e2).getName());
}
});
treeViewer.setInput(getList());
treeUpdater = new DelayedTreeUpdater<FileListFolder>(treeViewer);
tableViewer = new TableViewer(table);
FilelistTableProvider ftap= new FilelistTableProvider();
tableViewer.setContentProvider(ftap);
tableUpdater = new DelayedTableUpdater<IFileListItem>(tableViewer);
tva = new TableViewerAdministrator<IDownloadable>(tableViewer,
Arrays.asList(new FileColumn(), new Type(),new Size(),new TTHRoot(),new ExactSize(),new Path()),
GUIPI.fileListTable,0);
tva.apply();
setControlsForFontAndColour(tableViewer.getTable(),treeViewer.getTree());
//makeActions();
spi.addViewer(tableViewer);
spi.addViewer(treeViewer);
getSite().setSelectionProvider(spi);
createContextPopup(tableViewer);
createContextPopup(treeViewer);
// treeViewer.refresh();
updateTotal();
treeViewer.expandToLevel(2);
addListener();
FileList list = getList();
IDownloadable in = ((FilelistEditorInput)getEditorInput()).getInitialSelection();
IFileListItem item = null;
IDownloadable input = list.getRoot();
if ( in != null) { //TODO might not work correctly with multiple users..
FileListFolder parentFolder = list.getRoot().getByPath(in.getOnlyPath());
if (in.isFile()) {
if (parentFolder != null) {
item = parentFolder.getFilePerName(in.getName());
}
if (item == null) {
item = list.search( ((IDownloadableFile)in).getTTHRoot() );
if (item != null) {
parentFolder = item.getParent();
}
}
} else {
if (parentFolder != null) {
item = parentFolder.getChildPerName(in.getName());
}
}
// logger.debug("item: "+item.getPath());
// if (in.isFile()) {
// select = list.search( ((IDownloadableFile)in).getTTHRoot() );
// if (parentFolder == null && select != null) {
// parentFolder = select.getParent();
// }
// }
if (parentFolder != null) {
input = parentFolder;
// logger.debug(input.getPath());
}
}
final Object iInput = input;
final Object selected = item;
new SUIJob(tree) {
@Override
public void run() {
tableViewer.setInput(iInput);
if (selected != null) {
tableViewer.setSelection(new StructuredSelection(selected), true);
}
}
}.schedule();
getList().addObserver(this);
}
public void update(IObservable<StatusObject> o, StatusObject arg) {
IFileListItem item = (IFileListItem)arg.getValue();
FileListFolder parent = (FileListFolder)arg.getDetailObject();
if (item.isFile()) {
if (parent.equals(tableViewer.getInput())) {
tableUpdater.put(arg.getType(), item);
}
} else {
treeUpdater.put(arg.getType(), (FileListFolder)item, parent);
}
new SUIJob(tree) {
@Override
public void run() {
updateTotal();
}
}.scheduleIfNotRunning(1000, this);
}
public void dispose() {
if (fileList != null) {
fileList.deleteObserver(this);
fileList = null;
}
OPEN_FILELIST_EDITORS--;
super.dispose();
}
public void next() {
if (found != null && !found.isEmpty()) {
searchIndex++;
IFileListItem current = found.get(searchIndex % found.size());
tableViewer.setInput(current.getParent());
tableViewer.setSelection(new StructuredSelection(current), true);
}
}
public void search(String searchstring) {
if (!searchstring.equals(lastSearch)) {
lastSearch = searchstring;
searchIndex = -1;
found = getList().search(lastSearch);
}
next();
}
private synchronized FileList getList() {
if (fileList == null ) {
fileList = ((FilelistEditorInput)getEditorInput()).getFilelistDescriptor().getFilelist();
}
return fileList;
}
private void createColumns() {
final TreeColumn newColumnTreeColumn = new TreeColumn(tree, SWT.NONE);
newColumnTreeColumn.setWidth(1000);
}
private void addListener(){
//add a listener in the tree on selection .. show that folder in the table..
treeViewer.addSelectionChangedListener(new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event){
IStructuredSelection selection =
(IStructuredSelection) event.getSelection();
Object selectedFolder = selection.getFirstElement();
tableViewer.setInput(selectedFolder);
logger.debug("TreeViewer setting selected: "+selectedFolder+ " "+event.getSource().toString());
}
});
// a listener that expands a folder
treeViewer.addDoubleClickListener(new IDoubleClickListener(){
public void doubleClick(DoubleClickEvent event){
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
Object selectedFolder = selection.getFirstElement();
if (selectedFolder instanceof FileListFolder) {
treeViewer.expandToLevel(selectedFolder, 1);
}
}
});
//add a listener for doubleclicks in the table on a folder --> go one deeper.. ( and show it BACK in the tree)
tableViewer.addDoubleClickListener(new IDoubleClickListener(){
public void doubleClick(DoubleClickEvent event){
IStructuredSelection selection = (IStructuredSelection) event.getSelection();
Object selected = selection.getFirstElement();
if (selected instanceof FileListFolder) {
tableViewer.setInput(selected);
} else if (selected instanceof IDownloadableFile) {
executeCommand(DownloadHandler.ID);
}
}
});
tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
public void selectionChanged(SelectionChangedEvent event){
IStructuredSelection selection =
(IStructuredSelection) event.getSelection();
Object selected = selection.getFirstElement();
if (selected instanceof IFileListItem) {
IFileListItem item = (IFileListItem)selected;
StructuredSelection newSel = new StructuredSelection(item.getParent());
if (!newSel.equals(treeViewer.getSelection())) {
treeViewer.setSelection(newSel,true);
}
}
}
});
}
private void updateTotal() {
totalsize.setText(Lang.Size+": "+SizeEnum.getReadableSize(getList().getSharesize()));
totalFiles.setText(Lang.Files+": "+getList().getNumberOfFiles());
totalFiles.getParent().layout();
}
private void setContained(FileListFolder folder) {
containedFiles.setText(""+Lang.Files+": "+folder.getContainedFiles() );
containedSize.setText(Lang.Size+": "+SizeEnum.getReadableSize(folder.getSize()));
containedFiles.getParent().layout();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
tree.setFocus();
}
class FilelistTableProvider implements IStructuredContentProvider {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
if (inputElement instanceof FileListFolder){
FileListFolder folder = (FileListFolder)inputElement;
setContained(folder);
treeViewer.expandToLevel(folder, 1);
List<IFileListItem> children = folder.getChildren();
return children.toArray();
}
return new Object[0];
}
public void dispose() {
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
}
}
// public static class FileListFolderUp extends FileListFolder {
//
// private final FileListFolder copy;
//
// public FileListFolderUp( FileListFolder copy) {
// super(copy.getFilelist(), copy.getParent(), "..");
// this.copy = copy;
// }
//
// public AbstractDownloadQueueEntry download() {
// return copy.download();
// }
//
// public AbstractDownloadQueueEntry download(File target) {
// return copy.download(target);
// }
//
// public FileListFolder getChildPerName(String foldernameOfTheChild) {
// return copy.getChildPerName(foldernameOfTheChild);
// }
//
// public List<IFileListItem> getChildren() {
// return copy.getChildren();
// }
//
// public int getContainedFiles() {
// return copy.getContainedFiles();
// }
//
// public long getContainedSize() {
// return copy.getContainedSize();
// }
//
// public List<FileListFile> getFiles() {
// return copy.getFiles();
// }
//
// public List<FileListFolder> getSubfolders() {
// return copy.getSubfolders();
// }
//
// }
public static class FilelistTreeProvider implements ITreeContentProvider , ILabelProvider {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILabelProvider#getImage(java.lang.Object)
*/
public Image getImage(Object element) {
return IconManager.get().getFolderIcon();
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ILabelProvider#getText(java.lang.Object)
*/
public String getText(Object element) {
if(element instanceof FileListFolder){
FileListFolder ff=((FileListFolder)element);
if (ff.getParent() == null) { //if it is the root folder ... show the username
return ff.getFilelist().getUsr().getNick();
} else {
return ff.getName(); //fielname
}
}
return null;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getChildren(java.lang.Object)
*/
public Object[] getChildren(Object parentElement) {
if (parentElement instanceof FileListFolder) {
return ((FileListFolder)parentElement).getChildren().toArray();
}
return new Object[]{};
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#getParent(java.lang.Object)
*/
public Object getParent(Object element) {
if (element instanceof FileListFolder) {
return ((FileListFolder)element).getParent();
}
return ((FileListFile)element).getParent();
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ITreeContentProvider#hasChildren(java.lang.Object)
*/
public boolean hasChildren(Object element) {
return ((FileListFolder)element).hasSubfolders();
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object)
*/
public Object[] getElements(Object inputElement) {
return new Object[]{ ((FileList)inputElement).getRoot()};
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#dispose()
*/
public void dispose() {}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IBaseLabelProvider#addListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void addListener(ILabelProviderListener listener) {}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IBaseLabelProvider#isLabelProperty(java.lang.Object, java.lang.String)
*/
public boolean isLabelProperty(Object element, String property) {
return false;
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.IBaseLabelProvider#removeListener(org.eclipse.jface.viewers.ILabelProviderListener)
*/
public void removeListener(ILabelProviderListener listener) {}
}
public static class FolderFilter extends ViewerFilter {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerFilter#select(org.eclipse.jface.viewers.Viewer, java.lang.Object, java.lang.Object)
*/
@Override
public boolean select(Viewer viewer, Object parentElement, Object element) {
return element instanceof FileListFolder;
}
}
}