/**
* This file is part of VisiCut.
* Copyright (C) 2011 - 2013 Thomas Oster <thomas.oster@rwth-aachen.de>
* RWTH Aachen University - 52062 Aachen, Germany
*
* VisiCut is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* VisiCut is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with VisiCut. If not, see <http://www.gnu.org/licenses/>.
**/
package com.t_oster.uicomponents;
import com.t_oster.liblasercut.platform.Util;
import java.awt.geom.Rectangle2D;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
/**
*
* @author Thomas Oster <thomas.oster@rwth-aachen.de>
*/
public class PositionPanel extends javax.swing.JPanel implements PropertyChangeListener
{
/**
* Creates new form PositionPanel
*/
public PositionPanel()
{
initComponents();
tfX.addPropertyChangeListener(UnitTextfield.PROP_VALUE, this);
tfY.addPropertyChangeListener(UnitTextfield.PROP_VALUE, this);
tfWidth.addPropertyChangeListener(UnitTextfield.PROP_VALUE, this);
tfHeight.addPropertyChangeListener(UnitTextfield.PROP_VALUE, this);
tfAngle.addPropertyChangeListener(UnitTextfield.PROP_VALUE, this);
}
private boolean ignoreTextfieldUpdates = false;
public void propertyChange(PropertyChangeEvent pce)
{
if (pce.getSource().equals(tfAngle))
{
double oldAngle = this.angle;
this.angle = tfAngle.getValue();
firePropertyChange(PROP_ANGLE, oldAngle, angle);
}
else if (!ignoreTextfieldUpdates)
{
if (cbProportional.isSelected())
{
ignoreTextfieldUpdates = true;
if (this.rectangle.getWidth() != 0 || this.getRectangle().getHeight() != 0)
{
double whfactor = this.rectangle.getHeight()/this.rectangle.getWidth();
if (pce.getSource().equals(tfWidth))
{
tfHeight.setValue(tfWidth.getValue()*whfactor);
}
else if (pce.getSource().equals(tfHeight))
{
tfWidth.setValue(tfHeight.getValue()/whfactor);
}
}
ignoreTextfieldUpdates = false;
}
Rectangle2D oldRectangle = this.rectangle;
this.rectangle = this.getRectangleFromTextfields();
firePropertyChange(PROP_RECTANGLE, oldRectangle, this.rectangle);
}
}
private double angle = 0;
public static final String PROP_ANGLE = "angle";
/**
* Get the value of angle
*
* @return the value of angle
*/
public double getAngle()
{
return angle;
}
private void updateAngleText()
{
this.tfAngle.setValue(this.angle);
}
private void updateRectanlgeText()
{
this.ignoreTextfieldUpdates = true;
tfWidth.setValue(this.rectangle.getWidth());
tfHeight.setValue(this.rectangle.getHeight());
updateXYText();
this.ignoreTextfieldUpdates = false;
}
/**
* Set the value of angle
*
* @param angle new value of angle
*/
public void setAngle(double angle)
{
double oldAngle = this.angle;
if (oldAngle != angle)
{
this.angle = checkNaN(angle);
this.updateAngleText();
firePropertyChange(PROP_ANGLE, oldAngle, angle);
}
}
private Rectangle2D rectangle = null;
public static final String PROP_RECTANGLE = "rectangle";
/**
* Get the value of rectangle
*
* @return the value of rectangle
*/
public Rectangle2D getRectangle()
{
return rectangle;
}
private void updateXYText()
{
AncorPointPanel.Position p = this.ancorPointPanel1.getPosition();
double x,y;
if (this.rectangle == null)
{
x = 0;
y = 0;
}
else
{
switch (p)
{
case TOP_LEFT:
x = this.rectangle.getMinX();
y = this.rectangle.getMinY();
break;
case TOP_CENTER:
x = this.rectangle.getWidth() != 0 ? this.rectangle.getCenterX() : this.rectangle.getMinX();
y = this.rectangle.getMinY();
break;
case TOP_RIGHT:
x = this.rectangle.getMaxX();
y = this.rectangle.getMinY();
break;
case CENTER_LEFT:
x = this.rectangle.getMinX();
y = this.rectangle.getHeight() != 0 ? this.rectangle.getCenterY() : this.rectangle.getMinY();
break;
case CENTER_CENTER:
x = this.rectangle.getWidth() != 0 ? this.rectangle.getCenterX() : this.rectangle.getMinX();
y = this.rectangle.getHeight() != 0 ? this.rectangle.getCenterY() : this.rectangle.getMinY();
break;
case CENTER_RIGHT:
x = this.rectangle.getMaxX();
y = this.rectangle.getHeight() != 0 ? this.rectangle.getCenterY() : this.rectangle.getMinY();
break;
case BOTTOM_LEFT:
x = this.rectangle.getMinX();
y = this.rectangle.getMaxY();
break;
case BOTTOM_CENTER:
x = this.rectangle.getWidth() != 0 ? this.rectangle.getCenterX() : this.rectangle.getMinX();
y = this.rectangle.getMaxY();
break;
case BOTTOM_RIGHT:
x = this.rectangle.getMaxX();
y = this.rectangle.getMaxY();
break;
default:
x = 0;
y = 0;
break;
}
}
boolean oldIgnoreTextfieldUpdates = ignoreTextfieldUpdates;
ignoreTextfieldUpdates = true;
tfX.setValue(checkNaN(x));
tfY.setValue(checkNaN(y));
ignoreTextfieldUpdates = oldIgnoreTextfieldUpdates;
}
/**
* Checks d if it's = NaN and
* returns 0 in this case, else d
* @param d
* @return d or 0 if d == NaN
*/
private double checkNaN(double d)
{
return Double.isNaN(d) ? 0 : d;
}
private Rectangle2D getRectangleFromTextfields()
{
try
{
double w = tfWidth.getValue();
double h = tfHeight.getValue();
double x = tfX.getValue();
double y = tfY.getValue();
switch (this.ancorPointPanel1.getPosition())
{
case TOP_LEFT:
break;
case TOP_CENTER:
x -= w/2;
break;
case TOP_RIGHT:
x -= w;
break;
case CENTER_LEFT:
y -= h/2;
break;
case CENTER_CENTER:
y -= h/2;
x -= w/2;
break;
case CENTER_RIGHT:
y -= h/2;
x -= w;
break;
case BOTTOM_LEFT:
y -= h;
break;
case BOTTOM_CENTER:
y -= h;
x -= w/2;
break;
case BOTTOM_RIGHT:
y -= h;
x -= w;
break;
default:
x = 0;
y = 0;
}
return new Rectangle2D.Double(x,y,w,h);
}
catch (NumberFormatException e)
{
return this.rectangle;
}
}
/**
* Set the value of rectangle
*
* @param rectangle new value of rectangle
*/
public void setRectangle(Rectangle2D rectangle)
{
Rectangle2D oldRectangle = this.rectangle;
if (Util.differ(oldRectangle, rectangle))
{
this.rectangle = new Rectangle2D.Double(checkNaN(rectangle.getX()), checkNaN(rectangle.getY()), checkNaN(rectangle.getWidth()), checkNaN(rectangle.getHeight()));
this.updateRectanlgeText();
firePropertyChange(PROP_RECTANGLE, oldRectangle, this.rectangle);
}
}
/**
* This method is called from within the constructor to initialize the form.
* WARNING: Do NOT modify this code. The content of this method is always
* regenerated by the Form Editor.
*/
@SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents()
{
lbY1 = new java.awt.Label();
lbX1 = new java.awt.Label();
lbY2 = new java.awt.Label();
jPanel1 = new javax.swing.JPanel();
lbX = new java.awt.Label();
lbY = new java.awt.Label();
ancorPointPanel1 = new com.t_oster.uicomponents.AncorPointPanel();
tfX = new com.t_oster.uicomponents.LengthTextfield();
tfY = new com.t_oster.uicomponents.LengthTextfield();
tfHeight = new com.t_oster.uicomponents.LengthTextfield();
tfAngle = new com.t_oster.uicomponents.AngleTextfield();
tfWidth = new com.t_oster.uicomponents.LengthTextfield();
cbProportional = new javax.swing.JCheckBox();
java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("com/t_oster/uicomponents/resources/PositionPanel"); // NOI18N
lbY1.setText(bundle.getString("HEIGHT")); // NOI18N
lbX1.setText(bundle.getString("WIDTH")); // NOI18N
lbY2.setText(bundle.getString("ANGLE")); // NOI18N
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(bundle.getString("REFERENCE"))); // NOI18N
lbX.setText(bundle.getString("X")); // NOI18N
lbY.setText(bundle.getString("Y")); // NOI18N
ancorPointPanel1.addPropertyChangeListener(new java.beans.PropertyChangeListener()
{
public void propertyChange(java.beans.PropertyChangeEvent evt)
{
ancorPointPanel1PropertyChange(evt);
}
});
javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
jPanel1.setLayout(jPanel1Layout);
jPanel1Layout.setHorizontalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(ancorPointPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(lbX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tfX, javax.swing.GroupLayout.DEFAULT_SIZE, 128, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(lbY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(tfY, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
.addContainerGap())
);
jPanel1Layout.setVerticalGroup(
jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(ancorPointPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(0, 21, Short.MAX_VALUE))
.addGroup(jPanel1Layout.createSequentialGroup()
.addContainerGap()
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
.addComponent(lbX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addComponent(tfX, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGap(1, 1, 1)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(jPanel1Layout.createSequentialGroup()
.addGap(1, 1, 1)
.addComponent(tfY, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
);
cbProportional.setText(bundle.getString("PROPORTIONAL")); // NOI18N
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
this.setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbY1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbX1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lbY2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(tfAngle, javax.swing.GroupLayout.PREFERRED_SIZE, 191, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
.addComponent(tfHeight, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
.addComponent(tfWidth, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, 85, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(cbProportional)))))
.addContainerGap(25, Short.MAX_VALUE))
);
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbX1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tfWidth, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbY1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tfHeight, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addGroup(layout.createSequentialGroup()
.addGap(23, 23, 23)
.addComponent(cbProportional)))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addComponent(lbY2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(tfAngle, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
.addContainerGap(74, Short.MAX_VALUE))
);
}// </editor-fold>//GEN-END:initComponents
private void ancorPointPanel1PropertyChange(java.beans.PropertyChangeEvent evt)//GEN-FIRST:event_ancorPointPanel1PropertyChange
{//GEN-HEADEREND:event_ancorPointPanel1PropertyChange
this.updateXYText();
}//GEN-LAST:event_ancorPointPanel1PropertyChange
// Variables declaration - do not modify//GEN-BEGIN:variables
private com.t_oster.uicomponents.AncorPointPanel ancorPointPanel1;
private javax.swing.JCheckBox cbProportional;
private javax.swing.JPanel jPanel1;
private java.awt.Label lbX;
private java.awt.Label lbX1;
private java.awt.Label lbY;
private java.awt.Label lbY1;
private java.awt.Label lbY2;
private com.t_oster.uicomponents.AngleTextfield tfAngle;
private com.t_oster.uicomponents.LengthTextfield tfHeight;
private com.t_oster.uicomponents.LengthTextfield tfWidth;
private com.t_oster.uicomponents.LengthTextfield tfX;
private com.t_oster.uicomponents.LengthTextfield tfY;
// End of variables declaration//GEN-END:variables
}