package jas2.util.moverlayeredpane;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import jas2.util.multibuttontoolbar.*;
import jas2.plot.EditableLabel;
import java.beans.*;


/**
 * The MoverLayeredPane does not replace the JLayeredPane of the JRootPane it
 * lives in, it coexists with it.  Although this might seem weird and you might
 * keep slipping into the mindset (like I did) of thinking that the JRootPane
 * manages the MoverLayeredPane just like its own JLayeredPane (making it fill
 * up the whole window, etc), keep in mind that JLayeredPane extends JComponent
 * (just like JPanel does) and so can be used like any other JComponent...
 * 
 * @author Peter Armstrong
 * @author Tony Johnson
 */
public class MoverLayeredPane extends JLayeredPane {
	//
	//constructors
	//
	public MoverLayeredPane() 
   {
		super();
      setLayout(new MLPLayout());
		contentPanel = new MoverPanel();
		borderPanel = new BorderPanel();
		add(contentPanel, BOTTOM_LAYER);
		add(borderPanel, BORDER_LAYER);
		contentPanel.setVisible(true);
		setCursorState(CursorStates.OBJECT_SELECTION);
	}
	
	//
	//public methods
	//
	public JComponent getContentPanel() 
   {
		return contentPanel;
	}
   public JComponent getBorderPanel()
   {
      return borderPanel;
   }
	
	public void setCursorState(int newState) {
		cursorState = newState;
		switch (cursorState) {
		case CursorStates.OBJECT_CREATION :
			setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));//!PA - redundant?
			contentPanel.setCursor(Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR));
			break;
		case CursorStates.OBJECT_SELECTION :
			setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));//!PA - redundant?
			contentPanel.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
			break;
		default :
		}
	}
	
	//
	//public constants
	//
	public interface CursorStates {
		int OBJECT_SELECTION = 0, OBJECT_CREATION = 1;
	}
	
	//
	//private methods
	//
	
	//
	//member variables
	//
	private static final Integer BOTTOM_LAYER = new Integer(0);
		//This is the layer that components are added to.
		//This has the same value as JLayeredPane.DEFAULT_LAYER so that
		//components that get added w/o layer specified end up here.
	private static final Integer BORDER_LAYER = new Integer(50);
		//This is the layer that borders are drawn on.
	private MoverPanel contentPanel;
		//This is the subclass of JPanel which gets the components.
		//It is the MoverLayeredPane's job to ensure that this JPanel is the
		//same size as the MoverLayeredPane.
		//Note that the "contentPanel" of the MoverLayeredPane is NOT the same
		//thing as the contentPane of the JLayeredPane owned by the JRootPane.
		//Initially we had named them both the same thing to show the
		//similarity as a hint to the client programmer, but unlike Tony I am
		//too easily confused by such things.  Hence "contentPanel" :P
	private BorderPanel borderPanel;
		//This is the subclass of JPanel which gets the borders.
		//It is the MoverLayeredPane's job to ensure that this JPanel is the
		//same size as the MoverLayeredPane.
	private int cursorState;
		//The cursor state determines the results of mouse events...
	private Component pocusComponent;
		//"pocus" is like focus, except that it indicates which component
		//gets the handle border drawn around it.  This may be the same
		//component as the one with the focus, or it may be an ancestor
		//(on the GUI, not in terms of inheritance) of the component.
		//Specifically, only "top-level" components (i.e. ones with the
		//MoverPanel as their parent) have the "pocus" and the focus at the
		//same time.
	private Point offsetFromTopLeftCorner;
		//The offsetFromTopLeftCorner is used to adjust the location of
		//the component being MOVED (not resized).  We compute this offset
		//once and store it in this point, and then whenever we move the
		//component we need to adjust it by this offset.  This creates
		//the effect of the cursor staying at the same spot on the
		//component as it was when the user started dragging.
	private Rectangle initialSize = null;
	
	//private MLPObjectFactory theMLPObjectFactory = null;
		//theMLPObjectFactory is the currently selected factory which implements
		//the MLPObjectFactory interface--currently either MLPArrowFactory or
		//MLPLabelFactory.  It maintains its own state and constructs the
		//appropriate type of object.
	
	//other local vars from glass pane code
	private Point dragOffset;
	private Point dragStart;
	private JPopupMenu pm;
	private int numRepaints = 0;
	private static final int REPAINT_FUDGE_FACTOR = 10;
	private static final int FULL_REPAINT = 5;
	private static int numEvents = 0;//debug
	
	//
	//inner classes
	//
	
    /** 
     * A custom layout manager that is responsible for the layout of 
     * JPanels inside the MoverLayeredPane--basically, all it does is
     * ensure that they are the size of the MoverLayeredPane.
     */
    protected class MLPLayout implements LayoutManager {
        /**
         * Returns the amount of space the layout would like to have.
         *
         * @param the Container for which this layout manager is being used
         * @return a Dimension object containing the layout's preferred size
         */ 
        public Dimension preferredLayoutSize(Container parent) {
			return parent.getSize();
        }
        /**
         * Returns the minimum amount of space the layout needs.
         *
         * @param the Container for which this layout manager is being used
         * @return a Dimension object containing the layout's minimum size
         */ 
        public Dimension minimumLayoutSize(Container parent) {
			return parent.getSize();
		}
        /**
         * Returns the maximum amount of space the layout can use.
         *
         * @param the Container for which this layout manager is being used
         * @return a Dimension object containing the layout's maximum size
         */ 
        public Dimension maximumLayoutSize(Container target) {
			return target.getSize();
        }
        /**
         * Instructs the layout manager to perform the layout for the specified
         * container.
         *
         * @param the Container for which this layout manager is being used
         */ 
        public void layoutContainer(Container parent) {
			contentPanel.setSize(parent.getSize());
			contentPanel.setLocation(0,0);
			borderPanel.setSize(parent.getSize());
			borderPanel.setLocation(0,0);
        }
        public void addLayoutComponent(String name, Component comp) {}
        public void removeLayoutComponent(Component comp) {}
    }
	
	/**
	 * The panel that the borders are drawn on.
	 */
	class BorderPanel extends JPanel {
		BorderPanel() {
			this(Color.blue);
		}
		BorderPanel(Color color) {
			super(new java.awt.BorderLayout());
			setOpaque(false);
			borderComponent = new BorderComponent();
			borderComponent.setVisible(true);
			add(borderComponent);//default to CENTER
			//setBackground(Color.red);									//!PA - debug
		}
		
		//
		//member variables
		//
		private BorderComponent borderComponent;
		
		//
		//inner classes
		//
		
		/**
		 * The BorderComponent has 2 jobs:
		 * 1. Draw the border for the pocusComponent.
		 * 2. Mouse events first go to the BorderComponent's contains() method.
		 *    This method should return true IFF the the mouse event was on
		 *    the border of the pocusComponent.  If contains() is true, the
		 *    BorderComponent needs to process the mouse event accordingly.
		 *    If contains() is false, the BorderComponent needs to do
		 *    NOTHING (notice the beauty of this approach compared to the
		 *    glass pane approach!) as the mouse event will automatically be
		 *    passed on to the correct target.  This could result in a transfer
		 *    of focus/pocus--the key thing to note is that this will happen
		 *    without the BorderComponent doing anything special.  Now, when it
		 *    does happen, the pocusComponent will be set and the
		 *    BorderComponent will draw the new border!
		 */
		private class BorderComponent extends JComponent {
			BorderComponent() {
				this(Color.blue);
			}
			BorderComponent(Color color) {
				theMOB = new DefaultMOB(color, 7, 7, 5, Color.red, 8, 6);
				enableEvents(AWTEvent.MOUSE_EVENT_MASK |
							 AWTEvent.MOUSE_MOTION_EVENT_MASK);
			}
			
			//
			//methods
			//
			public void paint(Graphics g) {
				theMOB.paintBorder(pocusComponent, g);
			}
			
			public boolean contains(int x, int y) {
				return theMOB.isPointOverTheBorder(pocusComponent, new Point(x,y));
			}
			
			protected void processMouseEvent(MouseEvent e) {

				if (e.isPopupTrigger()) {
					//theToolBarPopupMenu.show(e.getComponent(), e.getXlen(), e.getYlen());
				} else {
					switch (e.getID()) {
					case MouseEvent.MOUSE_CLICKED :
						break;
					case MouseEvent.MOUSE_ENTERED :
						break;
					case MouseEvent.MOUSE_EXITED :
						break;
					case MouseEvent.MOUSE_PRESSED :
						if (getCursor() != null) {
							switch (getCursor().getType()) {
								case Cursor.MOVE_CURSOR :
									Point topLeftCorner = pocusComponent.getLocation();
									offsetFromTopLeftCorner =
										new Point((e.getPoint().x - topLeftCorner.x),
												  (e.getPoint().y - topLeftCorner.y));
									break;
								case Cursor.E_RESIZE_CURSOR :
								case Cursor.W_RESIZE_CURSOR :
								case Cursor.N_RESIZE_CURSOR :
								case Cursor.S_RESIZE_CURSOR :
								case Cursor.NE_RESIZE_CURSOR :
								case Cursor.NW_RESIZE_CURSOR :
								case Cursor.SE_RESIZE_CURSOR :
								case Cursor.SW_RESIZE_CURSOR :
									initialSize = pocusComponent.getBounds();
									break;
								case Cursor.CROSSHAIR_CURSOR :
									dragStart = e.getPoint();
									break;
								default:
									break;
							}
						} else {
						}
						break;
					case MouseEvent.MOUSE_RELEASED :
						repaint();
						if (getCursor() != null) {
							if (getCursor().getType() == Cursor.MOVE_CURSOR) {
								moveSelectedComponent(e.getPoint());
								//moveWithParent = false;//!PA - figure out how to set this in object

							} else {
								pocusComponent = null;
							}
						} else {
							pocusComponent = null;
						}
						break;
					default :
						break;
					}
				}
			}
			protected void processMouseMotionEvent(MouseEvent e) {
				switch (e.getID()) {
				case MouseEvent.MOUSE_MOVED :
					int newCursor = theMOB.getCursor(pocusComponent, e.getPoint());
					if (newCursor != currentCursor) {
						setCursor(Cursor.getPredefinedCursor(newCursor));
						currentCursor = newCursor;
					}
					break;
				case MouseEvent.MOUSE_DRAGGED :
					Rectangle r = theMOB.getRepaintRegion(pocusComponent);
					repaint(r.x - repaintExtra,
							r.y - repaintExtra,
							r.width + repaintExtra * 2,
							r.height + repaintExtra * 2);
					if (getCursor().getType() == Cursor.MOVE_CURSOR) {
						moveSelectedComponent(e.getPoint());
					} else {
						switch (getCursor().getType()) {
							case Cursor.N_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), true);
								break;
							case Cursor.E_RESIZE_CURSOR :
								resizeHorizontal(e.getPoint(), false);
								break;
							case Cursor.S_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), false);
								break;
							case Cursor.W_RESIZE_CURSOR :
								resizeHorizontal(e.getPoint(), true);
								break;
							case Cursor.NE_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), true);
								resizeHorizontal(e.getPoint(), false);
								break;
							case Cursor.NW_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), true);
								resizeHorizontal(e.getPoint(), true);
								break;
							case Cursor.SE_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), false);
								resizeHorizontal(e.getPoint(), false);
								break;
							case Cursor.SW_RESIZE_CURSOR :
								resizeVertical(e.getPoint(), false);
								resizeHorizontal(e.getPoint(), true);
								break;
							default:
								return;
						}
		//				moveWithParent = false;//!PA - replace with new version of this
						validate();
					}
					break;
				default :
					break;
				}
			}
			private boolean isPointInWindow(Point thePoint) {
				return (thePoint.x <= getSize().width &&
						thePoint.x > 0 &&
						thePoint.y <= getSize().height &&
						thePoint.y > 0);
			}
			private void moveSelectedComponent(Point currentPoint) {
				Point topLeftCorner		= new Point(currentPoint.x - offsetFromTopLeftCorner.x,
													currentPoint.y - offsetFromTopLeftCorner.y);
				int buttonLeftEdge = topLeftCorner.x;
				int buttonRightEdge = topLeftCorner.x + pocusComponent.getBounds().width;
				int buttonTopEdge = topLeftCorner.y;
				int buttonBottomEdge = topLeftCorner.y + pocusComponent.getBounds().height;
				if (buttonLeftEdge < 0) {
					topLeftCorner.x = 0;
				} else if (buttonRightEdge >= getSize().width) {
					topLeftCorner.x = getSize().width - pocusComponent.getBounds().width;
				}
				if (buttonTopEdge < 0) {
					topLeftCorner.y = 0;
				} else if (buttonBottomEdge >= getSize().height) {
					topLeftCorner.y = getSize().height - pocusComponent.getBounds().height;
				}
				pocusComponent.setLocation(topLeftCorner);
			}
			/**
			 * Transforms the cursor location to the closest location on the
			 * content pane.
			 * 
			 * @param currentPoint the actual cursor location (point)
			 * @return the transformed point
			 */
			private Point mapToPointInWindow(Point currentPoint) {
				Point retval = new Point();
				if (currentPoint.x > getSize().width) {
					retval.x = getSize().width;
				} else if (currentPoint.x < 0) {
					retval.x = 0;
				} else {
					retval.x = currentPoint.x;
				}
				if (currentPoint.y > getSize().height) {
					retval.y = getSize().height;
				} else if (currentPoint.y < 0) {
					retval.y = 0;
				} else {
					retval.y = currentPoint.y;
				}
				return retval;
			}
			/**
			 * Resize either north or south.  If and when Java gets a parameterized
			 * type mechanism this method should be combined with resizeHorizontal().
			 */
			private void resizeVertical(Point currentPoint, boolean isNorthHandle) {
				Point currentWindowPoint = mapToPointInWindow(currentPoint);
				Point initialWindowPoint = new Point(initialSize.x, initialSize.y);
				Rectangle b = pocusComponent.getBounds();
				int newHeight;
				if (isNorthHandle) {
					newHeight = initialSize.height + initialWindowPoint.y - currentWindowPoint.y;
				} else {
					newHeight = currentWindowPoint.y - initialWindowPoint.y;
				}
				if (newHeight >= pocusComponent.getMinimumSize().height) {
					if (isNorthHandle) {
						b.y = currentWindowPoint.y;
					}
					b.height = newHeight;
				} else {
					if (isNorthHandle) {
						b.y = new Point(initialWindowPoint.x, initialWindowPoint.y +
										initialSize.height - pocusComponent.getMinimumSize().height).y;
					}
					b.height = pocusComponent.getMinimumSize().height;
				}
				pocusComponent.setBounds(b);
			}
			/**
			 * Resize either east or west.  If and when Java gets a parameterized
			 * type mechanism this method should be combined with resizeVertical().
			 */
			private void resizeHorizontal(Point currentPoint, boolean isWestHandle) {
				Point currentWindowPoint = mapToPointInWindow(currentPoint);
				Point initialWindowPoint = new Point(initialSize.x, initialSize.y);
				Rectangle b = pocusComponent.getBounds();
				int newWidth;
				if (isWestHandle) {
					newWidth = initialSize.width + initialWindowPoint.x - currentWindowPoint.x;
				} else {
					newWidth = currentWindowPoint.x - initialWindowPoint.x;
				}
				if (newWidth >= pocusComponent.getMinimumSize().width) {
					if (isWestHandle) {
						b.x = currentWindowPoint.x;
					}
					b.width = newWidth;
				} else {
					if (isWestHandle) {
						b.x = new Point(initialWindowPoint.x + initialSize.width -
										pocusComponent.getMinimumSize().width, initialWindowPoint.y).x;
					}
					b.width = pocusComponent.getMinimumSize().width;
				}
				pocusComponent.setBounds(b);
			}

			//
			//member variables
			//
			private MovableObjectBorder theMOB;		//"I'm gonna make you a border you can't refuse."
			private int currentCursor;
			private int repaintExtra = 20;	//the number of pixels around the component to repaint
			
		}//BorderComponent
	}//BorderPanel
	
	class MoverPanel extends JPanel {
		//
		//constructors
		//
		MoverPanel() {
			super(null);//initialize with no layout manager
			enableEvents(AWTEvent.CONTAINER_EVENT_MASK |
						 AWTEvent.MOUSE_EVENT_MASK |
						 AWTEvent.MOUSE_MOTION_EVENT_MASK);
			smartfl = new SmartFocusListener();
			smartcl = new SmartContainerListener();
			addContainerListener(smartcl);
			//setBackground(Color.yellow);								//!PA - debug
		}
		//
		//methods
		//
		Component findChildThatContainsPoint(MouseEvent e) {
			Component[] children = getComponents();
			Component temp = null;
			for (int i = 0; i < children.length; i++) {
				if (children[i].contains(e.getX() - children[i].getLocation().x,
										 e.getY() - children[i].getLocation().y)) {
					return children[i];
				}
			}
			return null;
		}
		/**
		 * @param add true if listeners are being added, false if removed
		 * @param comp the component which is getting listeners added to it and its kids
		 * @param recursionLevel the level (top = 0) in the hierarchy of calls
		 * @param topLevelComponent the top level component (which is actually added to the MoverPanel)
		 */
		private void recursiveListenerAddOrRemove(boolean add, Component comp,
												  int recursionLevel, Component topLevelComponent) {
			if (add) {
				comp.addFocusListener(smartfl);
				if (comp instanceof Container) {
					((Container)comp).addContainerListener(smartcl);
				}
			} else {
				comp.removeFocusListener(smartfl);
				if (comp instanceof Container) {
					((Container)comp).removeContainerListener(smartcl);
				}
			}
			if (comp instanceof Container) {
				Component[] grandkids = ((Container)comp).getComponents();
				for (int i=0; i < grandkids.length; i++) {
					recursiveListenerAddOrRemove(add, grandkids[i], recursionLevel+1, topLevelComponent);
				}
			}
		}

		protected void processMouseEvent(MouseEvent e) {
			if (e.isPopupTrigger()) {
				//theToolBarPopupMenu.show(e.getComponent(), e.getXlen(), e.getYlen());
			} else {
				Component childThatContainsPoint = findChildThatContainsPoint(e);
				switch (e.getID()) {
				case MouseEvent.MOUSE_PRESSED :
					switch (cursorState) {
					case CursorStates.OBJECT_CREATION :
						//theMLPObjectFactory.mousePressed(e, this);
						break;
					case CursorStates.OBJECT_SELECTION :
						if (childThatContainsPoint != null) {
							childThatContainsPoint.dispatchEvent(
								SwingUtilities.convertMouseEvent(e.getComponent(), e, childThatContainsPoint));
						}
						break;
					default :
					}
					break;
				case MouseEvent.MOUSE_CLICKED :
				case MouseEvent.MOUSE_RELEASED :
					switch (cursorState) {
					case CursorStates.OBJECT_CREATION :
						//theMLPObjectFactory.mouseReleased(e, this);
						break;
					case CursorStates.OBJECT_SELECTION :
						if (childThatContainsPoint != null) {
							childThatContainsPoint.requestFocus();
						} else {
							pocusComponent = null;
							requestFocus();
							repaint();
						}
						break;
					default :
					}
					break;
				default :
					super.processMouseEvent(e);
				}//switch
			}//else
		}//processMouseEvent
		
		protected void processMouseMotionEvent(MouseEvent e) {
			if (e.getID() == MouseEvent.MOUSE_DRAGGED) {
				switch (cursorState) {
				case CursorStates.OBJECT_CREATION :
					//theMLPObjectFactory.mouseDragged(e, this);
					break;
				case CursorStates.OBJECT_SELECTION :
					break;
				default :
				}
			}
		}//processMouseMotionEvent
		
		//
		//member variables
		//
		private SmartFocusListener smartfl;
			//This listener gets added to EVERY component in order to track who
			//has focus.
		private SmartContainerListener smartcl;
			//This listener gets added to EVERY component in order to track the
			//addition and removal of components.
		
		//
		//inner classes
		//
		
		/**
		 * used for both the MoverPanel and all its nested components that are containers
		 */
		class SmartContainerListener extends ContainerAdapter {
			public void componentAdded(ContainerEvent e) {
				recursiveListenerAddOrRemove(true, e.getChild(), 0, e.getChild());
			}
			public void componentRemoved(ContainerEvent e) {
				recursiveListenerAddOrRemove(false, e.getChild(), 0, e.getChild());
			}
		}//class SmartContainerListener
		
		/**
		 * used to set the pocus based on the focus...
		 */
		class SmartFocusListener extends FocusAdapter {
			/**
			 * sets the pocus to the component which is the direct child of the
			 * MoverPanel (and is hence either the component itself or one of
			 * its ancestors)
			 */
			//!PA this used to show the glass pane, now what should it do???
			public void focusGained(FocusEvent e) {
				Component comp = e.getComponent();
				while (comp.getParent() != MoverPanel.this) {
					comp = comp.getParent();
				}
				pocusComponent = comp;
				repaint();
			}
			//!PA this used to hide the glass pane, now what should it do???
			public void focusLost(FocusEvent e) {
			}
		}//class SmartFocusListener
	}//class MoverPanel
	
	//
	//testing methods
	//
	public static MoverLayeredPane getSampleLayeredPane() {
		MoverLayeredPane mlp = new MoverLayeredPane();
		
		//Now create a bunch of objects (incl. nested objects) to add to the
		//contentPanel of the MoverLayeredPane so we can test the border code.
		JButton b1 = new JButton("Button 1");
		JButton b2 = new JButton("Button 2");
		JButton b3 = new JButton("Button 3");
		JPanel p1 = new JPanel();
		JButton pb1 = new JButton("hi iam a button");
		p1.add(pb1);
		JLabel lab1 = new JLabel("this is a JLabel");
		lab1.setBorder(BorderFactory.createLineBorder(Color.red));
		lab1.setSize(lab1.getPreferredSize());
		lab1.setVisible(true);
		p1.add(lab1);
		p1.addFocusListener(
			new FocusAdapter() {
				public void focusGained(FocusEvent e) {
				}
			});
		JTextField ijtf = new JTextField("inner text field!");
		ijtf.setLocation(50, 50);
		ijtf.setSize(ijtf.getPreferredSize());
		p1.add(ijtf);
		p1.setSize(p1.getPreferredSize().width + 40, p1.getPreferredSize().height + 40);
		p1.setLocation(250,250);
		p1.setBorder(BorderFactory.createLineBorder(Color.black));
		JLabel lab2 = new JLabel("a JLabel on its own");
		lab2.setBorder(BorderFactory.createLineBorder(Color.cyan));
		lab2.setSize(lab2.getPreferredSize());
		lab2.setVisible(true);
		lab2.setLocation(300,100);
		JTextField jtf = new JTextField("Hello world!");
		jtf.setLocation(50, 50);
		jtf.setSize(jtf.getPreferredSize());
		b1.setSize(b1.getPreferredSize());
		b2.setSize(b2.getPreferredSize());
		b3.setSize(b3.getPreferredSize());
		b1.setLocation(100,100);
		b2.setLocation(200,200);
		b3.setLocation(300,300);
		b1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}});
		b2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}});
		b3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
			}});
		
		//Now add these objects to the contentPanel
		mlp.getContentPanel().add(lab2);
		mlp.getContentPanel().add(p1);
		mlp.getContentPanel().add(b1);
		mlp.getContentPanel().add(b2);
		mlp.getContentPanel().add(b3);
		mlp.getContentPanel().add(jtf);
		return mlp;
	}
	
	public static void main(String[] args) {
		//Create the JFrame which is the test harness and create the instance
		//of the MoverLayeredPane which we will test.  Put that instance
		//in the middle of the JFrame to show that yes Virginia, the
		//MoverLayeredPane does not have to fill the JFrame.
		MoverLayeredPane mlp = getSampleLayeredPane();
		mlp.setSize(800, 600);
		mlp.setLocation(50, 50);
		JFrame f = new JFrame();
		f.getContentPane().setLayout(null);
		f.getContentPane().add(mlp);
		f.setSize(900, 700);
		f.setVisible(true);
		f.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
			  Window w = e.getWindow();
			  w.setVisible(false);
			  w.dispose();
			  System.exit(0);
			}});
		mlp.revalidate();
		mlp.repaint();
	}//main

	

	public void setMLPObjectFactory(MLPLabelFactory mlpLabelFactory) {
		// TODO Auto-generated method stub
		
	}

	public void setMLPObjectFactory(MLPArrowFactory theArrowFactory) {
		// TODO Auto-generated method stub
		
	}

	
}//class MoverLayeredPane

 

Ads help maintain this website.