package net.xoetrope.builder.editor;
import javax.swing.JPanel;
import java.awt.Point;
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.util.Vector;
import java.awt.event.ComponentEvent;
import java.awt.AWTEvent;
import java.awt.Event;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.JToggleButton;
import java.awt.Rectangle;
import javax.swing.SwingUtilities;
import java.awt.Component;
import java.util.prefs.Preferences;
import java.awt.SystemColor;
/**
* <p> Copyright (c) Xoetrope Ltd., 2002-2003</p>
* <p> $Revision: 1.7 $</p>
* <p> License: see License.txt</p>
*/
public class XGuidePane extends JPanel implements ActionListener
{
private int left, top, width, height;
private static final int NORMAL = 0;
private static final int ADD_VERTICAL_GUIDE = 1;
private static final int ADD_HORIZONTAL_GUIDE = 2;
private static final int MOVE_VERTICAL_GUIDE = 3;
private static final int MOVE_HORIZONTAL_GUIDE = 4;
private static final int GRID_SNAP_RANGE = 3;
private int mode = NORMAL;
private int selectedGuideIdx = -1;
private Point oldP;
private JToggleButton editBtn;
private boolean editMode;
private boolean paintGuides;
private int snapRange;
private Vector horzGuides = new Vector();
private Vector vertGuides = new Vector();
public XGuidePane()
{
setLayout( null );
setOpaque( false );
left = top = 10;
width = 640;
height = 480;
snapRange = GRID_SNAP_RANGE;
Preferences prefs = Preferences.userNodeForPackage( XuiEditor.class );
snapRange = Integer.parseInt( prefs.get( "GuideSnapRange", Integer.toString( snapRange ) ));
editBtn = new JToggleButton();
editBtn.setBounds( 0, 0, 10, 10 );
editBtn.addActionListener( this );
add( editBtn );
editMode = false;
paintGuides = true;
}
public void actionPerformed( ActionEvent e )
{
if ( !editMode ) {
enableEvents( AWTEvent.MOUSE_EVENT_MASK );
enableEvents( AWTEvent.MOUSE_MOTION_EVENT_MASK );
}
else {
disableEvents( AWTEvent.MOUSE_EVENT_MASK );
disableEvents( AWTEvent.MOUSE_MOTION_EVENT_MASK );
}
editMode = !editMode;
editBtn.setSelected( editMode );
int numChildren = getComponentCount();
for ( int i = 0; i < numChildren; i++ ) {
Component c = (Component)getComponent( i );
if ( c != editBtn )
c.setVisible( !editMode );
}
}
/**
* Remove all the children
*/
public void clear()
{
int numChildren = getComponentCount();
Component children[] = getComponents();
for ( int i = 0; i < numChildren; i++ ) {
if ( children[ i ] != editBtn )
remove( children[ i ] );
}
}
/**
* Toggle the painting of the guides and gutters
* @param doPaint true to do the painting
*/
public void setPaintGuides( boolean doPaint )
{
paintGuides = doPaint;
editBtn.setVisible( doPaint );
}
/**
* Get the flag indicating painting of the guides and gutters
* @param true if the guides are painted
*/
public boolean getPaintGuides()
{
return paintGuides;
}
public void paintComponent( Graphics g )
{
if ( paintGuides ) {
Rectangle clipRect = g.getClipBounds();
paintGrid( g, clipRect );
paintGutters( g, clipRect );
}
else
super.paintComponent( g );
}
public void paintGrid( Graphics g, Rectangle clipRect )
{
g.setColor( new Color( 255, 0, 0, 56 ) );
int numVertGuides = vertGuides.size();
for ( int i = 0; i < numVertGuides; i++ ) {
int coord = ( ( Integer )vertGuides.elementAt( i ) ).intValue();
g.drawLine( left + coord, top, left + coord, top + height );
}
int numHorzGuides = horzGuides.size();
for ( int i = 0; i < numHorzGuides; i++ ) {
int coord = ( ( Integer )horzGuides.elementAt( i ) ).intValue();
g.drawLine( left, top + coord, left + width, top + coord );
}
}
public void paintGutters( Graphics g, Rectangle clipRect )
{
Dimension d = getSize();
int right = Math.min( d.width, clipRect.x + clipRect.width );
int startX = clipRect.x;
int bottom = Math.min( d.height, clipRect.y + clipRect.height );
int startY = clipRect.y;
startX -= startX % 5;
startY -= startY % 5;
int delta = 1;
if ( startY < top ) {
// Draw the background
g.setColor( SystemColor.control );
g.fillRect( startX, 0, right -startX, top );
// Draw the edges
g.setColor( SystemColor.controlDkShadow );
g.drawLine( left, top - 1, d.width - 1, top - 1 );
// Draw the top minor grid lines
int ht = top / 2;
for ( int x = startX; x < right; x += 5 ) {
g.drawLine( x, ht - delta, x, top - 1 );
delta = -delta;
}
// Draw the top major grid lines
ht = top / 4;
for ( int x = startX; x < right; x += 100 )
g.drawLine( x, ht, x, top - 1 );
}
if ( startX < left ) {
// Draw the background
g.setColor( SystemColor.control );
g.fillRect( 0, startY, left, height - startY );
// Draw the edges
g.setColor( SystemColor.controlDkShadow );
g.drawLine( left - 1, top - 1, left - 1, d.height - 1 );
// Draw the left hand minor grid lines
int wh = left / 2;
for ( int y = startY; y < bottom; y += 5 ) {
g.drawLine( wh - delta, y, left - 1, y );
delta = -delta;
}
// Draw the left hand major grid lines
wh = left / 4;
for ( int y = startY; y < bottom; y += 100 )
g.drawLine( wh, y, left - 1, y );
}
}
/**
* Set the dimensions of the page container whos grid is being rendered
* @param x
* @param y
* @param w
* @param h
*/
public void setPageBounds( int x, int y, int w, int h )
{
left = x;
top = y;
width = w;
height = h;
}
public void processMouseEvent( MouseEvent e )
{
if ( e.getID() == MouseEvent.MOUSE_PRESSED )
mousePressed( e );
else if ( e.getID() == MouseEvent.MOUSE_RELEASED )
mouseReleased( e );
super.processMouseEvent( e );
}
public void processMouseMotionEvent( MouseEvent e )
{
if ( e.getID() == MouseEvent.MOUSE_DRAGGED )
mouseDragged( e );
super.processMouseMotionEvent( e );
}
public void mousePressed( MouseEvent e )
{
oldP = e.getPoint();
if ( oldP.y < top ) {
mode = ADD_HORIZONTAL_GUIDE;
}
else if ( oldP.x < left ) {
mode = ADD_VERTICAL_GUIDE;
}
else {
int numVertGuides = vertGuides.size();
for ( int i = 0; i < numVertGuides; i++ ) {
int coord = ( ( Integer )vertGuides.elementAt( i ) ).intValue();
if ( Math.abs( coord - ( oldP.x - left ) ) < 2 ) {
mode = MOVE_VERTICAL_GUIDE;
selectedGuideIdx = i;
return;
}
}
int numHorzGuides = horzGuides.size();
for ( int i = 0; i < numHorzGuides; i++ ) {
int coord = ( ( Integer )horzGuides.elementAt( i ) ).intValue();
if ( Math.abs( coord - ( oldP.y - top ) ) < 2 ) {
mode = MOVE_HORIZONTAL_GUIDE;
selectedGuideIdx = i;
}
}
}
}
public void mouseReleased( MouseEvent e )
{
Point p = e.getPoint();
if ( mode == ADD_HORIZONTAL_GUIDE ) {
if ( ( p.y > left ) && ( p.y < height + top ) )
horzGuides.add( new Integer( p.y - top ) );
}
else if ( mode == ADD_VERTICAL_GUIDE ) {
if ( ( p.x > top ) && ( p.x < width + left ) )
vertGuides.add( new Integer( p.x - left ) );
}
else if ( mode == MOVE_VERTICAL_GUIDE ) {
if ( selectedGuideIdx > -1 ) {
vertGuides.removeElementAt( selectedGuideIdx );
if ( p.x > left )
vertGuides.add( new Integer( p.x - left ) );
}
}
else if ( mode == MOVE_HORIZONTAL_GUIDE ) {
if ( selectedGuideIdx > -1 ) {
horzGuides.removeElementAt( selectedGuideIdx );
if ( p.y > top )
horzGuides.add( new Integer( p.y - top ) );
}
}
else
return;
mode = NORMAL;
selectedGuideIdx = -1;
repaint();
}
public void mouseDragged( MouseEvent e )
{
if ( mode == NORMAL )
return;
else {
Point p = e.getPoint();
Graphics g = getGraphics();
Color moveColor = new Color( 255, 0, 0, 56 );
g.setXORMode( moveColor );
if ( ( mode == ADD_HORIZONTAL_GUIDE ) || ( mode == MOVE_HORIZONTAL_GUIDE ) ) {
if ( ( p.x > top ) && ( p.x < width + left ) ) {
g.drawLine( left, oldP.y, left + width, oldP.y );
g.drawLine( left, p.y, left + width, p.y );
oldP = p;
}
}
else if ( ( mode == ADD_VERTICAL_GUIDE ) || ( mode == MOVE_VERTICAL_GUIDE ) ) {
if ( ( p.y > left ) && ( p.y < height + top ) ) {
g.drawLine( oldP.x, top, oldP.x, top + height );
g.drawLine( p.x, top, p.x, top + height );
oldP = p;
}
}
g.dispose();
g = null;
}
}
public void alignComponents( Vector selectedComponents )
{
int numComponents = selectedComponents.size();
int numVertGuides = vertGuides.size();
int numHorzGuides = horzGuides.size();
for ( int i = 0; i < numComponents; i++ ) {
XComponentSizer currentSizer = ( XComponentSizer )selectedComponents.elementAt( i );
Rectangle rect = currentSizer.getBounds();
for ( int iV = 0; iV < numVertGuides; iV++ ) {
int coord = ( ( Integer )vertGuides.elementAt( iV ) ).intValue() + left +1;
Point convertedCoord = SwingUtilities.convertPoint( this, coord, 0, currentSizer.getParent() );
// Check the left edge and then the right edge
if ( Math.abs( convertedCoord.x - rect.x ) <= snapRange )
currentSizer.setLocation( convertedCoord.x, rect.y );
else if ( Math.abs( convertedCoord.x - ( rect.x + rect.width ) ) <= snapRange )
currentSizer.setSize( convertedCoord.x - rect.x, rect.height );
}
// Refresh the rect as it may have changed
rect = currentSizer.getBounds();
for ( int iH = 0; iH < numHorzGuides; iH++ ) {
int coord = ( ( Integer )horzGuides.elementAt( iH ) ).intValue() + top +1;
Point convertedCoord = SwingUtilities.convertPoint( this, 0, coord, currentSizer.getParent() );
// Check the top edge and then the bottom
if ( Math.abs( convertedCoord.y - rect.y ) <= snapRange )
currentSizer.setLocation( rect.x, convertedCoord.y );
else if ( Math.abs( convertedCoord.y - ( rect.y + rect.height ) ) <= snapRange )
currentSizer.setSize( rect.width, convertedCoord.y - rect.y );
}
}
}
/**
* Get the guide coordinates
* @param vert
* @return
*/
public Vector getGuideCoords( boolean vert )
{
if ( vert )
return vertGuides;
else
return horzGuides;
}
}
|