blob: 715e70027eb362a5db500d1bcbe45c175b34f35b [file] [log] [blame]
/*
* 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() +
"]";
}
}