StyledString.java
package swingtree.style;
import org.jspecify.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import swingtree.SwingTree;
import swingtree.api.Configurator;
import swingtree.api.Styler;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Function;
/**
* A {@link StyledString} is a uniformly styled snippet of text which is typically part of a sequence
* of styled strings that together make up a visually rich text in the <i>SwingTree</i> style API.
* More specifically, you can pass instances of this to {@link TextConf#content(StyledString...)}
* as part of a {@link ComponentStyleDelegate#text(Configurator)} sub-style configuration.<br>
* This class has value semantics and is immutable, so any potential {@link Configurator} referenced
* by an instance of this class is expected to be a pure function that produces the same output
* given the same input and has no side effects. <br>
*
* @see swingtree.UIForAnySwing#withStyle(Styler)
* @see ComponentStyleDelegate#text(Configurator)
* @see TextConf#content(StyledString...)
* @see FontConf
*/
public final class StyledString {
private static final Logger log = LoggerFactory.getLogger(StyledString.class);
/**
* Creates a styled string with the given string but no style information.<br>
* The style of the string will be inherited from the context in which it is used within the style engine. <br>
* @param string The string content of the styled string. It must not be null.
* @return A new styled string with the given string and no style information.
* @throws NullPointerException if the given string is null.
*/
public static StyledString of( String string ) {
return new StyledString(string, (Object) null);
}
/**
* Creates a styled string with the given string and style information provided by the given font {@link Configurator}.<br>
* The font configurator takes in an inherited {@link FontConf} and produces a new {@link FontConf}
* derived to hold the desired style information for the string.
* @param fontConfigurator A configurator that takes in an inherited {@link FontConf} and produces a new {@link FontConf}
* derived to hold the desired style information for the string. It must not be null and
* <b>must be a pure function</b> that produces the same output given the same input and has no side effects.
* @param string The string content of the styled string. It must not be null.
* @return A new styled string with the given string and style information provided by the given font configurator.
* @throws NullPointerException if the given string or font configurator is null.
*/
public static StyledString of( Configurator<FontConf> fontConfigurator, String string ) {
return new StyledString(string, fontConfigurator);
}
private final String _string;
private final @Nullable Object _configuratorOrFontConf;
private StyledString(String string, Configurator<FontConf> fontConfigurator) {
this(Objects.requireNonNull(string), (Object) Objects.requireNonNull(fontConfigurator));
}
private StyledString(String string, FontConf fontConf) {
this(Objects.requireNonNull(string), (Object) Objects.requireNonNull(fontConf));
}
private StyledString(String string, @Nullable Object fontConfigurator) {
_string = Objects.requireNonNull(string);
_configuratorOrFontConf = fontConfigurator;
}
/**
* Returns the string content of this styled string.
* This is the actual text that will be rendered when this styled string is used in a style configuration. <br>
* @return The string content of this styled string. It is guaranteed to be non-null.
*/
public String string() {
return _string;
}
/**
* Returns a new styled string with the same style information as this styled string but with a new string content. <br>
* This is useful for when you want to reuse the same style information for different string content. <br>
* @param string The new string content for the styled string. It must not be null.
* @return A new styled string with the same style information as this styled string but with the given string content.
* @throws NullPointerException if the given string is null.
*/
public StyledString withString(String string) {
return new StyledString(string, _configuratorOrFontConf);
}
StyledString mapStyle( Function<FontConf, FontConf> mapper ) {
if ( _configuratorOrFontConf instanceof FontConf ) {
try {
FontConf newConf = mapper.apply((FontConf) _configuratorOrFontConf);
return new StyledString(_string, newConf);
} catch (Exception e) {
log.error(SwingTree.get().logMarker(), "Error mapping font conf for string '{}'", _string, e);
}
}
return this;
}
Optional<FontConf> fontConf() {
if ( _configuratorOrFontConf instanceof FontConf ) {
return Optional.of( (FontConf) _configuratorOrFontConf );
}
return Optional.empty();
}
StyledString resolveUsing(FontConf startConf) {
if ( _configuratorOrFontConf instanceof Configurator ) {
// We run the start conf through the configurator to get the new conf:
Configurator<FontConf> configurator = (Configurator<FontConf>) _configuratorOrFontConf;
try {
FontConf newConf = configurator.configure(startConf);
return new StyledString(_string, newConf);
} catch (Exception e) {
log.error(SwingTree.get().logMarker(), "Error configuring font conf for string '{}'", _string, e);
}
}
return this;
}
@Override
public String toString() {
return "StyledString[" +
"string='" + _string + "', " +
"style=" + (_configuratorOrFontConf == null ? "?" : String.valueOf(_configuratorOrFontConf)) +
"]";
}
@Override
public boolean equals(Object o) {
if ( this == o )
return true;
if ( o == null || getClass() != o.getClass() )
return false;
StyledString that = (StyledString) o;
return _string.equals(that._string) && Objects.equals(_configuratorOrFontConf, that._configuratorOrFontConf);
}
@Override
public int hashCode() {
return Objects.hash(_string, _configuratorOrFontConf);
}
}