All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.api.visual.widget.LabelWidget Maven / Gradle / Ivy

There is a newer version: RELEASE230
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.netbeans.api.visual.widget;

import org.netbeans.modules.visual.util.GeomUtil;

import java.awt.*;
import java.awt.font.FontRenderContext;
import java.awt.font.GlyphVector;
import java.awt.geom.AffineTransform;
import java.awt.geom.Rectangle2D;

/**
 * A widget representing a text. The widget is not opaque and is checking clipping for by default.
 * 

* It allows to set 4 types of horizontal and vertical alignments (by default LEFT as horizontal and BASELINE as vertical). *

* Swing Font-hinting feature may cause the labels are not rendered completely. * Using setUseGlyphVector you may force the label to be converted to a glyph vector * which scales correctly for any zoom factor. * * @author David Kaspar */ public class LabelWidget extends Widget { /** * The text alignment */ public enum Alignment { LEFT, RIGHT, CENTER, BASELINE } /** * The text vertical alignment */ public enum VerticalAlignment { TOP, BOTTOM, CENTER, BASELINE } /** * The text orientation * @since 2.1 */ public enum Orientation { NORMAL, ROTATE_90//, ROTATE_180, ROTATE_270, MIRROR, MIRROR_ROTATE_90, MIRROR_ROTATE_180, MIRROR_ROTATE_270 } private String label; private Alignment alignment = Alignment.LEFT; private VerticalAlignment verticalAlignment = VerticalAlignment.BASELINE; private Orientation orientation = Orientation.NORMAL; private boolean paintAsDisabled; private boolean useGlyphVector = false; private GlyphVector cacheGlyphVector; private String cacheLabel; private Font cacheFont; /** * Creates a label widget. * @param scene the scene */ public LabelWidget (Scene scene) { this (scene, null); } /** * Creates a label widget with a label. * @param scene the scene * @param label the label */ public LabelWidget (Scene scene, String label) { super (scene); setOpaque (false); // setCursor (new Cursor (Cursor.TEXT_CURSOR)); setLabel (label); setCheckClipping (true); } /** * Returns a label. * @return the label */ public String getLabel () { return label; } /** * Sets a label. * @param label the label */ public void setLabel (String label) { if (GeomUtil.equals (this.label, label)) return; this.label = label; revalidate (); } /** * Returns a text horizontal alignment. * @return the text horizontal alignment */ public Alignment getAlignment () { return alignment; } /** * Sets a text horizontal alignment. * @param alignment the text horizontal alignment */ public void setAlignment (Alignment alignment) { this.alignment = alignment; repaint (); } /** * Gets a text vertical alignment. * @return the text vertical alignment */ public VerticalAlignment getVerticalAlignment () { return verticalAlignment; } /** * Sets a text vertical alignment. * @param verticalAlignment the text vertical alignment */ public void setVerticalAlignment (VerticalAlignment verticalAlignment) { this.verticalAlignment = verticalAlignment; repaint (); } /** * Gets a text orientation. * @return the text orientation * @since 2.1 */ public Orientation getOrientation() { return orientation; } /** * Sets a text orientation. * @param orientation the text orientation * @since 2.1 */ public void setOrientation(Orientation orientation) { this.orientation = orientation; revalidate(); } /** * Returns whether the label is painted as disabled. * @return true, if the label is painted as disabled */ public boolean isPaintAsDisabled () { return paintAsDisabled; } /** * Sets whether the label is painted as disabled. * @param paintAsDisabled if true, then the label is painted as disabled */ public void setPaintAsDisabled (boolean paintAsDisabled) { boolean repaint = this.paintAsDisabled != paintAsDisabled; this.paintAsDisabled = paintAsDisabled; if (repaint) repaint (); } /** * Returns whether the label widget is using glyph vector for rendering text. * @return true, if the label widget is using glyph vector * @since 2.7 */ public boolean isUseGlyphVector () { return useGlyphVector; } /** * Sets whether the label widget is using glyph vector for rendering text. *

* Note that using glyph vector could slow-down the rendering performance. * Note that if you are not using glyph vector then the text may be clipped when a scene has zoom factor different from 1.0. * @param useGlyphVector if true, then a glyph vector is used for rendering text * @since 2.7 */ public void setUseGlyphVector (boolean useGlyphVector) { if (this.useGlyphVector == useGlyphVector) return; this.useGlyphVector = useGlyphVector; cacheGlyphVector = null; cacheLabel = null; cacheFont = null; revalidate (); } private void assureGlyphVector () { Font font = getFont (); FontRenderContext fontRenderContext = getGraphics ().getFontRenderContext (); if (cacheGlyphVector != null && cacheFont == font && cacheLabel == label) return; cacheFont = font; cacheLabel = label; cacheGlyphVector = font.createGlyphVector (new FontRenderContext (new AffineTransform (), fontRenderContext.isAntiAliased (), fontRenderContext.usesFractionalMetrics ()), cacheLabel); } /** * Calculates a client area for the label. * @return the client area */ protected Rectangle calculateClientArea () { if (label == null) return super.calculateClientArea (); Rectangle rectangle; if (useGlyphVector) { assureGlyphVector (); rectangle = GeomUtil.roundRectangle (cacheGlyphVector.getVisualBounds ()); rectangle.grow (1, 1); // WORKAROUND - even text antialiasing is included into the boundary } else { Graphics2D gr = getGraphics (); if (gr == null) { // #192529 return super.calculateClientArea(); } FontMetrics fontMetrics = gr.getFontMetrics (getFont ()); Rectangle2D stringBounds = fontMetrics.getStringBounds (label, gr); rectangle = GeomUtil.roundRectangle (stringBounds); } switch (orientation) { case NORMAL: return rectangle; case ROTATE_90: return new Rectangle (rectangle.y, - rectangle.x - rectangle.width, rectangle.height, rectangle.width); default: throw new IllegalStateException (); } } /** * Paints the label widget. */ protected void paintWidget () { if (label == null) return; Graphics2D gr = getGraphics (); if (useGlyphVector) assureGlyphVector (); else gr.setFont (getFont ()); FontMetrics fontMetrics = gr.getFontMetrics (); Rectangle clientArea = getClientArea (); int x; int y; switch (orientation) { case NORMAL: switch (alignment) { case BASELINE: x = 0; break; case LEFT: x = clientArea.x; break; case CENTER: if (useGlyphVector) x = clientArea.x + (clientArea.width - getCacheGlyphVectorWidth ()) / 2; else x = clientArea.x + (clientArea.width - fontMetrics.stringWidth (label)) / 2; break; case RIGHT: if (useGlyphVector) x = clientArea.x + clientArea.width - getCacheGlyphVectorWidth (); else x = clientArea.x + clientArea.width - fontMetrics.stringWidth (label); break; default: return; } switch (verticalAlignment) { case BASELINE: y = 0; break; case TOP: y = clientArea.y + fontMetrics.getAscent (); break; case CENTER: y = clientArea.y + (clientArea.height + fontMetrics.getAscent () - fontMetrics.getDescent ()) / 2; break; case BOTTOM: y = clientArea.y + clientArea.height - fontMetrics.getDescent (); break; default: return; } break; case ROTATE_90: switch (alignment) { case BASELINE: x = 0; break; case LEFT: x = clientArea.x + fontMetrics.getAscent (); break; case CENTER: x = clientArea.x + (clientArea.width + fontMetrics.getAscent () - fontMetrics.getDescent ()) / 2; break; case RIGHT: x = clientArea.x + clientArea.width - fontMetrics.getDescent (); break; default: return; } switch (verticalAlignment) { case BASELINE: y = 0; break; case TOP: if (useGlyphVector) y = clientArea.y + getCacheGlyphVectorWidth (); else y = clientArea.y + fontMetrics.stringWidth (label); break; case CENTER: if (useGlyphVector) y = clientArea.y + (clientArea.height + getCacheGlyphVectorWidth ()) / 2; else y = clientArea.y + (clientArea.height + fontMetrics.stringWidth (label)) / 2; break; case BOTTOM: y = clientArea.y + clientArea.height; break; default: return; } break; default: return; } AffineTransform previousTransform = gr.getTransform (); gr.translate (x, y); switch (orientation) { case NORMAL: break; case ROTATE_90: gr.rotate (- GeomUtil.M_PI_2); break; default: throw new IllegalStateException (); } Paint background = getBackground (); if (paintAsDisabled && background instanceof Color) { Color color = ((Color) background); gr.setColor (color.brighter ()); if (useGlyphVector) gr.fill (cacheGlyphVector.getOutline (1, 1)); else gr.drawString (label, 1, 1); gr.setColor (color.darker ()); if (useGlyphVector) gr.fill (cacheGlyphVector.getOutline ()); else gr.drawString (label, 0, 0); } else { gr.setColor (getForeground ()); if (useGlyphVector) gr.fill (cacheGlyphVector.getOutline ()); else gr.drawString (label, 0, 0); } gr.setTransform(previousTransform); } private int getCacheGlyphVectorWidth () { return GeomUtil.roundRectangle (cacheGlyphVector.getVisualBounds ()).width; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy