<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">/*
 * FieldPanel.java
 *
 * Created on February 6, 2007, 12:42 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package usda.weru.erosion.barriereditor;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Insets;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import javax.swing.JPanel;
import usda.weru.erosion.DataStore;

/**
 *
 * @author Joseph Levin
 */
public class FieldPanel extends JPanel implements PropertyChangeListener, ComponentListener, MouseListener, MouseMotionListener {
    private static final long serialVersionUID = 1L;
    
    /** Identifies change in user's single-file selection. */
    public static final String SELECTED_BARRIER_CHANGED_PROPERTY = "SelectedBarrierChangedProperty";

	/**
	 *
	 */
	protected PropertyChangeSupport c_changes;

	/**
	 *
	 */
	protected FieldDataModel c_data;

	/**
	 *
	 */
	protected AffineTransform c_transform;

	/**
	 *
	 */
	protected BarrierPolygon c_hoverBarrier;

	/**
	 *
	 */
	protected Color c_hoverColor = new Color(153, 204, 255);

	/**
	 *
	 */
	protected Color c_barrierColor = Color.RED;

	/**
	 *
	 */
	protected Insets c_margin = new Insets(25,25,25,25);

	/**
	 *
	 */
	protected double c_scale = 1;

	/**
	 *
	 */
	protected double c_minimumVisibleBarrierWidth = 3;
    
    
    
    /**
     * Creates a new instance of FieldPanel
     */
    public FieldPanel() {
        c_changes = new PropertyChangeSupport(this);
        addComponentListener(this);
        addMouseListener(this);
        addMouseMotionListener(this);
    }

	/**
	 *
	 * @param l
	 */
	@Override
    public void addPropertyChangeListener(PropertyChangeListener l){
        c_changes.addPropertyChangeListener(l);
    }

	/**
	 *
	 * @param l
	 */
	@Override
    public void removePropertyChangeListener(PropertyChangeListener l){
        c_changes.removePropertyChangeListener(l);
    }

	/**
	 *
	 * @param model
	 */
	public void setFieldDataModel(FieldDataModel model){
        if (c_data != null){
            c_data.removePropertyChangeListener(this);
        }
        c_data = model;
        c_data.addPropertyChangeListener(this);
    }

	/**
	 *
	 * @param evt
	 */
	@Override
    public void propertyChange(PropertyChangeEvent evt) {
        String property = evt.getPropertyName();
        if (property.equals(DataStore.SimField)){
            calculateTransform();
            repaint();
        } else if (property.equals(DataStore.SimRegAngle)){
            calculateTransform();
            repaint();
        } else if (property.startsWith(DataStore.BarriersObj)){
            calculateTransform();
            repaint();
        }
        
    }
    
    private Rectangle addBounds(Rectangle base, Rectangle add){
        if (add == null) return base;
        base.x = Math.min(base.x, add.x);
        base.y = Math.min(base.y, add.y);
        base.width = Math.max(base.width, add.width + add.x);
        base.height = Math.max(base.height, add.height + add.y);
        
        
        return base;
    }

	/**
	 *
	 */
	protected void calculateTransform(){
        //Panel size minus the margins
        double pWidth = getWidth() - c_margin.left - c_margin.right - getInsets().left - getInsets().right;
        double pHeight = getHeight() - c_margin.top - c_margin.bottom - getInsets().top - getInsets().bottom;
        double pAspect = pWidth / pHeight;
        
        
        
        
        Rectangle bounds = c_data.getFieldPolygon().getBounds();        
        for (int b = 0; b &lt; c_data.getBarrierCount(); b++){
            bounds = addBounds(bounds, c_data.getBarrier(b).getBounds());                        
        }
        
        
        double bWidth = bounds.getWidth() - bounds.getX() ;
        double bHeight = bounds.getHeight() - bounds.getY();
        
        double fAspect = bWidth / bHeight;
        
        if (fAspect &gt; pAspect){
            //Resize by width
            c_scale = pWidth / bWidth;
        } else{
            //Resize by height
            c_scale = pHeight / bHeight;
        }
        
        //Panel size to field scale
        double myWidth = getWidth() / c_scale;  
        double myHeight = getHeight() / c_scale;
                        
        double x = (myWidth / 2) - (bWidth / 2) - bounds.x;
        double y = (myHeight / 2) - (bHeight / 2) - bounds.y;
        
        
        c_transform = new AffineTransform();
        //Flip on the horizontal axis
        c_transform.scale(1, -1);
        c_transform.translate(0, -getHeight());
        //Rotate the field
        c_transform.rotate(Math.toRadians(-c_data.getFieldAngle()), getWidth()/2., getHeight()/2.);
        //Scale the field
        c_transform.scale(c_scale, c_scale);
        //Move drawing origin to the corner of the field, this allows the drawing code to just use the polygons
        c_transform.translate(x, y);
        
    }

	/**
	 *
	 * @param g
	 */
	@Override
    protected void paintComponent(Graphics g) {
        if (c_data == null){
            super.paintComponent(g);
            return;
        } else if (c_transform == null || c_scale &lt; 0){
            calculateTransform();
            repaint();
            return;
        }
        BufferedImage image = new BufferedImage(getWidth(), getHeight(), BufferedImage.TYPE_INT_ARGB);
        Graphics g2 = image.createGraphics();
        if (isOpaque()){
            g.setColor(getBackground());
            g.fillRect(0,0,getWidth(), getHeight());
        }
        paintField(g2);
        g.drawImage(image, 0, 0, null);
        //paintTextOverlays(g);
    }

	/**
	 *
	 * @param g
	 */
	protected void paintField(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
        
        //apply the transforms used
        g2d.setTransform(c_transform);
        
        //Paint the field
        g2d.setColor(Color.GREEN);
        g2d.fillPolygon(c_data.getFieldPolygon());
        
        //paint Field border
        g2d.setStroke(new BasicStroke(3.0f/(float)c_scale));
        g2d.setColor(Color.BLACK);
        g2d.drawPolygon(c_data.getFieldPolygon());
        
        
        //Paint barriers
        for (int i = 0; i &lt; c_data.getBarrierCount(); i++){
            BarrierPolygon barrier = c_data.getBarrier(i);
            
            if (barrier.getWid() * c_scale &lt; c_minimumVisibleBarrierWidth){
                //The barrier is too small, so we display it larger
                if (barrier == c_hoverBarrier){
                    g2d.setStroke(new BasicStroke(((float)c_minimumVisibleBarrierWidth + 3.f)/(float)c_scale));
                    g2d.setColor(c_hoverColor);
                    g2d.drawLine((int)barrier.getX1(), (int)barrier.getY1(), (int)barrier.getX2(), (int)barrier.getY2());
                }
                g2d.setStroke(new BasicStroke((float)c_minimumVisibleBarrierWidth/(float)c_scale));
                g2d.setColor(c_barrierColor);
                g2d.drawLine((int)barrier.getX1(), (int)barrier.getY1(), (int)barrier.getX2(), (int)barrier.getY2());
                
                
                
            } else{
                g2d.setColor(c_barrierColor);
                g2d.fillPolygon(barrier);
                if (barrier == c_hoverBarrier){
                    //the mouse is over this barrier
                    g2d.setColor(c_hoverColor);
                    g2d.setStroke(new BasicStroke(3.0f/(float)c_scale));
                    g2d.drawPolygon(barrier);
                }
            }
            
        }
        
        //Paint the dotted field border
        float dash[] = { 10.0f / (float)c_scale };
        float miter = 10.0f / (float)c_scale;
        miter = Math.max(miter, 1.0f);
        g2d.setStroke(new BasicStroke(1.0f / (float)c_scale, BasicStroke.CAP_SQUARE,BasicStroke.JOIN_MITER, miter, dash, 0.0f/ (float)c_scale));
        g2d.setColor(Color.BLACK);
        g2d.drawPolygon(c_data.getFieldPolygon());
        
        
    }

	/**
	 *
	 * @param g
	 */
	protected void paintTextOverlays(Graphics g) {
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.translate(getWidth()/2, getHeight()/2);
        g2d.rotate(Math.toRadians(c_data.getFieldAngle()));
        g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
        g2d.setColor(Color.BLACK);
        //g2d.drawString("X-Length", c_margin.left, (int)(getHeight() - (c_margin.bottom /2)));
        //g2d.drawString("X-Length", -25, (int) (SYLen / 2)+20);
        g2d.drawString("X-Length (m)", -25, (getHeight() / 2) + 20);
        
        g2d.rotate(Math.toRadians(90));
        
        g2d.drawString("Y-Length (m)", -25, (getWidth() / 2) + 20);
        //g2d.drawString("Y-Length", 100, 100);
        //g2d.drawString("Y-Length", 100, 100);
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void componentResized(ComponentEvent e) {
        calculateTransform();
        repaint();
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void componentMoved(ComponentEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void componentShown(ComponentEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void componentHidden(ComponentEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseClicked(MouseEvent e) {
        if (c_transform == null) return;
        Point2D sourcePoint = new Point2D.Double(e.getX(), e.getY());
        try {
            Point2D inversePoint = c_transform.inverseTransform(sourcePoint, null);
            for (int i = 0; i &lt; c_data.getBarrierCount(); i++){
                BarrierPolygon barrier = c_data.getBarrier(i);
                if (barrier.contains(inversePoint)){
                    c_changes.firePropertyChange(SELECTED_BARRIER_CHANGED_PROPERTY, null, barrier);
                    return;
                }
            }
            c_changes.firePropertyChange(SELECTED_BARRIER_CHANGED_PROPERTY, null, null);
            
        } catch (NoninvertibleTransformException ex) {
            return;
        }
        
        
        
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mousePressed(MouseEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseReleased(MouseEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseEntered(MouseEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseExited(MouseEvent e) {
        if (c_hoverBarrier != null){
            c_hoverBarrier = null;
            repaint();
        }
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseDragged(MouseEvent e) {
    }

	/**
	 *
	 * @param e
	 */
	@Override
    public void mouseMoved(MouseEvent e) {
        if (c_transform == null){
            c_hoverBarrier = null;
            return;
        }
        Point2D sourcePoint = new Point2D.Double(e.getX(), e.getY());
        try {
            Point2D inversePoint = c_transform.inverseTransform(sourcePoint, null);
            for (int i = 0; i &lt; c_data.getBarrierCount(); i++){
                BarrierPolygon barrier = c_data.getBarrier(i);
                if (barrier.contains(inversePoint)){
                    if (barrier != c_hoverBarrier){
                        c_hoverBarrier = barrier;
                        repaint();
                    }
                    return;
                }
            }
            
            if (c_hoverBarrier != null){
                c_hoverBarrier = null;
                repaint();
            }
            
        } catch (NoninvertibleTransformException ex) {
            return;
        }
    }
    
    
    
    
    
    
    
    
}
</pre></body></html>