| /******************************************************************************* |
| * Copyright (c) 2000, 2013 IBM Corporation 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: |
| * IBM Corporation - initial API and implementation |
| * QNX Software System |
| * Andrew Ferguson (Symbian) - refactored to TokenStore (previously part of AbstractCScanner) |
| *******************************************************************************/ |
| package org.eclipse.cdt.internal.ui.text; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import org.eclipse.jface.preference.IPreferenceStore; |
| import org.eclipse.jface.preference.PreferenceConverter; |
| import org.eclipse.jface.resource.StringConverter; |
| import org.eclipse.jface.text.TextAttribute; |
| import org.eclipse.jface.text.rules.IToken; |
| import org.eclipse.jface.text.rules.Token; |
| import org.eclipse.jface.util.PropertyChangeEvent; |
| import org.eclipse.swt.SWT; |
| import org.eclipse.swt.graphics.Color; |
| import org.eclipse.swt.graphics.RGB; |
| import org.eclipse.swt.widgets.Display; |
| |
| import org.eclipse.cdt.ui.PreferenceConstants; |
| import org.eclipse.cdt.ui.text.IColorManager; |
| import org.eclipse.cdt.ui.text.ITokenStore; |
| |
| |
| /** |
| * Maintains a pool of tokens identified by a String ID. |
| * Supports styles per token. |
| * Updates token instances on property changes. |
| */ |
| |
| public class TokenStore implements ITokenStore { |
| private IColorManager fColorManager; |
| private IPreferenceStore fPreferenceStore; |
| |
| private Map<String, IToken> fTokenMap= new HashMap<String, IToken>(); |
| private String[] fPropertyNamesColor; |
| |
| private boolean fNeedsLazyColorLoading; |
| |
| /** |
| * Maintains tokens for a specified set of property keys. Automatically also |
| * copes with bold, italic, strike-through and underlined versions of the key. |
| * @param manager the IColorManager to retrieve token colors from |
| * @param store the {@link IPreferenceStore} to fetch property preferences from |
| */ |
| public TokenStore(IColorManager manager, IPreferenceStore store, String[] propertyNamesColor) { |
| fColorManager= manager; |
| fPreferenceStore= store; |
| |
| fPropertyNamesColor= propertyNamesColor; |
| |
| fNeedsLazyColorLoading= Display.getCurrent() == null; |
| for (int i= 0; i < fPropertyNamesColor.length; i++) { |
| if(fPropertyNamesColor[i].endsWith(PreferenceConstants.EDITOR_BOLD_SUFFIX) |
| || fPropertyNamesColor[i].endsWith(PreferenceConstants.EDITOR_ITALIC_SUFFIX) |
| || fPropertyNamesColor[i].endsWith(PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX) |
| || fPropertyNamesColor[i].endsWith(PreferenceConstants.EDITOR_UNDERLINE_SUFFIX)) { |
| throw new IllegalArgumentException(); // XXX |
| } |
| if (fNeedsLazyColorLoading) |
| addTokenWithProxyAttribute(fPropertyNamesColor[i]); |
| else |
| addToken(fPropertyNamesColor[i]); |
| } |
| } |
| |
| /** |
| * In the case where at the time of IToken construction, the Display was not |
| * ready to construct colors. |
| */ |
| @Override |
| public void ensureTokensInitialised() { |
| if (fNeedsLazyColorLoading && Display.getCurrent() != null) { |
| for (int i= 0; i < fPropertyNamesColor.length; i++) { |
| addToken(fPropertyNamesColor[i]); |
| } |
| fNeedsLazyColorLoading= false; |
| } |
| } |
| |
| private void addTokenWithProxyAttribute(String colorKey) { |
| fTokenMap.put(colorKey, new Token(createTextAttribute(colorKey, true))); |
| } |
| |
| private void addToken(String colorKey) { |
| if (fColorManager != null && colorKey != null && fColorManager.getColor(colorKey) == null) { |
| RGB rgb= PreferenceConverter.getColor(fPreferenceStore, colorKey); |
| fColorManager.unbindColor(colorKey); |
| fColorManager.bindColor(colorKey, rgb); |
| } |
| |
| if (!fNeedsLazyColorLoading) |
| fTokenMap.put(colorKey, new Token(createTextAttribute(colorKey, false))); |
| else { |
| Token token= ((Token)fTokenMap.get(colorKey)); |
| if (token != null) |
| token.setData(createTextAttribute(colorKey, false)); |
| } |
| } |
| |
| /** |
| * Create a text attribute based on the given color, bold, italic, strikethrough and underline preference keys. |
| * |
| * @param colorKey the color preference key |
| * @param boldKey the bold preference key |
| * @param italicKey the italic preference key |
| * @param strikethroughKey the strikethrough preference key |
| * @param underlineKey the italic preference key |
| * @return the created text attribute |
| * @since 3.0 |
| */ |
| private TextAttribute createTextAttribute(String colorKey, boolean isNull) { |
| Color color= null; |
| if (!isNull) |
| color= fColorManager.getColor(colorKey); |
| |
| String boldKey= colorKey + PreferenceConstants.EDITOR_BOLD_SUFFIX; |
| String italicKey= colorKey + PreferenceConstants.EDITOR_ITALIC_SUFFIX; |
| String strikethroughKey= colorKey + PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX; |
| String underlineKey= colorKey + PreferenceConstants.EDITOR_UNDERLINE_SUFFIX; |
| |
| int style= fPreferenceStore.getBoolean(boldKey) ? SWT.BOLD : SWT.NORMAL; |
| if (fPreferenceStore.getBoolean(italicKey)) |
| style |= SWT.ITALIC; |
| |
| if (fPreferenceStore.getBoolean(strikethroughKey)) |
| style |= TextAttribute.STRIKETHROUGH; |
| |
| if (fPreferenceStore.getBoolean(underlineKey)) |
| style |= TextAttribute.UNDERLINE; |
| |
| return new TextAttribute(color, null, style); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.cdt.ui.text.ITokenStore#getToken(java.lang.String) |
| */ |
| @Override |
| public IToken getToken(String key) { |
| return getTokenInner(key); |
| } |
| |
| private Token getTokenInner(String key) { |
| ensureTokensInitialised(); |
| return (Token) fTokenMap.get(key); |
| } |
| |
| private int indexOf(String property) { |
| if (property != null) { |
| int length= fPropertyNamesColor.length; |
| for (int i= 0; i < length; i++) { |
| if (property.startsWith(fPropertyNamesColor[i])) { |
| int pLength= property.length(); |
| if(fPropertyNamesColor[i].length() < pLength) { |
| String end= property.substring(fPropertyNamesColor[i].length()); |
| if (end.equals(PreferenceConstants.EDITOR_BOLD_SUFFIX) |
| || end.equals(PreferenceConstants.EDITOR_ITALIC_SUFFIX) |
| || end.equals(PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX) |
| || end.equals(PreferenceConstants.EDITOR_UNDERLINE_SUFFIX)) { |
| return i; |
| } |
| } else if (fPropertyNamesColor[i].equals(property)) { |
| return i; |
| } |
| } |
| } |
| } |
| return -1; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#affectsBehavior(org.eclipse.jface.util.PropertyChangeEvent) |
| */ |
| @Override |
| public boolean affectsBehavior(PropertyChangeEvent event) { |
| return indexOf(event.getProperty()) >= 0; |
| } |
| |
| /* |
| * (non-Javadoc) |
| * @see org.eclipse.cdt.ui.IPropertyChangeParticipant#adaptToPreferenceChange(org.eclipse.jface.util.PropertyChangeEvent) |
| */ |
| @Override |
| public void adaptToPreferenceChange(PropertyChangeEvent event) { |
| String property= event.getProperty(); |
| int i= indexOf(property); |
| if (property.startsWith(fPropertyNamesColor[i])) { |
| Token token= getTokenInner(fPropertyNamesColor[i]); |
| if(property.length() == fPropertyNamesColor[i].length()) { |
| adaptToColorChange(token, event); |
| } else { |
| String end= property.substring(fPropertyNamesColor[i].length()); |
| if (end.equals(PreferenceConstants.EDITOR_BOLD_SUFFIX)) { |
| adaptToStyleChange(token, event, SWT.BOLD); |
| } else if (end.equals(PreferenceConstants.EDITOR_ITALIC_SUFFIX)) { |
| adaptToStyleChange(token, event, SWT.ITALIC); |
| } else if (end.equals(PreferenceConstants.EDITOR_STRIKETHROUGH_SUFFIX)) { |
| adaptToStyleChange(token, event, TextAttribute.STRIKETHROUGH); |
| } else if (end.equals(PreferenceConstants.EDITOR_UNDERLINE_SUFFIX)) { |
| adaptToStyleChange(token, event, TextAttribute.UNDERLINE); |
| } |
| } |
| } |
| } |
| |
| private void adaptToColorChange(Token token, PropertyChangeEvent event) { |
| RGB rgb= null; |
| |
| Object value= event.getNewValue(); |
| if (value instanceof RGB) |
| rgb= (RGB) value; |
| else if (value instanceof String) |
| rgb= StringConverter.asRGB((String) value); |
| |
| if (rgb != null) { |
| |
| String property= event.getProperty(); |
| Color color= fColorManager.getColor(property); |
| |
| if ((color == null || !rgb.equals(color.getRGB()))) { |
| fColorManager.unbindColor(property); |
| fColorManager.bindColor(property, rgb); |
| |
| color= fColorManager.getColor(property); |
| } |
| |
| Object data= token.getData(); |
| if (data instanceof TextAttribute) { |
| TextAttribute oldAttr= (TextAttribute) data; |
| token.setData(new TextAttribute(color, oldAttr.getBackground(), oldAttr.getStyle())); |
| } |
| } |
| } |
| |
| private void adaptToStyleChange(Token token, PropertyChangeEvent event, int styleAttribute) { |
| boolean eventValue= false; |
| Object value= event.getNewValue(); |
| if (value instanceof Boolean) |
| eventValue= ((Boolean) value).booleanValue(); |
| else if (IPreferenceStore.TRUE.equals(value)) |
| eventValue= true; |
| |
| Object data= token.getData(); |
| if (data instanceof TextAttribute) { |
| TextAttribute oldAttr= (TextAttribute) data; |
| boolean activeValue= (oldAttr.getStyle() & styleAttribute) == styleAttribute; |
| if (activeValue != eventValue) |
| token.setData(new TextAttribute(oldAttr.getForeground(), oldAttr.getBackground(), eventValue ? oldAttr.getStyle() | styleAttribute : oldAttr.getStyle() & ~styleAttribute)); |
| } |
| } |
| |
| /** |
| * Returns the preference store. |
| * |
| * @return the preference store. |
| * |
| * @since 3.0 |
| */ |
| @Override |
| public IPreferenceStore getPreferenceStore() { |
| return fPreferenceStore; |
| } |
| } |