/*******************************************************************************
* Copyright (c) 2009 Conselleria de Infraestructuras y Transporte, Generalitat
* de la Comunitat Valenciana . 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: Francisco Javier Cano Muñoz (Prodevelop) - initial api contribution
*
******************************************************************************/
package kr.co.apexsoft.stella.modeler.explorer.dialog;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import kr.co.apexsoft.stella.modeler.explorer.core.ApexDIWrapper;
import kr.co.apexsoft.stella.modeler.explorer.core.ApexProjectWrapper;
import kr.co.apexsoft.stella.modeler.explorer.core.ApexStellaProjectMap;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.facet.infra.browser.uicore.internal.model.LinkItem;
import org.eclipse.gmf.runtime.notation.Diagram;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.dialogs.TrayDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IContentProvider;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.papyrus.views.modelexplorer.ModelExplorerView;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
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.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.navigator.CommonNavigator;
import org.eclipse.ui.navigator.CommonViewer;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
/**
* A dialog that allows searching elements in the Model navigator by name.
*
* @author <a href="mailto:fjcano@prodevelop.es">Francisco Javier Cano Munoz</a>
*
* @author cedric dumoulin
*/
public class ApexNavigatorSearchDialog extends TrayDialog {
private ITreeContentProvider contentProvider = null;
private ILabelProvider labelProvider = null;
private Object root = null;
private ISelectionProvider viewer = null;
private List<Object> matchedObjects = Collections.emptyList();
protected int currentIndex = 0;
private Label matchesLabel;
private Text searchText;
private Button backButton;
private Button nextButton;
private Button caseButton;
/**
*
* Constructor.
*
* @param shell
* @param modelNavigator
* @deprecated Use {@link #NavigatorSearchDialog(Shell, TreeViewer)}
*/
public ApexNavigatorSearchDialog(Shell shell, CommonNavigator modelNavigator) {
super(shell);
IContentProvider cprovider = modelNavigator.getCommonViewer()
.getContentProvider();
if(cprovider instanceof ITreeContentProvider) {
contentProvider = (ITreeContentProvider)cprovider;
}
root = modelNavigator.getCommonViewer().getInput();
viewer = modelNavigator.getCommonViewer();
labelProvider = (ILabelProvider)modelNavigator.getCommonViewer()
.getLabelProvider();
}
/**
* Constructor.
*
* @param shell
* Shell used to show this Dialog
* @param viewer
* @param contentProvider
* @param labelProvider
* @param root
*/
public ApexNavigatorSearchDialog(Shell shell, TreeViewer viewer) {
super(shell);
this.viewer = viewer;
try {
this.labelProvider = (ILabelProvider)viewer.getLabelProvider();
this.contentProvider = (ITreeContentProvider)viewer.getContentProvider();
} catch (ClassCastException e) {
// Content or label provider are not of appropriate type.
// let them null
}
this.root = viewer.getInput();
}
/**
* Constructor.
*
* @param shell Shell used to show this Dialog
* @param viewer
* @param contentProvider
* @param labelProvider
* @param root
*/
public ApexNavigatorSearchDialog(Shell shell, Viewer viewer, ITreeContentProvider contentProvider, ILabelProvider labelProvider, Object root) {
super(shell);
this.viewer = viewer;
this.contentProvider = contentProvider;
this.labelProvider = labelProvider;
this.root = root;
}
/**
* Sets a new selection for the associated {@link ISelectionProvider} and optionally makes it visible.
* <p>
* Subclasses must implement this method.
* </p>
*
* @param selection the new selection
* @param reveal <code>true</code> if the selection is to be made
* visible, and <code>false</code> otherwise
*/
private void fireSetSelection( ISelection selection, boolean reveal) {
// Note : if we want to force reveal, it is possible to check if
// selectionProvider instanceof Viewer, and then call selectionProvider.setSelection(selection, true).
// By default a TreeViewer reveal the selection.
if(viewer instanceof CommonViewer) {
if(selection instanceof IStructuredSelection) {
IStructuredSelection structured = (IStructuredSelection)selection;
ModelExplorerView.reveal(Iterables.transform(Lists.newArrayList(structured.iterator()), new Function<Object, EObject>() {
public EObject apply(Object arg0) {
if(arg0 instanceof IAdaptable) {
IAdaptable adapt = (IAdaptable)arg0;
return getAdapter(adapt, EObject.class);
}
return null;
}
}), (CommonViewer)viewer);
}
} else if(viewer instanceof Viewer) {
Viewer view = (Viewer)viewer;
view.setSelection(selection, true);
}
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets
* .Composite)
*/
@Override
protected Control createDialogArea(Composite parent) {
Composite background = new Composite(parent, SWT.None);
GridData bgData = new GridData(GridData.FILL_BOTH);
bgData.minimumWidth = 300;
background.setLayoutData(bgData);
GridLayout bgLayout = new GridLayout();
bgLayout.numColumns = 2;
background.setLayout(bgLayout);
createSearchTextComposite(background);
return background;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.jface.dialogs.Dialog#createButtonsForButtonBar(org.eclipse
* .swt.widgets.Composite)
*/
@Override
protected void createButtonsForButtonBar(Composite parent) {
backButton = createButton(parent, IDialogConstants.BACK_ID,
IDialogConstants.BACK_LABEL, false);
nextButton = createButton(parent, IDialogConstants.NEXT_ID,
IDialogConstants.NEXT_LABEL, false);
createButton(parent, IDialogConstants.OK_ID, IDialogConstants.OK_LABEL,
true);
backButton.setEnabled(false);
nextButton.setEnabled(false);
nextButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
if(currentIndex >= matchedObjects.size() - 1) {
currentIndex = 0;
} else {
currentIndex++;
}
fireSetSelection(new StructuredSelection(matchedObjects.get(currentIndex)), true);
}
});
backButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
if(currentIndex <= 0) {
currentIndex = matchedObjects.size() - 1;
} else {
currentIndex--;
}
fireSetSelection(new StructuredSelection(matchedObjects.get(currentIndex)), true);
}
});
}
private void createSearchTextComposite(Composite background) {
Label searchLabel = new Label(background, SWT.None);
searchLabel.setText("Search:");
searchLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
searchText = new Text(background, SWT.SEARCH);
searchText.setFocus();
searchText.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
searchText.addKeyListener(getKeyListener());
caseButton = new Button(background, SWT.CHECK);
caseButton.setText("Case sensitive?");
GridData caseButtonData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
caseButtonData.horizontalSpan = 2;
caseButton.setSelection(false);
caseButton.setLayoutData(caseButtonData);
caseButton.addSelectionListener(new SelectionListener() {
public void widgetDefaultSelected(SelectionEvent e) {
}
public void widgetSelected(SelectionEvent e) {
updateMatches();
}
});
Label resultsLabel = new Label(background, SWT.None);
resultsLabel.setText("Results:");
resultsLabel.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_END));
matchesLabel = new Label(background, SWT.None);
matchesLabel.setText("No matchings.");
matchesLabel
.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING
| GridData.FILL_HORIZONTAL));
}
protected void clearMatches() {
matchedObjects = Collections.emptyList();
currentIndex = 0;
backButton.setEnabled(false);
nextButton.setEnabled(false);
matchesLabel.setText("");
}
private void updateMatches() {
if(contentProvider == null && labelProvider == null) {
return;
}
String pattern = searchText.getText();
if(pattern.length() == 0) {
clearMatches();
return;
}
if(!caseButton.getSelection()) {
pattern = pattern.toUpperCase();
}
launchSearch(pattern, contentProvider.getElements(root));
// Update matches label
matchesLabel.setText(matchedObjects.size() + " matches found");
// Select first match and update buttons
if(!matchedObjects.isEmpty()) {
fireSetSelection(new StructuredSelection(matchedObjects.get(0)), true);
nextButton.setEnabled(true);
backButton.setEnabled(true);
} else {
nextButton.setEnabled(false);
backButton.setEnabled(false);
}
}
protected void launchSearch(final String pattern, final Object[] root) {
final boolean caseSensitive = caseButton.getSelection();
ProgressMonitorDialog dialog = new ProgressMonitorDialog(null);
try {
dialog.run(true, true, new IRunnableWithProgress() {
public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
matchedObjects = searchPattern(pattern, caseSensitive, Arrays.asList(root), monitor);
currentIndex = 0;
}
});
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* apex updated - hanmomhanda
*
* 원래 model explorer는 launchSearch(pattern, contentProvider.getElements(root))가 launchSearch(pattern, model)이나
* StellaModelExplorer는 launchSearch(pattern, contentProvider.getElements(root))가 launchSearch(pattern, project[])라 오작동 발생
*
* @param pattern
* @param caseSensitive
* @param objects
* @param monitor
* @return
*/
private List<Object> searchPattern(String pattern, boolean caseSensitive, List<Object> objects, IProgressMonitor monitor) {
if(monitor.isCanceled()) {
return Collections.emptyList();
}
List<Object> matches = new ArrayList<Object>();
List<Object> children = new ArrayList<Object>();
String objectLabel;
/* apex improved start */
for(Object o : objects) {
// o 가 IProject이면
// di[] 를 가져오고
// 각 di[]에서 UmlModel을 가져온다
if ( o instanceof IProject ) {
IProject project = (IProject)o;
String projectPath = project.getLocationURI().getPath();
ApexProjectWrapper projectWrapper = null;
if ( ApexStellaProjectMap.getProjectMap().containsKey(projectPath) ) {
projectWrapper = (ApexProjectWrapper) ApexStellaProjectMap.getProjectMap().get(projectPath);
if ( projectWrapper != null ) {
Map<String, ApexDIWrapper> diWrapperMap = projectWrapper.getDIWrapperMap();
for(ApexDIWrapper diWrapper : diWrapperMap.values()) {
List<Object> modelElementItems = diWrapper.getChildren();
matches.addAll(searchPattern(pattern, caseSensitive, modelElementItems, monitor));
}
}
}
} else {
// Search matches in this level
if(!(o instanceof Diagram)) {
objectLabel = caseSensitive ? labelProvider.getText(o) : labelProvider.getText(o).toUpperCase();
if(objectLabel.contains(pattern)) {
matches.add(o);
}
Object[] objChildren = contentProvider.getChildren(o);
EObject parentEObj = (EObject)getAdapter(o, EObject.class);
for(int i = 0; i < objChildren.length; i++) {
Object child = objChildren[i];
//If child can be adapted into a LinkNode, find its referenced EObjects
// if(getAdapter(child, LinkNode.class) != null) {
if(getAdapter(child, LinkItem.class) != null) {
for(Object referencedObject : contentProvider.getChildren(child)) {
EObject referencedEObject = (EObject)((IAdaptable)referencedObject).getAdapter(EObject.class);
if(referencedEObject != null && (parentEObj == null || parentEObj.equals(referencedEObject.eContainer()))) {
children.add(referencedObject);
}
}
}
//If it is an EObject, add it to the list
else {
EObject eObject = (EObject)((IAdaptable)child).getAdapter(EObject.class);
if(eObject != null && eObject.eContainer() != null && (parentEObj == null || eObject.eContainer().equals(parentEObj))) {
children.add(child);
}
}
}
}
}
}
/* apex improved start */
/* apex replaced
for(Object o : objects) {
// Search matches in this level
if(!(o instanceof Diagram)) {
objectLabel = caseSensitive ? labelProvider.getText(o) : labelProvider.getText(o).toUpperCase();
if(objectLabel.contains(pattern)) {
matches.add(o);
}
EObject parentEObj = (EObject)getAdapter(o, EObject.class);
for(int i = 0; i < contentProvider.getChildren(o).length; i++) {
Object child = contentProvider.getChildren(o)[i];
//If child can be adapted into a LinkNode, find its referenced EObjects
if(getAdapter(child, LinkNode.class) != null) {
for(Object referencedObject : contentProvider.getChildren(child)) {
EObject referencedEObject = (EObject)((IAdaptable)referencedObject).getAdapter(EObject.class);
if(referencedEObject != null && (parentEObj == null || parentEObj.equals(referencedEObject.eContainer()))) {
children.add(referencedObject);
}
}
}
//If it is an EObject, add it to the list
else {
EObject eObject = (EObject)((IAdaptable)child).getAdapter(EObject.class);
if(eObject != null && eObject.eContainer() != null && (parentEObj == null || eObject.eContainer().equals(parentEObj))) {
children.add(child);
}
}
}
}
}
*/
if(!children.isEmpty()) {
matches.addAll(searchPattern(pattern, caseSensitive, children, monitor));
}
return matches;
}
@SuppressWarnings("unchecked")
public <T> T getAdapter(Object object, Class<? extends T> toAdapt) {
T result = null;
if(object instanceof IAdaptable) {
IAdaptable adaptable = (IAdaptable)object;
result = (T)adaptable.getAdapter(toAdapt);
}
if(result == null) {
result = (T)Platform.getAdapterManager().getAdapter(object, toAdapt);
}
return result;
}
protected KeyListener getKeyListener() {
return new KeyListener() {
public void keyPressed(KeyEvent e) {
//nothing to do
}
public void keyReleased(KeyEvent e) {
updateMatches();
}
};
}
}