欢迎来到虫虫下载站 | 资源下载 资源专辑 关于我们
虫虫下载站

userwindowlistener.java

PIY(Program It Yourself)是一个基于Java的应用程序开发环境
JAVA
第 1 页 / 共 2 页
字号:
package piy;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;

/**
* Listens on windows and the underlying components.  When the mouse is clicked, the relevant
* component becomes selected, or if the mode is set to add component, a component is added.
* @author David Vivash
* @version 1.0.2, 18/4/01
*/
public final class UserWindowListener implements Observer
{
	protected static UserWindowListener instance = null;

	//selected component border information
	protected static int selectedBorderWidth	= 5;
	protected static Color selectedBorderColor	= Color.yellow;

	//selected component's regions relative to the glasspane's (0,0) coords
	private Rectangle[] selectedRegion	= new Rectangle[9];

	//State constants denote what will happen on the next mouse click
	protected static final int ADD_COMPONENT	= 1; //clicking and dragging on a window will add a component/container
	protected static final int SELECT			= 2; //clicking on a window/component/container will select it
	protected static final int RESIZE_COMPONENT	= 3; //dragging the mouse resizes a component/container
	protected static final int MOVE_COMPONENT	= 4; //dragging the mouse moves a component/container

	//current edit type from the constants above
	private static int editType = SELECT;

	//What has currently been selected
	private Component selectedComponent	= null;
	private JFrame selectedWindow		= null;
	private JFrame oldWindow			= null; //the previously selected window

	/**
	* Private constructor only callable from this class.
	*/
	private UserWindowListener() {
		UserWindowListener.instance = this;
		PIY.getInstance().addObserver(this);
	}

	/**
	* Get the instance of this class that is being used.
	* @return the only allowed instance of this class
	*/
	protected static UserWindowListener getInstance() {
		if (instance == null) instance = new UserWindowListener();
		return instance;
	}

	/**
	* Listens on a particular frame and across all components on that frame.
	* (Changes the frame glasspane).  This should be used on <i>all</i> UserWindows
	* being editted.  The frame being listened on should be visible.
	* @param frame the JFrame (UserWindow) to listen on
	*/
	public void listenOnFrame(JFrame frame) {
		PIYGlassPane pane = new PIYGlassPane((UserWindow)frame);
		frame.setGlassPane(pane);

		frame.setVisible(true);
		pane.setVisible(true); //pane has to be set visible after the frame is
		pane.repaint();
	}
	
	/**
	* "Selects" the specified component.  That is, it places a border around the component
	* which allows the user to move and resize it.  Any previously selected component is
	* deselected, and PIY is informed of the SELECT event.  If the component specified is
	* null, the currently selected component is deselected and no new component is
	* selected.  In this case, PIY is informed of the DESELECT event.
	* @param component the component to select
	*/
	public void selectComponent(Component component) {
		
		if (component != null)
			selectedWindow = getWindow(component);

		selectedComponent = component;

		if (oldWindow != null) oldWindow.repaint();

		oldWindow = selectedWindow;

		if (selectedWindow != null) selectedWindow.repaint();
		
		setupRegions();
		
		//tell PIY of the selection
		PIY.getInstance().actionPerformed(new ActionEvent(this, 
											ActionEvent.ACTION_PERFORMED, 
											selectedComponent !=  null ? PIY.COMPONENT_SELECTED : 
																		PIY.COMPONENT_DESELECTED));
																				
	}

	/**
	* Sets up the bounding border on the selected component
	*/
	private void setupRegions() {
		if ((selectedComponent == null) || (selectedWindow == null)) {
			//reset all regions
			for (int i=0; i<6; i++) selectedRegion[i] = new Rectangle(-1,-1,0,0);
		} else if (selectedWindow.isShowing()) {
			Point pos = ((PIYGlassPane)selectedWindow.getGlassPane()).getPaneLocation(selectedComponent);
			selectedRegion[0] = new Rectangle(pos, selectedComponent.getSize()); //centre
			
			int w = selectedBorderWidth;
			int width = selectedComponent.getWidth(), height = selectedComponent.getHeight();
			
			selectedRegion[1] = new Rectangle(pos.x-w, pos.y-w, 2*w, 2*w);			//top/left
			selectedRegion[2] = new Rectangle(pos.x+width-w, pos.y-w, 2*w, 2*w);	//top/right
			selectedRegion[3] = new Rectangle(pos.x-w, pos.y+height-w, 2*w, 2*w);	//bottom/left
			selectedRegion[4] = new Rectangle(pos.x+width-w, pos.y+height-w, 2*w, 2*w); //bottom/right

			selectedRegion[5] = new Rectangle(pos.x+w, pos.y-w, width-w, w);		//top border
			selectedRegion[6] = new Rectangle(pos.x+w, pos.y+height, width-w, w);	//bottom border
			selectedRegion[7] = new Rectangle(pos.x-w, pos.y+w, w, height-w);		//left border
			selectedRegion[8] = new Rectangle(pos.x+width, pos.y+w, w, height-w);	//right border
		}	
	
	}

	public UserWindow getCurrentWindow() { return (UserWindow)selectedWindow; }
	public void setCurrentWindow(JFrame win) { selectedWindow = win; }
	public Component getSelectedComponent() { return selectedComponent; }

	/**
	* Reinitialises the bounding box to reflect a change in position or size of 
	* the  currently selected component
	*/
	public void validateBoundingBox() {
		setupRegions();
		if (selectedWindow != null) selectedWindow.repaint();		
	}

	/**
	* Get the JFrame on which the specified component is situated.
	* @param component the component placed on a userwindow
	* @return the JFrame on which the component is placed
	*/
	private JFrame getWindow(Component component) {
		Component parent = component;
		
		while (!( (parent = parent.getParent()) instanceof JFrame) ) { }
		
		return (JFrame)parent;
	}


	protected static int getEditType() { return editType; }
	protected static void setEditType(int type) { editType = type; } 

	protected Rectangle[] getSelectedRegion() { return selectedRegion; }

	//------------- Observer Method -------------------
	public void update(Observable o, Object arg) {
		ActionEvent e = (ActionEvent)arg;

		if ( (e.getActionCommand().equals(PIY.COMPONENT_CHOSEN)) ||
			 (e.getActionCommand().equals(PIY.CONTAINER_CHOSEN)) ) {

			if (selectedComponent != null) selectComponent(null); //deselect the currently selected compponent/container
			editType = ADD_COMPONENT;

		} else if (e.getActionCommand().equals(PIY.COMPONENT_SELECTED)) {
			editType = SELECT;
		} else if (e.getActionCommand().equals(PIY.COMPONENT_DESELECTED)) {
			editType = SELECT;
		}
	}

}

/**
* This pane is placed over the top of the content pane, and acts as a sheet of glass.
* Input events are trapped by this so undelying components do not receive event
* notifications.  The primary use of this class is to implement the selection,
* resizing and moving of the underlying components.
* @author David Vivash
* @version 1.3, 19/04/01
*/
final class PIYGlassPane extends JComponent implements MouseInputListener {
	
	private int startx=0, starty=0, endx=0, endy=0, diffx=0, diffy=0;
	private UserWindow window = null;

	private Container clickedIn = null;

	//the regions that a mouse can be over on a component
	private static final int NONE			= -1;
	private static final int CENTRE			= 0;
	private static final int TOP_LEFT		= 1;
	private static final int TOP_RIGHT		= 2;
	private static final int BOTTOM_LEFT	= 3;
	private static final int BOTTOM_RIGHT	= 4;
	private static final int TOP_BORDER		= 5;
	private static final int BOTTOM_BORDER	= 6;
	private static final int LEFT_BORDER	= 7;
	private static final int RIGHT_BORDER	= 8;

	private int inside = NONE; //which region on the selected component the mouse is over

	/**
	* Set up a glass pane on a particular user window.  The constructor sets up the pane, but
	* doesn't add it to the specified window.
	* @param window the user window on which to add the pane
	*/	
	public PIYGlassPane(UserWindow window) {
		addMouseListener(this);
		addMouseMotionListener(this);
		this.window = window;
	}
		
	/** Java 1.3 gets moody if we don't have this */
	//public boolean isOpaque() { return false; }
	
	/**
	* Draws a rectangle onto the graphics context.  If the width or height are negative,
	* the rectangle is drawn to the left or upwards respectively.
	*/
	private void drawRect(Graphics g, int x, int y, int width, int height) {
		if (width < 0) {
			x+=width;
			width = -width;
		}
		if (height < 0) {
			y+=height;
			height = -height;
		}

		g.drawRect(x, y, width, height);
	}
	
	/**
	* Gets the position relative to this pane of the specified component.
	* @param component the component whose location is to be determined
	* @return the location of the component relative to (0,0) on this glass pane
	*/
	protected Point getPaneLocation(Component component) {
		Point location = component.getLocationOnScreen();
		Point thisLocation = getLocationOnScreen();

		return new Point(location.x - thisLocation.x, location.y - thisLocation.y);
	}

	/**
	* Checks to see which container contains the point specified, then returns the position
	* of the point relative to the position of that container.
	* @param the container in which the point should be moved relative to
	* @param pos the point to be returned relative to its container
	* @return the point relative to the container
	*/
	private Point getPointLocation(Container container, Point pos) {
		int screenx = pos.x + getLocationOnScreen().x - container.getLocationOnScreen().x;
		int screeny = pos.y + getLocationOnScreen().y - container.getLocationOnScreen().y;
		
		return new Point(screenx, screeny);
	}

	//standard paint method which paints over the top of components.  This is only called if
	//this pane is "visible" - the pane can only be made visible once the frame it is contained
	//within is visible.  
	public void paint(Graphics g) {
		super.paint(g);	

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -