Package com.ardor3d.extension.ui.text.parser

Source Code of com.ardor3d.extension.ui.text.parser.ForumLikeMarkupParser

/**
* Copyright (c) 2008-2012 Ardor Labs, Inc.
*
* This file is part of Ardor3D.
*
* Ardor3D is free software: you can redistribute it and/or modify it
* under the terms of its license which may be found in the accompanying
* LICENSE file or at <http://www.ardor3d.com/LICENSE>.
*/

package com.ardor3d.extension.ui.text.parser;

import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.StringTokenizer;

import com.ardor3d.extension.ui.text.StyleConstants;
import com.ardor3d.extension.ui.text.StyleSpan;
import com.ardor3d.math.ColorRGBA;
import com.ardor3d.math.type.ReadOnlyColorRGBA;
import com.google.common.collect.Lists;

public class ForumLikeMarkupParser implements StyleParser {

    Comparator<StyleSpan> endSorter = new Comparator<StyleSpan>() {
        public int compare(final StyleSpan o1, final StyleSpan o2) {
            return o1.getSpanStart() + o1.getSpanLength() - (o2.getSpanStart() + o2.getSpanLength());
        }
    };

    @Override
    public String parseStyleSpans(final String text, final List<StyleSpan> store) {
        final StringBuilder rVal = new StringBuilder("");
        int index = 0;
        TagStatus tagStatus = TagStatus.NONE;
        String currTagText = "";
        final LinkedList<StyleSpan> buildingSpans = Lists.newLinkedList();
        final StringTokenizer st = new StringTokenizer(text, "[]\\", true);
        String token;
        while (st.hasMoreTokens()) {
            token = st.nextToken();
            // escape char
            if (tagStatus == TagStatus.NONE && "\\".equals(token)) {
                if (st.hasMoreTokens()) {
                    token = st.nextToken();
                    if ("[".equals(token) || "]".equals(token)) {
                        rVal.append(token);
                        index++;
                        continue;
                    } else {
                        rVal.append('\\');
                        rVal.append(token);
                        index += token.length() + 1;
                        continue;
                    }
                } else {
                    rVal.append('\\');
                    index++;
                    continue;
                }
            }

            // start token
            else if (tagStatus == TagStatus.NONE && "[".equals(token)) {
                tagStatus = TagStatus.START_TAG;
                continue;
            }

            else if (tagStatus == TagStatus.START_TAG) {
                currTagText = token;
                tagStatus = TagStatus.IN_TAG;
                continue;
            }

            // end token
            else if (tagStatus == TagStatus.IN_TAG && "]".equals(token)) {
                tagStatus = TagStatus.NONE;
                // interpret tag:
                // BOLD
                if ("b".equalsIgnoreCase(currTagText)) {
                    // start a new bold span
                    buildingSpans.add(new StyleSpan(StyleConstants.KEY_BOLD, Boolean.TRUE, index, 0));
                } else if ("/b".equalsIgnoreCase(currTagText)) {
                    // find last BOLD entry and add length
                    endSpan(StyleConstants.KEY_BOLD, store, index, buildingSpans);
                }

                // ITALICS
                else if ("i".equalsIgnoreCase(currTagText)) {
                    // start a new italics span
                    buildingSpans.add(new StyleSpan(StyleConstants.KEY_ITALICS, Boolean.TRUE, index, 0));
                } else if ("/i".equalsIgnoreCase(currTagText)) {
                    // find last ITALICS entry and add length
                    endSpan(StyleConstants.KEY_ITALICS, store, index, buildingSpans);
                }

                // COLOR
                else if (currTagText.toLowerCase().startsWith("c=")) {
                    // start a new color span
                    try {
                        // parse a color
                        final String c = currTagText.substring(2);
                        buildingSpans.add(new StyleSpan(StyleConstants.KEY_COLOR, ColorRGBA.parseColor(c, null), index,
                                0));
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                } else if ("/c".equalsIgnoreCase(currTagText)) {
                    // find last BOLD entry and add length
                    endSpan(StyleConstants.KEY_COLOR, store, index, buildingSpans);
                }

                // SIZE
                else if (currTagText.toLowerCase().startsWith("size=")) {
                    // start a new size span
                    try {
                        // parse a size
                        final int i = Integer.parseInt(currTagText.substring(5));
                        buildingSpans.add(new StyleSpan(StyleConstants.KEY_SIZE, i, index, 0));
                    } catch (final Exception e) {
                        e.printStackTrace();
                    }
                } else if ("/size".equalsIgnoreCase(currTagText)) {
                    // find last SIZE entry and add length
                    endSpan(StyleConstants.KEY_SIZE, store, index, buildingSpans);
                }

                // FAMILY
                else if (currTagText.toLowerCase().startsWith("f=")) {
                    // start a new family span
                    final String family = currTagText.substring(2);
                    buildingSpans.add(new StyleSpan(StyleConstants.KEY_FAMILY, family, index, 0));
                } else if ("/f".equalsIgnoreCase(currTagText)) {
                    // find last FAMILY entry and add length
                    endSpan(StyleConstants.KEY_FAMILY, store, index, buildingSpans);
                } else {
                    // not really a tag, so put it back.
                    rVal.append('[');
                    rVal.append(currTagText);
                    rVal.append(']');
                    tagStatus = TagStatus.NONE;
                }

                currTagText = "";
                continue;
            }

            // anything else
            rVal.append(token);
            index += token.length();
        }

        // close any remaining open tags
        while (!buildingSpans.isEmpty()) {
            final StyleSpan span = buildingSpans.getLast();
            endSpan(span.getStyle(), store, index, buildingSpans);
        }

        // return plain text
        return rVal.toString();
    }

    private void endSpan(final String key, final List<StyleSpan> store, final int index,
            final LinkedList<StyleSpan> buildingSpans) {
        for (final Iterator<StyleSpan> it = buildingSpans.descendingIterator(); it.hasNext();) {
            final StyleSpan next = it.next();
            if (key.equals(next.getStyle())) {
                next.setSpanLength(index - next.getSpanStart());
                store.add(next);
                it.remove();
                break;
            }
        }
    }

    @Override
    public String addStyleMarkup(final String plainText, final List<StyleSpan> spans) {
        if (spans.isEmpty()) {
            return plainText;
        }

        // list of spans, sorted by start index
        final List<StyleSpan> starts = Lists.newArrayList();
        starts.addAll(spans);
        Collections.sort(starts);

        // list of spans, to be sorted by end index
        final List<StyleSpan> ends = Lists.newLinkedList();

        final StringBuilder builder = new StringBuilder();

        // go through all chars and add starts and ends
        for (int index = 0, max = plainText.length(); index < max; index++) {
            // close markup
            while (!ends.isEmpty()) {
                final StyleSpan span = ends.get(0);
                if (span.getSpanStart() + span.getSpanLength() == index) {
                    builder.append(getMarkup(span, true));
                    ends.remove(0);
                } else {
                    break;
                }
            }

            // add starts
            while (!starts.isEmpty()) {
                final StyleSpan span = starts.get(0);
                if (span.getSpanStart() == index) {
                    builder.append(getMarkup(span, false));
                    ends.add(span);
                    starts.remove(0);
                    Collections.sort(ends, endSorter);
                } else {
                    break;
                }
            }

            builder.append(plainText.charAt(index));
        }

        // close any remaining markup:
        while (!ends.isEmpty()) {
            final StyleSpan span = ends.get(0);
            builder.append(getMarkup(span, true));
            ends.remove(0);
        }

        return builder.toString();
    }

    private String getMarkup(final StyleSpan span, final boolean end) {
        if (StyleConstants.KEY_BOLD.equalsIgnoreCase(span.getStyle())) {
            return end ? "[/b]" : "[b]";
        } else if (StyleConstants.KEY_ITALICS.equalsIgnoreCase(span.getStyle())) {
            return end ? "[/i]" : "[i]";
        } else if (StyleConstants.KEY_FAMILY.equalsIgnoreCase(span.getStyle())) {
            return end ? "[/f]" : "[f=" + span.getValue() + "]";
        } else if (StyleConstants.KEY_SIZE.equalsIgnoreCase(span.getStyle())) {
            return end ? "[/size]" : "[size=" + span.getValue() + "]";
        } else if (StyleConstants.KEY_COLOR.equalsIgnoreCase(span.getStyle()) && span.getValue() instanceof ColorRGBA) {
            return end ? "[/c]" : "[c=" + ((ReadOnlyColorRGBA) span.getValue()).asHexRRGGBBAA() + "]";
        }

        return "";
    }

    enum TagStatus {
        NONE, START_TAG, IN_TAG
    }
}
TOP

Related Classes of com.ardor3d.extension.ui.text.parser.ForumLikeMarkupParser

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.