/*
* Copyright 2015 MovingBlocks
*
* 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 org.terasology.rendering.nui.widgets.browser.data.basic.flow;
import org.terasology.math.geom.Rect2i;
import org.terasology.rendering.assets.font.Font;
import org.terasology.rendering.nui.Canvas;
import org.terasology.rendering.nui.widgets.browser.ui.style.FallbackTextRenderStyle;
import org.terasology.rendering.nui.widgets.browser.ui.style.TextRenderStyle;
public class TextFlowRenderable implements FlowRenderable<TextFlowRenderable> {
private final String text;
private TextRenderStyle textRenderStyle;
private final String hyperlink;
public TextFlowRenderable(String text, TextRenderStyle textRenderStyle, String hyperlink) {
this.text = text;
this.textRenderStyle = textRenderStyle;
this.hyperlink = hyperlink;
}
@Override
public void render(Canvas canvas, Rect2i bounds, TextRenderStyle defaultRenderStyle) {
TextRenderStyle safeRenderStyle = getTextRenderStyle(defaultRenderStyle);
Font font = safeRenderStyle.getFont(hyperlink != null);
int lineHeight = font.getLineHeight();
Rect2i bottomBounds = Rect2i.createFromMinAndSize(bounds.minX(), bounds.maxY() - lineHeight, bounds.sizeX(), lineHeight);
canvas.drawTextRaw(text, font, safeRenderStyle.getColor(hyperlink != null), bottomBounds);
}
@Override
public int getMinWidth(TextRenderStyle defaultRenderStyle) {
Font font = getTextRenderStyle(defaultRenderStyle).getFont(hyperlink != null);
int minWidth = 0;
String[] words = text.split("[ \\n]");
for (String word : words) {
int width = font.getWidth(word);
minWidth = Math.max(minWidth, width);
}
return minWidth;
}
@Override
public int getWidth(TextRenderStyle defaultRenderStyle) {
Font font = getTextRenderStyle(defaultRenderStyle).getFont(hyperlink != null);
return font.getWidth(text);
}
@Override
public int getHeight(TextRenderStyle defaultRenderStyle) {
Font font = getTextRenderStyle(defaultRenderStyle).getFont(hyperlink != null);
return font.getLineHeight();
}
@Override
public String getAction() {
return hyperlink;
}
@Override
public FlowRenderable.SplitResult<TextFlowRenderable> splitAt(TextRenderStyle defaultRenderStyle, int width) {
Font font = getTextRenderStyle(defaultRenderStyle).getFont(hyperlink != null);
if (!text.contains("\n")) {
int wholeTextWidth = font.getWidth(text);
if (wholeTextWidth <= width) {
return new SplitResult<>(this, null);
}
}
int spaceWidth = font.getWidth(' ');
boolean first = true;
int usedSpace = 0;
StringBuilder before = new StringBuilder();
StringBuilder after = new StringBuilder();
boolean appendingToBefore = true;
String[] lines = text.split("\n");
String[] words = lines[0].split(" ");
for (String word : words) {
if (appendingToBefore) {
if (!first) {
usedSpace += spaceWidth;
before.append(" ");
}
usedSpace += font.getWidth(word);
if (usedSpace > width) {
if (before.length() == 0) {
return new SplitResult<>(null, this);
} else {
appendingToBefore = false;
after.append(word);
}
} else {
before.append(word);
}
first = false;
} else {
after.append(" ");
after.append(word);
}
}
if (lines[0].endsWith(" ")) {
after.append(" ");
}
after = trimLeft(after);
boolean firstLine = true;
for (int i = 1; i < lines.length; i++) {
if (!firstLine || after.length() > 0) {
after.append("\n");
}
after.append(lines[i]);
firstLine = false;
}
String beforeText = trimRight(before).toString();
String afterText = after.toString();
if (afterText.isEmpty()) {
return new SplitResult<>(
new TextFlowRenderable(beforeText, textRenderStyle, hyperlink), null);
} else {
return new SplitResult<>(
new TextFlowRenderable(beforeText, textRenderStyle, hyperlink),
new TextFlowRenderable(afterText, textRenderStyle, hyperlink));
}
}
private TextRenderStyle getTextRenderStyle(TextRenderStyle defaultRenderStyle) {
if (textRenderStyle == null) {
return defaultRenderStyle;
}
return new FallbackTextRenderStyle(textRenderStyle, defaultRenderStyle);
}
private StringBuilder trimRight(StringBuilder stringBuilder) {
int size = stringBuilder.length();
for (int i = size - 1; i >= 0; i--) {
if (stringBuilder.charAt(i) != ' ') {
stringBuilder.replace(i + 1, size, "");
break;
}
}
return stringBuilder;
}
private StringBuilder trimLeft(StringBuilder stringBuilder) {
int size = stringBuilder.length();
for (int i = 0; i < size; i++) {
if (stringBuilder.charAt(i) != ' ') {
stringBuilder.replace(0, i, "");
break;
}
}
return stringBuilder;
}
}