/* * Copyright (c) 2010-2012 Célio Cidral Junior. * * 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.tomighty.ui.swing.laf; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsEnvironment; import java.awt.RenderingHints; import java.awt.Toolkit; 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.AttributedCharacterIterator.Attribute; import java.text.AttributedString; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.inject.Inject; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.plaf.basic.BasicLabelUI; import org.tomighty.ui.theme.Colors; import org.tomighty.ui.theme.Look; public class SexyLabelUI extends BasicLabelUI { @Inject private Look look; @Override public void paint(Graphics g, JComponent c) { JLabel label = (JLabel)c; String text = label.getText(); if(text == null || text.trim().length() == 0) { return; } new TextRenderer(label).render((Graphics2D) g); } private class TextRenderer { private final JLabel label; public TextRenderer(JLabel label) { this.label = label; } public void render(Graphics2D g) { configureGraphics(g); WrappedLines lines = breakLines(g); drawLines(lines, g); } private void configureGraphics(Graphics2D g) { Map<?, ?> desktopHints = (Map<?, ?>) Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints"); if(desktopHints != null) { g.setRenderingHints(desktopHints); } g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); } private WrappedLines breakLines(Graphics2D g) { Dimension size = label.getSize(); float maxWidth = size.width; AttributedString attributedText = new AttributedString(label.getText(), textAttributes()); AttributedCharacterIterator textIterator = attributedText.getIterator(); FontRenderContext fontRendering = g.getFontRenderContext(); LineBreakMeasurer measurer = new LineBreakMeasurer(textIterator, fontRendering); WrappedLines lines = new WrappedLines(); while(measurer.getPosition() < textIterator.getEndIndex()) { TextLayout layout = measurer.nextLayout(maxWidth); lines.add(layout); } return lines; } private Map<Attribute, Object> textAttributes() { Map<Attribute, Object> attributes = new HashMap<Attribute, Object>(); attributes.putAll(label.getFont().getAttributes()); attributes.put(TextAttribute.FONT, font()); return attributes; } private Font font() { Font originalFont = label.getFont(); if(!canRenderAllCharacters(originalFont)) { Font[] allFonts = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for(Font anotherFont : allFonts) { if(canRenderAllCharacters(anotherFont)) { return anotherFont; } } } return originalFont; } private boolean canRenderAllCharacters(Font font) { return false; } private void drawLines(WrappedLines lines, Graphics2D g) { Colors colors = look.colors(); float y = originY(lines); for(TextLayout line : lines.list) { float x = xFor(line); y += line.getAscent() - line.getDescent(); Color shadowColor = colors.shadow(); g.setColor(shadowColor); line.draw(g, x-1, y-1); g.setColor(colors.text()); line.draw(g, x, y); y += line.getDescent(); } } private float xFor(TextLayout line) { return (float) (label.getSize().getWidth() / 2.0 - line.getAdvance() / 2f); } private float originY(WrappedLines lines) { return (float) (label.getSize().getHeight() / 2.0 - lines.height / 2f); } } private class WrappedLines { List<TextLayout> list = new ArrayList<TextLayout>(); float width = 0f; float height = 0f; public void add(TextLayout line) { float advance = line.getAdvance(); if(advance > width) width = advance; height += line.getAscent(); list.add(line); } } }