blob: 43b07f20469d0bdb789c68960cfd3b82a2bd98bf [file] [log] [blame]
/*
* Copyright (c) 2007-2013, 2015 Eike Stepper (Berlin, Germany) 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:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.net4j.util.ui.views;
import org.eclipse.net4j.ui.shared.SharedIcons;
import org.eclipse.net4j.util.container.IContainer;
import org.eclipse.net4j.util.event.IListener;
import org.eclipse.net4j.util.internal.ui.actions.IntrospectAction;
import org.eclipse.net4j.util.internal.ui.bundle.OM;
import org.eclipse.net4j.util.internal.ui.messages.Messages;
import org.eclipse.net4j.util.ui.UIUtil;
import org.eclipse.net4j.util.ui.actions.SafeAction;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IContributionManager;
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.ImageDescriptor;
import org.eclipse.jface.viewers.DecoratingStyledCellLabelProvider;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IBaseLabelProvider;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ISetSelectionTarget;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.views.properties.IPropertySheetPage;
import org.eclipse.ui.views.properties.PropertySheetPage;
public abstract class ContainerView extends ViewPart implements ISelectionProvider, ISetSelectionTarget
{
private Shell shell;
private ContainerItemProvider<IContainer<Object>> itemProvider;
private TreeViewer viewer;
private ISelectionChangedListener selectionListener = new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
ITreeSelection selection = (ITreeSelection)event.getSelection();
IActionBars bars = getViewSite().getActionBars();
ContainerView.this.selectionChanged(bars, selection);
}
};
private Action refreshAction = new RefreshAction();
private Action collapseAllAction = new CollapseAllAction();
private PropertySheetPage propertySheetPage;
public ContainerView()
{
}
public Shell getShell()
{
return shell;
}
public TreeViewer getViewer()
{
return viewer;
}
@Override
public void setFocus()
{
viewer.getControl().setFocus();
}
public void resetInput()
{
final IContainer<?> container = getContainer();
Runnable runnable = new Runnable()
{
public void run()
{
try
{
viewer.setInput(container);
}
catch (RuntimeException ignore)
{
}
}
};
try
{
Display display = getDisplay();
if (display.getThread() == Thread.currentThread())
{
runnable.run();
}
else
{
display.asyncExec(runnable);
}
}
catch (RuntimeException ignore)
{
}
}
/**
* @since 3.0
*/
public ISelection getSelection()
{
if (viewer != null)
{
return viewer.getSelection();
}
return StructuredSelection.EMPTY;
}
/**
* @since 3.0
*/
public void setSelection(ISelection selection)
{
if (viewer != null)
{
viewer.setSelection(selection);
}
}
/**
* @since 3.0
*/
public void addSelectionChangedListener(ISelectionChangedListener listener)
{
if (viewer != null)
{
viewer.addSelectionChangedListener(listener);
}
}
/**
* @since 3.0
*/
public void removeSelectionChangedListener(ISelectionChangedListener listener)
{
if (viewer != null)
{
viewer.removeSelectionChangedListener(listener);
}
}
public void selectReveal(ISelection selection)
{
if (viewer != null)
{
viewer.setSelection(selection, true);
}
}
@Override
public final void createPartControl(Composite parent)
{
shell = parent.getShell();
Composite composite = UIUtil.createGridComposite(parent, 1);
Control control = createUI(composite);
control.setLayoutData(UIUtil.createGridData());
hookContextMenu();
hookDoubleClick();
contributeToActionBars();
createdUI();
}
protected Control createUI(Composite parent)
{
viewer = new TreeViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
initViewer();
viewer.addSelectionChangedListener(selectionListener);
getSite().setSelectionProvider(this);
return viewer.getControl();
}
/**
* @since 3.1
*/
protected void createdUI()
{
}
/**
* @since 3.1
*/
protected void initViewer()
{
itemProvider = createContainerItemProvider();
viewer.setContentProvider(createContentProvider());
viewer.setLabelProvider(createLabelProvider());
viewer.setSorter(createViewerSorter());
resetInput();
}
/**
* @since 3.3
*/
protected ViewerSorter createViewerSorter()
{
return itemProvider;
}
/**
* @since 3.0
*/
protected IContentProvider createContentProvider()
{
return itemProvider;
}
/**
* @since 3.0
*/
protected IBaseLabelProvider createLabelProvider()
{
ILabelDecorator labelDecorator = createLabelDecorator();
return new DecoratingStyledCellLabelProvider(itemProvider, labelDecorator, null);
}
/**
* @since 3.0
*/
protected ILabelDecorator createLabelDecorator()
{
return PlatformUI.getWorkbench().getDecoratorManager().getLabelDecorator();
}
protected ContainerItemProvider<IContainer<Object>> createContainerItemProvider()
{
return new ContainerItemProvider<IContainer<Object>>(getRootElementFilter())
{
@Override
public Image getImage(Object obj)
{
Image image = getElementImage(obj);
if (image == null)
{
image = super.getImage(obj);
}
return image;
}
@Override
public String getText(Object obj)
{
String text = getElementText(obj);
if (text == null)
{
text = super.getText(obj);
}
return text;
}
@Override
public Color getForeground(Object obj)
{
Color color = getElementForeground(obj);
if (color == null)
{
color = super.getForeground(obj);
}
return color;
}
@Override
public Color getBackground(Object obj)
{
Color color = getElementBackground(obj);
if (color == null)
{
color = super.getBackground(obj);
}
return color;
}
@Override
public Font getFont(Object obj)
{
Font font = getElementFont(obj);
if (font == null)
{
font = super.getFont(obj);
}
return font;
}
};
}
protected String getElementText(Object element)
{
return null;
}
protected Image getElementImage(Object element)
{
return null;
}
/**
* @since 3.0
*/
protected Color getElementForeground(Object element)
{
return null;
}
/**
* @since 3.0
*/
protected Color getElementBackground(Object element)
{
return null;
}
/**
* @since 3.0
*/
protected Font getElementFont(Object element)
{
return null;
}
protected IElementFilter getRootElementFilter()
{
return null;
}
protected abstract IContainer<?> getContainer();
protected void hookDoubleClick()
{
viewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
ITreeSelection selection = (ITreeSelection)viewer.getSelection();
Object object = selection.getFirstElement();
doubleClicked(object);
}
});
}
protected void hookContextMenu()
{
MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
menuMgr.setRemoveAllWhenShown(true);
menuMgr.addMenuListener(new IMenuListener()
{
public void menuAboutToShow(IMenuManager manager)
{
ITreeSelection selection = (ITreeSelection)viewer.getSelection();
fillContextMenu(manager, selection);
}
});
Menu menu = menuMgr.createContextMenu(viewer.getControl());
viewer.getControl().setMenu(menu);
getSite().registerContextMenu(menuMgr, viewer);
}
protected void contributeToActionBars()
{
IActionBars bars = getViewSite().getActionBars();
fillLocalPullDown(bars.getMenuManager());
fillLocalToolBar(bars.getToolBarManager());
}
protected void fillLocalPullDown(IMenuManager manager)
{
addRefreshAction(manager);
manager.add(new IntrospectAction(getViewer()));
}
protected void fillLocalToolBar(IToolBarManager manager)
{
addCollapseAllAction(manager);
}
protected void fillContextMenu(IMenuManager manager, ITreeSelection selection)
{
itemProvider.fillContextMenu(manager, selection);
}
/**
* @since 3.5
*/
protected void addSeparator(IContributionManager manager)
{
manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
}
/**
* @since 3.5
*/
protected void addRefreshAction(IContributionManager manager)
{
manager.add(refreshAction);
}
/**
* @since 3.5
*/
protected void addCollapseAllAction(IContributionManager manager)
{
manager.add(collapseAllAction);
}
protected void selectionChanged(IActionBars bars, ITreeSelection selection)
{
}
protected void doubleClicked(Object object)
{
if (object instanceof ContainerItemProvider.ErrorElement)
{
try
{
UIUtil.getActiveWorkbenchPage().showView(UIUtil.ERROR_LOG_ID);
}
catch (PartInitException ex)
{
OM.LOG.error(ex);
}
}
else if (object != null && viewer.isExpandable(object))
{
if (viewer.getExpandedState(object))
{
viewer.collapseToLevel(object, TreeViewer.ALL_LEVELS);
}
else
{
viewer.expandToLevel(object, 1);
}
}
}
/**
* @since 3.1
*/
protected void refreshPressed()
{
itemProvider.clearNodesCache();
UIUtil.refreshViewer(viewer);
}
/**
* @since 3.3
*/
protected void collapseAllPressed()
{
getViewer().collapseAll();
}
protected void closeView()
{
try
{
getDisplay().syncExec(new Runnable()
{
public void run()
{
try
{
getSite().getPage().hideView(ContainerView.this);
ContainerView.this.dispose();
}
catch (Exception ignore)
{
}
}
});
}
catch (Exception ignore)
{
}
}
protected void showMessage(String message)
{
showMessage(MessageType.INFORMATION, message);
}
protected boolean showMessage(MessageType type, String message)
{
switch (type)
{
case INFORMATION:
MessageDialog.openInformation(viewer.getControl().getShell(), getTitle(), message);
return true;
case ERROR:
MessageDialog.openError(viewer.getControl().getShell(), getTitle(), message);
return true;
case WARNING:
MessageDialog.openWarning(viewer.getControl().getShell(), getTitle(), message);
return true;
case CONFIRM:
return MessageDialog.openConfirm(viewer.getControl().getShell(), getTitle(), message);
case QUESTION:
return MessageDialog.openQuestion(viewer.getControl().getShell(), getTitle(), message);
default:
return true;
}
}
/**
* @since 3.1
*/
protected Action getRefreshAction()
{
return refreshAction;
}
/**
* @since 3.3
*/
public Action getCollapseAllAction()
{
return collapseAllAction;
}
protected Display getDisplay()
{
Display display = viewer.getControl().getDisplay();
if (display == null)
{
display = UIUtil.getDisplay();
}
return display;
}
@Override
@SuppressWarnings("unchecked")
public <T> T getAdapter(Class<T> adapter)
{
if (adapter == IPropertySheetPage.class)
{
if (propertySheetPage == null)
{
propertySheetPage = new PropertySheetPage();
}
return (T)propertySheetPage;
}
return super.getAdapter(adapter);
}
/**
* @since 3.5
*/
public void refreshPropertySheetPage()
{
if (propertySheetPage != null)
{
propertySheetPage.refresh();
}
}
public void refreshViewer(boolean updateLabels)
{
itemProvider.refreshViewer(updateLabels);
}
public void refreshElement(Object element, boolean updateLabels)
{
itemProvider.refreshElement(element, updateLabels);
}
public void updateLabels(Object element)
{
itemProvider.updateLabels(element);
}
public void revealElement(Object element)
{
itemProvider.revealElement(element);
}
/**
* @since 3.3
*/
public void expandElement(Object element, int level)
{
itemProvider.expandElement(element, level);
}
public static ImageDescriptor getAddImageDescriptor()
{
return SharedIcons.getDescriptor(SharedIcons.ETOOL_ADD);
}
public static ImageDescriptor getDeleteImageDescriptor()
{
return SharedIcons.getDescriptor(SharedIcons.ETOOL_DELETE);
}
public static ImageDescriptor getRefreshImageDescriptor()
{
return SharedIcons.getDescriptor(SharedIcons.ETOOL_REFRESH);
}
/**
* @since 3.3
*/
public static ImageDescriptor getCollapseAllImageDescriptor()
{
return SharedIcons.getDescriptor(SharedIcons.ETOOL_COLLAPSE_ALL);
}
protected static enum MessageType
{
INFORMATION, ERROR, WARNING, CONFIRM, QUESTION
}
/**
* @author Eike Stepper
*/
private final class RefreshAction extends SafeAction
{
private RefreshAction()
{
super(Messages.getString("ContainerView_1"), Messages.getString("ContainerView_2"), getRefreshImageDescriptor()); //$NON-NLS-1$ //$NON-NLS-2$
}
@Override
protected void safeRun() throws Exception
{
refreshPressed();
}
}
/**
* @author Eike Stepper
*/
private final class CollapseAllAction extends SafeAction
{
private CollapseAllAction()
{
super(Messages.getString("ContainerView_3"), Messages.getString("ContainerView_4"), //$NON-NLS-1$ //$NON-NLS-2$
getCollapseAllImageDescriptor());
}
@Override
protected void safeRun() throws Exception
{
collapseAllPressed();
}
}
/**
* @author Eike Stepper
* @since 3.0
*/
public static class Default<CONTAINER extends IContainer<?>> extends ContainerView
{
private CONTAINER container;
public Default()
{
}
protected IListener getContainerListener()
{
return null;
}
@Override
protected CONTAINER getContainer()
{
return container;
}
public void setContainer(CONTAINER container)
{
if (this.container != container)
{
IListener containerListener = getContainerListener();
if (containerListener != null && this.container != null)
{
this.container.removeListener(containerListener);
}
this.container = container;
if (containerListener != null && this.container != null)
{
this.container.addListener(containerListener);
}
resetInput();
}
}
}
}