/* * RapidMiner * * Copyright (C) 2001-2008 by Rapid-I and the contributors * * Complete list of developers available at our web site: * * http://rapid-i.com * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 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 Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.gui.look.fc; import java.awt.Dimension; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Insets; import java.util.Enumeration; import java.util.Vector; import javax.swing.JComponent; import javax.swing.SwingConstants; import javax.swing.UIManager; /** * A new swing component similar to a label but containing multiple lines. * * @author Ingo Mierswa * @version $Id: MultipleLinesLabel.java,v 1.3 2008/05/09 20:57:26 ingomierswa Exp $ */ public class MultipleLinesLabel extends JComponent implements SwingConstants { private static final long serialVersionUID = -4783596538296904867L; private int lineHeight, lineAscent; private int maxWidth = -1; private int textHeight = -1; private int[] lineWidths; private int btnMarginWidth = 1; private String text = ""; private boolean multiLine = true; private static Font labelFont = new java.awt.Font("SansSerif", 0, 11); private int horizontalAlignment = LEADING; private int textAlignment = LEADING; private int verticalAlignment = CENTER; private FontMetrics fontMetrics; private Vector<String> vector; private boolean needUpdate = true; public MultipleLinesLabel() { this("", CENTER, CENTER, TOP); } public MultipleLinesLabel(String text) { this(text, LEADING, LEADING, TOP); } public MultipleLinesLabel(String text, int horizontalAlignment) { this(text, horizontalAlignment, LEADING, CENTER); } public MultipleLinesLabel(String text, int horizontalAlignment, int textAlignment) { this(text, horizontalAlignment, textAlignment, CENTER); } public MultipleLinesLabel(String str, int horizontalAlignment, int textAlignment, int verticalAlignment) { this.setForeground(UIManager.getColor("Label.foreground")); this.setBackground(UIManager.getColor("textHighlight")); this.setFont(labelFont); setText(str); this.horizontalAlignment = horizontalAlignment; this.textAlignment = textAlignment; this.verticalAlignment = verticalAlignment; this.needUpdate = true; } private void updateTextVector() { this.vector = new Vector<String>(); int w = this.getWidth(); if (w > 6) { w -= 4; } int counter = 0; char[] ca = this.text.toCharArray(); String tempStr = ""; Vector<String> sentVec = new Vector<String>(); char lastChar; lastChar = ca[0]; tempStr += lastChar; for (int i = 1; i < ca.length; i++) { if (lastChar == ' ') { if (ca[i] == ' ') { tempStr += ca[i]; } else { sentVec.add(tempStr); tempStr = String.valueOf(ca[i]); } } else { if (ca[i] == ' ') { sentVec.add(tempStr); tempStr = String.valueOf(ca[i]); } else { tempStr += ca[i]; } } lastChar = ca[i]; } if (!tempStr.equals("")) { sentVec.add(tempStr); } Enumeration els = sentVec.elements(); StringBuffer lineStr = new StringBuffer(); while (els.hasMoreElements()) { String str = els.nextElement().toString(); counter++; if (this.fontMetrics.stringWidth(str) <= w) { if ((this.fontMetrics.stringWidth(lineStr + str) <= w)) { lineStr.append(str); } else { if (!lineStr.equals("")) { this.vector.add(lineStr.toString()); lineStr = new StringBuffer(); } lineStr = new StringBuffer(str); } } else { if (!lineStr.equals("")) { this.vector.add(lineStr.toString()); lineStr = new StringBuffer(); } ca = str.toCharArray(); int first = 0; for (int i = 0; i < ca.length; i++) { if (this.fontMetrics.stringWidth(str.substring(first, i)) > w) { this.vector.add(str.substring(first, i - 1)); first = i - 1; } } lineStr = new StringBuffer(str.substring(first, str.length())); } } if (lineStr.length() > 0) { this.vector.add(lineStr.toString()); } } private void recalculateDimension() { this.fontMetrics = getFontMetrics(getFont()); this.lineHeight = this.fontMetrics.getHeight(); this.lineAscent = this.fontMetrics.getAscent(); this.lineWidths = new int[this.vector.size()]; this.maxWidth = 0; for (int i = 0; i < this.vector.size(); i++) { this.lineWidths[i] = this.fontMetrics.stringWidth(this.vector.elementAt(i)); this.maxWidth = Math.max(this.maxWidth, this.lineWidths[i]); } this.maxWidth += 2 * this.btnMarginWidth; this.textHeight = this.vector.size() * this.lineHeight; revalidate(); } @Override public Dimension getMaximumSize() { return new Dimension(Short.MAX_VALUE, Short.MAX_VALUE); } @Override public Dimension getMinimumSize() { return new Dimension(10, 20); } public Dimension getMinimumSize1() { if ((this.maxWidth == -1) || (this.textHeight == -1)) { recalculateDimension(); } Insets insets = getInsets(); return new Dimension(this.maxWidth + insets.left + insets.right, this.textHeight + insets.top + insets.bottom); } private void paintOneLine(Graphics g, Dimension d, Insets insets, int y) { int ha = getBidiHorizontalAlignment(this.horizontalAlignment); int ww = this.fontMetrics.stringWidth(this.text); int x = 0; if (ha == LEFT) { ha = getBidiHorizontalAlignment(this.textAlignment); if (ha == LEFT) { x = insets.left; } else if (ha == RIGHT) { x = this.maxWidth - ww + insets.left; } else if (ha == CENTER) { x = insets.left + (this.maxWidth - ww) / 2; } } else if (ha == RIGHT) { ha = getBidiHorizontalAlignment(this.textAlignment); if (ha == LEFT) { x = d.width - this.maxWidth - insets.right; } else if (ha == RIGHT) { x = d.width - ww - insets.right; } else if (ha == CENTER) { x = d.width - this.maxWidth - insets.right + (this.maxWidth - ww) / 2; } } else if (ha == CENTER) { ha = getBidiHorizontalAlignment(this.textAlignment); // Just imagine that ha=LEFT (much easier), and follow code int clientAreaWidth = d.width - insets.left - insets.right; if (ha == LEFT) { x = insets.left + (clientAreaWidth - this.maxWidth) / 2; } else if (ha == RIGHT) { x = insets.left + (clientAreaWidth - this.maxWidth) / 2 + (this.maxWidth - ww); } else if (ha == CENTER) { x = insets.left + (clientAreaWidth - ww) / 2; } } int re = (this.getHeight() + this.fontMetrics.getHeight()) / 2 - 2; int w = this.fontMetrics.stringWidth(this.text); int last = 0; if (w > this.getWidth()) { char[] ca = this.text.toCharArray(); last = ca.length; for (int i = 0; i < ca.length; i++) { if (this.fontMetrics.stringWidth(this.text.substring(0, i) + "..." + 2) > getWidth()) { last = i - 1; g.drawString(this.text.substring(0, last) + "...", 2, re); return; } } } g.drawString(this.text, x, re); } @Override protected void paintComponent(Graphics g) { if ((this.getWidth() <= 0) || (this.getHeight() <= 0)) { return; } super.paintComponent(g); updateInfo(); //background if (isOpaque()) { g.setColor(this.getBackground()); g.fillRect(0, 0, getWidth(), getHeight()); } g.setColor(this.getForeground()); Dimension d = getSize(); if ((d.width != this.maxWidth) || (d.height != this.textHeight)) { recalculateDimension(); } Insets insets = this.getInsets(); int y = 0; y = insets.top + this.lineAscent; if (this.multiLine) { paintMultiLine(g, d, insets, y); } else { paintOneLine(g, d, insets, y); } } private void paintMultiLine(Graphics g, Dimension d, Insets insets, int y) { for (int i = 0; i < this.vector.size(); i++) { int x = 0; int clientAreaWidth = d.width - insets.left - insets.right; x = insets.left + (clientAreaWidth - this.lineWidths[i]) / 2; x += this.btnMarginWidth; g.drawString(this.vector.elementAt(i), x, y); y += this.lineHeight; } } private void updateInfo() { if ((this.text == null) || (this.text == "")) { return; } if (!this.needUpdate) { return; } updateTextVector(); recalculateDimension(); this.needUpdate = false; } public void setText(String str) { this.text = str; this.fontMetrics = getFontMetrics(getFont()); this.needUpdate = true; } private int getBidiHorizontalAlignment(int ha) { if (ha == LEADING) { if (getComponentOrientation().isLeftToRight()) { ha = LEFT; } else { ha = RIGHT; } } else if (ha == TRAILING) { if (getComponentOrientation().isLeftToRight()) { ha = RIGHT; } else { ha = LEFT; } } return ha; } public int getVerticalAlignment() { return this.verticalAlignment; } public void setVerticalAlignment(int verticalAlignment) { this.verticalAlignment = verticalAlignment; this.needUpdate = true; repaint(); } public int getHorizontalAlignment() { return this.horizontalAlignment; } public void setHorizontalAlignment(int horizontalAlignment) { this.horizontalAlignment = horizontalAlignment; this.needUpdate = true; repaint(); } public int getTextAlignment() { return this.textAlignment; } public void setTextAlignment(int textAlignment) { this.textAlignment = textAlignment; this.needUpdate = true; repaint(); } public void setMultiLine(boolean b) { this.multiLine = b; this.needUpdate = true; updateInfo(); } public void setNeed_update(boolean need_update) { this.needUpdate = need_update; } public int getPreferredLineWidth() { return this.fontMetrics.stringWidth(this.text); } public int getPreferredLineHeight() { return this.fontMetrics.getHeight(); } public int getLineDiff() { if (this.vector.size() > 1) { return this.fontMetrics.getHeight() * (this.vector.size() - 1); } else { return 0; } } @Override public Dimension getPreferredSize() { if (this.multiLine) { return new Dimension(getPreferredLineWidth(), this.fontMetrics.getHeight() * this.vector.size()); } else { return new Dimension(getPreferredLineWidth(), this.fontMetrics.getHeight()); } } }