/******************************************************************************* * Copyright (c) 2014 Mentor Graphics 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: * Mentor Graphics - initial API and implementation *******************************************************************************/ package com.codesourcery.installer.ui; import java.util.HashMap; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StyleRange; import org.eclipse.swt.custom.StyledText; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.Font; import org.eclipse.swt.graphics.FontData; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Composite; /** * Provides a label that can be formatted using certain HTML tags. The tags * supported are: * <ul> * <li><b></b> Bold text<li> * <li><i></i> Italic text<li> * <li><u></u> Underlined text<li> * <li><strike></strike> Strikethrough text<li> * <li><small></small> Smaller text<li> * <li><big></big> Bigger text<li> * </ul> * * Tags can be nested. i.e. specifying <small> twice will format the text * reduced in font size by 2. */ public class FormattedLabel extends Composite { /** Text for label */ private String text; /** Label text */ private StyledText labelText = null; /** Font cache */ private HashMap<String, Font> fontCache = new HashMap<String, Font>(); /** * Constructor * * @param parent Parent of widget * @param style style */ public FormattedLabel(Composite parent, int style) { super(parent, SWT.NONE); setLayout(new FillLayout()); // Force read only for label labelText = new StyledText(this, style | SWT.READ_ONLY); labelText.setBackground(getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_BACKGROUND)); labelText.setForeground(getShell().getDisplay().getSystemColor(SWT.COLOR_WIDGET_FOREGROUND)); labelText.setEnabled(false); labelText.setEditable(false); setFont(parent.getFont()); } @Override public void dispose() { // Dispose of cached fonts for (Font font : fontCache.values()) { font.dispose(); } fontCache.clear(); super.dispose(); } /** * Sets the widget text. * * @param text Text for the widget */ public void setText(String text) { this.text = text; setHtmlStyledText(labelText, text); } /** * Get the widget text. * * @return the Widget text */ public String getText() { return labelText.getText(); } /** * Sets the background color. * * @param background Background color */ public void setBackground(Color background) { labelText.setBackground(background); } /** * Sets the foreground color. * * @param foreground Foreground color */ public void setForeground(Color foreground) { labelText.setForeground(foreground); } /** * Returns a font from the cache or creates one. * * @param fontSize Font size * @param bold <code>true</code> for bold font * @param italic <code>true</code> for italic font * * @return Font */ private Font getFont(int fontSize, boolean bold, boolean italic) { // Font key StringBuffer buffer = new StringBuffer(); buffer.append(Integer.toString(fontSize)); buffer.append(Boolean.toString(bold)); buffer.append(Boolean.toString(italic)); String spec = buffer.toString(); // Get font from cache Font font = fontCache.get(spec); // Create font if required and add to cache if (font == null) { FontData fontData = getFont().getFontData()[0]; fontData.setHeight(fontSize); int style = SWT.NORMAL; if (bold) { style |= SWT.BOLD; } if (italic) { style |= SWT.ITALIC; } fontData.setStyle(style); font = new Font(getShell().getDisplay(), fontData); fontCache.put(spec, font); } return font; } /** * Applies HTML styles from text to a StyledText widget. * * @param label StyledText widget * @param text Text with HTML formatting */ public void setHtmlStyledText(StyledText label, String text) { // set text label w/o style tags String labelText = text.replace("<b>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</b>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("<i>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</i>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("<u>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</u>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("<strike>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</strike>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("<small>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</small>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("<big>", ""); //$NON-NLS-1$ //$NON-NLS-2$ labelText = labelText.replace("</big>", ""); //$NON-NLS-1$ //$NON-NLS-2$ label.setText(labelText); int length = labelText.length(); if (length == 0) return; // Reset stles label.setStyleRange(new StyleRange(0, length - 1, null, null, SWT.NORMAL)); FontData defaultFontData = getFont().getFontData()[0]; int defaultFontSize = defaultFontData.getHeight(); boolean bold = false; boolean italic = false; boolean underline = false; boolean strikethrough = false; int fontSize = defaultFontSize; int offset = 0; int start = -1; // Loop through formatted text for (int index = 0; index < text.length(); index ++) { // Start of tag if (text.charAt(index) == '<') { // End of tag int endTagIndex = text.indexOf('>', index); if (endTagIndex != -1) { // Get tag String tag = text.substring(index, endTagIndex + 1); if ((start != offset) && (start != -1)) { StyleRange styleRange = new StyleRange(); styleRange.start = start; styleRange.length = offset - start; // If not default font, get the font if (fontSize != defaultFontSize) { styleRange.font = getFont(fontSize, bold, italic); } // Else just set the style else { styleRange.fontStyle = SWT.NORMAL; if (bold) { styleRange.fontStyle |= SWT.BOLD; } if (italic) { styleRange.fontStyle |= SWT.ITALIC; } } styleRange.underline = underline; styleRange.strikeout = strikethrough; label.setStyleRange(styleRange); } start = offset; // Bold if ("<b>".equalsIgnoreCase(tag)) { bold = true; } else if ("</b>".equalsIgnoreCase(tag)) { bold = false; } // Italic else if ("<i>".equalsIgnoreCase(tag)) { italic = true; } else if ("</i>".equalsIgnoreCase(tag)) { italic = false; } // Underline else if ("<u>".equalsIgnoreCase(tag)) { underline = true; } else if ("</u>".equalsIgnoreCase(tag)) { underline = false; } // Strike-through else if ("<strike>".equalsIgnoreCase(tag)) { strikethrough = true; } else if ("</strike>".equalsIgnoreCase(tag)) { strikethrough = false; } // Smaller text else if ("<small>".equalsIgnoreCase(tag)) { if (fontSize > 1) { fontSize --; } } else if ("</small>".equalsIgnoreCase(tag)) { fontSize ++; } // Larger text else if ("<big>".equalsIgnoreCase(tag)) { fontSize ++; } else if ("</big>".equalsIgnoreCase(tag)) { if (fontSize > 1) { fontSize --; } } index += tag.length() - 1; } } else { offset ++; } } } @Override public void setFont(Font font) { super.setFont(font); labelText.setFont(font); if (text != null) { setText(text); } } /** @see org.eclipse.swt.widgets.Control#setEnabled(boolean) */ public void setEnabled(boolean enabled) { labelText.setEnabled(enabled); } /** @see org.eclipse.swt.custom.StyledText#setWordWrap(boolean) */ public void setWordWrap(boolean wrap) { labelText.setWordWrap(wrap); } }