package com.github.czyzby.lml.parser.impl.tag.macro; import com.badlogic.gdx.utils.ObjectMap; import com.github.czyzby.kiwi.util.common.Strings; import com.github.czyzby.kiwi.util.gdx.collection.GdxArrays; import com.github.czyzby.kiwi.util.gdx.collection.GdxMaps; import com.github.czyzby.lml.parser.LmlParser; import com.github.czyzby.lml.parser.LmlStyleSheet; import com.github.czyzby.lml.parser.impl.tag.AbstractMacroLmlTag; import com.github.czyzby.lml.parser.tag.LmlTag; /** Allows to add styles to LML style sheet at runtime. Assigns default attribute values to the chosen tags. Expects at * least 2 arguments: tag and attribute names. Default attribute value can be passed with either third argument or data * between macro tags. Both tags and attributes arguments accept arrays, so multiple tags or attributes can be modified * at once. For example: <blockquote> * * <pre> * <:style button tablePad 3 /> * <:style button tablePad>3</:style button tablePad> * </pre> * * </blockquote>Both of these macro invocations would assign "3" as default value of "tablePad" attribute in all * "button" tags. * <p> * Note that this macro supports optional named attributes: <blockquote> * * <pre> * <:style tag="button" attribute="tablePad" value="3" /> * <:style tag="button" attribute="tablePad">3</:style button tablePad> * </pre> * * </blockquote>To modify multiple tags or attributes at once, separate their names with ';' (by default) to create a * LML array: <blockquote> * * <pre> * <:style tag="button;textButton" attribute="tablePadLeft;tablePadRight" value="3" /> * </pre> * * </blockquote> * * @author MJ * @see LmlParser#getStyleSheet() */ public class StyleLmlMacroTag extends AbstractMacroLmlTag { /** Optional name of the first attribute: name of the tag to modify. */ public static final String TAG_ATTRIBUTE = "tag"; /** Optional name of the second attribute: name of the attribute to set. */ public static final String ATTRIBUTE_ATTRIBUTE = "attribute"; /** Optional name of the third attribute: default value of the attribute. */ public static final String VALUE_ATTRIBUTE = "value"; private String content; public StyleLmlMacroTag(final LmlParser parser, final LmlTag parentTag, final StringBuilder rawTagData) { super(parser, parentTag, rawTagData); } @Override public void handleDataBetweenTags(final CharSequence rawData) { if (Strings.isNotWhitespace(rawData)) { content = rawData.toString(); } } @Override public void closeTag() { if (GdxArrays.sizeOf(getAttributes()) < 2) { getParser().throwErrorIfStrict("Style macro needs at least 2 attributes: tag and attribute names."); return; } final String[] tagNames = getTagNames(); final String[] attributeNames = getAttributeNames(); final String defaultValue = getDefaultValueArgument(); if (tagNames == null || tagNames.length == 0 || attributeNames == null || attributeNames.length == 0 || defaultValue == null) { getParser().throwErrorIfStrict( "Style macro needs at least 2 arguments: tag and attribute names. Default attribute value can be set with third argument or data between macro tags. All 3 values are required."); return; } final LmlStyleSheet styleSheet = getParser().getStyleSheet(); for (final String tag : tagNames) { for (final String attribute : attributeNames) { styleSheet.addStyle(tag, attribute, defaultValue); } } } /** @return names of the modified tags extracted from attributes parsed as array. Assumes there is at least 1 * attribute. */ protected String[] getTagNames() { final String tagNames = getTagNameArgument(); return tagNames == null ? null : getParser().parseArray(tagNames, getActor()); } /** @return name of the set attribute extracted from attributes parsed as array. Assumes there are at least 2 macro * attributes. */ private String[] getAttributeNames() { final String attributeNames = getAttributeNameArgument(); return attributeNames == null ? null : getParser().parseArray(attributeNames, getActor()); } /** @return raw data of names of the modified tags extracted from attributes. Assumes there is at least 1 * attribute. */ protected String getTagNameArgument() { final ObjectMap<String, String> attributes = getNamedAttributes(); if (GdxMaps.isNotEmpty(attributes)) { return attributes.get(TAG_ATTRIBUTE); } return getAttributes().first(); } /** @return raw data of names of the set attributes extracted from arguments. Assumes there are at least 2 macro * attributes. */ protected String getAttributeNameArgument() { final ObjectMap<String, String> attributes = getNamedAttributes(); if (GdxMaps.isNotEmpty(attributes)) { return attributes.get(ATTRIBUTE_ATTRIBUTE); } return getAttributes().get(1); } /** @return default value of the set attribute extracted from attributes or tag content. */ protected String getDefaultValueArgument() { if (content != null) { return content; } final ObjectMap<String, String> attributes = getNamedAttributes(); if (GdxMaps.isNotEmpty(attributes)) { return attributes.get(VALUE_ATTRIBUTE); } if (GdxArrays.sizeOf(getAttributes()) >= 3) { return getAttributes().get(2); } return null; } @Override public String[] getExpectedAttributes() { return new String[] { TAG_ATTRIBUTE, ATTRIBUTE_ATTRIBUTE, VALUE_ATTRIBUTE }; } }