com.alee.extended.label.StyleRanges Maven / Gradle / Ivy
/*
* This file is part of WebLookAndFeel library.
*
* WebLookAndFeel library is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* WebLookAndFeel library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with WebLookAndFeel library. If not, see .
*/
package com.alee.extended.label;
import com.alee.api.annotations.NotNull;
import com.alee.api.annotations.Nullable;
import com.alee.utils.TextUtils;
import java.util.ArrayList;
import java.util.List;
/**
* Base implementation of style ranges.
* It provides a convenient way of parsing text with custom style syntax.
* Plain text is kept within {@link #styledText} field and styles list is kept within {@link #styleRanges} field.
* Supported syntax settings depend on the {@link IStyleSettings} implementation used.
*
* @author Mikle Garin
* @see How to use WebStyledLabel
* @see IStyleSettings
*/
public class StyleRanges implements IStyleRanges
{
/**
* todo 1. Add multi-level styling support (sub-styles)
*/
/**
* Text containing style syntax.
*/
@Nullable
protected final String styledText;
/**
* Cached plain text extracted from {@link #styledText}.
*/
@Nullable
protected String plainText;
/**
* Cached style ranges extracted from {@link #styledText}.
*/
@Nullable
protected List styleRanges;
/**
* Constructs new style ranges.
*
* @param styledText text containing style syntax
*/
public StyleRanges ( @Nullable final String styledText )
{
this.styledText = styledText;
}
@Nullable
@Override
public String getPlainText ()
{
return parseStyledText ().plainText;
}
@NotNull
@Override
public List getStyleRanges ()
{
final List styleRanges = parseStyledText ().styleRanges;
if ( styleRanges == null )
{
throw new RuntimeException ( "Unable to parse style ranges for text: " + styledText );
}
return styleRanges;
}
/**
* Parses text containing style syntax.
* As a result {@link #plainText} and {@link #styleRanges} fields will be filled-in.
*
* @return resulting {@link StyleRanges}
*/
@NotNull
protected StyleRanges parseStyledText ()
{
// Parse only if it is needed and it wasn't already completed
if ( styleRanges == null )
{
styleRanges = new ArrayList ();
if ( TextUtils.notEmpty ( styledText ) )
{
int begin = nextUnescaped ( styledText, "{", 0 );
if ( begin != -1 )
{
plainText = "";
String trimmedText = styledText;
while ( begin != -1 )
{
final int end = nextUnescaped ( trimmedText, "}", begin + 1 );
if ( end != -1 )
{
// Clipping statement
final String statement = trimmedText.substring ( begin + 1, end );
if ( statement.equals ( "br" ) )
{
// Adding linebreak and proceeding
plainText += trimmedText.substring ( 0, begin ) + "\n";
}
else
{
// Parsing possible style syntax
final TextRange range = parseStatement ( plainText.length () + begin, statement );
if ( range != null && range.getStyleRange () != null )
{
// Adding text and style range
plainText += trimmedText.substring ( 0, begin ) + range.getText ();
styleRanges.add ( range.getStyleRange () );
}
else
{
// Adding plain text
plainText += trimmedText.substring ( 0, begin ) + statement;
}
}
// Continue to next
trimmedText = trimmedText.substring ( end + 1 );
begin = nextUnescaped ( trimmedText, "{", 0 );
}
else
{
// Something wrong with the syntax
// Abort parsing and add the rest as plain text
break;
}
}
plainText += trimmedText;
}
else
{
plainText = styledText;
}
}
else
{
plainText = null;
}
}
return this;
}
/**
* Returns next unescaped text that fits specified pattern.
*
* @param text text to look for the pattern in
* @param pattern pattern to find
* @param from starting search index
* @return next unescaped text that fits specified pattern
*/
protected int nextUnescaped ( @NotNull final String text, @NotNull final String pattern, final int from )
{
// todo Enhance this syntax with an escape recognition, probably an "\\" one
return text.indexOf ( pattern, from );
}
/**
* Returns {@link TextRange} parsed from statement.
*
* @param startIndex {@link StyleRange} start index
* @param statement {@link String} statement
* @return {@link TextRange} parsed from statement
*/
@Nullable
protected TextRange parseStatement ( final int startIndex, @NotNull final String statement )
{
TextRange textRange = null;
try
{
// Looking for the settings separator
final int sep = statement.lastIndexOf ( ":" );
if ( sep != -1 )
{
// Parsing style range
final String text = statement.substring ( 0, sep );
final String settings = statement.substring ( sep + 1 );
final IStyleSettings styleSettings = getStyleSettings ( startIndex, text.length (), settings );
final StyleRange styleRange = styleSettings.getStyleRange ();
if ( styleRange != null )
{
textRange = new TextRange ( text, styleRange );
}
}
}
catch ( final Exception ignored )
{
// Ignoring any exceptions in style parsing
}
return textRange;
}
/**
* Returns {@link IStyleSettings} implementation which will resolve style settings.
*
* @param startIndex {@link StyleRange} start index
* @param length {@link StyleRange} length
* @param settings {@link String} style settings
* @return {@link IStyleSettings} implementation which will resolve style settings
*/
@NotNull
protected IStyleSettings getStyleSettings ( final int startIndex, final int length, @NotNull final String settings )
{
return new StyleSettings ( startIndex, length, settings );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy