/** * $RCSfile: ,v $ * $Revision: $ * $Date: $ * * Copyright (C) 2004-2011 Jive Software. All rights reserved. * * 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.jivesoftware.spark.component; import javax.swing.JComponent; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Insets; import java.awt.font.FontRenderContext; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.text.AttributedCharacterIterator; import java.text.AttributedString; public class JMultilineLabel extends JComponent { private static final long serialVersionUID = 3061233171993075054L; private String text; private Insets margin = new Insets(1, 1, 1, 1); private int maxWidth = Integer.MAX_VALUE; private boolean justify; private final FontRenderContext frc = new FontRenderContext(null, false, false); private void morph() { revalidate(); repaint(); } public String getText() { return text; } public void setText(String text) { String old = this.text; this.text = text; firePropertyChange("text", old, this.text); if ((old == null) ? text != null : !old.equals(text)) morph(); } public int getMaxWidth() { return maxWidth; } public void setMaxWidth(int maxWidth) { if (maxWidth <= 0) throw new IllegalArgumentException(); int old = this.maxWidth; this.maxWidth = maxWidth; firePropertyChange("maxWidth", old, this.maxWidth); if (old != this.maxWidth) morph(); } public boolean isJustified() { return justify; } public void setJustified(boolean justify) { boolean old = this.justify; this.justify = justify; firePropertyChange("justified", old, this.justify); if (old != this.justify) repaint(); } public Dimension getPreferredSize() { return paintOrGetSize(null, getMaxWidth()); } public Dimension getMinimumSize() { return getPreferredSize(); } protected void paintComponent(Graphics g) { super.paintComponent(g); paintOrGetSize((Graphics2D)g, getWidth()); } private Dimension paintOrGetSize(Graphics2D g, int width) { Insets insets = getInsets(); width -= insets.left + insets.right + margin.left + margin.right; float w = insets.left + insets.right + margin.left + margin.right; float x = insets.left + margin.left, y = insets.top + margin.top; if (width > 0 && text != null && text.length() > 0) { AttributedString as = new AttributedString(getText()); as.addAttribute(TextAttribute.FONT, getFont()); AttributedCharacterIterator aci = as.getIterator(); LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc); float max = 0; while (lbm.getPosition() < aci.getEndIndex()) { TextLayout textLayout = lbm.nextLayout(width); if (g != null && isJustified() && textLayout.getVisibleAdvance() > 0.80 * width) textLayout = textLayout.getJustifiedLayout(width); if (g != null) textLayout.draw(g, x, y + textLayout.getAscent()); y += textLayout.getDescent() + textLayout.getLeading() + textLayout.getAscent(); max = Math.max(max, textLayout.getVisibleAdvance()); } w += max; } return new Dimension((int)Math.ceil(w), (int)Math.ceil(y) + insets.bottom + margin.bottom); } }