/* * Copyright 2003-2014 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 jetbrains.mps.editor.runtime.style; import jetbrains.mps.editor.runtime.style.StyleAttributeMap.DiscardValue; import jetbrains.mps.openapi.editor.style.Style.IntPair; import jetbrains.mps.openapi.editor.style.StyleAttribute; import java.util.ArrayList; import java.util.Collection; public class TopLevelStyleMap extends StyleMap<Object> { public int getSize() { return values.length; } public <T> Object getValue(StyleAttribute<T> attribute, int index) { int topPointer = this.search(attribute.getIndex()); return getValue(attribute, topPointer, index); } public int set(int attributeIndex, int topPointer, Object value) { if (!(value instanceof StyleAttributeMap)) { return super.set(attributeIndex, topPointer, value); } StyleAttributeMap attributes = (StyleAttributeMap) value; if (attributes.indexes.length == 0) { return super.set(attributeIndex, topPointer, null); } else if (attributes.indexes.length == 1 && attributes.indexes[0] == 0) { return super.set(attributeIndex, topPointer, attributes.values[0]); } else { return super.set(attributeIndex, topPointer, attributes); } } public <T> Object getValue(StyleAttribute<T> attribute, int topPointer, int index) { Object styleMapOrValue = get(topPointer); int pointer = StyleAttributeMap.search(styleMapOrValue, index); return StyleAttributeMap.get(styleMapOrValue, this, topPointer, pointer); } public <T> void setValue(StyleAttribute<T> attribute, int index, Object value) { int topPointer = this.search(attribute.getIndex()); setValue(attribute, topPointer, index, value); } /** * @return new value of topPointer */ public <T> int setValue(StyleAttribute<T> attribute, int topPointer, int index, Object value) { Object styleMapOrValue = get(topPointer); int pointer = StyleAttributeMap.search(styleMapOrValue, index); return setValue(attribute, topPointer, index, pointer, value); } private <T> int setValue(StyleAttribute<T> attribute, int topPointer, int index, int pointer, Object value) { Object styleMapOrValue = get(topPointer); if (value == null) { if (!StyleAttributeMap.isStyleAttributeMapEmpty(topPointer, pointer, index)) { return deleteValue(styleMapOrValue, attribute, topPointer, index, pointer); } else { return topPointer; } } else { if (StyleAttributeMap.isStyleAttributeMapEmpty(topPointer, pointer, index)) { return insertValue(styleMapOrValue, attribute, topPointer, index, pointer, value); } else { return replaceValue(styleMapOrValue, attribute, topPointer, index, pointer, value); } } } private <T> int deleteValue(Object styleMapOrValue, StyleAttribute<T> attribute, int topPointer, int index, int pointer) { assert !StyleAttributeMap.isStyleAttributeMapEmpty(topPointer, pointer, index); if (!(styleMapOrValue instanceof StyleAttributeMap)) { return set(attribute.getIndex(), topPointer, null); } else { StyleAttributeMap styleMap = (StyleAttributeMap) styleMapOrValue; styleMap.delete(pointer); if (styleMap.indexes.length == 1 && styleMap.indexes[0] == 0) { return set(attribute.getIndex(), topPointer, styleMap.values[0]); } if (styleMap.indexes.length == 0) { return set(attribute.getIndex(), topPointer, null); } return topPointer; } } private <T> int replaceValue(Object styleMapOrValue, StyleAttribute<T> attribute, int topPointer, int index, int pointer, Object value) { assert !StyleAttributeMap.isStyleAttributeMapEmpty(topPointer, pointer, index); if (!(styleMapOrValue instanceof StyleAttributeMap)) { assert index == 0; return set(attribute.getIndex(), topPointer, value); } else { StyleAttributeMap styleMap = (StyleAttributeMap) styleMapOrValue; styleMap.values[pointer] = value; return topPointer; } } private <T> int insertValue(Object styleMapOrValue, StyleAttribute<T> attribute, int topPointer, int index, int pointer, Object value) { assert StyleAttributeMap.isStyleAttributeMapEmpty(topPointer, pointer, index); if (!(styleMapOrValue instanceof StyleAttributeMap)) { if (index == 0) { return set(attribute.getIndex(), topPointer, value); } else { StyleAttributeMap<T> result = new StyleAttributeMap<T>(); result.setValue(index, value); if (!TopLevelStyleMap.isEmpty(topPointer)) { result.setValue(0, get(topPointer)); } return set(attribute.getIndex(), topPointer, result); } } else { StyleAttributeMap styleMap = (StyleAttributeMap) styleMapOrValue; styleMap.insert(index, pointer, value); return topPointer; } } public <T> Collection<IntPair<Object>> getAll(StyleAttribute<T> attribute) { int topPointer = this.search(attribute.getIndex()); return getAll(attribute, topPointer); } public <T> Collection<IntPair<Object>> getAll(StyleAttribute<T> attribute, int topPointer) { Object styleMapOrValue = get(topPointer); if (!(styleMapOrValue instanceof StyleAttributeMap)) { ArrayList<IntPair<Object>> result = new ArrayList<IntPair<Object>>(1); if (!TopLevelStyleMap.isEmpty(topPointer)) { result.add(new IntPair<Object>(0, get(topPointer))); } return result; } else { StyleAttributeMap<T> styleMap = (StyleAttributeMap<T>) styleMapOrValue; return styleMap.getAll(); } } public <T> Collection<IntPair<T>> getDiscardNullReplaced(StyleAttribute<T> attribute) { int topPointer = this.search(attribute.getIndex()); return getDiscardNullReplaced(attribute, topPointer); } public <T> Collection<IntPair<T>> getDiscardNullReplaced(StyleAttribute<T> attribute, int topPointer) { Object styleMapOrValue = get(topPointer); if (!(styleMapOrValue instanceof StyleAttributeMap)) { ArrayList<IntPair<T>> result = new ArrayList<IntPair<T>>(1); if (!TopLevelStyleMap.isEmpty(topPointer)) { result.add(new IntPair<T>(0, get(topPointer) instanceof DiscardValue ? null : (T) get(topPointer))); } return result; } else { StyleAttributeMap<T> styleMap = (StyleAttributeMap<T>) styleMapOrValue; return styleMap.getDiscardNullReplaced(); } } public <T> IntPair<T> getTopPair(StyleAttribute<T> attribute) { int topPointer = this.search(attribute.getIndex()); return getTopPair(attribute, topPointer); } public <T> IntPair<T> getTopPair(StyleAttribute<T> attribute, int topPointer) { Object styleMapOrValue = get(topPointer); if (!(styleMapOrValue instanceof StyleAttributeMap)) { if (TopLevelStyleMap.isEmpty(topPointer) || get(topPointer) instanceof DiscardValue) { return null; } else { return new IntPair<T>(0, (T) get(topPointer)); } } else { StyleAttributeMap styleMap = (StyleAttributeMap) styleMapOrValue; for (int i = styleMap.indexes.length - 1; i >= 0; i--) { if (!(styleMap.values[i] instanceof DiscardValue)) { return new IntPair<T>(styleMap.indexes[i], (T) styleMap.values[i]); } } return null; } } }