I was following the lead of the best looking widget I could find on the web. Of which there were only a few - Apple's HIG seems to discourage putting text into Meters, and I don't personally think it looks all that great myself.
I don't know what else I could use that would be guaranteed to contrast well with the fill colour. Greg Brown wrote: > Just wondering - why are you trying to match the display background > here? Might there be another color you could pull from the theme that > would be appropriate? > > On Oct 29, 2009, at 10:23 AM, Noel Grandin wrote: > >> >> One of the things I don't like in my commit here is that I'm hard-coding >> a color (Color.LIGHT_GRAY), which I had to do to match the background >> color, which is also hard-coded in DisplaySkin. >> >> Surely these colours should be in the theme file? >> >> Mind you, now that I am searching for them I see that quite a lot of >> Skin classes hard-code colors. I guess that's a problem for another day. >> >> -- Noel. >> >> [email protected] wrote: >>> Author: noelgrandin >>> Date: Thu Oct 29 14:11:56 2009 >>> New Revision: 830954 >>> >>> URL: http://svn.apache.org/viewvc?rev=830954&view=rev >>> Log: >>> PIVOT-33 Add support for Meter#text property in TerraMeterSkin >>> >>> Modified: >>> >>> incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraMeterSkin.java >>> >>> >>> Modified: >>> incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraMeterSkin.java >>> >>> URL: >>> http://svn.apache.org/viewvc/incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraMeterSkin.java?rev=830954&r1=830953&r2=830954&view=diff >>> >>> ============================================================================== >>> >>> --- >>> incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraMeterSkin.java >>> (original) >>> +++ >>> incubator/pivot/trunk/wtk/src/org/apache/pivot/wtk/skin/terra/TerraMeterSkin.java >>> Thu Oct 29 14:11:56 2009 >>> @@ -17,16 +17,23 @@ >>> package org.apache.pivot.wtk.skin.terra; >>> >>> import java.awt.Color; >>> +import java.awt.Font; >>> import java.awt.GradientPaint; >>> import java.awt.Graphics2D; >>> import java.awt.RenderingHints; >>> +import java.awt.Shape; >>> +import java.awt.font.FontRenderContext; >>> +import java.awt.font.LineMetrics; >>> +import java.awt.geom.Rectangle2D; >>> >>> +import org.apache.pivot.collections.Dictionary; >>> import org.apache.pivot.wtk.Component; >>> import org.apache.pivot.wtk.Dimensions; >>> import org.apache.pivot.wtk.GraphicsUtilities; >>> import org.apache.pivot.wtk.Meter; >>> import org.apache.pivot.wtk.MeterListener; >>> import org.apache.pivot.wtk.Orientation; >>> +import org.apache.pivot.wtk.Platform; >>> import org.apache.pivot.wtk.Theme; >>> import org.apache.pivot.wtk.skin.ComponentSkin; >>> >>> @@ -36,18 +43,23 @@ >>> */ >>> public class TerraMeterSkin extends ComponentSkin >>> implements MeterListener { >>> - private Color color; >>> + private Color fillColor; >>> private Color gridColor; >>> private float gridFrequency; >>> + private Font font; >>> + private Color textColor; >>> >>> + private static final FontRenderContext FONT_RENDER_CONTEXT = >>> new FontRenderContext(null, true, false); >>> private static final int DEFAULT_WIDTH = 100; >>> private static final int DEFAULT_HEIGHT = 12; >>> >>> public TerraMeterSkin() { >>> TerraTheme theme = (TerraTheme)Theme.getTheme(); >>> - color = theme.getColor(16); >>> + fillColor = theme.getColor(16); >>> gridColor = theme.getColor(10); >>> gridFrequency = 0.25f; >>> + font = theme.getFont(); >>> + textColor = theme.getColor(1); >>> } >>> >>> @Override >>> @@ -65,25 +77,77 @@ >>> >>> @Override >>> public int getPreferredWidth(int height) { >>> - // Meter has no content, so its preferred width is hard >>> coded in the >>> + Meter meter = (Meter)getComponent(); >>> + String text = meter.getText(); >>> + >>> + int preferredWidth; >>> + if (text != null >>> + && text.length() > 0) { >>> + Rectangle2D stringBounds = font.getStringBounds(text, >>> FONT_RENDER_CONTEXT); >>> + preferredWidth = >>> (int)Math.ceil(stringBounds.getWidth()) + 2; >>> + } else { >>> + preferredWidth = 0; >>> + } >>> + >>> + // If Meter has no content, its preferred width is hard >>> coded in the >>> // class and is not affected by the height constraint. >>> - return DEFAULT_WIDTH; >>> + preferredWidth = Math.max(preferredWidth, DEFAULT_WIDTH); >>> + >>> + return preferredWidth; >>> } >>> >>> @Override >>> public int getPreferredHeight(int width) { >>> - // Meter has no content, so its preferred height is hard >>> coded in the >>> + Meter meter = (Meter)getComponent(); >>> + String text = meter.getText(); >>> + >>> + int preferredHeight = 0; >>> + if (text!=null && text.length()>0) { >>> + LineMetrics lm = font.getLineMetrics("", >>> FONT_RENDER_CONTEXT); >>> + preferredHeight = (int)Math.ceil(lm.getHeight()) + 2; >>> + } >>> + >>> + // If Meter has no content, its preferred height is hard >>> coded in the >>> // class and is not affected by the width constraint. >>> - return DEFAULT_HEIGHT; >>> + preferredHeight = Math.max(preferredHeight, DEFAULT_HEIGHT); >>> + >>> + return preferredHeight; >>> } >>> >>> @Override >>> public Dimensions getPreferredSize() { >>> - // Meter has no content, so its preferred size is hard >>> coded in the class. >>> - return new Dimensions(DEFAULT_WIDTH, DEFAULT_HEIGHT); >>> + Meter meter = (Meter)getComponent(); >>> + String text = meter.getText(); >>> + >>> + int preferredWidth = 0; >>> + int preferredHeight = 0; >>> + if (text!=null && text.length()>0) { >>> + Rectangle2D stringBounds = font.getStringBounds(text, >>> FONT_RENDER_CONTEXT); >>> + preferredWidth = >>> (int)Math.ceil(stringBounds.getWidth()) + 2; >>> + LineMetrics lm = font.getLineMetrics("", >>> FONT_RENDER_CONTEXT); >>> + preferredHeight = (int)Math.ceil(lm.getHeight()) + 2; >>> + } >>> + >>> + // If Meter has no content, its preferred size is hard >>> coded in the class. >>> + preferredWidth = Math.max(preferredWidth, DEFAULT_WIDTH); >>> + preferredHeight = Math.max(preferredHeight, DEFAULT_HEIGHT); >>> + >>> + return new Dimensions(preferredWidth, preferredHeight); >>> } >>> >>> @Override >>> + public int getBaseline(int width) { >>> + Meter meter = (Meter)getComponent(); >>> + String text = meter.getText(); >>> + if (text!=null && text.length()>0) { >>> + LineMetrics lm = font.getLineMetrics("", >>> FONT_RENDER_CONTEXT); >>> + return (int)Math.ceil(lm.getAscent() - 2); >>> + } else { >>> + return -1; >>> + } >>> + } >>> + >>> + @Override >>> public void layout() { >>> // No-op >>> } >>> @@ -92,35 +156,65 @@ >>> public void paint(Graphics2D graphics) { >>> Meter meter = (Meter)getComponent(); >>> >>> - // TODO Paint text >>> - >>> int width = getWidth(); >>> int height = getHeight(); >>> int meterStop = (int)(meter.getPercentage() * width); >>> >>> - graphics.setPaint(new GradientPaint(0, 0, >>> TerraTheme.brighten(color), >>> - 0, height, TerraTheme.darken(color))); >>> graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, >>> RenderingHints.VALUE_ANTIALIAS_ON); >>> + if (FONT_RENDER_CONTEXT.isAntiAliased()) { >>> + >>> graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, >>> + Platform.getTextAntialiasingHint()); >>> + } >>> + if (FONT_RENDER_CONTEXT.usesFractionalMetrics()) { >>> + >>> graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, >>> + RenderingHints.VALUE_FRACTIONALMETRICS_ON); >>> + } >>> + >>> + // Paint the interior fill >>> + graphics.setPaint(new GradientPaint(0, 0, >>> TerraTheme.brighten(fillColor), >>> + 0, height, TerraTheme.darken(fillColor))); >>> graphics.fillRect(0, 0, meterStop, height); >>> >>> + // Paint the grid >>> graphics.setPaint(gridColor); >>> GraphicsUtilities.drawRect(graphics, 0, 0, width, height); >>> - >>> int nLines = (int)Math.ceil(1 / gridFrequency) - 1; >>> float gridSeparation = width * gridFrequency; >>> for (int i = 0; i < nLines; i++) { >>> int gridX = (int)((i + 1) * gridSeparation); >>> GraphicsUtilities.drawLine(graphics, gridX, 0, height, >>> Orientation.VERTICAL); >>> } >>> + >>> + String text = meter.getText(); >>> + if (text!=null && text.length()>0) { >>> + LineMetrics lm = font.getLineMetrics("", >>> FONT_RENDER_CONTEXT); >>> + int ascent = Math.round(lm.getAscent()); >>> + Rectangle2D stringBounds = font.getStringBounds(text, >>> FONT_RENDER_CONTEXT); >>> + int textWidth = (int)Math.ceil(stringBounds.getWidth()); >>> + int textX = (width - textWidth - 2) / 2 + 1; >>> + >>> + // Paint the text >>> + Shape previousClip = graphics.getClip(); >>> + graphics.clipRect(0, 0, meterStop, height); >>> + graphics.setPaint(Color.LIGHT_GRAY); >>> + graphics.setFont(font); >>> + graphics.drawString(meter.getText(), textX, ascent+1); >>> + graphics.setClip(previousClip); >>> + graphics.clipRect(meterStop, 0, width, height); >>> + graphics.setPaint(textColor); >>> + graphics.setFont(font); >>> + graphics.drawString(meter.getText(), textX, ascent+1); >>> + graphics.setClip(previousClip); >>> + } >>> } >>> >>> public Color getColor() { >>> - return color; >>> + return fillColor; >>> } >>> >>> public void setColor(Color color) { >>> - this.color = color; >>> + this.fillColor = color; >>> repaintComponent(); >>> } >>> >>> @@ -169,6 +263,35 @@ >>> setGridFrequency(gridFrequency.floatValue()); >>> } >>> >>> + public Font getFont() { >>> + return font; >>> + } >>> + >>> + public void setFont(Font font) { >>> + if (font == null) { >>> + throw new IllegalArgumentException("font is null."); >>> + } >>> + >>> + this.font = font; >>> + invalidateComponent(); >>> + } >>> + >>> + public final void setFont(String font) { >>> + if (font == null) { >>> + throw new IllegalArgumentException("font is null."); >>> + } >>> + >>> + setFont(decodeFont(font)); >>> + } >>> + >>> + public final void setFont(Dictionary<String, ?> font) { >>> + if (font == null) { >>> + throw new IllegalArgumentException("font is null."); >>> + } >>> + >>> + setFont(Theme.deriveFont(font)); >>> + } >>> + >>> /** >>> * Listener for meter percentage changes. >>> * >>> >>> >>> >> >
