/* * Copyright 2000-2009 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. */ /* * @author max */ package com.intellij.openapi.editor.markup; import com.intellij.openapi.util.Comparing; import com.intellij.util.ConcurrencyUtil; import com.intellij.util.containers.StripedLockConcurrentHashMap; import org.intellij.lang.annotations.JdkConstants; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import java.awt.*; public class AttributesFlyweight { private static final StripedLockConcurrentHashMap<FlyweightKey, AttributesFlyweight> entries = new StripedLockConcurrentHashMap<FlyweightKey, AttributesFlyweight>(); private static final ThreadLocal<FlyweightKey> ourKey = new ThreadLocal<FlyweightKey>(); private final int myHashCode; private final Color myForeground; private final Color myBackground; @JdkConstants.FontStyle private final int myFontType; private final Color myEffectColor; private final EffectType myEffectType; private final Color myErrorStripeColor; private static class FlyweightKey implements Cloneable { private Color foreground; private Color background; @JdkConstants.FontStyle private int fontType; private Color effectColor; private EffectType effectType; private Color errorStripeColor; private FlyweightKey() { } @Override public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof FlyweightKey)) return false; FlyweightKey key = (FlyweightKey)o; if (fontType != key.fontType) return false; if (background != null ? !background.equals(key.background) : key.background != null) return false; if (effectColor != null ? !effectColor.equals(key.effectColor) : key.effectColor != null) return false; if (effectType != key.effectType) return false; if (errorStripeColor != null ? !errorStripeColor.equals(key.errorStripeColor) : key.errorStripeColor != null) return false; if (foreground != null ? !foreground.equals(key.foreground) : key.foreground != null) return false; return true; } @Override public int hashCode() { return calcHashCode(foreground, background, fontType, effectColor, effectType, errorStripeColor); } @Override protected FlyweightKey clone() { try { return (FlyweightKey)super.clone(); } catch (CloneNotSupportedException e) { throw new RuntimeException(e); } } } @NotNull public static AttributesFlyweight create(Color foreground, Color background, @JdkConstants.FontStyle int fontType, Color effectColor, EffectType effectType, Color errorStripeColor) { FlyweightKey key = ourKey.get(); if (key == null) { ourKey.set(key = new FlyweightKey()); } key.foreground = foreground; key.background = background; key.fontType = fontType; key.effectColor = effectColor; key.effectType = effectType; key.errorStripeColor = errorStripeColor; AttributesFlyweight flyweight = entries.get(key); if (flyweight != null) { return flyweight; } AttributesFlyweight newValue = new AttributesFlyweight(foreground, background, fontType, effectColor, effectType, errorStripeColor); return ConcurrencyUtil.cacheOrGet(entries, key.clone(), newValue); } private AttributesFlyweight(Color foreground, Color background, @JdkConstants.FontStyle int fontType, Color effectColor, EffectType effectType, Color errorStripeColor) { myForeground = foreground; myBackground = background; myFontType = fontType; myEffectColor = effectColor; myEffectType = effectType; myErrorStripeColor = errorStripeColor; myHashCode = calcHashCode(foreground, background, fontType, effectColor, effectType, errorStripeColor); } private static int calcHashCode(Color foreground, Color background, int fontType, Color effectColor, EffectType effectType, Color errorStripeColor) { int result = foreground != null ? foreground.hashCode() : 0; result = 31 * result + (background != null ? background.hashCode() : 0); result = 31 * result + fontType; result = 31 * result + (effectColor != null ? effectColor.hashCode() : 0); result = 31 * result + (effectType != null ? effectType.hashCode() : 0); result = 31 * result + (errorStripeColor != null ? errorStripeColor.hashCode() : 0); return result; } public Color getForeground() { return myForeground; } public Color getBackground() { return myBackground; } @JdkConstants.FontStyle public int getFontType() { return myFontType; } public Color getEffectColor() { return myEffectColor; } public EffectType getEffectType() { return myEffectType; } public Color getErrorStripeColor() { return myErrorStripeColor; } @NotNull public AttributesFlyweight withForeground(Color foreground) { return Comparing.equal(foreground, myForeground) ? this : create(foreground, myBackground, myFontType, myEffectColor, myEffectType, myErrorStripeColor); } @NotNull public AttributesFlyweight withBackground(Color background) { return Comparing.equal(background, myBackground) ? this : create(myForeground, background, myFontType, myEffectColor, myEffectType, myErrorStripeColor); } @NotNull public AttributesFlyweight withFontType(@JdkConstants.FontStyle int fontType) { return fontType == myFontType ? this : create(myForeground, myBackground, fontType, myEffectColor, myEffectType, myErrorStripeColor); } @NotNull public AttributesFlyweight withEffectColor(Color effectColor) { return Comparing.equal(effectColor, myEffectColor) ? this : create(myForeground, myBackground, myFontType, effectColor, myEffectType, myErrorStripeColor); } @NotNull public AttributesFlyweight withEffectType(EffectType effectType) { return Comparing.equal(effectType, myEffectType) ? this : create(myForeground, myBackground, myFontType, myEffectColor, effectType, myErrorStripeColor); } @NotNull public AttributesFlyweight withErrorStripeColor(Color stripeColor) { return Comparing.equal(stripeColor, myErrorStripeColor) ? this : create(myForeground, myBackground, myFontType, myEffectColor, myEffectType, stripeColor); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AttributesFlyweight that = (AttributesFlyweight)o; if (myFontType != that.myFontType) return false; if (myBackground != null ? !myBackground.equals(that.myBackground) : that.myBackground != null) return false; if (myEffectColor != null ? !myEffectColor.equals(that.myEffectColor) : that.myEffectColor != null) return false; if (myEffectType != that.myEffectType) return false; if (myErrorStripeColor != null ? !myErrorStripeColor.equals(that.myErrorStripeColor) : that.myErrorStripeColor != null) return false; if (myForeground != null ? !myForeground.equals(that.myForeground) : that.myForeground != null) return false; return true; } @Override public int hashCode() { return myHashCode; } @NonNls @Override public String toString() { return "AttributesFlyweight{myForeground=" + myForeground + ", myBackground=" + myBackground + ", myFontType=" + myFontType + ", myEffectColor=" + myEffectColor + ", myEffectType=" + myEffectType + ", myErrorStripeColor=" + myErrorStripeColor + '}'; } }