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

org.apache.pivot.wtk.skin.ImageViewSkin Maven / Gradle / Ivy

The 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.apache.pivot.wtk.skin;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Composite;
import java.awt.Graphics2D;
import java.awt.Transparency;

import org.apache.pivot.wtk.Bounds;
import org.apache.pivot.wtk.Component;
import org.apache.pivot.wtk.Dimensions;
import org.apache.pivot.wtk.GraphicsUtilities;
import org.apache.pivot.wtk.HorizontalAlignment;
import org.apache.pivot.wtk.ImageView;
import org.apache.pivot.wtk.ImageViewListener;
import org.apache.pivot.wtk.VerticalAlignment;
import org.apache.pivot.wtk.media.Image;
import org.apache.pivot.wtk.media.ImageListener;

/**
 * Image view skin.
 * 

* TODO Add a rotation (float) style. */ public class ImageViewSkin extends ComponentSkin implements ImageViewListener { private Color backgroundColor = null; private float opacity = 1.0f; private HorizontalAlignment horizontalAlignment = HorizontalAlignment.CENTER; private VerticalAlignment verticalAlignment = VerticalAlignment.CENTER; private boolean fill = false; private boolean preserveAspectRatio = true; private int imageX = 0; private int imageY = 0; private float scaleX = 1; private float scaleY = 1; private ImageListener imageListener = new ImageListener() { @Override public void sizeChanged(Image image, int previousWidth, int previousHeight) { invalidateComponent(); } @Override public void baselineChanged(Image image, int previousBaseline) { invalidateComponent(); } @Override public void regionUpdated(Image image, int x, int y, int width, int height) { // TODO A rounding error is causing an off-by-one error; we're // accounting for it here by adding 1 to width and height Bounds bounds = new Bounds(imageX + (int)Math.floor(x * scaleX), imageY + (int)Math.floor(y * scaleY), (int)Math.ceil(width * scaleX) + 1, (int)Math.ceil(height * scaleY) + 1); repaintComponent(bounds); } }; @Override public void install(Component component) { super.install(component); ImageView imageView = (ImageView)component; imageView.getImageViewListeners().add(this); Image image = imageView.getImage(); if (image != null) { image.getImageListeners().add(imageListener); } } @Override public int getPreferredWidth(int height) { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); return (image == null) ? 0 : image.getWidth(); } @Override public int getPreferredHeight(int width) { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); return (image == null) ? 0 : image.getHeight(); } @Override public Dimensions getPreferredSize() { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); return (image == null) ? new Dimensions(0, 0) : new Dimensions(image.getWidth(), image.getHeight()); } @Override public int getBaseline(int width, int height) { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); int baseline = -1; if (image != null) { baseline = image.getBaseline(); if (baseline != -1) { Dimensions imageSize = image.getSize(); if (fill) { // Scale to fit if (preserveAspectRatio) { float aspectRatio = (float)width / (float)height; float imageAspectRatio = (float)imageSize.width / (float)imageSize.height; if (aspectRatio > imageAspectRatio) { baseline *= (float)height / (float)imageSize.height; } else { float scaleYLocal = (float)width / (float)imageSize.width; baseline *= scaleYLocal; baseline += (int)(height - imageSize.height * scaleYLocal) / 2; } } else { baseline *= (float)height / (float)imageSize.height; } } else { if (verticalAlignment == VerticalAlignment.CENTER) { baseline += (height - imageSize.height) / 2; } else if (verticalAlignment == VerticalAlignment.BOTTOM) { baseline += height - imageSize.height; } } } } return baseline; } @Override public void layout() { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); if (image != null) { int width = getWidth(); int height = getHeight(); Dimensions imageSize = image.getSize(); if (fill) { // Scale to fit if (preserveAspectRatio) { float aspectRatio = (float)width / (float)height; float imageAspectRatio = (float)imageSize.width / (float)imageSize.height; if (aspectRatio > imageAspectRatio) { imageY = 0; scaleY = (float)height / (float)imageSize.height; imageX = (int)(width - imageSize.width * scaleY) / 2; scaleX = scaleY; } else { imageX = 0; scaleX = (float)width / (float)imageSize.width; imageY = (int)(height - imageSize.height * scaleX) / 2; scaleY = scaleX; } } else { imageX = 0; scaleX = (float)width / (float)imageSize.width; imageY = 0; scaleY = (float)height / (float)imageSize.height; } } else { if (horizontalAlignment == HorizontalAlignment.CENTER) { imageX = (width - imageSize.width) / 2; } else if (horizontalAlignment == HorizontalAlignment.RIGHT) { imageX = width - imageSize.width; } else { imageX = 0; } scaleX = 1.0f; if (verticalAlignment == VerticalAlignment.CENTER) { imageY = (height - imageSize.height) / 2; } else if (verticalAlignment == VerticalAlignment.BOTTOM) { imageY = height - imageSize.height; } else { imageY = 0; } scaleY = 1.0f; } } } @Override public void paint(Graphics2D graphics) { ImageView imageView = (ImageView)getComponent(); Image image = imageView.getImage(); int width = getWidth(); int height = getHeight(); if (backgroundColor != null) { graphics.setPaint(backgroundColor); graphics.fillRect(0, 0, width, height); } if (image != null) { Graphics2D imageGraphics = (Graphics2D)graphics.create(); imageGraphics.translate(imageX, imageY); imageGraphics.scale(scaleX, scaleY); // Apply an alpha composite if the opacity value is less than // the current alpha float alpha = 1.0f; Composite composite = imageGraphics.getComposite(); if (composite instanceof AlphaComposite) { AlphaComposite alphaComposite = (AlphaComposite)composite; alpha = alphaComposite.getAlpha(); } if (opacity < alpha) { imageGraphics.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, opacity)); } image.paint(imageGraphics); imageGraphics.dispose(); } } /** * @return * false; image views are not focusable. */ @Override public boolean isFocusable() { return false; } @Override public boolean isOpaque() { return (backgroundColor != null && backgroundColor.getTransparency() == Transparency.OPAQUE); } /** * Returns the color that is painted behind the image */ public Color getBackgroundColor() { return backgroundColor; } /** * Sets the color that is painted behind the image */ public void setBackgroundColor(Color backgroundColor) { this.backgroundColor = backgroundColor; repaintComponent(); } /** * Sets the color that is painted behind the image * @param backgroundColor Any of the * {@linkplain GraphicsUtilities#decodeColor color values recognized by Pivot}. */ public final void setBackgroundColor(String backgroundColor) { if (backgroundColor == null) { throw new IllegalArgumentException("backgroundColor is null."); } setBackgroundColor(GraphicsUtilities.decodeColor(backgroundColor)); } /** * Returns the opacity of the image, in [0,1]. */ public float getOpacity() { return opacity; } /** * Sets the opacity of the image. * @param opacity A number between 0 (transparent) and 1 (opaque) */ public void setOpacity(float opacity) { if (opacity < 0 || opacity > 1) { throw new IllegalArgumentException("Opacity out of range [0,1]."); } this.opacity = opacity; repaintComponent(); } /** * Sets the opacity of the image. * @param opacity A number between 0 (transparent) and 1 (opaque) */ public final void setOpacity(Number opacity) { if (opacity == null) { throw new IllegalArgumentException("opacity is null."); } setOpacity(opacity.floatValue()); } /** * Returns the horizontal alignment of the image. */ public HorizontalAlignment getHorizontalAlignment() { return horizontalAlignment; } /** * Sets the horizontal alignment of the image. * Ignored if the fill style is true. */ public void setHorizontalAlignment(HorizontalAlignment horizontalAlignment) { if (horizontalAlignment == null) { throw new IllegalArgumentException("horizontalAlignment is null."); } this.horizontalAlignment = horizontalAlignment; layout(); repaintComponent(); } /** * Returns the vertical alignment of the image. */ public VerticalAlignment getVerticalAlignment() { return verticalAlignment; } /** * Sets the vertical alignment of the image. * Ignored if the fill style is true. */ public void setVerticalAlignment(VerticalAlignment verticalAlignment) { if (verticalAlignment == null) { throw new IllegalArgumentException("verticalAlignment is null."); } this.verticalAlignment = verticalAlignment; layout(); repaintComponent(); } /** * Returns a boolean indicating whether the image will be scaled to fit * the space in which it is placed. */ public boolean getFill() { return fill; } /** * Sets a boolean indicating whether the image will be scaled to fit * the space in which it is placed. Note that for scaling to occur, * the ImageView must specify a preferred size or be placed * in a container that constrains its size. */ public void setFill(boolean fill) { this.fill = fill; layout(); repaintComponent(); } /** * Returns a boolean indicating whether, when the image is scaled, * its aspect ratio is preserved. */ public boolean getPreserveAspectRatio() { return preserveAspectRatio; } /** * Sets a boolean indicating whether, when the image is scaled, * its aspect ratio is preserved. * Ignored if the fill style is false. */ public void setPreserveAspectRatio(boolean preserveAspectRatio) { this.preserveAspectRatio = preserveAspectRatio; layout(); repaintComponent(); } // Image view events @Override public void imageChanged(ImageView imageView, Image previousImage) { if (previousImage != null) { previousImage.getImageListeners().remove(imageListener); } Image image = imageView.getImage(); if (image != null) { image.getImageListeners().add(imageListener); } invalidateComponent(); } @Override public void asynchronousChanged(ImageView imageView) { // No-op } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy