| import com.whitemagicsoftware.kmcaster.ui.AutofitLabel; | ||
| -import com.whitemagicsoftware.kmcaster.ui.BoundsCalculator; | ||
| -import com.whitemagicsoftware.kmcaster.ui.ScalableDimension; | ||
| import com.whitemagicsoftware.kmcaster.util.ConsecutiveEventCounter; | ||
| // Determine whether there are separate parts for the key label. | ||
| final var index = keyValue.indexOf( ' ' ); | ||
| - | ||
| - final var component = getHardwareComponent( state ); | ||
| - final var bounds = BoundsCalculator.getBounds( component ); | ||
| - final var compDimen = new ScalableDimension( bounds ); | ||
| // If there's a space in the name, the text before the space is | ||
| // positioned in the upper-left while the text afterwards takes up | ||
| // the remainder. This is used for number pad keys, backspace, enter, | ||
| // tab, and a few others. | ||
| if( index > 0 ) { | ||
| // Label for "Num", "Back", "Tab", and other dual-labelled keys. | ||
| sup.setText( keyValue.substring( 0, index ) ); | ||
| - sup.transform( compDimen.scale( .6f ) ); | ||
| + sup.transform( .6f ); | ||
| // Label for number pad keys or icon glyphs. | ||
| main.setText( keyValue.substring( index + 1 ) ); | ||
| - main.transform( compDimen.scale( .9f ) ); | ||
| + main.transform( .9f ); | ||
| // Shift the main label down away from the superscript. | ||
| tally.setText( mKeyCounter.toString() ); | ||
| - tally.transform( compDimen.scale( .25f ) ); | ||
| + tally.transform( .25f ); | ||
| tally.setVisible( true ); | ||
| } | ||
| /** | ||
| + * Lazily initialized to the parent's container's safe drawing area. | ||
| + */ | ||
| + private Rectangle mParentBounds; | ||
| + | ||
| + /** | ||
| * Constructs an instance of {@link AutofitLabel} that can rescale itself | ||
| * relative to either the parent {@link Container} or a given dimension. | ||
| setFont( computeScaledFont() ); | ||
| - final var bounds = BoundsCalculator.getBounds( getParent() ); | ||
| + final var bounds = getParentBounds(); | ||
| // LEFT by default. | ||
| public void transform( final Dimension dimension ) { | ||
| transform( dimension.width, dimension.height ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Scales the dimensions of the label to fit its parent's boundaries, | ||
| + * then multiplying the value by the given factor. | ||
| + * | ||
| + * @param factor The scaling coefficient value. | ||
| + */ | ||
| + public void transform( final float factor ) { | ||
| + final var compDimen = new ScalableDimension( getParentBounds() ); | ||
| + transform( compDimen.scale( factor ) ); | ||
| } | ||
| /** | ||
| * Scales the dimensions of the label to fit its parent's boundaries, while | ||
| * maintaining the aspect ratio, then relocate the label with respect to | ||
| * the vertical and horizontal alignment. | ||
| */ | ||
| public void transform() { | ||
| - final var bounds = BoundsCalculator.getBounds( getParent() ); | ||
| + final var bounds = getParentBounds(); | ||
| transform( bounds.width, bounds.height ); | ||
| } | ||
| scaledFont = scaledFont.deriveFont( (float) scaledPt ); | ||
| - final var bounds = getBounds( text, scaledFont, g ); | ||
| + final var bounds = getTextExtents( text, scaledFont, g ); | ||
| final var fontWidthPx = (int) bounds.getWidth(); | ||
| final var fontHeightPx = (int) bounds.getHeight(); | ||
| // Recompute the bounds of the label based on the text extents that fit. | ||
| - final var bounds = getBounds( text, scaledFont, g ); | ||
| - setSize( (int) bounds.getWidth(), (int) bounds.getHeight() ); | ||
| + final var extents = getTextExtents( text, scaledFont, g ); | ||
| + setSize( (int) extents.getWidth(), (int) extents.getHeight() ); | ||
| return scaledFont; | ||
| * @return Text width and height. | ||
| */ | ||
| - private Rectangle2D getBounds( | ||
| + private Rectangle2D getTextExtents( | ||
| final String text, final Font font, final Graphics graphics ) { | ||
| return getFontMetrics( font ).getStringBounds( text, graphics ); | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the bounds of the parent component, accounting for insets. | ||
| + * | ||
| + * @return The parent's safe drawing area. | ||
| + */ | ||
| + private Rectangle getParentBounds() { | ||
| + return mParentBounds == null | ||
| + ? mParentBounds = getBounds( getParent() ) | ||
| + : mParentBounds; | ||
| + } | ||
| + | ||
| + /** | ||
| + * Returns the safe area for writing on the {@link Container} parameter | ||
| + * provided during construction. | ||
| + * | ||
| + * @return The {@link Container}'s safe area, based on the | ||
| + * {@link Container}'s bounded dimensions and insets. | ||
| + */ | ||
| + public static Rectangle getBounds( final Container container ) { | ||
| + final var insets = container.getInsets(); | ||
| + | ||
| + return new Rectangle( | ||
| + insets.left, insets.top, | ||
| + container.getWidth() - (insets.left + insets.right), | ||
| + container.getHeight() - (insets.top + insets.bottom) | ||
| + ); | ||
| } | ||
| } | ||
| -/* | ||
| - * Copyright 2020 White Magic Software, Ltd. | ||
| - * | ||
| - * All rights reserved. | ||
| - * | ||
| - * Redistribution and use in source and binary forms, with or without | ||
| - * modification, are permitted provided that the following conditions are met: | ||
| - * | ||
| - * o Redistributions of source code must retain the above copyright | ||
| - * notice, this list of conditions and the following disclaimer. | ||
| - * | ||
| - * o Redistributions in binary form must reproduce the above copyright | ||
| - * notice, this list of conditions and the following disclaimer in the | ||
| - * documentation and/or other materials provided with the distribution. | ||
| - * | ||
| - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
| - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
| - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | ||
| - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
| - * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | ||
| - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | ||
| - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
| - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
| - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| - */ | ||
| -package com.whitemagicsoftware.kmcaster.ui; | ||
| - | ||
| -import java.awt.*; | ||
| - | ||
| -/** | ||
| - * Responsible for computing the safe region for displaying information on | ||
| - * a given {@link Container}. The safe region is computed using the | ||
| - * {@link Container}'s bounds {@link Rectangle} and {@link Insets}. | ||
| - */ | ||
| -public final class BoundsCalculator { | ||
| - | ||
| - /** | ||
| - * Returns the safe area for writing on the {@link Container} parameter | ||
| - * provided during construction. | ||
| - * | ||
| - * @return The {@link Container}'s safe area, based on the | ||
| - * {@link Container}'s bounded dimensions and insets. | ||
| - */ | ||
| - public static Rectangle getBounds( final Container container ) { | ||
| - final var insets = container.getInsets(); | ||
| - | ||
| - return new Rectangle( | ||
| - insets.left, insets.top, | ||
| - container.getWidth() - (insets.left + insets.right), | ||
| - container.getHeight() - (insets.top + insets.bottom) | ||
| - ); | ||
| - } | ||
| -} | ||
| Author | DaveJarvis <email> |
|---|---|
| Date | 2020-07-29 14:46:44 GMT-0700 |
| Commit | 2ba150d60cfd06d5aa4e6a132317dc08d73d01f6 |
| Parent | 8200e28 |
| Delta | 53 lines added, 70 lines removed, 17-line decrease |