blob: 4b578dcfbcbd1874fd39cad7a12c337a8146bf0d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 BSI Business Systems Integration AG.
* 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:
* BSI Business Systems Integration AG - initial API and implementation
******************************************************************************/
package org.eclipse.scout.sdk.ui.util;
import java.net.URI;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider;
import org.eclipse.jdt.ui.JavaElementImageDescriptor;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.scout.commons.StringUtility;
import org.eclipse.scout.sdk.jdt.compile.ScoutSeverityManager;
import org.eclipse.scout.sdk.ui.internal.ScoutSdkUi;
import org.eclipse.scout.sdk.ui.view.outline.pages.IPage;
import org.eclipse.scout.sdk.ui.view.outline.pages.ITypePage;
import org.eclipse.scout.sdk.util.resources.ResourceUtility;
import org.eclipse.scout.sdk.util.type.ITypeFilter;
import org.eclipse.scout.sdk.util.type.TypeUtility;
import org.eclipse.scout.sdk.workspace.IScoutBundle;
import org.eclipse.scout.sdk.workspace.IScoutBundleFilter;
import org.eclipse.scout.sdk.workspace.ScoutBundleFilters;
import org.eclipse.scout.sdk.workspace.type.ScoutTypeUtility;
import org.eclipse.swt.graphics.Drawable;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorReference;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.ITextEditor;
/**
* <h3>{@link UiUtility}</h3>
*
* @author Andreas Hoegger
* @since 1.0.8 07.03.2011
*/
@SuppressWarnings("restriction")
public final class UiUtility {
private UiUtility() {
}
/**
* Shows the given java element in the java editor.
*
* @param e
* The element to focus
* @param createNew
* indicates if a new editor should be opened if not open yet. If false, the element will only be shown if
* there is a java editor open yet.
*/
public static void showJavaElementInEditor(IJavaElement e, boolean createNew) {
try {
IEditorPart editor = null;
if (createNew) {
editor = JavaUI.openInEditor(e);
}
else {
editor = EditorUtility.isOpenInEditor(e);
if (editor != null) {
PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().activate(editor);
}
}
if (editor != null) {
JavaUI.revealInEditor(editor, e);
if (editor instanceof ITextEditor) {
ITextEditor textEditor = (ITextEditor) editor;
IRegion reg = textEditor.getHighlightRange();
if (reg != null) {
textEditor.setHighlightRange(reg.getOffset(), reg.getLength(), true);
}
}
}
}
catch (Exception ex) {
ScoutSdkUi.logWarning(ex);
}
}
/**
* Returns the extent of the given string. No tab
* expansion or carriage return processing will be performed.
* <p>
* The <em>extent</em> of a string is the width and height of the rectangular area it would cover if drawn in the
* given font.
* </p>
*
* @param text
* @param f
* @param context
* @return a point containing the extent of the string
*/
public static Point getTextBounds(String text, Font f, Drawable context) {
GC gc = new GC(context);
gc.setFont(f);
return gc.stringExtent(text);
}
/**
* Gets the shortened text based on the given input so that the text returned is smaller than the given bounds.
*
* @param origText
* The original text that should be shortened to match into bounds.
* @param f
* The {@link Font} to use to calculate the text length.
* @param context
* The context in which the calculation should be performed.
* @param bounds
* The number of pixels. The returned text will be shorter than this limit if rendered in the given context
* with the given font.
* @return The text shortened to given bounds including an ellipsis if it has been cut.
*/
public static String getTextForBounds(String origText, Font f, Drawable context, int bounds) {
return getTextForBounds(origText, f, context, bounds, "…");
}
/**
* Gets the shortened text based on the given input so that the text returned is smaller than the given bounds.
*
* @param origText
* The original text that should be shortened to match into bounds.
* @param f
* The {@link Font} to use to calculate the text length.
* @param context
* The context in which the calculation should be performed.
* @param bounds
* The number of pixels. The returned text will be shorter than this limit if rendered in the given context
* with the given font.
* @param ellipsis
* The suffix to add if the given origText has been shortened or null if no suffix should be added.
* @return The text shortened to given bounds including the given ellipsis if it has been cut.
*/
public static String getTextForBounds(String origText, Font f, Drawable context, int bounds, String ellipsis) {
if (bounds <= 0) {
return origText;
}
String cleanedEllipsis = null;
if (StringUtility.hasText(ellipsis)) {
cleanedEllipsis = ellipsis;
}
else {
cleanedEllipsis = "";
}
StringBuilder sb = new StringBuilder(origText);
GC gc = new GC(context);
gc.setFont(f);
Point p = gc.stringExtent(sb.toString());
while (p.x > bounds && sb.length() > 0) {
sb.deleteCharAt(sb.length() - 1);
p = gc.stringExtent(sb.toString() + cleanedEllipsis);
}
String ret = sb.toString();
if (ret.equals(origText)) {
return origText;
}
else {
return sb.toString() + cleanedEllipsis;
}
}
/**
* Gets the packages suffix of the given selection.<br>
* This method calculates the java package that surrounds the current selection and returns the suffix (the package
* part after the symbolic name of the containing bundle).
*
* @param selection
* The selection to evaluate
* @return A string with the package suffix or null.
*/
public static String getPackageSuffix(IStructuredSelection selection) {
if (selection == null) {
return null;
}
return getPackageSuffix(UiUtility.adapt(selection.getFirstElement(), IJavaElement.class));
}
/**
* Gets the packages suffix of the given element.<br>
* This method calculates the java package that surrounds the given element and returns the suffix (the package
* part after the symbolic name of the containing bundle).
*
* @param element
* The element
* @return A string with the package suffix or null.
*/
public static String getPackageSuffix(IJavaElement element) {
if (TypeUtility.exists(element)) {
IPackageFragment targetPackage = (IPackageFragment) element.getAncestor(IJavaElement.PACKAGE_FRAGMENT);
if (TypeUtility.exists(targetPackage)) {
String pck = targetPackage.getElementName();
IScoutBundle declaringBundle = ScoutTypeUtility.getScoutBundle(targetPackage);
if (declaringBundle != null && pck.startsWith(declaringBundle.getSymbolicName()) && pck.length() > declaringBundle.getSymbolicName().length()) {
return pck.substring(declaringBundle.getSymbolicName().length() + 1);
}
}
}
return null;
}
/**
* Closes all open instances of the given editor.<br>
* If the editors are dirty, the user is asked if they should be saved.
*
* @param editorId
* The editor id filter or null if all editors should be closed.
* @param files
* The files filter or null. Only the editors of those files are closed.
* @return true if all editors have been closed. false otherwise (e.g. when the user presses cancel in the save dirty
* editor confirmation message box).
*/
public static boolean closeEditors(String editorId, Set<IFile> files) {
for (IWorkbenchWindow w : PlatformUI.getWorkbench().getWorkbenchWindows()) {
for (IWorkbenchPage p : w.getPages()) {
IEditorReference[] editorReferences = p.getEditorReferences();
List<IEditorReference> partsToSave = new ArrayList<IEditorReference>(editorReferences.length);
for (IEditorReference r : editorReferences) {
if (editorId == null || editorId.equals(r.getId())) {
if (files == null || files.isEmpty() || isEditorInputInFiles(r, files)) {
partsToSave.add(r);
}
}
}
if (!partsToSave.isEmpty()) {
boolean success = p.closeEditors(partsToSave.toArray(new IEditorReference[partsToSave.size()]), true);
if (!success) {
return false;
}
}
}
}
return true;
}
private static boolean isEditorInputInFiles(IEditorReference ref, Set<IFile> files) {
try {
IEditorInput editorInput = ref.getEditorInput();
if (editorInput instanceof IURIEditorInput) {
IURIEditorInput input = (IURIEditorInput) editorInput;
URI uriToSearch = input.getURI();
for (IFile f : files) {
if (URIUtil.sameURI(uriToSearch, f.getLocationURI())) {
return true;
}
}
}
}
catch (PartInitException e) {
ScoutSdkUi.logError("Unable to get file input of editor.", e);
}
return false;
}
/**
* Tries to calculate the most specific scout bundle that contains the given selection.
*
* @param selection
* @return
*/
public static IScoutBundle getScoutBundleFromSelection(IStructuredSelection selection) {
return getScoutBundleFromSelection(selection, null);
}
/**
* Tries to calculate the most specific scout bundle that contains the given selection.
* The given filter is taken into account so that clients can influence which types of scout bundles around the
* selected one that should be used.<br>
*
* @param selection
* @param filter
* @return
*/
public static IScoutBundle getScoutBundleFromSelection(IStructuredSelection selection, IScoutBundleFilter filter) {
if (selection != null) {
IScoutBundle b = UiUtility.adapt(selection.getFirstElement(), IScoutBundle.class);
if (b != null) {
if (filter == null || filter.accept(b)) {
return b;
}
else {
IScoutBundle parentShared = b.getParentBundle(ScoutBundleFilters.getBundlesOfTypeFilter(IScoutBundle.TYPE_SHARED), b, true);
if (parentShared != null) {
IScoutBundle candidate = parentShared.getChildBundle(ScoutBundleFilters.getMultiFilterAnd(ScoutBundleFilters.getWorkspaceBundlesFilter(), filter), b, true);
if (candidate != null) {
return candidate;
}
}
else {
IScoutBundle candidate = b.getChildBundle(ScoutBundleFilters.getMultiFilterAnd(ScoutBundleFilters.getWorkspaceBundlesFilter(), filter), b, false);
if (candidate != null) {
return candidate;
}
}
}
}
}
return null;
}
public static IType getTypeFromSelection(IStructuredSelection selection) {
return getTypeFromSelection(selection, null);
}
public static IType getTypeFromSelection(IStructuredSelection selection, ITypeFilter filter) {
return getTypeFromSelection(selection.getFirstElement(), filter);
}
private static IType getTypeFromSelection(Object o, ITypeFilter filter) {
IType t = UiUtility.adapt(o, IType.class);
if (TypeUtility.exists(t) && (filter == null || filter.accept(t))) {
return t;
}
return null;
}
public static Set<IType> getTypesFromSelection(IStructuredSelection selection, ITypeFilter filter) {
Set<IType> result = new LinkedHashSet<IType>(selection.size());
if (selection.isEmpty()) {
return result;
}
Iterator<?> it = selection.iterator();
while (it.hasNext()) {
Object o = it.next();
IType t = getTypeFromSelection(o, filter);
if (t != null) {
result.add(t);
}
}
return result;
}
/**
* Tries to convert the given element into the given class.
* This method respects scout IPage classes.
*
* @param element
* The element to convert.
* @param targetClass
* The class in which it should be converted.
* @return the converted element or null if the conversion could not be done.
*/
@SuppressWarnings("unchecked")
public static <T> T adapt(Object element, Class<T> targetClass) {
if (element == null || targetClass == null) {
return null;
}
if (targetClass.isInstance(element)) {
return (T) element;
}
// get element out of the pages
if (element instanceof IPage) {
IPage page = (IPage) element;
IScoutBundle sb = page.getScoutBundle();
if (sb != null) {
element = sb;
}
do {
if (page instanceof ITypePage) {
ITypePage astp = (ITypePage) page;
IType t = astp.getType();
if (TypeUtility.exists(t)) {
element = t;
break;
}
}
page = page.getParent();
}
while (page != null);
}
// try to adapt
if (element instanceof IAdaptable) {
IAdaptable ad = (IAdaptable) element;
T result = (T) ad.getAdapter(targetClass);
if (result == null) {
// try to get a resource
IResource r = (IResource) ad.getAdapter(IResource.class);
if (!ResourceUtility.exists(r)) {
IJavaElement je = (IJavaElement) ad.getAdapter(IJavaElement.class);
if (TypeUtility.exists(je)) {
r = je.getResource();
}
}
if (ResourceUtility.exists(r)) {
// try to convert from a resource
result = (T) r.getAdapter(targetClass);
}
}
return result;
}
return null;
}
/**
* Gets an image descriptor for classes.<br>
* The image descriptor includes flags like abstract, final, static, deprecated. Furthermore it shows different icons
* for interfaces and classes and includes the severity flags of the classes (e.g. error or warning).
*
* @param type
* The type for which the icon should be returned.
* @return The image descriptor.
*/
public static ImageDescriptor getTypeImageDescriptor(IType type) {
return getTypeImageDescriptor(type, true);
}
public static ImageDescriptor getTypeImageDescriptor(IType type, boolean showSeverity) {
int flags = -1;
try {
flags = type.getFlags();
}
catch (JavaModelException e) {
}
boolean isInterface = Flags.isInterface(flags);
boolean isInner = TypeUtility.exists(type.getDeclaringType());
int severity = 0;
if (showSeverity) {
ScoutSeverityManager.getInstance().getSeverityOf(type);
}
ImageDescriptor desc = JavaElementImageProvider.getTypeImageDescriptor(isInner, isInterface, flags, false);
int adornmentFlags = 0;
if (Flags.isFinal(flags)) {
adornmentFlags |= JavaElementImageDescriptor.FINAL;
}
if (Flags.isAbstract(flags) && !isInterface) {
adornmentFlags |= JavaElementImageDescriptor.ABSTRACT;
}
if (Flags.isStatic(flags)) {
adornmentFlags |= JavaElementImageDescriptor.STATIC;
}
if (Flags.isDeprecated(flags)) {
adornmentFlags |= JavaElementImageDescriptor.DEPRECATED;
}
if (severity == IMarker.SEVERITY_ERROR) {
adornmentFlags |= JavaElementImageDescriptor.ERROR;
}
else if (severity == IMarker.SEVERITY_WARNING) {
adornmentFlags |= JavaElementImageDescriptor.WARNING;
}
return new JavaElementImageDescriptor(desc, adornmentFlags, JavaElementImageProvider.BIG_SIZE);
}
}