Code
class LineWrapToolTip extends JToolTip {
private static final double JAVA17 = 17.0;
private static final JLabel MEASURER = new JLabel(" ");
private static final int TIP_WIDTH = 200;
private final JTextArea textArea = new JTextArea(0, 20);
protected LineWrapToolTip() {
super();
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
textArea.setOpaque(true);
// textArea.setColumns(20);
LookAndFeel.installColorsAndFont(
textArea, "ToolTip.background", "ToolTip.foreground", "ToolTip.font");
setLayout(new BorderLayout());
add(textArea);
}
@Override public final void setLayout(LayoutManager mgr) {
super.setLayout(mgr);
}
@Override public final Component add(Component comp) {
return super.add(comp);
}
@Override public Dimension getPreferredSize() {
Dimension d = getLayout().preferredLayoutSize(this);
Dimension dim;
String version = System.getProperty("java.specification.version");
if (Double.parseDouble(version) >= JAVA17) {
dim = getTextAreaSize17(d);
} else {
dim = getTextAreaSize8(d);
}
return dim;
}
private Dimension getTextAreaSize8(Dimension d) {
Font font = textArea.getFont();
MEASURER.setFont(font);
MEASURER.setText(textArea.getText());
Insets i = getInsets();
int pad = getTextAreaPaddingWidth(i);
// d.width = Math.min(d.width, MEASURER.getPreferredSize().width + pad);
d.width = Math.min(TIP_WIDTH, MEASURER.getPreferredSize().width + pad);
// JDK-8226513 JEditorPane is shown with incorrect size - Java Bug System
// https://bugs.openjdk.org/browse/JDK-8226513
AttributedString as = new AttributedString(textArea.getText());
as.addAttribute(TextAttribute.FONT, font);
AttributedCharacterIterator aci = as.getIterator();
FontMetrics fm = textArea.getFontMetrics(font);
FontRenderContext frc = fm.getFontRenderContext();
LineBreakMeasurer lbm = new LineBreakMeasurer(aci, frc);
float y = 0f;
while (lbm.getPosition() < aci.getEndIndex()) {
TextLayout tl = lbm.nextLayout(TIP_WIDTH);
y += tl.getDescent() + tl.getLeading() + tl.getAscent();
}
d.height = (int) y + getTextAreaPaddingHeight(i);
return d;
}
private Dimension getTextAreaSize17(Dimension d) {
MEASURER.setFont(textArea.getFont());
MEASURER.setText(textArea.getText());
int pad = getTextAreaPaddingWidth(getInsets());
d.width = Math.min(d.width, MEASURER.getPreferredSize().width + pad);
return d;
}
private int getTextAreaPaddingWidth(Insets i) {
// @see BasicTextUI.java
// margin required to show caret in the rightmost position
int caretMargin = -1;
Object property = UIManager.get("Caret.width");
if (property instanceof Number) {
caretMargin = ((Number) property).intValue();
}
property = textArea.getClientProperty("caretWidth");
if (property instanceof Number) {
caretMargin = ((Number) property).intValue();
}
if (caretMargin < 0) {
caretMargin = 1;
}
Insets ti = textArea.getInsets();
return i.left + i.right + ti.left + ti.right + caretMargin;
// Insets tm = textArea.getMargin();
// return i.left + i.right + ti.left + ti.right + tm.left + tm.right;
}
private int getTextAreaPaddingHeight(Insets i) {
Insets ti = textArea.getInsets();
return i.top + i.bottom + ti.top + ti.bottom;
}
@Override public void setTipText(String tipText) {
String oldValue = textArea.getText();
textArea.setText(tipText);
firePropertyChange("tiptext", oldValue, tipText);
if (!Objects.equals(oldValue, tipText)) {
revalidate();
repaint();
}
}
@Override public String getTipText() {
return Optional.ofNullable(textArea).map(JTextArea::getText).orElse(null);
}
}
References
No comments:
Post a Comment