/* * Jitsi, the OpenSource Java VoIP and Instant Messaging client. * * Copyright @ 2015 Atlassian Pty Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package net.java.sip.communicator.impl.protocol.irc; import java.util.*; /** * Builder for constructing a formatted text. * * @author Danny van Heumen */ public class FormattedTextBuilder { /** * stack with formatting control chars. */ private final Stack<ControlChar> formatting = new Stack<ControlChar>(); /** * formatted text container. */ private final StringBuilder text = new StringBuilder(); /** * Append a string of text. * * Make sure that the text is safe for your purposes, as it is appended * without further modifications. * * @param text string of text */ public void append(final String text) { this.text.append(text); } /** * Append a character. * * Make sure that the character is safe for your purposes, as it is appended * without further modifications. * * @param c character */ public void append(final char c) { this.text.append(c); } /** * Apply a control char for formatting. * * @param c the control char */ public void apply(final ControlChar c) { // start control char formatting this.formatting.add(c); this.text.append(c.getHtmlStart()); } /** * Test whether or not a control character is already active. * * @param controlClass the class of control char * @return returns true if control char's class of formatting is active, or * false otherwise. */ public boolean isActive(final Class<? extends ControlChar> controlClass) { for (ControlChar c : this.formatting) { if (c.getClass() == controlClass) { return true; } } return false; } /** * Cancel the active control char of the specified class. * * @param controlClass the class of control char * @param stopAfterFirst stop after the first occurrence */ public void cancel(final Class<? extends ControlChar> controlClass, final boolean stopAfterFirst) { final Stack<ControlChar> rewind = new Stack<ControlChar>(); while (!this.formatting.empty()) { // unwind control chars looking for the cancelled control char ControlChar current = this.formatting.pop(); this.text.append(current.getHtmlEnd()); if (current.getClass() == controlClass) { if (stopAfterFirst) { break; } } else { rewind.push(current); } } while (!rewind.empty()) { // reapply remaining control characters ControlChar current = rewind.pop(); apply(current); } } /** * Cancel all active formatting. */ public void cancelAll() { while (!this.formatting.empty()) { ControlChar c = this.formatting.pop(); this.text.append(c.getHtmlEnd()); } } /** * Finish building the text string. Close outstanding control char * formatting and returns the result. * * @return returns the complete string as it is built */ public String done() { cancelAll(); return this.text.toString(); } /** * Return the formatted string in its current state. (This means that if * {@link #done()} was not yet called, it will print an intermediate state * of the formatted text.) * * @return returns current state of the formatted text */ public String toString() { return this.text.toString(); } }