📄 rtaupdatehandler.java~1~
字号:
/*
* 07/29/2004
*
* RTAUpdateHandler.java - Layout manager for the text area, and also forwards
* document changes to the view.
* 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.dnd.*;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.TooManyListenersException;
import javax.swing.event.*;
import javax.swing.plaf.UIResource;
import javax.swing.text.*;
/**
* Gets attached to the model (document) in an <code>RTextArea</code> and
* listens for document events. Forwards any document events to the root view
* so it can update accordingly. Also lays out the text area and handles focus
* accelerator changes.<p>This class is pretty much ripped off from a subclass
* in <code>BasicTextUI</code>.
*
* @author Robert Futrell
* @version 0.1
*/
class RTAUpdateHandler implements PropertyChangeListener, DocumentListener,
LayoutManager2 {
/**
* The "layout constraints" for the LayoutManager2 implementation.
* These are View objects for those components that are represented
* by a View in the View tree.
*/
private Hashtable constraints;
private RTextAreaUI ui;
/*****************************************************************************/
/**
* Constructor.
*/
RTAUpdateHandler(RTextAreaUI ui) {
this.ui = ui;
}
/*****************************************************************************/
/**
* This method gets called when a bound property is changed.
* We are looking for document changes on the editor.
*/
public final void propertyChange(PropertyChangeEvent evt) {
Object oldValue = evt.getOldValue();
Object newValue = evt.getNewValue();
String propertyName = evt.getPropertyName();
// Both are documents, but either could be null.
if ((oldValue instanceof Document) || (newValue instanceof Document)) {
if (oldValue != null)
((Document)oldValue).removeDocumentListener(this);
if (newValue != null) {
((Document)newValue).addDocumentListener(this);
if ("document" == propertyName) {
ui.setView(null);
ui.propertyChange(evt);
ui.modelChanged();
return;
}
}
ui.modelChanged();
}
if ("focusAccelerator" == propertyName) {
ui.updateFocusAcceleratorBinding(true);
}
else if ("componentOrientation" == propertyName) {
// Changes in ComponentOrientation require the views to be
// rebuilt.
ui.modelChanged();
}
else if ("font" == propertyName) {
ui.modelChanged();
}
else if ("transferHandler" == propertyName) {
DropTarget dropTarget = ui.getRTextArea().getDropTarget();
if (dropTarget instanceof UIResource) {
if (RTextAreaUI.dropTargetListener == null)
RTextAreaUI.dropTargetListener = new RTADropTargetListener();
}
try {
dropTarget.addDropTargetListener(RTextAreaUI.dropTargetListener);
} catch (TooManyListenersException tmle) {
// should not happen... swing drop target is multicast
}
}
else if ("editable" == propertyName) {
ui.modelChanged();
}
ui.propertyChange(evt);
}
/*****************************************************************************/
/**
* The insert notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#insertUpdate
*/
public final void insertUpdate(DocumentEvent e) {
Rectangle alloc = (ui.painted) ? ui.getVisibleEditorRect() : null;
ui.rootView.insertUpdate(e, alloc);
}
/*****************************************************************************/
/**
* The remove notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#removeUpdate
*/
public final void removeUpdate(DocumentEvent e) {
Rectangle alloc = (ui.painted) ? ui.getVisibleEditorRect() : null;
ui.rootView.removeUpdate(e, alloc);
}
/*****************************************************************************/
/**
* The change notification. Gets sent to the root of the view structure
* that represents the portion of the model being represented by the
* editor. The factory is added as an argument to the update so that
* the views can update themselves in a dynamic (not hardcoded) way.
*
* @param e The change notification from the currently associated
* document.
* @see DocumentListener#changeUpdate
*/
public final void changedUpdate(DocumentEvent e) {
Rectangle alloc = (ui.painted) ? ui.getVisibleEditorRect() : null;
ui.rootView.changedUpdate(e, alloc);
}
/*****************************************************************************/
/**
* Adds the specified component with the specified name to
* the layout.
* @param name the component name
* @param comp the component to be added
*/
public void addLayoutComponent(String name, Component comp) {
// not supported
}
/*****************************************************************************/
/**
* Removes the specified component from the layout.
* @param comp the component to be removed
*/
public void removeLayoutComponent(Component comp) {
if (constraints != null) {
// remove the constraint record
constraints.remove(comp);
}
}
/*****************************************************************************/
/**
* Calculates the preferred size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
*
* @see #minimumLayoutSize
*/
public Dimension preferredLayoutSize(Container parent) {
// should not be called (JComponent uses UI instead)
return null;
}
/*****************************************************************************/
/**
* Calculates the minimum size dimensions for the specified
* panel given the components in the specified parent container.
* @param parent the component to be laid out
* @see #preferredLayoutSize
*/
public Dimension minimumLayoutSize(Container parent) {
// should not be called (JComponent uses UI instead)
return null;
}
/*****************************************************************************/
/**
* Lays out the container in the specified panel. This is
* implemented to position all components that were added
* with a View object as a constraint. The current allocation
* of the associated View is used as the location of the
* component.
* <p>
* A read-lock is acquired on the document to prevent the
* view tree from being modified while the layout process
* is active.
*
* @param parent the component which needs to be laid out
*/
public void layoutContainer(Container parent) {
if ((constraints != null) && (! constraints.isEmpty())) {
Rectangle alloc = ui.getVisibleEditorRect();
if (alloc != null) {
RTextAreaDocument doc = (RTextAreaDocument)ui.
getRTextArea().getDocument();
doc.readLock();
try {
ui.rootView.setSize(alloc.width, alloc.height);
Enumeration components = constraints.keys();
while (components.hasMoreElements()) {
Component comp = (Component) components.nextElement();
View v = (View) constraints.get(comp);
Shape ca = calculateViewPosition(alloc, v);
if (ca != null) {
Rectangle compAlloc = (ca instanceof Rectangle) ?
(Rectangle) ca : ca.getBounds();
comp.setBounds(compAlloc);
}
}
} finally {
doc.readUnlock();
}
}
}
}
/*****************************************************************************/
/**
* Find the Shape representing the given view.
*/
Shape calculateViewPosition(Shape alloc, View v) {
int pos = v.getStartOffset();
View child = null;
for (View parent=ui.rootView; (parent!=null) && (parent!=v); parent=child) {
int index = parent.getViewIndex(pos, Position.Bias.Forward);
alloc = parent.getChildAllocation(index, alloc);
child = parent.getView(index);
}
return (child != null) ? alloc : null;
}
/*****************************************************************************/
/**
* Adds the specified component to the layout, using the specified
* constraint object. We only store those components that were added
* with a constraint that is of type View.
*
* @param comp the component to be added
* @param constraint where/how the component is added to the layout.
*/
public void addLayoutComponent(Component comp, Object constraint) {
if (constraint instanceof View) {
if (constraints == null)
constraints = new Hashtable(7);
constraints.put(comp, constraint);
}
}
/*****************************************************************************/
/**
* Returns the maximum size of this component.
* @see java.awt.Component#getMinimumSize()
* @see java.awt.Component#getPreferredSize()
* @see LayoutManager
*/
public Dimension maximumLayoutSize(Container target) {
// should not be called (JComponent uses UI instead)
return null;
}
/*****************************************************************************/
/**
* Returns the alignment along the x axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentX(Container target) {
return 0.5f;
}
/*****************************************************************************/
/**
* Returns the alignment along the y axis. This specifies how
* the component would like to be aligned relative to other
* components. The value should be a number between 0 and 1
* where 0 represents alignment along the origin, 1 is aligned
* the furthest away from the origin, 0.5 is centered, etc.
*/
public float getLayoutAlignmentY(Container target) {
return 0.5f;
}
/*****************************************************************************/
/**
* Invalidates the layout, indicating that if the layout manager
* has cached information it should be discarded.
*/
public void invalidateLayout(Container target) {
}
/*****************************************************************************/
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -