| /* |
| * Copyright 2000-2010 JetBrains s.r.o. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.intellij.openapi.editor.markup; |
| |
| import com.intellij.openapi.diagnostic.Logger; |
| import com.intellij.openapi.util.*; |
| import org.intellij.lang.annotations.JdkConstants; |
| import org.jdom.Element; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.awt.*; |
| import java.lang.reflect.Field; |
| |
| /** |
| * Defines the visual representation (colors and effects) of text. |
| */ |
| public class TextAttributes implements JDOMExternalizable, Cloneable { |
| private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.editor.markup.TextAttributes"); |
| |
| public static final TextAttributes ERASE_MARKER = new TextAttributes(); |
| |
| private boolean myEnforcedDefaults = false; |
| |
| /** |
| * Merges (layers) the two given text attributes. |
| * |
| * @param under Text attributes to merge "under". |
| * @param above Text attributes to merge "above", overriding settings from "under". |
| * @return Merged attributes instance. |
| */ |
| public static TextAttributes merge(TextAttributes under, TextAttributes above) { |
| if (under == null) return above; |
| if (above == null) return under; |
| |
| TextAttributes attrs = under.clone(); |
| if (above.getBackgroundColor() != null){ |
| attrs.setBackgroundColor(above.getBackgroundColor()); |
| } |
| if (above.getForegroundColor() != null){ |
| attrs.setForegroundColor(above.getForegroundColor()); |
| } |
| attrs.setFontType(above.getFontType() | under.getFontType()); |
| |
| if (above.getEffectColor() != null){ |
| attrs.setEffectColor(above.getEffectColor()); |
| attrs.setEffectType(above.getEffectType()); |
| } |
| return attrs; |
| } |
| |
| private static class Externalizable implements Cloneable, JDOMExternalizable { |
| public Color FOREGROUND = null; |
| public Color BACKGROUND = null; |
| |
| @JdkConstants.FontStyle |
| public int FONT_TYPE = Font.PLAIN; |
| |
| public Color EFFECT_COLOR = null; |
| public int EFFECT_TYPE = EFFECT_BORDER; |
| public Color ERROR_STRIPE_COLOR = null; |
| |
| private static final int EFFECT_BORDER = 0; |
| private static final int EFFECT_LINE = 1; |
| private static final int EFFECT_WAVE = 2; |
| private static final int EFFECT_STRIKEOUT = 3; |
| private static final int EFFECT_BOLD_LINE = 4; |
| private static final int EFFECT_BOLD_DOTTED_LINE = 5; |
| |
| @Override |
| public Object clone() throws CloneNotSupportedException { |
| return super.clone(); |
| } |
| |
| @Override |
| public void readExternal(Element element) throws InvalidDataException { |
| DefaultJDOMExternalizer.readExternal(this, element); |
| if (FONT_TYPE < 0 || FONT_TYPE > 3) { |
| LOG.info("Wrong font type: " + FONT_TYPE); |
| FONT_TYPE = 0; |
| } |
| } |
| |
| @Override |
| public void writeExternal(Element element) throws WriteExternalException { |
| DefaultJDOMExternalizer.writeExternal(this, element, new DefaultJDOMExternalizer.JDOMFilter() { |
| @Override |
| public boolean isAccept(@NotNull Field field) { |
| try { |
| if (field.getType().equals(Color.class) && field.get(Externalizable.this) == null) return false; |
| if (field.getType().equals(int.class) && field.getInt(Externalizable.this) == 0) return false; |
| } |
| catch (IllegalAccessException e) { |
| LOG.error("Can not access: " + field.getName()); |
| } |
| return true; |
| } |
| }); |
| } |
| |
| private EffectType getEffectType() { |
| switch (EFFECT_TYPE) { |
| case EFFECT_BORDER: |
| return EffectType.BOXED; |
| case EFFECT_BOLD_LINE: |
| return EffectType.BOLD_LINE_UNDERSCORE; |
| case EFFECT_LINE: |
| return EffectType.LINE_UNDERSCORE; |
| case EFFECT_STRIKEOUT: |
| return EffectType.STRIKEOUT; |
| case EFFECT_WAVE: |
| return EffectType.WAVE_UNDERSCORE; |
| case EFFECT_BOLD_DOTTED_LINE: |
| return EffectType.BOLD_DOTTED_LINE; |
| default: |
| return null; |
| } |
| } |
| |
| private void setEffectType(EffectType effectType) { |
| if (effectType == EffectType.BOXED) { |
| EFFECT_TYPE = EFFECT_BORDER; |
| } |
| else if (effectType == EffectType.LINE_UNDERSCORE) { |
| EFFECT_TYPE = EFFECT_LINE; |
| } |
| else if (effectType == EffectType.BOLD_LINE_UNDERSCORE) { |
| EFFECT_TYPE = EFFECT_BOLD_LINE; |
| } |
| else if (effectType == EffectType.STRIKEOUT) { |
| EFFECT_TYPE = EFFECT_STRIKEOUT; |
| } |
| else if (effectType == EffectType.WAVE_UNDERSCORE) { |
| EFFECT_TYPE = EFFECT_WAVE; |
| } |
| else if (effectType == EffectType.BOLD_DOTTED_LINE) { |
| EFFECT_TYPE = EFFECT_BOLD_DOTTED_LINE; |
| } |
| else { |
| EFFECT_TYPE = -1; |
| } |
| } |
| } |
| |
| private AttributesFlyweight myAttrs; |
| |
| public TextAttributes() { |
| this(null, null, null, EffectType.BOXED, Font.PLAIN); |
| } |
| |
| public TextAttributes(Color foregroundColor, Color backgroundColor, Color effectColor, EffectType effectType, @JdkConstants.FontStyle int fontType) { |
| setAttributes(foregroundColor, backgroundColor, effectColor, null, effectType, fontType); |
| } |
| |
| public void setAttributes(Color foregroundColor, |
| Color backgroundColor, |
| Color effectColor, |
| Color errorStripeColor, |
| EffectType effectType, |
| @JdkConstants.FontStyle int fontType) { |
| myAttrs = AttributesFlyweight.create(foregroundColor, backgroundColor, fontType, effectColor, effectType, errorStripeColor); |
| } |
| |
| public boolean isEmpty(){ |
| return getForegroundColor() == null && getBackgroundColor() == null && getEffectColor() == null && getFontType() == Font.PLAIN; |
| } |
| |
| public boolean isFallbackEnabled() { |
| return isEmpty() && !myEnforcedDefaults; |
| } |
| |
| public void reset() { |
| setForegroundColor(null); |
| setBackgroundColor(null); |
| setEffectColor(null); |
| setFontType(Font.PLAIN); |
| } |
| |
| @NotNull |
| public AttributesFlyweight getFlyweight() { |
| return myAttrs; |
| } |
| |
| @NotNull |
| public static TextAttributes fromFlyweight(AttributesFlyweight flyweight) { |
| TextAttributes f = new TextAttributes(); |
| f.myAttrs = flyweight; |
| return f; |
| } |
| |
| public Color getForegroundColor() { |
| return myAttrs.getForeground(); |
| } |
| |
| public void setForegroundColor(Color color) { |
| myAttrs = myAttrs.withForeground(color); |
| } |
| |
| public Color getBackgroundColor() { |
| return myAttrs.getBackground(); |
| } |
| |
| public void setBackgroundColor(Color color) { |
| myAttrs = myAttrs.withBackground(color); |
| } |
| |
| public Color getEffectColor() { |
| return myAttrs.getEffectColor(); |
| } |
| |
| public void setEffectColor(Color color) { |
| myAttrs = myAttrs.withEffectColor(color); |
| } |
| |
| public Color getErrorStripeColor() { |
| return myAttrs.getErrorStripeColor(); |
| } |
| |
| public void setErrorStripeColor(Color color) { |
| myAttrs = myAttrs.withErrorStripeColor(color); |
| } |
| |
| public EffectType getEffectType() { |
| return myAttrs.getEffectType(); |
| } |
| |
| public void setEffectType(EffectType effectType) { |
| myAttrs = myAttrs.withEffectType(effectType); |
| } |
| |
| @JdkConstants.FontStyle |
| public int getFontType() { |
| return myAttrs.getFontType(); |
| } |
| |
| public void setFontType(@JdkConstants.FontStyle int type) { |
| if (type < 0 || type > 3) { |
| LOG.error("Wrong font type: " + type); |
| type = 0; |
| } |
| myAttrs = myAttrs.withFontType(type); |
| } |
| |
| @Override |
| public TextAttributes clone() { |
| TextAttributes cloned = new TextAttributes(); |
| cloned.myAttrs = myAttrs; |
| cloned.myEnforcedDefaults = myEnforcedDefaults; |
| return cloned; |
| } |
| |
| public boolean equals(Object obj) { |
| if(!(obj instanceof TextAttributes)) { |
| return false; |
| } |
| // myAttrs are interned, see com.intellij.openapi.editor.markup.AttributesFlyweight.create() |
| return myAttrs == ((TextAttributes)obj).myAttrs; |
| } |
| |
| public int hashCode() { |
| return myAttrs.hashCode(); |
| } |
| |
| @Override |
| public void readExternal(Element element) throws InvalidDataException { |
| Externalizable ext = new Externalizable(); |
| ext.readExternal(element); |
| myAttrs = AttributesFlyweight.create(ext.FOREGROUND, |
| ext.BACKGROUND, |
| ext.FONT_TYPE, |
| ext.EFFECT_COLOR, |
| ext.getEffectType(), |
| ext.ERROR_STRIPE_COLOR); |
| if (isEmpty()) myEnforcedDefaults = true; |
| } |
| |
| @Override |
| public void writeExternal(Element element) throws WriteExternalException { |
| Externalizable ext = new Externalizable(); |
| |
| ext.FOREGROUND = myAttrs.getForeground(); |
| ext.BACKGROUND = myAttrs.getBackground(); |
| ext.FONT_TYPE = myAttrs.getFontType(); |
| ext.EFFECT_COLOR = myAttrs.getEffectColor(); |
| ext.ERROR_STRIPE_COLOR = myAttrs.getErrorStripeColor(); |
| ext.setEffectType(myAttrs.getEffectType()); |
| |
| ext.writeExternal(element); |
| } |
| |
| @Override |
| public String toString() { |
| return "[" + |
| getForegroundColor() + |
| "," + |
| getBackgroundColor() + |
| "," + |
| getFontType() + |
| "," + |
| getEffectType() + |
| "," + |
| getEffectColor() + |
| "," + |
| getErrorStripeColor() + |
| "]"; |
| } |
| } |