/** * Copyright (c) 2010, 2013 Darmstadt University of Technology. * 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: * Marcel Bruch - initial API and implementation. */ package org.eclipse.recommenders.completion.rcp.processable; import static org.eclipse.recommenders.completion.rcp.processable.ProposalTag.CONTEXT; import java.util.Map; import org.eclipse.jdt.core.CompletionProposal; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.contentassist.ICompletionProposal; import org.eclipse.jface.viewers.DecorationOverlayIcon; import org.eclipse.jface.viewers.IDecoration; import org.eclipse.jface.viewers.StyledString; import org.eclipse.jface.viewers.StyledString.Styler; import org.eclipse.recommenders.completion.rcp.IRecommendersCompletionContext; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.TextStyle; import com.google.common.base.Optional; import com.google.common.collect.Maps; public final class Proposals { private static final Map<CacheKey, Image> CACHE = Maps.newHashMap(); private Proposals() { // Not meant to be instantiated } public static void overlay(IProcessableProposal proposal, ImageDescriptor icon) { overlay(proposal, icon, IDecoration.TOP_LEFT); } /** * @param decorationCorner * e.g. {@link IDecoration#TOP_LEFT} */ public static void overlay(IProcessableProposal proposal, ImageDescriptor icon, int decorationCorner) { Image originalImage = proposal.getImage(); CacheKey key = new CacheKey(originalImage, icon, decorationCorner); Image newImage = CACHE.get(key); if (newImage == null) { DecorationOverlayIcon decorator = new DecorationOverlayIcon(originalImage, icon, decorationCorner); newImage = decorator.createImage(); CACHE.put(key, newImage); } proposal.setImage(newImage); } public static IRecommendersCompletionContext getContext(IProcessableProposal proposal) { return proposal.<IRecommendersCompletionContext>getTag(CONTEXT).orNull(); } /** * Null-safe variant of {@link IProcessableProposal#getPrefix()} that returns the * {@link IRecommendersCompletionContext#getPrefix()} in case the proposal returns null. */ public static String getPrefix(IProcessableProposal proposal) { String prefix = proposal.getPrefix(); if (prefix == null) { prefix = getContext(proposal).getPrefix(); } return prefix; } public static Optional<CompletionProposal> getCoreProposal(ICompletionProposal proposal) { if (proposal instanceof IProcessableProposal) { IProcessableProposal pp = (IProcessableProposal) proposal; return pp.getCoreProposal(); } return Optional.absent(); } public static <T> Optional<T> getTag(ICompletionProposal proposal, String tag) { if (proposal instanceof IProcessableProposal) { IProcessableProposal pp = (IProcessableProposal) proposal; for (IProposalTag t : pp.tags()) { if (t.name().equals(tag)) { return pp.getTag(t); } } } return Optional.absent(); } public static boolean isKindOneOf(ICompletionProposal proposal, int... kinds) { CompletionProposal cp = getCoreProposal(proposal).orNull(); if (cp != null) { for (int kind : kinds) { if (cp.getKind() == kind) { return true; } } } return false; } /** * Returns a deep copy of the given styles string. */ public static StyledString copyStyledString(final StyledString displayString) { final StyledString copy = new StyledString(displayString.getString()); for (final StyleRange range : displayString.getStyleRanges()) { copy.setStyle(range.start, range.length, new Styler() { @Override public void applyStyles(final TextStyle textStyle) { textStyle.background = range.background; textStyle.borderColor = range.borderColor; textStyle.borderStyle = range.borderStyle; textStyle.font = range.font; textStyle.foreground = range.foreground; } }); } return copy; } private static final class CacheKey { final Image image; final ImageDescriptor overlay; final int corner; public CacheKey(Image image, ImageDescriptor overlay, int corner) { super(); this.image = image; this.overlay = overlay; this.corner = corner; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + corner; result = prime * result + (image == null ? 0 : image.hashCode()); result = prime * result + (overlay == null ? 0 : overlay.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } CacheKey other = (CacheKey) obj; if (corner != other.corner) { return false; } if (image == null) { if (other.image != null) { return false; } } else if (!image.equals(other.image)) { return false; } if (overlay == null) { if (other.overlay != null) { return false; } } else if (!overlay.equals(other.overlay)) { return false; } return true; } } }