/* *------------------------------------------------------------------------------ * Copyright (C) 2015 University of Dundee. All rights reserved. * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * *------------------------------------------------------------------------------ */ package org.openmicroscopy.shoola.agents.metadata.util; import javax.swing.JTextPane; import javax.swing.event.HyperlinkEvent; import javax.swing.event.HyperlinkListener; /** * A {@link JTextPane} which can be expanded/collapsed * * @author Dominik Lindner      <a * href="mailto:d.lindner@dundee.ac.uk">d.lindner@dundee.ac.uk</a> * @since 5.1 */ public class ExpandableTextPane extends JTextPane { /** Default numbers of lines shown in collapsed state */ public final static int DEFAULT_LINES = 3; /** Regex for html linebreak tags */ private static final String LINEBREAK = "<(b|B|h|H)(r|R)/?>"; /** Number of lines shown in collapsed state */ private int showLines = DEFAULT_LINES; /** The original text */ private String text = ""; /** Flag if component is shown in expanded state */ private boolean expanded = false; /** Flag to show 'show more/less' links */ private boolean showMoreLink = true; /** * Creates a new instance with {@link #DEFAULT_LINES} of line number shown * in collapsed state */ public ExpandableTextPane() { this(DEFAULT_LINES, true); } /** * Creates a new instance with {@link #DEFAULT_LINES} of line number shown * in collapsed state * * @param showMoreLink * Pass <code>true</code> to show a 'show more/less' link to * expand/collapse the component */ public ExpandableTextPane(boolean showMoreLink) { this(DEFAULT_LINES, showMoreLink); } /** * Creates a new instance with {@link #DEFAULT_LINES} of line number shown * in collapsed state * * @param showLines * Number of lines shown in collapsed state */ public ExpandableTextPane(int showLines) { this(showLines, true); } /** * Creates a new instance which shows a specific number of lines in * collapsed state * * @param showLines * Number of lines shown in collapsed state * @param showMoreLink * Pass <code>true</code> to show a 'show more/less' link to * expand/collapse the component */ public ExpandableTextPane(int showLines, boolean showMoreLink) { setContentType("text/html"); setEditable(false); this.showLines = showLines; this.showMoreLink = showMoreLink; if (showMoreLink) { addHyperlinkListener(new HyperlinkListener() { @Override public void hyperlinkUpdate(HyperlinkEvent e) { if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { setExpanded(!isExpanded()); } } }); } } @Override /** * Sets the text displayed in the component. * For linebreak the "<br>" HTML tag has to be used; other HTML tags * can be used. */ public void setText(String t) { this.text = t.replaceAll("<(H|h)(T|t)(M|m)(L|l)/?>", ""); if (expanded || getLineCount() < showLines) { super.setText(getSubstring(Integer.MAX_VALUE)); } else { super.setText(getSubstring(showLines)); } } /** * Expands/Collapses the component * * @param b * Pass <code>true</code> to expand, <code>false</code> to * collapse */ public void setExpanded(boolean b) { this.expanded = b; if (expanded) { super.setText(getSubstring(Integer.MAX_VALUE)); } else { super.setText(getSubstring(showLines)); } } /** * Returns if the component is currently in expanded state * * @return See above */ public boolean isExpanded() { return this.expanded; } /** * Returns if the component can be expanded * * @return See above */ public boolean isExpandable() { return getLineCount() >= showLines; } /** * Get the total number of lines in the original text * * @return */ private int getLineCount() { if (text.trim().length() == 0) return 0; return text.split(LINEBREAK).length; } /** * Return the first lines up to nLines (adds a "..." line to the end of the * String returned) * * @param nLines * Maximum number of lines * @return See above */ private String getSubstring(int nLines) { String[] lines = text.split(LINEBREAK); StringBuilder result = new StringBuilder(); result.append("<html>"); int i = 0; for (; i < nLines && i < lines.length; i++) { result.append(lines[i]); result.append("<br/>"); } if (i < lines.length) { if (showMoreLink) result.append("<a href=\"/\">Show more...</a>"); else result.append("..."); } else if (showMoreLink && isExpanded()) { result.append("<a href=\"/\">Show less...</a>"); } result.append("</html>"); return result.toString(); } }