com.github.czyzby.lml.util.LmlParserBuilder Maven / Gradle / Ivy
package com.github.czyzby.lml.util;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Preferences;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TooltipManager;
import com.badlogic.gdx.utils.I18NBundle;
import com.github.czyzby.kiwi.util.gdx.reflection.Reflection;
import com.github.czyzby.lml.annotation.processor.OnChangeProcessor;
import com.github.czyzby.lml.parser.LmlData;
import com.github.czyzby.lml.parser.LmlParser;
import com.github.czyzby.lml.parser.LmlSyntax;
import com.github.czyzby.lml.parser.LmlTemplateReader;
import com.github.czyzby.lml.parser.action.ActionContainer;
import com.github.czyzby.lml.parser.action.ActorConsumer;
import com.github.czyzby.lml.parser.impl.AbstractLmlParser;
import com.github.czyzby.lml.parser.impl.DefaultLmlData;
import com.github.czyzby.lml.parser.impl.DefaultLmlParser;
import com.github.czyzby.lml.parser.tag.LmlAttribute;
import com.github.czyzby.lml.parser.tag.LmlTag;
import com.github.czyzby.lml.parser.tag.LmlTagProvider;
/** Simplifies construction of {@code LmlParser} by initiating an instance of {@link DefaultLmlParser}. Note that
* {@link LmlParserBuilder#build()} method returns an instance of parser that is actually created in builder's
* constructor - calling building method multiple times always returns the same parser instance. In a sense, this
* builder is more of a "preference setter" rather than "complex object constructor".
*
* @author MJ */
public class LmlParserBuilder {
private final AbstractLmlParser parser;
/** Constructs a new builder that wraps around an instance of {@link DefaultLmlParser}. */
public LmlParserBuilder() {
this(new DefaultLmlData());
}
/** Constructs a new builder that wraps around an instance of {@link DefaultLmlParser}.
*
* @param lmlData stores data needed to properly parse LML templates. */
public LmlParserBuilder(final LmlData lmlData) {
parser = getInstanceOfParser(lmlData);
}
/** @param lmlData contains LML parsing data.
* @return a new instance of an extension of {@link AbstractLmlParser}. */
protected AbstractLmlParser getInstanceOfParser(final LmlData lmlData) {
return new DefaultLmlParser(lmlData);
}
/** @param defaultSkin will be set as the default {@link Skin} instance used when no ID is specified.
* @return this for chaining. */
public LmlParserBuilder skin(final Skin defaultSkin) {
parser.getData().setDefaultSkin(defaultSkin);
return this;
}
/** @param id will register value under this ID (ignoring case).
* @param skin will be available in LML templates through the chosen ID.
* @return this for chaining. */
public LmlParserBuilder skin(final String id, final Skin skin) {
parser.getData().addSkin(id, skin);
return this;
}
/** @param tag all tags with this name (case ignored) will have the attribute applied.
* @param attribute name of the attribute.
* @param defaultValue default value of the attribute, used if attribute is not already set in the tag.
* @return this for chaining. */
public LmlParserBuilder style(final String tag, final String attribute, final String defaultValue) {
parser.getStyleSheet().addStyle(tag, attribute, defaultValue);
return this;
}
/** @param styleSheetPath LML style sheet data file.
* @return this for chaining. */
public LmlParserBuilder styles(final FileHandle styleSheetPath) {
parser.parseStyleSheet(styleSheetPath);
return this;
}
/** @param styleSheetPath path to internal file storing LML style sheet data.
* @return this for chaining. */
public LmlParserBuilder stylesPath(final String styleSheetPath) {
parser.parseStyleSheet(Gdx.files.internal(styleSheetPath));
return this;
}
/** @param defaultPreferences will be set as the default {@link Preferences} instance used when no ID is specified.
* @return this for chaining. */
public LmlParserBuilder preferences(final Preferences defaultPreferences) {
parser.getData().setDefaultPreferences(defaultPreferences);
return this;
}
/** @param id will register value under this ID (ignoring case).
* @param preferences will be available in LML templates through the chosen ID.
* @return this for chaining. */
public LmlParserBuilder preferences(final String id, final Preferences preferences) {
parser.getData().addPreferences(id, preferences);
return this;
}
/** @param defaultI18nBundle will be set as the default {@link I18NBundle} instance used when no ID is specified.
* @return this for chaining. */
public LmlParserBuilder i18nBundle(final I18NBundle defaultI18nBundle) {
parser.getData().setDefaultI18nBundle(defaultI18nBundle);
return this;
}
/** @param id will register value under this ID (ignoring case).
* @param i18nBundle will be available in LML templates through the chosen ID.
* @return this for chaining. */
public LmlParserBuilder i18nBundle(final String id, final I18NBundle i18nBundle) {
parser.getData().addI18nBundle(id, i18nBundle);
return this;
}
/** @param defaultTooltipManager will be set as the default {@link TooltipManager} instance used when no ID is
* specified.
* @return this for chaining. */
public LmlParserBuilder tooltipManager(final TooltipManager defaultTooltipManager) {
parser.getData().setDefaultTooltipManager(defaultTooltipManager);
return this;
}
/** @param id will register value under this ID (ignoring case).
* @param tooltipManager will be available in LML templates through the chosen ID.
* @return this for chaining. */
public LmlParserBuilder tooltipManager(final String id, final TooltipManager tooltipManager) {
parser.getData().addTooltipManager(id, tooltipManager);
return this;
}
/** @param id name of the argument, as it will be available in LML templates.
* @param argument will be converted to string according to its type. Object arrays and iterables are automatically
* converted to LML arrays.
* @return this for chaining.
* @see LmlUtilities#toAction(String)
* @see LmlUtilities#toAction(String, String)
* @see LmlUtilities#toArrayArgument(Iterable)
* @see LmlUtilities#toArrayArgument(Object...)
* @see LmlUtilities#toBundleLine(String)
* @see LmlUtilities#toBundleLine(String, String)
* @see LmlUtilities#toPreference(String)
* @see LmlUtilities#toPreference(String, String)
* @see LmlUtilities#toRangeArrayArgument(Object, int, int) */
public LmlParserBuilder argument(final String id, final Object argument) {
parser.getData().addArgument(id, argument);
return this;
}
/** @param id ID of the action as available in LML views. If the passed ID collides with a name of registered
* {@link ActionContainer} method, {@link ActorConsumer} takes priority.
* @param action can consume one argument (usually an actor or a string) and return a value. If a method with the
* specified ID appears in a LML template, this action will be found and invoked (or attached as a
* listener, or used otherwise). {@link ActorConsumer} does not rely on reflection, so might be somewhat
* noticeably faster on some devices, but usually the overhead is very small as opposed to using
* reflection-based actions.
* @return this for chaining.
* @see #actions(String, ActionContainer) */
public LmlParserBuilder action(final String id, final ActorConsumer, ?> action) {
parser.getData().addActorConsumer(id, action);
return this;
}
/** @param id ID of the action container, that can be optionally added to method invocations in LML templates. ID
* has to be present only if there are method name collisions, otherwise undetermined method will be
* chosen.
* @param actionContainer its one-arg and no-arg methods will be available as actions in LML templates. This uses
* reflection, so action containers should be properly included in GWT reflection pool.
* @return this for chaining.
* @see com.github.czyzby.lml.annotation.LmlAction */
public LmlParserBuilder actions(final String id, final ActionContainer actionContainer) {
parser.getData().addActionContainer(id, actionContainer);
return this;
}
/** @param id ID of the action container, that can be optionally added to method invocations in LML templates. ID
* has to be present only if there are method name collisions, otherwise undetermined method will be
* chosen.
* @param actionContainerClass initiated with no-arg constructor using reflection. Its one-arg and no-arg methods
* will be available as actions in LML templates. This uses reflection, so action containers should be
* properly included in GWT reflection pool.
* @return this for chaining.
* @see com.github.czyzby.lml.annotation.LmlAction */
public LmlParserBuilder actions(final String id, final Class extends ActionContainer> actionContainerClass) {
return actions(id, Reflection.newInstance(actionContainerClass));
}
/** @param processor can process attributes of specified actor base class. Every object of handled class (or class
* that extends it) will be able to parse the attribute using this processor.
* @param names aliases of the attribute, as available in LML templates.
* @return this for chaining.
* @see LmlAttribute
* @see com.github.czyzby.lml.parser.impl.tag.macro.NewAttributeLmlMacroTag */
public LmlParserBuilder attribute(final LmlAttribute extends Actor> processor, final String... names) {
parser.getSyntax().addAttributeProcessor(processor, names);
return this;
}
/** @param tagProvider creates instances of {@link LmlTag}. {@link LmlTagProvider} is basically a simple functional
* interface - it's the LmlTag implementation that manages the actor. The constructed LmlTag instances
* usually handle a single actor at a time.
* @param names aliases of the tag, as available in LML templates.
* @return this for chaining.
* @see LmlTag
* @see com.github.czyzby.lml.parser.impl.tag.AbstractActorLmlTag
* @see com.github.czyzby.lml.parser.impl.tag.macro.NewTagLmlMacroTag */
public LmlParserBuilder tag(final LmlTagProvider tagProvider, final String... names) {
parser.getSyntax().addTagProvider(tagProvider, names);
return this;
}
/** @param macroTagProvider creates instances of {@link LmlTag}. {@link LmlTagProvider} is basically a simple
* functional interface - it's the LmlTag implementation that manages the macro. Macro tags manage text
* between their tags, allowing to modify template's structure.
* @param names aliases of the macro, as available in LML templates.
* @return this for chaining.
* @see LmlTag
* @see com.github.czyzby.lml.parser.impl.tag.AbstractMacroLmlTag
* @see com.github.czyzby.lml.parser.impl.tag.macro.MetaLmlMacroTag */
public LmlParserBuilder macro(final LmlTagProvider macroTagProvider, final String... names) {
parser.getSyntax().addMacroTagProvider(macroTagProvider, names);
return this;
}
/** @param processor updates a field through reflection when a specified actor changes its state.
* @return this for chaining.
* @see OnChangeProcessor
* @see com.github.czyzby.lml.parser.impl.annotation.processor.AbstractOnChangeProcessor */
public LmlParserBuilder onChangeProcessor(final OnChangeProcessor processor) {
parser.getData().addOnChangeProcessor(processor);
return this;
}
/** @param strict if false, some template syntax errors will be ignored. Useful for prototyping or planning and
* checking unfinished views
* @return this for chaining. */
public LmlParserBuilder strict(final boolean strict) {
parser.setStrict(strict);
return this;
}
/** @param nested if true, regular comments can be nested - basically, comments can contain comments, which isn't
* normal HTML behavior. This, however, forces you to keep your comments valid even when they are
* "commented out" (otherwise parser doesn't know when to exit from nested comments), so comment macros
* are generally preferred to using nested comments.
* @return this for chaining. */
public LmlParserBuilder nestedComments(final boolean nested) {
parser.setNestedComments(nested);
return this;
}
/** @param amount amount of lines (included in exception message) before and after the line that caused the error.
* Cannot be negative.
* @return this for chaining. */
public LmlParserBuilder debugLinesOnException(final int amount) {
parser.setLinesAmountPrintedOnException(amount);
return this;
}
/** @param reader determines how LML templates are read. Do not modify unless you are sure what you're doing.
* @return this for chaining.
* @see com.github.czyzby.lml.parser.impl.DefaultLmlTemplateReader */
public LmlParserBuilder templateReader(final LmlTemplateReader reader) {
parser.setTemplateReader(reader);
return this;
}
/** @param syntax contains the operators, markers, tags, attributes and macros that are parsed and handled by LML
* parser. Make sure to register your custom data with {@link #attribute(LmlAttribute, String...)},
* {@link #tag(LmlTagProvider, String...)} and {@link #macro(LmlTagProvider, String...)} after invoking
* this method, otherwise changes will take places in the previous syntax.
* @return this for chaining.
* @see com.github.czyzby.lml.parser.impl.DefaultLmlSyntax */
public LmlParserBuilder syntax(final LmlSyntax syntax) {
parser.setSyntax(syntax);
return this;
}
/** @return an instance of {@link LmlParser}. Each builder returns the same instance of each call of this method, so
* if you need multiple parsers for any reason, use a separate builder to construct it.
* @see LmlParser#parseTemplate(String)
* @see LmlParser#parseTemplate(com.badlogic.gdx.files.FileHandle)
* @see LmlParser#fillStage(com.badlogic.gdx.scenes.scene2d.Stage, String)
* @see LmlParser#fillStage(com.badlogic.gdx.scenes.scene2d.Stage, com.badlogic.gdx.files.FileHandle)
* @see LmlParser#createView(Class, String)
* @see LmlParser#createView(Object, String)
* @see LmlParser#createView(Class, com.badlogic.gdx.files.FileHandle)
* @see LmlParser#createView(Object, com.badlogic.gdx.files.FileHandle) */
public LmlParser build() {
return parser;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy