/*
* Copyright (c) 2004-2011 Marco Maccaferri and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Marco Maccaferri - initial API and implementation
*/
package org.eclipsetrader.ui.internal.repositories;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.viewers.AbstractTreeViewer;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerDropAdapter;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.dnd.Clipboard;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DragSource;
import org.eclipse.swt.dnd.DragSourceEvent;
import org.eclipse.swt.dnd.DragSourceListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.actions.ActionFactory;
import org.eclipse.ui.handlers.IHandlerService;
import org.eclipse.ui.part.ViewPart;
import org.eclipsetrader.core.repositories.IRepository;
import org.eclipsetrader.core.repositories.IRepositoryChangeListener;
import org.eclipsetrader.core.repositories.IRepositoryRunnable;
import org.eclipsetrader.core.repositories.IRepositoryService;
import org.eclipsetrader.core.repositories.RepositoryChangeEvent;
import org.eclipsetrader.core.views.IView;
import org.eclipsetrader.core.views.IViewItem;
import org.eclipsetrader.core.views.IViewVisitor;
import org.eclipsetrader.ui.SelectionProvider;
import org.eclipsetrader.ui.UIConstants;
import org.eclipsetrader.ui.internal.UIActivator;
import org.eclipsetrader.ui.navigator.RepositoryObjectTransfer;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
public class RepositoryExplorer extends ViewPart {
private static final String K_EXPANDED = "expanded";
private TreeViewer viewer;
private IMemento memento;
private Action refreshAction;
private Action collapseAllAction;
private Action expandAllAction;
private Action copyAction;
private Action pasteAction;
private Action deleteAction;
private Job refreshJob = new Job(Messages.RepositoryExplorer_RefreshJobName) {
@Override
protected IStatus run(IProgressMonitor monitor) {
monitor.beginTask(getName(), IProgressMonitor.UNKNOWN);
final RepositoryTree tree = viewer.getInput() != null ? (RepositoryTree) viewer.getInput() : new RepositoryTree(getRepositoryService());
tree.refresh();
if (!viewer.getControl().isDisposed()) {
try {
viewer.getControl().getDisplay().asyncExec(new Runnable() {
@Override
public void run() {
if (!viewer.getControl().isDisposed()) {
if (viewer.getInput() == null) {
viewer.setInput(tree);
if (memento != null) {
String s = memento.getString("expanded");
if (s != null) {
String[] sr = s.split(";");
final Set<Integer> itemHash = new HashSet<Integer>();
for (int i = 0; i < sr.length; i++) {
try {
itemHash.add(Integer.parseInt(sr[i]));
} catch (Exception e) {
// Do nothing
}
}
tree.accept(new IViewVisitor() {
@Override
public boolean visit(IView view) {
return true;
}
@Override
public boolean visit(IViewItem viewItem) {
if (itemHash.contains(viewItem.hashCode())) {
viewer.setExpandedState(viewItem, true);
}
return true;
}
});
}
}
}
else {
viewer.refresh();
}
}
}
});
} catch (SWTException e) {
if (e.code != SWT.ERROR_DEVICE_DISPOSED) {
throw e;
}
}
}
monitor.done();
return Status.OK_STATUS;
}
};
private IRepositoryChangeListener resourceListener = new IRepositoryChangeListener() {
@Override
public void repositoryResourceChanged(RepositoryChangeEvent event) {
try {
refreshJob.join();
} catch (Exception e) {
}
refreshJob.schedule();
}
};
public RepositoryExplorer() {
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.ViewPart#init(org.eclipse.ui.IViewSite, org.eclipse.ui.IMemento)
*/
@Override
public void init(IViewSite site, IMemento memento) throws PartInitException {
super.init(site, memento);
this.memento = memento;
ImageRegistry imageRegistry = UIActivator.getDefault().getImageRegistry();
site.setSelectionProvider(new SelectionProvider());
refreshAction = new Action(Messages.RepositoryExplorer_Refresh, imageRegistry.getDescriptor(UIConstants.REFRESH_ICON)) {
@Override
public void run() {
refreshJob.setUser(true);
refreshJob.schedule();
}
};
collapseAllAction = new Action(Messages.RepositoryExplorer_CollapseAll, imageRegistry.getDescriptor(UIConstants.COLLAPSEALL_ICON)) {
@Override
public void run() {
viewer.collapseAll();
}
};
expandAllAction = new Action(Messages.RepositoryExplorer_ExpandAll, imageRegistry.getDescriptor(UIConstants.EXPANDALL_ICON)) {
@Override
public void run() {
viewer.expandAll();
}
};
copyAction = new Action(Messages.RepositoryExplorer_Copy) {
@Override
public void run() {
IAdaptable[] objects = getSelectedObject(viewer.getSelection());
if (objects.length != 0) {
Transfer[] transfer = new Transfer[objects.length];
for (int i = 0; i < transfer.length; i++) {
transfer[i] = RepositoryObjectTransfer.getInstance();
}
Clipboard clipboard = new Clipboard(Display.getDefault());
try {
clipboard.setContents(new Object[] {
objects
}, new Transfer[] {
RepositoryObjectTransfer.getInstance()
});
} finally {
clipboard.dispose();
}
}
}
};
copyAction.setImageDescriptor(imageRegistry.getDescriptor(UIConstants.COPY_EDIT_ICON));
copyAction.setDisabledImageDescriptor(imageRegistry.getDescriptor(UIConstants.COPY_EDIT_DISABLED_ICON));
copyAction.setId(ActionFactory.COPY.getId());
copyAction.setActionDefinitionId("org.eclipse.ui.edit.copy"); //$NON-NLS-1$
copyAction.setEnabled(false);
pasteAction = new Action(Messages.RepositoryExplorer_Paste) {
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
if (!selection.isEmpty()) {
RepositoryViewItem element = (RepositoryViewItem) selection.getFirstElement();
while (element.getParent() != null && !(element.getObject() instanceof IRepository)) {
element = (RepositoryViewItem) element.getParent();
}
IRepository destinationRepository = (IRepository) element.getObject();
Clipboard clipboard = new Clipboard(Display.getDefault());
try {
IAdaptable[] contents = (IAdaptable[]) clipboard.getContents(RepositoryObjectTransfer.getInstance());
if (contents.length != 0) {
IRepositoryService service = getRepositoryService();
RepositoryMoveJob job = new RepositoryMoveJob(service, contents, destinationRepository);
job.schedule();
}
} finally {
clipboard.dispose();
}
}
}
};
pasteAction.setImageDescriptor(imageRegistry.getDescriptor(UIConstants.PASTE_EDIT_ICON));
pasteAction.setDisabledImageDescriptor(imageRegistry.getDescriptor(UIConstants.PASTE_EDIT_DISABLED_ICON));
pasteAction.setId(ActionFactory.PASTE.getId());
pasteAction.setActionDefinitionId("org.eclipse.ui.edit.paste"); //$NON-NLS-1$
pasteAction.setEnabled(false);
deleteAction = new Action(Messages.RepositoryExplorer_Delete) {
@Override
public void run() {
final IAdaptable[] objects = getSelectedObject(viewer.getSelection());
if (objects.length != 0) {
if (!MessageDialog.openConfirm(getViewSite().getShell(), getPartName(), Messages.RepositoryExplorer_DeleteConfirmMessage)) {
return;
}
final IRepositoryService service = getRepositoryService();
service.runInService(new IRepositoryRunnable() {
@Override
public IStatus run(IProgressMonitor monitor) throws Exception {
service.deleteAdaptable(objects);
return Status.OK_STATUS;
}
}, null);
}
}
};
deleteAction.setImageDescriptor(imageRegistry.getDescriptor(UIConstants.DELETE_EDIT_ICON));
deleteAction.setDisabledImageDescriptor(imageRegistry.getDescriptor(UIConstants.DELETE_EDIT_DISABLED_ICON));
deleteAction.setId(ActionFactory.DELETE.getId());
deleteAction.setActionDefinitionId("org.eclipse.ui.edit.delete"); //$NON-NLS-1$
deleteAction.setEnabled(false);
IToolBarManager toolBarManager = site.getActionBars().getToolBarManager();
toolBarManager.add(expandAllAction);
toolBarManager.add(collapseAllAction);
toolBarManager.add(new Separator());
toolBarManager.add(refreshAction);
site.getActionBars().setGlobalActionHandler(copyAction.getId(), copyAction);
site.getActionBars().setGlobalActionHandler(pasteAction.getId(), pasteAction);
site.getActionBars().setGlobalActionHandler(deleteAction.getId(), deleteAction);
site.getActionBars().updateActionBars();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
*/
@Override
public void createPartControl(Composite parent) {
viewer = new TreeViewer(parent, SWT.MULTI);
viewer.getTree().setHeaderVisible(false);
viewer.getTree().setLinesVisible(false);
viewer.setLabelProvider(new RepositoryLabelProvider());
viewer.setContentProvider(new RepositoryContentProvider());
viewer.setSorter(new ViewerSorter());
viewer.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent event) {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
if (selection.size() == 1) {
Object element = selection.getFirstElement();
if (viewer.getExpandedState(element)) {
viewer.collapseToLevel(element, 1);
}
else {
viewer.expandToLevel(element, 1);
}
}
}
});
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
@Override
public void selectionChanged(SelectionChangedEvent event) {
IAdaptable[] objects = getSelectedObject(event.getSelection());
copyAction.setEnabled(objects.length != 0);
deleteAction.setEnabled(objects.length != 0);
getViewSite().getSelectionProvider().setSelection(event.getSelection());
}
});
viewer.addOpenListener(new IOpenListener() {
@Override
public void open(OpenEvent event) {
try {
IHandlerService service = (IHandlerService) getSite().getService(IHandlerService.class);
service.executeCommand("org.eclipse.ui.file.open", null);
} catch (Exception e) {
e.printStackTrace();
}
}
});
DragSource dragSource = new DragSource(viewer.getControl(), DND.DROP_COPY | DND.DROP_MOVE);
dragSource.setTransfer(new Transfer[] {
RepositoryObjectTransfer.getInstance()
});
dragSource.addDragListener(new DragSourceListener() {
@Override
public void dragStart(DragSourceEvent event) {
event.doit = getSelectedObject(viewer.getSelection()).length != 0;
}
@Override
public void dragSetData(DragSourceEvent event) {
if (RepositoryObjectTransfer.getInstance().isSupportedType(event.dataType)) {
event.data = getSelectedObject(viewer.getSelection());
}
}
@Override
public void dragFinished(DragSourceEvent event) {
}
});
viewer.addDropSupport(DND.DROP_COPY | DND.DROP_MOVE, new Transfer[] {
RepositoryObjectTransfer.getInstance()
}, new ViewerDropAdapter(viewer) {
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerDropAdapter#validateDrop(java.lang.Object, int, org.eclipse.swt.dnd.TransferData)
*/
@Override
public boolean validateDrop(Object target, int operation, TransferData transferType) {
return RepositoryObjectTransfer.getInstance().isSupportedType(transferType);
}
/* (non-Javadoc)
* @see org.eclipse.jface.viewers.ViewerDropAdapter#performDrop(java.lang.Object)
*/
@Override
public boolean performDrop(Object data) {
RepositoryViewItem element = (RepositoryViewItem) getCurrentTarget();
while (element.getParent() != null && !(element.getObject() instanceof IRepository)) {
element = (RepositoryViewItem) element.getParent();
}
IRepository destinationRepository = (IRepository) element.getObject();
IAdaptable[] contents = (IAdaptable[]) data;
if (contents.length != 0) {
IRepositoryService service = getRepositoryService();
RepositoryMoveJob job = new RepositoryMoveJob(service, contents, destinationRepository);
job.schedule();
}
return true;
}
});
MenuManager menuMgr = new MenuManager("#popupMenu", "popupMenu"); //$NON-NLS-1$ //$NON-NLS-2$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener() {
@Override
public void menuAboutToShow(IMenuManager menuManager) {
menuManager.add(new Separator("group.new"));
menuManager.add(new GroupMarker("group.goto"));
menuManager.add(new Separator("group.open"));
menuManager.add(new GroupMarker("group.openWith"));
menuManager.add(new Separator("group.show"));
menuManager.add(new Separator("group.edit"));
menuManager.add(new GroupMarker("group.reorganize"));
menuManager.add(new GroupMarker("group.port"));
menuManager.add(new Separator("group.generate"));
menuManager.add(new Separator("group.search"));
menuManager.add(new Separator("group.build"));
menuManager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
menuManager.add(new Separator("group.properties"));
menuManager.appendToGroup("group.show", new Action(Messages.RepositoryExplorer_ExpandAll) {
@Override
public void run() {
IStructuredSelection selection = (IStructuredSelection) viewer.getSelection();
for (Iterator<?> iter = selection.iterator(); iter.hasNext();) {
viewer.expandToLevel(iter.next(), AbstractTreeViewer.ALL_LEVELS);
}
}
});
menuManager.appendToGroup("group.edit", copyAction);
menuManager.appendToGroup("group.edit", pasteAction);
menuManager.appendToGroup("group.reorganize", deleteAction);
boolean enablePaste = false;
Clipboard clipboard = new Clipboard(Display.getDefault());
try {
TransferData[] transfers = clipboard.getAvailableTypes();
for (int i = 0; i < transfers.length; i++) {
if (RepositoryObjectTransfer.getInstance().isSupportedType(transfers[i])) {
enablePaste = true;
}
}
} finally {
clipboard.dispose();
}
pasteAction.setEnabled(enablePaste);
}
});
viewer.getControl().setMenu(menuMgr.createContextMenu(viewer.getControl()));
getSite().registerContextMenu(menuMgr, getSite().getSelectionProvider());
refreshJob.setUser(true);
refreshJob.schedule();
getRepositoryService().addRepositoryResourceListener(resourceListener);
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.WorkbenchPart#setFocus()
*/
@Override
public void setFocus() {
viewer.getControl().setFocus();
}
/* (non-Javadoc)
* @see org.eclipse.ui.part.ViewPart#saveState(org.eclipse.ui.IMemento)
*/
@Override
public void saveState(IMemento memento) {
Object[] o = viewer.getExpandedElements();
if (o != null && o.length != 0) {
StringBuffer s = new StringBuffer();
for (int i = 0; i < o.length; i++) {
if (i != 0) {
s.append(";");
}
s.append(o[i].hashCode());
}
memento.putString(K_EXPANDED, s.toString());
}
super.saveState(memento);
}
@Override
public void dispose() {
getRepositoryService().removeRepositoryResourceListener(resourceListener);
super.dispose();
}
protected IRepositoryService getRepositoryService() {
try {
BundleContext context = UIActivator.getDefault().getBundle().getBundleContext();
ServiceReference serviceReference = context.getServiceReference(IRepositoryService.class.getName());
IRepositoryService service = (IRepositoryService) context.getService(serviceReference);
context.ungetService(serviceReference);
return service;
} catch (Exception e) {
Status status = new Status(IStatus.ERROR, UIActivator.PLUGIN_ID, 0, "Error reading repository service", e); //$NON-NLS-1$
UIActivator.getDefault().getLog().log(status);
}
return null;
}
protected IAdaptable[] getSelectedObject(ISelection selection) {
List<IAdaptable> list = new ArrayList<IAdaptable>();
if (!selection.isEmpty() && selection instanceof IStructuredSelection) {
for (Object o : ((IStructuredSelection) selection).toArray()) {
if (!(((RepositoryViewItem) o).getObject() instanceof IAdaptable)) {
return new IAdaptable[0];
}
IAdaptable adaptable = (IAdaptable) ((RepositoryViewItem) o).getObject();
if (RepositoryObjectTransfer.checkMyType(adaptable)) {
list.add(adaptable);
}
}
}
return list.toArray(new IAdaptable[list.size()]);
}
}