package DDrawing;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.print.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.border.Border;
/**
* DArea is the junktion of the <code>JComponent</code>s and the <code>DComponent</code>s. It's the <code>DParent</code> which can be added to <code>JComponent</code>s
*/
public class DArea extends JComponent implements DParent, Printable{
/**
* the default minimal rectangle which is shown
*/
public static final DRectangle DEFAULT_MIN_RECT = new DRectangle(-1, -1, 2, 2);
private DContainer container;
/**
* min_rectangle is set, when all elements are removed
* visible_rect is the currently visible rectangle
*/
protected DRectangle min_rect = DEFAULT_MIN_RECT ;
/**
* min_rectangle is set, when all elements are removed
* visible_rect is the currently visible rectangle
*/
protected DRectangle visible_rect = DEFAULT_MIN_RECT ;
/**
* whether there is a grid gris is or not
*/
private DGrid grid;
private boolean auto_focus = false ;
private boolean auto_grid = false ;
private boolean grid_to_front = false ;
/**
* maximal number of grid lines
*/
private int max_grid = 10;
private DMeasures measures;
/**
* initializes the DArea with the initial capacity of 10 components
*/
public DArea(){
this( 10 );
}
/**
* initializes the DArea with the specialized initial capacity of components
* (@see java.util.Vector)
*
* @param the initial capacity
*/
public DArea( int initial_capacity ){
container = new DContainer();
container.setDParent( this );
grid = new DGrid( visible_rect, 1, 1 );
grid.setVisible( false );
grid.setDParent( this );
measures = new DMeasures( this );
}
/**
* returns the currently visible rectangle in DArea coordinates
*
* @return DRectangle the size and position of the visible area
*/
public DRectangle getDRectangle(){
return (DRectangle)visible_rect.clone();
}
/**
* switches the auto focus of this DArea on or off
*
* @param b on or off
*/
public void setAutoFocus( boolean b ){
boolean old = auto_focus;
auto_focus = b;
if( old != b ) repaint();
}
/**
* returns whether the DArea's auto focus is on or not
*
* @return <code>true</code> or <code>false</code>
*/
public boolean isOnAutoFocus(){ return auto_focus; }
/**
* sets the visible rectangle to this size
*
* @param x the x coordinate of the left border
* @param y the y coordinate of the bottom border
* @param width the width of the area
* @param height the height of the area
*/
public void setVisibleRectangle( double x, double y, double width, double height ){
//System.out.println("DArea.setVisibleRectangle(...)");
setVisibleRectangle( new DRectangle( x, y, width, height ) );
}
/**
* sets the visible rectangle
*
* @param rect the visible <code>DRectangle</code> in DArea coordinates
*/
public void setVisibleRectangle( DRectangle rect ){
//System.out.println("DArea.setVisibleRectangle(DRectangle)");
if( rect == null || rect.isEmpty() ) rect = (DRectangle)min_rect.clone();
if( !rect.equals( visible_rect ) && rect.width > 0 && rect.height > 0 ){
auto_focus = false;
visible_rect = (DRectangle)rect.clone();
repaint();
}
}
/**
* sets the minimal rectangle
*
* @param x
* @param y
* @param width
* @param height
*/
public void setMinRectangle( double x, double y, double width, double height ){
setMinRectangle( new DRectangle( x, y, width, height ) );
}
/**
* sets the minimal rectangle
*
* @param rect the visible <code>DRectangle</code> in DArea coordinates
*/
public void setMinRectangle( DRectangle rect ){
if( rect == null || rect.isEmpty() ) min_rect = DEFAULT_MIN_RECT;
else min_rect = (DRectangle)rect.clone();
}
/**
* paints the DArea by a Graphics object
*
* @param g the java.awt.Graphics object
*/
public void paint( Graphics g ){
//System.out.println("DArea.paint(Graphics)");
if( auto_focus ) {
container.restore();
visible_rect = (DRectangle)container.getRectangle().clone();
}
if( visible_rect.isEmpty() ) visible_rect = (DRectangle)min_rect.clone();
super.paint( g );
measures.setGraphics( g );
if( grid.isVisible() && !grid_to_front ) paintGrid( measures );
paintElements( measures );
if( grid.isVisible() && grid_to_front ) paintGrid( measures );
}
/**
* repaints a part of the visible area
*
* @param r the rectangle to repaint
*/
public void repaint( DRectangle r ){
//System.out.println("DArea.repaint(DRectangle)");
if( r == null ) throw
new IllegalArgumentException("Cannot repaint a null DRectangle");
if( r.isAll() || auto_focus ) repaint();
else{
Point p1 = measures.getPoint( r.x, r.y ),
p2 = measures.getPoint( r.x + r.width, r.y + r.height);
super.repaint( p1.x, p2.y, p2.x - p1.x + 1, p1.y - p2.y + 1);
}
}
/**
* adds a new component to the area
*
* @param e the new DElement
*/
public void addDElement( DElement e ){
container.addDElement( e );
}
/**
* removes a certain element from the area
*
* @param e the element to remove
*/
public boolean removeDElement( DElement e ){
return container.removeDElement( e );
}
/**
* removes all elements from the area
*/
public void removeAllDElements(){
visible_rect = (DRectangle)min_rect.clone();
container.removeAllDElements();
}
/**
* sets the grid visible or not
*
* @param aFlag visible or not
*/
public void setGridVisible( boolean aFlag ){
grid.setVisible( aFlag );
}
/**
* returns if the grid is visible
* <code>true</code> if the grid is visible or <code>false</code> if not
*
* @return true or false
*/
public boolean isGridVisible(){
return grid.isVisible();
}
/**
* sets the grid to the front
* that means that the grid is painted as last element
* default value is <code>false</code>
*
* @param aFlag grid t front or not
*/
public void setGridToFront( boolean aFlag ){
boolean old = grid_to_front;
grid_to_front = aFlag;
if( old != aFlag && grid.isVisible() ) repaint();
}
/**
* sets the grid's horizontal and vertical distance
* that means that the grid's lines will have these distances
* in area coordinates
*
* @param hor_dist the horizontal distance
* @param ver_dist the vertical distance
*/
public void setGrid( double hor_dist, double ver_dist ){
grid = new DGrid( visible_rect, hor_dist, ver_dist );
grid.setDParent( this );
auto_grid = false;
repaint();
}
/**
* sets tha auto grid on or off
* if it's on, the grid's distances (@see #setGrid(double, double))
* are automatically calculated that it looks pretty nice
*
* @param b auto grid on or not
*/
public void setAutoGrid( boolean b ){
if( b ) grid.setVisible( true );
if( b == auto_grid ) return;
auto_grid = b;
repaint();
}
/**
* returns if the auto grid is switched on
*
* @return true if the grid is on, else false
*/
public boolean hasAutoGrid(){ return auto_grid; }
/**
* sets the color of the grid
*
* @param java.awt.Color
*/
public void setGridColor( Color color ){
grid.setColor( color );
}
/**
* sets the maximal number of grid lines
* default value is 10
*
* @param no maximal number of grid lines
*/
public void setMaxGrid( int no ){
if( no < 1 ) return;
int old = max_grid;
max_grid = no;
if( old != no ) repaint();
}
/**
* prints the area and it's content
* @see java.awt.print.Printable and
* @see java.awt.print.PrintJob
*
* @param g the Graphics object
* @param pf the @see java.awt.print.PageFormat
* @param pi the page index
*
* @return int @see java.awt.print.Printable
*/
public int print( Graphics g, PageFormat pf, int pi ){
//System.out.println("DArea.print(...)");
if( pi > 0 ) return Printable.NO_SUCH_PAGE;
Border sb = getBorder();
if( !(sb instanceof ScaledBorder) ) sb = null;
else ( (ScaledBorder)sb ).show_outer_border = false;
PagePrinter printer = new PagePrinter( this, g, pf );
int ret = printer.print();
if( sb != null ) ( (ScaledBorder)sb ).show_outer_border = true;
return ret;
}
public void setXScale( DFunction x_s ){
if( x_s == null && measures.x_scale == null ) return;
measures.x_scale = x_s;
repaint();
}
public void setYScale( DFunction y_s ){
if( y_s == null && measures.y_scale == null ) return;
measures.y_scale = y_s;
repaint();
}
public DMeasures getDMeasures(){
return measures;
}
/**
* method paints the grid
* how the method paints the grid depends on whether the area is wrapped in a
* <code>ScaledBorder</code> or not and on the auto_grid option
*/
private void paintGrid( DMeasures m ){
//System.out.println("DArea.paintGrid(Measures)");
grid.rectangle = visible_rect;
if( auto_grid ){
Border border = getBorder();
if( border instanceof ScaledBorder ){
ScaledBorder sb = (ScaledBorder)border;
FontMetrics fm = m.getGraphics().getFontMetrics();
Dimension d = getSize();
DRectangle r = measures.getSourceOf( visible_rect );
grid.hor_dist = sb.getSrcdX(fm, d, r.x, r.x + r.width);
grid.ver_dist = sb.getSrcdY(fm, d, r.y, r.y + r.height);
}
else{
grid.hor_dist = ScaledBorder.aBitBigger( visible_rect.width / max_grid );
grid.ver_dist = ScaledBorder.aBitBigger( visible_rect.height / max_grid );
}
}
grid.paint( m );
}
/**
* this method asks the elements to paint themselves in the area if they
* really lie in it and if they are visible
*/
private void paintElements( DMeasures m ){
//System.out.println("DArea.paintElements(Measures)");
for( int i=0; i<container.elements.size(); i++ ){
DElement e = (DElement)container.elements.get(i);
if( e.isVisible() && visible_rect.getIntersection( e.getRectangle() ) != null )
e.paint( m );
}
}
}