⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtadroptargetlistener.java~1~

📁 具有不同语法高亮的编辑器实例
💻 JAVA~1~
字号:
/*
 * 07/29/2004
 *
 * RTADropTargetListener.java - Listens for drag-and-drop operations about to
 *         "drop" data into an RTextArea and handles things like scrolling the
 *         text area, selecting a location for the drop, etc.
 * Copyright (C) 2004 Robert Futrell
 * email@address.com
 * www.website.com
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
package org.fife.ui.rtextarea;

import java.awt.*;
import java.awt.event.*;
import java.awt.dnd.*;
import javax.swing.*;
import javax.swing.text.Caret;
import javax.swing.text.JTextComponent;


/**
 * Extends the "drop" functionality of an <code>RTextArea</code> so that a user
 * that is dropping data into an <code>RTextArea</code> will have the text area
 * scrolled if necessary, visually shows the drop location, etc.<p>
 * This class is pretty much a ripoff of an inner class of
 * <code>BasicTextUI</code>.
 *
 * @author Robert Futrell
 * @version 0.1
 */
class RTADropTargetListener implements DropTargetListener, ActionListener {

	private Timer timer;
	private Point lastPosition;
	private Rectangle  outer = new Rectangle();
	private Rectangle  inner = new Rectangle();
	private int	   hysteresis = 10;
	private boolean canImport;

	int dot;
	int mark;
	boolean visible;

	/** 
	 * The current component. The value is cached from the drop events and used
	 * by the timer. When a drag exits or a drop occurs, this value is cleared.
	 */
	private JComponent component;


/*****************************************************************************/


	/**
	 * construct a DropTargetAutoScroller
	 * <P>
	 * @param c the <code>Component</code>
	 * @param p the <code>Point</code>
	 */
	protected RTADropTargetListener() {
	}


/*****************************************************************************/


	/**
	 * called to save the state of a component in case it needs to
	 * be restored because a drop is not performed.
	 */
	protected void saveComponentState() {
		JTextComponent c = (JTextComponent)component;
		Caret caret = c.getCaret();
		dot = caret.getDot();
		mark = caret.getMark();
		visible = caret.isVisible();//caret instanceof DefaultCaret ?
							//((DefaultCaret)caret).isActive() :
							//caret.isVisible();
		caret.setVisible(true);
	}


/*****************************************************************************/


	/**
	 * called to restore the state of a component 
	 * because a drop was not performed.
	 */
	protected void restoreComponentState() {
		JTextComponent c = (JTextComponent)component;
		Caret caret = c.getCaret();
		caret.setDot(mark);
		caret.moveDot(dot);
		caret.setVisible(visible);
	}


/*****************************************************************************/


	/**
	 * called to restore the state of a component
	 * because a drop was performed.
	 */
	protected void restoreComponentStateForDrop() {
		JTextComponent c = (JTextComponent)component;
		Caret caret = c.getCaret();
		caret.setVisible(visible);
	}


/*****************************************************************************/


	/**
	 * called to set the insertion location to match the current
	 * mouse pointer coordinates.
	 */
	protected void updateInsertionLocation(Point p) {
		JTextComponent c = (JTextComponent)component;
		c.setCaretPosition(c.viewToModel(p));
	}


/*****************************************************************************/


	/**
	 * Update the geometry of the autoscroll region.  The geometry is
	 * maintained as a pair of rectangles.  The region can cause
	 * a scroll if the pointer sits inside it for the duration of the
	 * timer.  The region that causes the timer countdown is the area
	 * between the two rectangles.
	 * <p>
	 * This is implemented to use the visible area of the component 
	 * as the outer rectangle and the insets are based upon the
	 * Scrollable information (if any).  If the Scrollable is
	 * scrollable along an axis, the step increment is used as
	 * the autoscroll inset.  If the component is not scrollable,
	 * the insets will be zero (i.e. autoscroll will not happen).
	 */
	void updateAutoscrollRegion(JComponent c) {

		// compute the outer
		Rectangle visible = c.getVisibleRect();
		outer.setBounds(visible.x, visible.y, visible.width, visible.height);

		// compute the insets
		// TBD - the thing with the scrollable
		Insets i = new Insets(0, 0, 0, 0);
		if (c instanceof Scrollable) {
			Scrollable s = (Scrollable) c;
			i.left = s.getScrollableUnitIncrement(visible, SwingConstants.HORIZONTAL, 1);
			i.top = s.getScrollableUnitIncrement(visible, SwingConstants.VERTICAL, 1);
			i.right = s.getScrollableUnitIncrement(visible, SwingConstants.HORIZONTAL, -1);
			i.bottom = s.getScrollableUnitIncrement(visible, SwingConstants.VERTICAL, -1);
		}

		// set the inner from the insets
		inner.setBounds(visible.x + i.left, 
					visible.y + i.top,
					visible.width - (i.left + i.right),
					visible.height - (i.top  + i.bottom));
	}


/*****************************************************************************/


	/**
	 * Perform an autoscroll operation.  This is implemented to scroll by the
	 * unit increment of the Scrollable using scrollRectToVisible.  If the 
	 * cursor is in a corner of the autoscroll region, more than one axis will
	 * scroll.
	 */
	void autoscroll(JComponent c, Point pos) {

		if (c instanceof Scrollable) {
			Scrollable s = (Scrollable) c;
			if (pos.y < inner.y) {
				// scroll top downward
				int dy = s.getScrollableUnitIncrement(outer, SwingConstants.VERTICAL, 1);
				Rectangle r = new Rectangle(inner.x, outer.y - dy, inner.width, dy);
				c.scrollRectToVisible(r);
			}
			else if (pos.y > (inner.y + inner.height)) {
				// scroll bottom upward
				int dy = s.getScrollableUnitIncrement(outer, SwingConstants.VERTICAL, -1);
				Rectangle r = new Rectangle(inner.x, outer.y + outer.height, inner.width, dy);
				c.scrollRectToVisible(r);
			}

			if (pos.x < inner.x) {
				// scroll left side to the right
				int dx = s.getScrollableUnitIncrement(outer, SwingConstants.HORIZONTAL, 1);
				Rectangle r = new Rectangle(outer.x - dx, inner.y, dx, inner.height);
				c.scrollRectToVisible(r);
			}
			else if (pos.x > (inner.x + inner.width)) {
				// scroll right side to the left
				int dx = s.getScrollableUnitIncrement(outer, SwingConstants.HORIZONTAL, -1);
				Rectangle r = new Rectangle(outer.x + outer.width, inner.y, dx, inner.height);
				c.scrollRectToVisible(r);
			}
		}

	}


/*****************************************************************************/


	/**
	 * Initializes the internal properties if they haven't been already
	 * inited. This is done lazily to avoid loading of desktop properties.
	 */
	private void initPropertiesIfNecessary() {

		if (timer == null) {

			Toolkit t  = Toolkit.getDefaultToolkit();
			Integer    initial  = new Integer(100);
			Integer    interval = new Integer(100);

			try {
				initial = (Integer)t.getDesktopProperty(
									"DnD.Autoscroll.initialDelay");
			} catch (Exception e) {
				// ignore
			}
			try {
				interval = (Integer)t.getDesktopProperty(
									"DnD.Autoscroll.interval");
			} catch (Exception e) {
				// ignore
			}
			timer = new Timer(interval.intValue(), this);

			timer.setCoalesce(true);
			timer.setInitialDelay(initial.intValue());

			try {
				hysteresis = ((Integer)t.getDesktopProperty(
							"DnD.Autoscroll.cursorHysteresis")).intValue();
			} catch (Exception e) {
				// ignore
			}

		}

	}


/*****************************************************************************/


	static JComponent getComponent(DropTargetEvent e) {
		DropTargetContext context = e.getDropTargetContext();
		return (JComponent) context.getComponent();
	}


/*****************************************************************************/


	/**
	 * The timer fired, perform autoscroll if the pointer is within the
	 * autoscroll region.
	 * <P>
	 * @param e the <code>ActionEvent</code>
	 */
	public synchronized void actionPerformed(ActionEvent e) {
		updateAutoscrollRegion(component);
		if (outer.contains(lastPosition) && !inner.contains(lastPosition))
			autoscroll(component, lastPosition);
	}


/*****************************************************************************/


	public void dragEnter(DropTargetDragEvent e) {
		component = getComponent(e);
		TransferHandler th = component.getTransferHandler();
		canImport = th.canImport(component, e.getCurrentDataFlavors());
		if (canImport) {
			saveComponentState();
			lastPosition = e.getLocation();
			updateAutoscrollRegion(component);
			initPropertiesIfNecessary();
		}
	}


/*****************************************************************************/


	public void dragOver(DropTargetDragEvent e) {
		if (canImport) {
			Point p = e.getLocation();
			updateInsertionLocation(p);
			// check autoscroll
			synchronized(this) {
				if (Math.abs(p.x - lastPosition.x) > hysteresis ||
					Math.abs(p.y - lastPosition.y) > hysteresis) {
					// no autoscroll 
					if (timer.isRunning())
						timer.stop();
				}
				else {
					if (!timer.isRunning())
						timer.start();
				}
				lastPosition = p;
			}
		}
	}


/*****************************************************************************/


	public void dragExit(DropTargetEvent e) {
		if (canImport)
			restoreComponentState();
		cleanup();
	}


/*****************************************************************************/


	public void drop(DropTargetDropEvent e) {
		if (canImport)
			restoreComponentStateForDrop();
		cleanup();
	}


/*****************************************************************************/


	public void dropActionChanged(DropTargetDragEvent e) {
	}


/*****************************************************************************/


	/**
	 * Cleans up internal state after the drop has finished (either succeeded
	 * or failed).
	 */
	private void cleanup() {
		if (timer != null)
            timer.stop();
		component = null;
		lastPosition = null;
	}


/*****************************************************************************/

}

⌨️ 快捷键说明

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