package org.limewire.ui.swing.friends.chat; import java.awt.Font; import java.awt.FontMetrics; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; import javax.swing.text.html.StyleSheet; import org.jdesktop.application.Resource; import org.limewire.ui.swing.util.GuiUtils; class MessageTextImpl extends AbstractMessageImpl implements MessageText { private static final int MAX_LENGTH_PIXELS = 250;// smaller than chat window // width to account for // non-fixed width fonts private final String message; @Resource(key = "ChatInputPanel.textFont") private Font textFont; public MessageTextImpl(String senderName, String chatFriendId, Type type, String message) { super(senderName, chatFriendId, type); GuiUtils.assignResources(this); this.message = message; } @Override public String getMessageText() { return message; } @Override public String toString() { return getMessageText(); } @Override public String format() { return insertBreaksAddAnchorsTags(this.message.replace("<", "<").replace(">", ">")); } /** * Takes the given string creating anchor tags for whereever it finds urls, * and creating wbr tags whenever a word over the MAX_LENGTH_PIXELS is * encountered. */ private String insertBreaksAddAnchorsTags(String wrap) { StringTokenizer stringTokenizer = new StringTokenizer(wrap, " \n\t\r"); StringBuffer htmlString = new StringBuffer(); while (stringTokenizer.hasMoreTokens()) { String token = stringTokenizer.nextToken(); boolean isURL = URLWrapper.isURL(token); StringBuffer brokenString = new StringBuffer(); String[] brokenTokens = breakString(token); for (int i = 0; i < brokenTokens.length; i++) { brokenString.append(brokenTokens[i]); if (brokenTokens.length > 1) { brokenString.append("<wbr>"); } } // if the string is a url make sure to wrap it in an anchor tag if (isURL) { htmlString.append(URLWrapper.createAnchorTag(token, brokenString.toString().trim())); } else { htmlString.append(brokenString.toString()); } if(stringTokenizer.hasMoreTokens()) { htmlString.append(" "); } } return htmlString.toString(); } /** * Breaks up the given token into multiple Strings each with a maximum of * MAX_LENGTH_PIXELS wide. */ private String[] breakString(String token) { // TODO update to support full string int maxCharacters = getMaxCharacters(token); List<String> brokenStrings = new ArrayList<String>(); int index = 0; int length = token.length(); while (index < length) { int start = index; int end = index + maxCharacters; if (end > length) { end = length; } String brokenString = token.substring(start, end); brokenStrings.add(brokenString); index = end; } return brokenStrings.toArray(new String[brokenStrings.size()]); } private int getMaxCharacters(String token) { int pixelWidth1Character = getAverageCharacterWidthInString(token, textFont); return (MAX_LENGTH_PIXELS / pixelWidth1Character); } /** * Returns the width of the message in the given font and editor kit. */ private int getAverageCharacterWidthInString(String text, Font font) { //TODO optimize StyleSheet css = new StyleSheet(); FontMetrics fontMetrics = css.getFontMetrics(font); int averageCharacterWidthForFont = (int)Math.ceil((fontMetrics.stringWidth(text) /(double) text.length())); return averageCharacterWidthForFont; } }