package org.limewire.ui.swing.components; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Rectangle; import java.awt.image.BufferedImage; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JSlider; import javax.swing.plaf.basic.BasicSliderUI; import org.jdesktop.application.Resource; import org.limewire.ui.swing.util.GuiUtils; /** * UI delegate for the volume slider control. */ class VolumeSliderUI extends BasicSliderUI { @Resource private int preferredWidth; @Resource private int preferredHeight; @Resource private Icon thumbIcon; @Resource private Icon trackIcon; /** Thumb image for vertical orientation. */ private BufferedImage verticalThumbImage; /** Track image for vertical orientation. */ private BufferedImage verticalTrackImage; /** Thumb image for horizontal orientation. */ private BufferedImage horizontalThumbImage; /** Track image for horizontal orientation. */ private BufferedImage horizontalTrackImage; /** * Constructs a VolumeSliderUI for the specified slider component. */ public VolumeSliderUI(JSlider b) { super(b); GuiUtils.assignResources(this); initResources(); } /** * Initializes UI resources. */ private void initResources() { // Convert thumb icon to images if possible. The original icon must be // drawn for vertical orientation. if (thumbIcon instanceof ImageIcon) { verticalThumbImage = new BufferedImage(thumbIcon.getIconWidth(), thumbIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = verticalThumbImage.createGraphics(); g2d.drawImage(((ImageIcon) thumbIcon).getImage(), 0, 0, null); g2d.dispose(); // Create rotated image for horizontal orientation. horizontalThumbImage = new BufferedImage(thumbIcon.getIconHeight(), thumbIcon.getIconWidth(), BufferedImage.TYPE_INT_ARGB); g2d = horizontalThumbImage.createGraphics(); g2d.translate(0, thumbIcon.getIconWidth()); g2d.rotate(-Math.PI / 2); g2d.drawImage(((ImageIcon) thumbIcon).getImage(), 0, 0, null); g2d.dispose(); } // Convert track icon to images if possible. The original icon must be // drawn for vertical orientation. if (trackIcon instanceof ImageIcon) { verticalTrackImage = new BufferedImage(trackIcon.getIconWidth(), trackIcon.getIconHeight(), BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = verticalTrackImage.createGraphics(); g2d.drawImage(((ImageIcon) trackIcon).getImage(), 0, 0, null); g2d.dispose(); // Create rotated image for horizontal orientation. horizontalTrackImage = new BufferedImage(trackIcon.getIconHeight(), trackIcon.getIconWidth(), BufferedImage.TYPE_INT_ARGB); g2d = horizontalTrackImage.createGraphics(); g2d.translate(0, trackIcon.getIconWidth()); g2d.rotate(-Math.PI / 2); g2d.drawImage(((ImageIcon) trackIcon).getImage(), 0, 0, null); g2d.dispose(); } } /** * Returns the preferred size for horizontal orientation based on the image * sizes. */ @Override public Dimension getPreferredHorizontalSize() { if ((horizontalThumbImage != null) && (horizontalTrackImage != null)) { return new Dimension(Math.max(horizontalTrackImage.getWidth(), preferredHeight), Math.max(horizontalThumbImage.getHeight(), preferredWidth)); } else { return new Dimension(preferredHeight, preferredWidth); } } /** * Returns the preferred size for vertical orientation based on the image * sizes. */ @Override public Dimension getPreferredVerticalSize() { if ((verticalThumbImage != null) && (verticalTrackImage != null)) { return new Dimension(Math.max(verticalThumbImage.getWidth(), preferredWidth), Math.max(verticalTrackImage.getHeight(), preferredHeight)); } else { return new Dimension(preferredWidth, preferredHeight); } } /** * Returns the minimum size of the slider component. */ @Override public Dimension getMinimumSize(JComponent c) { // Calculate minimum size. Dimension minimumSize = super.getMinimumSize(c); if (slider.getOrientation() == JSlider.VERTICAL) { // For vertical slider, size must be as wide as the thumb image, // and as tall as the track image. if (verticalThumbImage != null) { minimumSize.width = Math.max(verticalThumbImage.getWidth(), minimumSize.width); } if (verticalTrackImage != null) { minimumSize.height = Math.max(verticalTrackImage.getHeight(), minimumSize.height); } } else { // For horizontal slider, size must be as tall as the thumb image, // and as wide as the track image. if (horizontalThumbImage != null) { minimumSize.height = Math.max(horizontalThumbImage.getHeight(), minimumSize.height); } if (horizontalTrackImage != null) { minimumSize.width = Math.max(horizontalTrackImage.getWidth(), minimumSize.width); } } return minimumSize; } /** * Returns the preferred size of the slider component. */ @Override public Dimension getPreferredSize(JComponent c) { // Calculate preferred size. Dimension preferredSize = super.getPreferredSize(c); // Adjust calculated sizes. The superclass method recalculates // vertical width or horizontal height, and we want to ensure these are // at least as big as the default preferred sizes. if (slider.getOrientation() == JSlider.VERTICAL) { preferredSize.width = Math.max(preferredWidth, preferredSize.width); } else { preferredSize.height = Math.max(preferredWidth, preferredSize.height); } return preferredSize; } /** * Calculates the track rectangle. The track rectangle defines the sliding * range for the thumb. This is basically the content rectangle indented * on the ends by the "track buffer", which is usually half of the thumb * size. */ @Override protected void calculateTrackRect() { if (verticalTrackImage == null) { super.calculateTrackRect(); return; } // used to center sliders added using BorderLayout.CENTER (bug 4275631) int centerSpacing = 0; if (slider.getOrientation() == JSlider.HORIZONTAL) { centerSpacing = thumbRect.height; if (slider.getPaintTicks()) centerSpacing += getTickLength(); if (slider.getPaintLabels()) centerSpacing += getHeightOfTallestLabel(); // Determine track position and size. The track length is equal to // the track image length, minus half of the thumb image length. trackRect.x = contentRect.x + (contentRect.width - (horizontalTrackImage.getWidth() - horizontalThumbImage.getWidth() / 2)) / 2; trackRect.y = contentRect.y + (contentRect.height - centerSpacing) / 2; trackRect.width = horizontalTrackImage.getWidth() - horizontalThumbImage.getWidth() / 2; trackRect.height = thumbRect.height; } else { centerSpacing = thumbRect.width; if (slider.getComponentOrientation().isLeftToRight()) { if (slider.getPaintTicks()) centerSpacing += getTickLength(); if (slider.getPaintLabels()) centerSpacing += getWidthOfWidestLabel(); } else { if (slider.getPaintTicks()) centerSpacing -= getTickLength(); if (slider.getPaintLabels()) centerSpacing -= getWidthOfWidestLabel(); } // Determine track position and size. The track length is equal to // the track image length, minus half of the thumb image length. trackRect.x = contentRect.x + (contentRect.width - centerSpacing) / 2; trackRect.y = contentRect.y + (contentRect.height - (verticalTrackImage.getHeight() - verticalThumbImage.getHeight() / 2)) / 2; trackRect.width = thumbRect.width; trackRect.height = verticalTrackImage.getHeight() - verticalThumbImage.getHeight() / 2; } } /** * Returns the size of a thumb. */ @Override protected Dimension getThumbSize() { BufferedImage thumbImage = (slider.getOrientation() == JSlider.VERTICAL) ? verticalThumbImage : horizontalThumbImage; if (thumbImage != null) { return new Dimension(thumbImage.getWidth(), thumbImage.getHeight()); } else { return super.getThumbSize(); } } /** * Paints the focus highlight. Overrides superclass method to do nothing. */ @Override public void paintFocus(Graphics g) { // Do nothing. } /** * Paints the track. This overrides the superclass method to use the track * image. */ @Override public void paintTrack(Graphics g) { // Get track image. BufferedImage trackImage = (slider.getOrientation() == JSlider.VERTICAL) ? verticalTrackImage : horizontalTrackImage; if (trackImage != null) { // Use content rectangle. Rectangle trackBounds = contentRect; // Determine position offset to center track image within content. int cx = (trackBounds.width - trackImage.getWidth()) / 2; int cy = (trackBounds.height - trackImage.getHeight()) / 2; // Create graphics copy. Graphics gTemp = g.create(); // Draw track image. gTemp.translate(trackBounds.x + cx, trackBounds.y + cy); gTemp.drawImage(trackImage, 0, 0, null); gTemp.dispose(); } else { super.paintTrack(g); } } /** * Paints the thumb. This overrides the superclass method to use the thumb * image. */ @Override public void paintThumb(Graphics g) { // Get thumb image. BufferedImage thumbImage = (slider.getOrientation() == JSlider.VERTICAL) ? verticalThumbImage : horizontalThumbImage; if (thumbImage != null) { // Get thumb position. Rectangle thumbBounds = thumbRect; // Create graphics copy. Graphics gTemp = g.create(); // Draw thumb image. gTemp.translate(thumbBounds.x, thumbBounds.y); gTemp.drawImage(thumbImage, 0, 0, null); gTemp.dispose(); } else { super.paintThumb(g); } } }