/*******************************************************************************
* Copyright (c) 2008, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.viewers;
/**
* A mutable string with styled ranges. All ranges mark substrings of the string
* and do not overlap. Styles are applied using instances of {@link Styler} to
* compute the result of {@link #getStyleRanges()}.
*
* The styled string can be built in the following two ways:
* <ul>
* <li>new strings with stylers can be appended</li>
* <li>stylers can by applied to ranges of the existing string</li>
* </ul>
*
* <p>
* This class may be instantiated; it is not intended to be subclassed.
* </p>
*
* @since 3.4
*/
public class StyledString {
public static abstract class Styler {
public abstract String applyStyles(String text);
}
public static Styler QUALIFIER_STYLER = new DefaultStyler("#FQN#");
public static Styler COUNTER_STYLER = new DefaultStyler("#COUNTER#");
private StringBuilder builder;
/** @param string */
public StyledString(String string) {
this();
builder.append(string);
}
/**
*
*/
public StyledString() {
builder = new StringBuilder();
}
/** @param cs */
public StyledString(char[] cs) {
this();
append(cs);
}
/**
* @param name
* @param styler
*/
public StyledString(String name, Styler styler) {
this();
append(name, styler);
}
/** @return */
public String getString() {
return builder.toString();
}
/** @param completion */
public StyledString append(char[] completion) {
builder.append(htmlEncode(new String(completion)));
return this;
}
/** @param c */
public StyledString append(char c) {
builder.append(c);
return this;
}
/** @param returnTypeSeparator */
public StyledString append(String returnTypeSeparator) {
builder.append(returnTypeSeparator);
return this;
}
/** @param qualifier */
public StyledString append(String qualifier, Styler styler) {
builder.append(styler.applyStyles(qualifier));
return this;
}
/** @param c */
public StyledString append(char c, Styler styler) {
builder.append(styler.applyStyles(String.valueOf(c)));
return this;
}
/** @param declaration */
public StyledString append(char[] declaration, Styler styler) {
builder.append(styler.applyStyles(new String(declaration)));
return this;
}
/**
* Inserts the character at the given offset. The inserted character will
* get the styler that is already at the given offset.
*
* @param ch
* the character to insert
* @param offset
* the insertion index
* @return returns a reference to this object
* @throws StringIndexOutOfBoundsException
* if <code>offset</code> is less than zero, or if <code>offset</code>
* is greater than the length of this object
* @since 3.5
*/
public StyledString insert(char ch, int offset) throws StringIndexOutOfBoundsException {
if (offset < 0 || offset > builder.length()) {
throw new StringIndexOutOfBoundsException(
"Invalid offset (" + offset + ")"); //$NON-NLS-1$//$NON-NLS-2$
}
// if (hasRuns()) {
// int runIndex = findRun(offset);
// if (runIndex < 0) {
// runIndex = -runIndex - 1;
// } else {
// runIndex = runIndex + 1;
// }
// StyleRunList styleRuns = getStyleRuns();
// final int size = styleRuns.size();
// for (int i = runIndex; i < size; i++) {
// StyleRun run = styleRuns.getRun(i);
// run.offset++;
// }
// }
builder.insert(offset, ch);
return this;
}
/**
* Appends a string with styles to the {@link StyledString}.
*
* @param string
* the string to append
* @return returns a reference to this object
*/
public StyledString append(StyledString string) {
if (string.length() == 0) {
return this;
}
// int offset = fBuffer.length();
builder.append(string.toString());
// List otherRuns = string.fStyleRuns;
// if (otherRuns != null && !otherRuns.isEmpty()) {
// for (int i = 0; i < otherRuns.size(); i++) {
// StyleRun curr = (StyleRun) otherRuns.get(i);
// if (i == 0 && curr.offset != 0) {
// appendStyleRun(null, offset); // appended string will
// // start with the default
// // color
// }
// appendStyleRun(curr.style, offset + curr.offset);
// }
// } else {
// appendStyleRun(null, offset); // appended string will start with
// // the default color
// }
return this;
}
/**
* Sets a styler to use for the given source range. The range must be
* subrange of actual string of this {@link StyledString}. Stylers
* previously set for that range will be overwritten.
*
* @param offset
* the start offset of the range
* @param length
* the length of the range
* @param styler
* the styler to set
*
* @throws StringIndexOutOfBoundsException
* if <code>start</code> is less than zero, or if offset plus
* length is greater than the length of this object.
*/
public void setStyle(int offset, int length, Styler styler) throws StringIndexOutOfBoundsException {
builder.replace(offset, offset + length, styler.applyStyles(builder.substring(offset, offset + length)));
}
/**
* Returns the length of the string of this {@link StyledString}.
*
* @return the length of the current string
*/
public int length() {
return builder.length();
}
/**
* HTML-encode a string. This simple method only replaces the five characters &, <, >, ", and '.
*
* @param input
* the String to convert
* @return a new String with HTML encoded characters
*/
public static String htmlEncode(String input) {
String output = input.replaceAll("&", "&");
output = output.replaceAll("<", "<");
output = output.replaceAll(">", ">");
output = output.replaceAll("\"", """);
output = output.replaceAll("'", "'");
return output;
}
}