blob: 9916bd94e74ce47be416fa144d535590b51d31ee [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2018 Borland Software Corporation and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Borland Software Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.m2m.internal.qvt.oml.editor.ui.colorer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.ListenerList;
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.Token;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
public class QVTColorManager extends IQVTColors {
public interface IHighlightingChanged {
void highlightingChanged(ColorDescriptor cd);
}
public class ColorDescriptor {
private TextAttribute fAttribute;
private Highlighting fHighlighting;
private Token fToken;
private final String fDisplayName;
private final String fEnabledKey;
private final String fBoldKey;
private final String fItalicKey;
private final String fColorKey;
private final String fStrikethroughKey;
private final String fUnderlineKey;
private final String fKey;
public ColorDescriptor(String key, String displayName, boolean canBeDisabled) {
fKey = key;
String baseKey = BASE_COLORS_KEY_PREFIX + key;
fDisplayName = displayName;
fBoldKey = baseKey + BOLD_SUFFIX;
fItalicKey = baseKey + ITALIC_SUFFIX;
fColorKey = baseKey + COLOR_SUFFIX;
fStrikethroughKey = baseKey + STRIKETHROUGH_SUFFIX;
fUnderlineKey = baseKey + UNDERLINE_SUFFIX;
fEnabledKey = canBeDisabled ? baseKey + ENABLED_SUFFIX : null;
}
public String key() {
return fKey;
}
public boolean canBeDisabled() {
return fEnabledKey != null;
}
public String getDisplayName() {
return fDisplayName;
}
public String getEnabledKey() {
return fEnabledKey;
}
public String getBoldKey() {
return fBoldKey;
}
public String getItalicKey() {
return fItalicKey;
}
public String getStrikethroughKey() {
return fStrikethroughKey;
}
public String getUnderlineKey() {
return fUnderlineKey;
}
public String getColorKey() {
return fColorKey;
}
public Highlighting getHighlighting() {
return fHighlighting;
}
public boolean isAffectedBy(String property) {
return property.equals(getColorKey()) || property.equals(getBoldKey()) || property.equals(getEnabledKey())
|| property.equals(getItalicKey()) || property.equals(getStrikethroughKey())
|| property.equals(getUnderlineKey());
}
/**
* UI thread only
*/
public TextAttribute createTextAttribute() {
if (fAttribute != null) {
return fAttribute;
}
addColor(getColorKey());
int style = fStore.getBoolean(getBoldKey()) ? SWT.BOLD : SWT.NORMAL;
if (fStore.getBoolean(getItalicKey()))
style |= SWT.ITALIC;
if (fStore.getBoolean(getStrikethroughKey()))
style |= TextAttribute.STRIKETHROUGH;
if (fStore.getBoolean(getUnderlineKey()))
style |= TextAttribute.UNDERLINE;
Color color = fColorManager.getColor(PreferenceConverter.getColor(fStore, getColorKey()));
fAttribute = new TextAttribute(color, null, style);
return fAttribute;
}
/**
* UI thread only
*/
public Highlighting createHighlighting() {
if (fHighlighting != null) {
return fHighlighting;
}
boolean isEnabled = canBeDisabled() ? fStore.getBoolean(getEnabledKey()) : true;
fHighlighting = new Highlighting(createTextAttribute(), isEnabled);
return fHighlighting;
}
public Token createToken() {
if (fToken != null) {
return fToken;
}
fToken = new Token(createTextAttribute());
return fToken;
}
public void disposeColor() {
if (fAttribute != null) {
removeColor(getColorKey());
fAttribute = null;
}
}
public TextAttribute getTextAttribute() {
return fAttribute;
}
public void setTextAttribute(TextAttribute ta) {
fAttribute = ta;
if (fHighlighting != null) {
fHighlighting.setTextAttribute(ta);
}
if (fToken != null) {
fToken.setData(ta);
}
}
}
public class Highlighting {
private TextAttribute fTextAttribute;
private boolean fIsEnabled;
public Highlighting(TextAttribute textAttribute, boolean isEnabled) {
setTextAttribute(textAttribute);
setEnabled(isEnabled);
}
public TextAttribute getTextAttribute() {
return fTextAttribute;
}
public void setTextAttribute(TextAttribute textAttribute) {
fTextAttribute = textAttribute;
}
public boolean isEnabled() {
return fIsEnabled;
}
public void setEnabled(boolean isEnabled) {
fIsEnabled = isEnabled;
}
}
ListenerList fColorChangedListeners = new ListenerList();
private final List<ColorDescriptor> fDescriptors;
private final Map<String, DefaultColoring> fKey2Default;
private final Map<String, ColorDescriptor> fKey2Descriptor;
private IPreferenceStore fStore;
private ColorManager fColorManager;
public QVTColorManager(IPreferenceStore store, ColorManager manager) {
fStore = store;
fColorManager = manager;
fDescriptors = new ArrayList<ColorDescriptor>();
fKey2Descriptor = new HashMap<String, ColorDescriptor>();
fKey2Default = new HashMap<String, DefaultColoring>();
initDescriptors();
}
void forceInitialize() {
for (ColorDescriptor next : fDescriptors) {
next.createToken();
}
}
public ColorDescriptor getColor(String id) {
return fKey2Descriptor.get(id);
}
private int addDescriptor(String key, String name, boolean canBeDisabled, DefaultColoring defaultSettings) {
assert key != null && name != null && defaultSettings != null;
ColorDescriptor cd = new ColorDescriptor(key, name, canBeDisabled);
fKey2Descriptor.put(key, cd);
fDescriptors.add(cd);
fKey2Default.put(key, defaultSettings);
return fDescriptors.size();
}
private void initDescriptors() {
addDescriptor(MULTILINE_COMMENT, Messages.SemanticKey_multiLineComment, false,
new DefaultColoring(new RGB(63, 127, 95), false, true, false, false));
addDescriptor(LINE_COMMENT, Messages.SemanticKey_singleLineComment, false,
new DefaultColoring(new RGB(63, 127, 95), false, true, false, false));
addDescriptor(TASK_TAG, Messages.SemanticKey_taskTags, false,
new DefaultColoring(new RGB(127, 159, 191), true, false, false, false));
addDescriptor(DOC_OTHERS, Messages.SemanticKey_Others, true,
new DefaultColoring(new RGB(63, 95, 191), false, false, false, false));
addDescriptor(DOC_TAG, Messages.SemanticKey_DocTags, true,
new DefaultColoring(new RGB(63, 95, 191), false, false, false, false));
addDescriptor(FATAL_ASSERT, Messages.SemanticKey_FatalAssertion, true,
new DefaultColoring(new RGB(255, 0, 0), false, false, false, false));
addDescriptor(KEYWORD, Messages.SemanticKey_Keywords, false,
new DefaultColoring(new RGB(127, 0, 85), true, false, false, false));
addDescriptor(STRING, Messages.SemanticKey_Strings, false,
new DefaultColoring(new RGB(42, 0, 255), false, false, false, false));
addDescriptor(NUMBER, Messages.SemanticKey_Numbers, false,
new DefaultColoring(new RGB(0, 128, 0), false, false, false, false));
addDescriptor(DEFAULT, Messages.SemanticKey_Others, false,
new DefaultColoring(new RGB(0, 0, 0), false, false, false, false));
// TODO - no urgent now
// addDescriptor(VARIABLE, "Local variable", true,
// new DefaultColoring(new RGB(13, 100, 0), false, false, false, false));
// addDescriptor(OPERATION_PARAMETER, "Operation parameter", true,
// new DefaultColoring(new RGB(13, 100, 0), false, false, false, false));
addDescriptor(MODEL_PARAMETER, Messages.SemanticKey_ModelParameters, true,
new DefaultColoring(new RGB(128, 128, 0), false, false, false, false));
addDescriptor(MODULE_ELEMENT, Messages.SemanticKey_ModuleElements, true,
new DefaultColoring(new RGB(111, 0, 74), false, false, false, false));
addDescriptor(RESULT_VARIABLE, Messages.SemanticKey_ResultVar, true,
new DefaultColoring(new RGB(0, 0, 160), true, false, false, false));
addDescriptor(SELF_VARIABLE, Messages.SemanticKey_SelfVar, true,
new DefaultColoring(new RGB(0, 0, 160), true, false, false, false));
addDescriptor(INTERMEDIATE_DATA, Messages.SemanticKey_IntermData, true,
new DefaultColoring(new RGB(108, 108, 108), false, false, false, false));
addDescriptor(USER_MODEL_ELEMENT, Messages.SemanticKey_UserModelElements, true,
new DefaultColoring(new RGB(0, 0, 192), false, false, false, false));
addDescriptor(STDLIB_ELEMENT, Messages.SemanticKey_StdlibElements, true,
new DefaultColoring(new RGB(0, 0, 0), false, true, false, false));
}
public void initializeDefaults() {
for (String nextColorKey : fKey2Default.keySet()) {
DefaultColoring settings = fKey2Default.get(nextColorKey);
initDefault(nextColorKey, settings);
}
}
private static class DefaultColoring {
private RGB rgb;
private boolean bold;
private boolean italic;
private boolean underline;
private boolean strikethrough;
public DefaultColoring(RGB rgb, boolean bold, boolean italic,
boolean underline, boolean strikethrough) {
this.rgb = rgb;
this.bold = bold;
this.italic = italic;
this.underline = underline;
this.strikethrough = strikethrough;
}
public RGB getRgb() {
return rgb;
}
public boolean isBold() {
return bold;
}
public boolean isItalic() {
return italic;
}
public boolean isUnderline() {
return underline;
}
public boolean isStrikethrough() {
return strikethrough;
}
}
private void initDefault(String id, DefaultColoring defaultSettings) {
ColorDescriptor cd = getColor(id);
assert cd != null;
PreferenceConverter.setDefault(fStore, cd.getColorKey(), defaultSettings.getRgb());
fStore.setDefault(cd.getBoldKey(), defaultSettings.isBold());
fStore.setDefault(cd.getItalicKey(), defaultSettings.isItalic());
fStore.setDefault(cd.getUnderlineKey(), defaultSettings.isUnderline());
fStore.setDefault(cd.getStrikethroughKey(), defaultSettings.isStrikethrough());
if (cd.canBeDisabled()) {
fStore.setDefault(cd.getEnabledKey(), true);
}
}
public void dispose() {
for (ColorDescriptor cd : fDescriptors) {
cd.disposeColor();
}
}
public void propertyChange(PropertyChangeEvent event) {
if (fStore == null) {
return;
}
String property = event.getProperty();
for (ColorDescriptor cd : fDescriptors) {
if (cd.getColorKey().equals(property)) {
adaptToTextForegroundChange(cd, event);
notifyStyleChanged(cd);
break;
}
if (cd.getBoldKey().equals(property)) {
adaptToTextStyleChange(cd, event, SWT.BOLD);
notifyStyleChanged(cd);
break;
}
if (cd.getItalicKey().equals(property)) {
adaptToTextStyleChange(cd, event, SWT.ITALIC);
notifyStyleChanged(cd);
break;
}
if (cd.getStrikethroughKey().equals(property)) {
adaptToTextStyleChange(cd, event, TextAttribute.STRIKETHROUGH);
notifyStyleChanged(cd);
break;
}
if (cd.getUnderlineKey().equals(property)) {
adaptToTextStyleChange(cd, event, TextAttribute.UNDERLINE);
notifyStyleChanged(cd);
break;
}
if (cd.canBeDisabled() && cd.getEnabledKey().equals(property)) {
adaptToEnablementChange(cd.getHighlighting(), event);
notifyStyleChanged(cd);
break;
}
}
}
public void addHighlightingChangedListener(IHighlightingChanged listener) {
fColorChangedListeners.add(listener);
}
public void removeHighlightingChangedListener(IHighlightingChanged listener) {
fColorChangedListeners.remove(listener);
}
private void notifyStyleChanged(ColorDescriptor cd) {
Object[] listeners = fColorChangedListeners.getListeners();
for (int i = 0; i < listeners.length; ++i) {
((IHighlightingChanged) listeners[i]).highlightingChanged(cd);
}
}
private void adaptToEnablementChange(Highlighting highlighting, PropertyChangeEvent event) {
if (highlighting == null) {
return;
}
Object value = event.getNewValue();
boolean eventValue;
if (value instanceof Boolean)
eventValue = ((Boolean) value).booleanValue();
else if (IPreferenceStore.TRUE.equals(value))
eventValue = true;
else
eventValue = false;
highlighting.setEnabled(eventValue);
}
private void adaptToTextForegroundChange(ColorDescriptor descriptor, PropertyChangeEvent event) {
if (descriptor.getTextAttribute() == null) {
return;
}
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);
}
TextAttribute oldAttr = descriptor.getTextAttribute();
descriptor.setTextAttribute(new TextAttribute(color, oldAttr.getBackground(), oldAttr.getStyle()));
}
}
private void adaptToTextStyleChange(ColorDescriptor descriptor, PropertyChangeEvent event, int styleAttribute) {
if (descriptor.getTextAttribute() == null) {
return;
}
boolean eventValue = false;
Object value = event.getNewValue();
if (value instanceof Boolean)
eventValue = ((Boolean) value).booleanValue();
else if (IPreferenceStore.TRUE.equals(value))
eventValue = true;
TextAttribute oldAttr = descriptor.getTextAttribute();
boolean activeValue = (oldAttr.getStyle() & styleAttribute) == styleAttribute;
if (activeValue != eventValue)
descriptor.setTextAttribute(new TextAttribute(oldAttr.getForeground(), oldAttr.getBackground(),
eventValue ? oldAttr.getStyle() | styleAttribute : oldAttr.getStyle() & ~styleAttribute));
}
private void addColor(String colorKey) {
if (fColorManager != null && colorKey != null && fColorManager.getColor(colorKey) == null) {
RGB rgb = PreferenceConverter.getColor(fStore, colorKey);
fColorManager.unbindColor(colorKey);
fColorManager.bindColor(colorKey, rgb);
}
}
private void removeColor(String colorKey) {
fColorManager.unbindColor(colorKey);
}
public boolean isAffected(PropertyChangeEvent event) {
String property = event.getProperty();
for (ColorDescriptor cd : fDescriptors) {
if (cd.isAffectedBy(property)) {
return true;
}
}
return false;
}
public ColorDescriptor[] getSemanticHighlightings() {
return fDescriptors.toArray(new ColorDescriptor[fDescriptors.size()]);
}
int getDescriptorIndex(ColorDescriptor colorDescriptor) {
return fDescriptors.indexOf(colorDescriptor);
}
}