/*
* This file is based on code by Piet Blok, with amendments by David Gilbert.
* For Piet's original code, see:
*
* http://www.pbjar.org/blogs/jxlayer/JXLayer_one.html
*
* Copyright (C) 2008 Piet Blok.
*
* Licensed 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.geoforge.guillc.jdesktop.jxlayer.plaf;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint;
import java.awt.Paint;
import java.awt.RadialGradientPaint;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Point2D;
import javax.swing.SwingUtilities;
import org.geoforge.awt.graphics2d.GfrUtilGraphics2D;
import org.jdesktop.jxlayer.JXLayer;
import org.jdesktop.jxlayer.plaf.AbstractLayerUI;
/**
* Shows a magnification glass on top of a component.
*/
public class MagnifierUI extends AbstractLayerUI {
//private int radius = 80;
private double magnifyingFactor = 4.0;
private Point2D point = new Point2D.Double();
/**
* Returns the magnifying scale factor.
*
* @return The magnifying scale factor.
*/
public double getMagnifyingFactor() {
return this.magnifyingFactor;
}
/**
* Sets the magnifying scale factor.
*
* @param factor the new scale factor.
*/
public void setMagnifyingFactor(double factor) {
this.magnifyingFactor = factor;
}
/**
* Returns the radius of the magnifying glass, in Java2D units.
*
* @return The radius.
*/
/*public int getRadius() {
return this.radius;
}*/
/**
* Sets the radius of the magnifying glass.
*
* @param radius the new radius (in Java2D units).
*/
/*public void setRadius(int radius) {
this.radius = radius;
}*/
/**
* Returns the current location of the magnifying glass.
*
* @return The current location.
*/
public Point2D getPoint() {
return this.point;
}
/**
* Sets the location of the magnifying glass.
*
* @param point the new location.
*/
public void setPoint(Point2D point) {
this.point.setLocation(point);
}
private double _dblRadiusBase_ = 40;
/**
* Paints the magnifying glass.
*
* @param g2d the graphics device.
* @param layer the layer.
*/
@Override
protected void paintLayer(Graphics2D g2d, JXLayer layer)
{
super.paintLayer(g2d, layer);
//Point2D point = getPoint();
double scale = getMagnifyingFactor();
double baseRadius = this._dblRadiusBase_; // getRadius();
double scaledRadius = (baseRadius / scale);
double strokeAdjust = 0.5;
double drawSize = 2 * (baseRadius + strokeAdjust);
double clipSize = 2 * scaledRadius;
Ellipse2D drawGlass = new Ellipse2D.Double(-strokeAdjust,
-strokeAdjust, drawSize, drawSize);
Ellipse2D clipGlass = new Ellipse2D.Double(0, 0, clipSize, clipSize);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
GfrUtilGraphics2D.s_setRenderingAntiAliasOn(g2d);
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION,
RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.translate(point.getX() - baseRadius, point.getY() - baseRadius);
Color oldColor = g2d.getColor();
g2d.setPaint(_createPaint_(drawGlass, false));
g2d.fill(drawGlass);
g2d.setColor(oldColor);
g2d.draw(drawGlass);
AffineTransform oldTransform = g2d.getTransform();
Shape oldClip = g2d.getClip();
g2d.scale(scale, scale);
g2d.clip(clipGlass);
g2d.translate(scaledRadius - point.getX(), scaledRadius - point.getY());
layer.paint(g2d);
g2d.setTransform(oldTransform);
g2d.setClip(oldClip);
g2d.setPaint(_createPaint_(drawGlass, true));
g2d.fill(drawGlass);
}
/**
* Updates the glass location in response to mouse events.
*
* @param e the event.
* @param layer the layer.
*/
@Override
protected void processMouseEvent(MouseEvent e, JXLayer layer) {
super.processMouseEvent(e, layer);
setPoint(SwingUtilities.convertPoint(e.getComponent(),
e.getPoint(), layer));
setDirty(true);
}
/**
* Updates the glass location in response to mouse events.
*
* @param e the event.
* @param layer the layer.
*/
@Override
protected void processMouseMotionEvent(MouseEvent e,
JXLayer layer) {
super.processMouseMotionEvent(e, layer);
setPoint(SwingUtilities.convertPoint(e.getComponent(),
e.getPoint(), layer));
setDirty(true);
}
/**
* A utility method to create the paint for the glass.
*
* @param glass the glass shape.
* @param transparent transparent?
*
* @return The paint.
*/
private Paint _createPaint_(Ellipse2D glass, boolean transparent)
{
Point2D center = new Point2D.Double(glass.getCenterX(),
glass.getCenterY());
float radius = (float) (glass.getCenterX() - glass.getX());
Point2D focus = new Point2D.Double(center.getX() - 0.5 * radius,
center.getY() - 0.5 * radius);
Color[] colors = new Color[] {
transparent ? new Color(255, 255, 255, 128) : Color.WHITE,
transparent ? new Color(0, 255, 255, 32) : Color.CYAN };
float[] fractions = new float[] { 0f, 1f };
RadialGradientPaint paint = new RadialGradientPaint(center, radius,
focus, fractions, colors,
MultipleGradientPaint.CycleMethod.NO_CYCLE);
return paint;
}
}