/******************************************************************************* * Copyright (c) 2014, 2015 Cisco Systems, Inc. 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 * *******************************************************************************/ package com.cisco.yangide.editor.editors; import org.eclipse.jdt.ui.PreferenceConstants; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.jface.preference.PreferenceConverter; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.graphics.RGB; import com.cisco.yangide.core.YangTypeUtil; import com.cisco.yangide.core.dom.ASTNamedNode; import com.cisco.yangide.core.dom.ASTNode; import com.cisco.yangide.core.dom.GroupingDefinition; import com.cisco.yangide.core.dom.Module; import com.cisco.yangide.core.dom.SimpleNode; import com.cisco.yangide.core.dom.SubModule; import com.cisco.yangide.core.dom.TypeDefinition; import com.cisco.yangide.core.dom.TypeReference; import com.cisco.yangide.core.dom.UsesNode; import com.cisco.yangide.editor.preferences.YangPreferencesMessages; /** * Semantic highlightings * * @author Alexey Kholupko */ public class SemanticHighlightings { /** * A named preference part that controls the highlighting of fields. */ public static final String TYPE = "type"; //$NON-NLS-1$ public static final String GROUPING = "grouping"; //$NON-NLS-1$ public static final String PREFIX = "prefix"; //$NON-NLS-1$ /** * Semantic highlightings */ private static SemanticHighlighting[] fgSemanticHighlightings; /** * Semantic highlighting for client types. */ private static final class TypeHighlighting extends SemanticHighlighting { /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#getPreferenceKey() */ @Override public String getPreferenceKey() { return TYPE; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextColor() */ @Override public RGB getDefaultTextColor() { return new RGB(128, 128, 0); } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextStyleBold() */ @Override public boolean isBoldByDefault() { return false; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isItalicByDefault() */ @Override public boolean isItalicByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isEnabledByDefault() */ @Override public boolean isEnabledByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDisplayName() */ @Override public String getDisplayName() { return YangPreferencesMessages.SemanticHighlighting_type; } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#consumes(org.eclipse.jdt. * internal.ui.javaeditor.SemanticToken) */ @Override public boolean consumes(ASTNode node) { if (node instanceof TypeReference) { String typeWholeName = ((TypeReference) node).getName(); return !YangTypeUtil.isBuiltInType(typeWholeName); } return node instanceof TypeDefinition; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingOffset(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingOffset(ASTNode node) { int result = -1; String nodeModulePrefix = null; if (node instanceof TypeReference) { nodeModulePrefix = ((TypeReference) node).getType().getPrefix(); } result = getHiglightingOffset(node, nodeModulePrefix); return result; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingLength(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingLength(ASTNode node) { int result = -1; String nodeModulePrefix = null; if (node instanceof TypeReference) { nodeModulePrefix = ((TypeReference) node).getType().getPrefix(); } result = getHiglightingLength(node, nodeModulePrefix); return result; } } /** * Semantic highlighting for client groupings. */ private static final class GroupingHighlighting extends SemanticHighlighting { /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#getPreferenceKey() */ @Override public String getPreferenceKey() { return GROUPING; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextColor() */ @Override public RGB getDefaultTextColor() { return new RGB(168, 98, 0); } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextStyleBold() */ @Override public boolean isBoldByDefault() { return false; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isItalicByDefault() */ @Override public boolean isItalicByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isEnabledByDefault() */ @Override public boolean isEnabledByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDisplayName() */ @Override public String getDisplayName() { return YangPreferencesMessages.SemanticHighlighting_grouping; } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#consumes(org.eclipse.jdt. * internal.ui.javaeditor.SemanticToken) */ @Override public boolean consumes(ASTNode node) { return node instanceof GroupingDefinition || node instanceof UsesNode; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingOffset(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingOffset(ASTNode node) { int result = -1; String nodeModulePrefix = null; if (node instanceof UsesNode) { nodeModulePrefix = ((UsesNode) node).getGrouping().getPrefix(); } result = getHiglightingOffset(node, nodeModulePrefix); return result; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingLength(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingLength(ASTNode node) { int result = -1; String nodeModulePrefix = null; if (node instanceof UsesNode) { nodeModulePrefix = ((UsesNode) node).getGrouping().getPrefix(); } result = getHiglightingLength(node, nodeModulePrefix); return result; } } /** * Semantic highlighting for fields. */ private static final class PrefixHighlighting extends SemanticHighlighting { /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#getPreferenceKey() */ @Override public String getPreferenceKey() { return PREFIX; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextColor() */ @Override public RGB getDefaultTextColor() { return new RGB(128, 128, 128); } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDefaultTextStyleBold() */ @Override public boolean isBoldByDefault() { return false; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isItalicByDefault() */ @Override public boolean isItalicByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#isEnabledByDefault() */ @Override public boolean isEnabledByDefault() { return true; } /* * @see org.eclipse.jdt.internal.ui.javaeditor.ISemanticHighlighting#getDisplayName() */ @Override public String getDisplayName() { return YangPreferencesMessages.SemanticHighlighting_prefix; } /* * @see * org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlighting#consumes(org.eclipse.jdt. * internal.ui.javaeditor.SemanticToken) */ @Override public boolean consumes(ASTNode node) { String thisModulePrefix = null; ASTNode thisModule = node.getModule(); if (thisModule instanceof SubModule) { thisModulePrefix = null;// ((SubModule) thisModule).getParentPrefix(); } else { SimpleNode<String> prefixNode = ((Module) thisModule).getPrefix(); if (prefixNode != null) { thisModulePrefix = prefixNode.getValue(); } } if (node instanceof TypeReference) { String typeWholeName = ((TypeReference) node).getName(); String typePrefix = ((TypeReference) node).getType().getPrefix(); return !YangTypeUtil.isBuiltInType(typeWholeName) && !typePrefix.equals(thisModulePrefix); } if (node instanceof UsesNode) { String usesPrefix = ((UsesNode) node).getGrouping().getPrefix(); if (usesPrefix != null) { return !usesPrefix.equals(thisModulePrefix); } } return false; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingOffset(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingOffset(ASTNode node) { if (node instanceof ASTNamedNode) { ASTNamedNode nnode = (ASTNamedNode) node; // increase offset because of quoted name return nnode.getName().length() != nnode.getNameLength() ? nnode.getNameStartPosition() + 1 : nnode .getNameStartPosition(); } return -1; } /* * (non-Javadoc) * * @see * com.cisco.yangide.editor.editors.SemanticHighlighting#getHiglightingLength(com.cisco. * yangide.core.dom.ASTNode) */ @Override public int getHiglightingLength(ASTNode node) { if (node instanceof TypeReference) { return ((TypeReference) node).getType().getPrefix().length(); } if (node instanceof UsesNode) { return ((UsesNode) node).getGrouping().getPrefix().length(); } return -1; } } /** * A named preference that controls the given semantic highlighting's color. */ public static String getColorPreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_COLOR_SUFFIX; } /** * A named preference that controls if the given semantic highlighting has the text attribute * bold. */ public static String getBoldPreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_BOLD_SUFFIX; } /** * A named preference that controls if the given semantic highlighting has the text attribute * italic. */ public static String getItalicPreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ITALIC_SUFFIX; } /** * A named preference that controls if the given semantic highlighting has the text attribute * strikethrough. */ public static String getStrikethroughPreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_STRIKETHROUGH_SUFFIX; } /** * A named preference that controls if the given semantic highlighting has the text attribute * underline. */ public static String getUnderlinePreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_UNDERLINE_SUFFIX; } /** * A named preference that controls if the given semantic highlighting is enabled. */ public static String getEnabledPreferenceKey(SemanticHighlighting semanticHighlighting) { return PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_PREFIX + semanticHighlighting.getPreferenceKey() + PreferenceConstants.EDITOR_SEMANTIC_HIGHLIGHTING_ENABLED_SUFFIX; } /** * @return The semantic highlightings, the order defines the precedence of matches, the first * match wins. */ public static SemanticHighlighting[] getSemanticHighlightings() { if (fgSemanticHighlightings == null) { fgSemanticHighlightings = new SemanticHighlighting[] { new TypeHighlighting(), new GroupingHighlighting(), new PrefixHighlighting() }; } return fgSemanticHighlightings; } /** * Initialize default preferences in the given preference store. * * @param store The preference store TODO refactor and call from PreferenceInitializer */ public static void initDefaults(IPreferenceStore store) { SemanticHighlighting[] semanticHighlightings = getSemanticHighlightings(); for (int i = 0, n = semanticHighlightings.length; i < n; i++) { SemanticHighlighting semanticHighlighting = semanticHighlightings[i]; setDefaultAndFireEvent(store, SemanticHighlightings.getColorPreferenceKey(semanticHighlighting), semanticHighlighting.getDefaultTextColor()); store.setDefault(SemanticHighlightings.getBoldPreferenceKey(semanticHighlighting), semanticHighlighting.isBoldByDefault()); store.setDefault(SemanticHighlightings.getItalicPreferenceKey(semanticHighlighting), semanticHighlighting.isItalicByDefault()); store.setDefault(SemanticHighlightings.getStrikethroughPreferenceKey(semanticHighlighting), semanticHighlighting.isStrikethroughByDefault()); store.setDefault(SemanticHighlightings.getUnderlinePreferenceKey(semanticHighlighting), semanticHighlighting.isUnderlineByDefault()); store.setDefault(SemanticHighlightings.getEnabledPreferenceKey(semanticHighlighting), semanticHighlighting.isEnabledByDefault()); } } /** * Tests whether <code>event</code> in <code>store</code> affects the enablement of semantic * highlighting. */ public static boolean affectsEnablement(IPreferenceStore store, PropertyChangeEvent event) { String relevantKey = null; SemanticHighlighting[] highlightings = getSemanticHighlightings(); for (int i = 0; i < highlightings.length; i++) { if (event.getProperty().equals(getEnabledPreferenceKey(highlightings[i]))) { relevantKey = event.getProperty(); break; } } if (relevantKey == null) { return false; } for (int i = 0; i < highlightings.length; i++) { String key = getEnabledPreferenceKey(highlightings[i]); if (key.equals(relevantKey)) { continue; } if (store.getBoolean(key)) { return false; // another is still enabled or was enabled before } } // all others are disabled, so toggling relevantKey affects the enablement return true; } /** * Tests whether semantic highlighting is currently enabled. */ public static boolean isEnabled(IPreferenceStore store) { SemanticHighlighting[] highlightings = getSemanticHighlightings(); boolean enable = false; for (int i = 0; i < highlightings.length; i++) { String enabledKey = getEnabledPreferenceKey(highlightings[i]); if (store.getBoolean(enabledKey)) { enable = true; break; } } return enable; } /** * Sets the default value and fires a property change event if necessary. */ private static void setDefaultAndFireEvent(IPreferenceStore store, String key, RGB newValue) { RGB oldValue = null; if (store.isDefault(key)) { oldValue = PreferenceConverter.getDefaultColor(store, key); } PreferenceConverter.setDefault(store, key, newValue); if (oldValue != null && !oldValue.equals(newValue)) { store.firePropertyChangeEvent(key, oldValue, newValue); } } /** * Do not instantiate */ private SemanticHighlightings() { } }