/*
* Copyright (c) 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
* Victor Roldan Betancort - maintenance
*/
package org.eclipse.emf.cdo.internal.ui.dialogs;
import org.eclipse.emf.cdo.internal.ui.editor.CDOEditor;
import org.eclipse.emf.cdo.ui.shared.SharedIcons;
import org.eclipse.net4j.util.StringUtil;
import org.eclipse.net4j.util.ui.UIUtil;
import org.eclipse.net4j.util.ui.widgets.SearchField;
import org.eclipse.net4j.util.ui.widgets.SearchField.FilterHandler;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.SashForm;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
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.Control;
import org.eclipse.ui.IWorkbenchPage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* @author Eike Stepper
*/
public class SelectClassDialog extends TitleAreaDialog
{
private final IWorkbenchPage page;
private final String title;
private final String message;
private EPackage.Registry registry = EPackage.Registry.INSTANCE;
private SearchField packageSearch;
private TableViewer packageViewer;
private SearchField classSearch;
private EClass selectedClass;
private TableViewer classViewer;
public SelectClassDialog(IWorkbenchPage page, String title, String message)
{
super(page.getWorkbenchWindow().getShell());
this.page = page;
this.title = title;
this.message = message;
setShellStyle(getShellStyle() | SWT.APPLICATION_MODAL | SWT.MAX | SWT.TITLE | SWT.RESIZE);
}
public IWorkbenchPage getPage()
{
return page;
}
public EPackage.Registry getRegistry()
{
return registry;
}
public void setRegistry(EPackage.Registry registry)
{
this.registry = registry;
}
public EClass getSelectedClass()
{
return selectedClass;
}
@Override
protected Point getInitialSize()
{
return new Point(750, 600);
}
@Override
protected Control createDialogArea(Composite parent)
{
getShell().setText(title);
setTitle(title);
setTitleImage(SharedIcons.getImage(SharedIcons.WIZBAN_PACKAGE_MANAGER));
setMessage(message);
Composite composite = new Composite((Composite)super.createDialogArea(parent), SWT.NONE);
composite.setLayoutData(UIUtil.createGridData());
composite.setLayout(new FillLayout(SWT.HORIZONTAL));
SashForm sashForm = new SashForm(composite, SWT.SMOOTH);
GridLayout packageLayout = new GridLayout(1, false);
packageLayout.marginWidth = 0;
packageLayout.marginHeight = 0;
Composite packageComposite = new Composite(sashForm, SWT.NONE);
packageComposite.setLayout(packageLayout);
PackageContentProvider packageContentProvider = new PackageContentProvider();
packageSearch = new SearchField(packageComposite, packageContentProvider)
{
@Override
protected void finishFilter()
{
packageViewer.getControl().setFocus();
}
};
packageSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
packageViewer = new TableViewer(packageComposite, SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
packageViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
// Does NOT work with update(element): packageViewer.setUseHashlookup(true);
packageViewer.setContentProvider(packageContentProvider);
packageViewer.setLabelProvider(new PackageLabelProvider(packageViewer));
packageViewer.setInput(registry);
packageViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
String nsURI = (String)selection.getFirstElement();
EPackage ePackage = ((EPackage.Registry)packageViewer.getInput()).getEPackage(nsURI);
classViewer.setInput(ePackage);
try
{
packageViewer.update(nsURI, null); // Doe NOT work with hash lookup!!!
}
catch (Exception ex)
{
//$FALL-THROUGH$
}
}
});
GridLayout classLayout = new GridLayout(1, false);
classLayout.marginWidth = 0;
classLayout.marginHeight = 0;
Composite classComposite = new Composite(sashForm, SWT.NONE);
classComposite.setLayout(classLayout);
ClassContentProvider classContentProvider = new ClassContentProvider();
classSearch = new SearchField(classComposite, classContentProvider)
{
@Override
protected void finishFilter()
{
classViewer.getControl().setFocus();
}
};
classSearch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
classViewer = new TableViewer(classComposite, SWT.BORDER | SWT.FULL_SELECTION | SWT.VIRTUAL);
classViewer.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
classViewer.setUseHashlookup(true);
classViewer.setContentProvider(classContentProvider);
classViewer.setLabelProvider(new ClassLabelProvider());
classViewer.addSelectionChangedListener(new ISelectionChangedListener()
{
public void selectionChanged(SelectionChangedEvent event)
{
IStructuredSelection selection = (IStructuredSelection)event.getSelection();
selectedClass = (EClass)selection.getFirstElement();
updateOkButton();
}
});
classViewer.addDoubleClickListener(new IDoubleClickListener()
{
public void doubleClick(DoubleClickEvent event)
{
okPressed();
}
});
sashForm.setWeights(new int[] { 2, 1 });
return composite;
}
@Override
protected void createButtonsForButtonBar(Composite parent)
{
super.createButtonsForButtonBar(parent);
updateOkButton();
}
private void updateOkButton()
{
Button button = getButton(IDialogConstants.OK_ID);
if (button != null)
{
button.setEnabled(selectedClass != null);
}
}
/**
* @author Eike Stepper
*/
private static final class PackageContentProvider implements IStructuredContentProvider, FilterHandler
{
private Viewer viewer;
private Object input;
private String filter;
private String[] elements;
public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
{
this.viewer = viewer;
input = newInput;
computeElements();
}
public void handleFilter(String filter)
{
this.filter = filter == null ? null : filter.toLowerCase();
computeElements();
viewer.refresh();
}
public Object[] getElements(Object inputElement)
{
return elements;
}
public void dispose()
{
elements = null;
}
private void computeElements()
{
if (input instanceof EPackage.Registry)
{
final EPackage.Registry registry = (EPackage.Registry)input;
List<String> nsURIs = new ArrayList<String>();
for (String nsURI : registry.keySet())
{
if (filter == null || nsURI.toLowerCase().contains(filter))
{
nsURIs.add(nsURI);
}
}
elements = nsURIs.toArray(new String[nsURIs.size()]);
Arrays.sort(elements);
}
else
{
elements = null;
}
if (elements == null)
{
elements = new String[0];
}
}
}
/**
* @author Eike Stepper
*/
private static final class PackageLabelProvider extends LabelProvider
{
private static final Image PACKAGE_IMAGE = SharedIcons.getImage(SharedIcons.OBJ_EPACKAGE);
private static final Image UNKNOWN_IMAGE = SharedIcons.getImage(SharedIcons.OBJ_EPACKAGE_UNKNOWN);
private final Viewer viewer;
public PackageLabelProvider(Viewer viewer)
{
this.viewer = viewer;
}
@Override
public Image getImage(Object element)
{
String nsURI = (String)element;
EPackage.Registry registry = (Registry)viewer.getInput();
Object value = registry.get(nsURI);
if (value instanceof EPackage)
{
return PACKAGE_IMAGE;
}
return UNKNOWN_IMAGE;
}
}
/**
* @author Eike Stepper
*/
private static final class ClassContentProvider implements IStructuredContentProvider, FilterHandler
{
private Viewer viewer;
private Object input;
private String filter;
private EClass[] elements;
public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
{
this.viewer = viewer;
input = newInput;
computeElements();
}
public void handleFilter(String filter)
{
this.filter = filter == null ? null : filter.toLowerCase();
computeElements();
viewer.refresh();
}
public Object[] getElements(Object inputElement)
{
return elements;
}
public void dispose()
{
elements = null;
}
private void computeElements()
{
if (input instanceof EPackage)
{
EPackage ePackage = (EPackage)input;
List<EClass> eClasses = new ArrayList<EClass>();
for (EClassifier eClassifier : ePackage.getEClassifiers())
{
if (eClassifier instanceof EClass)
{
EClass eClass = (EClass)eClassifier;
if (!eClass.isAbstract() && !eClass.isInterface())
{
if (filter == null || eClass.getName().toLowerCase().contains(filter))
{
eClasses.add(eClass);
}
}
}
}
elements = eClasses.toArray(new EClass[eClasses.size()]);
Arrays.sort(elements, new Comparator<EClass>()
{
public int compare(EClass c1, EClass c2)
{
return StringUtil.safe(c1.getName()).compareTo(StringUtil.safe(c2.getName()));
}
});
}
else
{
elements = null;
}
if (elements == null)
{
elements = new EClass[0];
}
}
}
/**
* @author Eike Stepper
*/
private static final class ClassLabelProvider extends LabelProvider
{
private static final Image CLASS_IMAGE = SharedIcons.getImage(SharedIcons.OBJ_ECLASS);
private final ComposedAdapterFactory adapterFactory;
private final ILabelProvider labelProvider;
public ClassLabelProvider()
{
adapterFactory = CDOEditor.createAdapterFactory(true);
labelProvider = new AdapterFactoryLabelProvider(adapterFactory);
}
@Override
public void dispose()
{
labelProvider.dispose();
adapterFactory.dispose();
super.dispose();
}
@Override
public Image getImage(Object element)
{
try
{
EClass eClass = (EClass)element;
EObject eObject = EcoreUtil.create(eClass);
Image image = labelProvider.getImage(eObject);
if (image != null)
{
return image;
}
}
catch (Exception ex)
{
//$FALL-THROUGH$
}
return CLASS_IMAGE;
}
@Override
public String getText(Object element)
{
return ((EClass)element).getName();
}
}
}