- /*
- * @(#)JComponent.java 2.211 03/08/26
- *
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
- */
- package javax.swing;
- import java.util.Hashtable;
- import java.util.Dictionary;
- import java.util.Enumeration;
- import java.util.Locale;
- import java.util.Vector;
- import java.util.EventListener;
- import java.util.Set;
- import java.util.TreeSet;
- import java.awt.*;
- import java.awt.event.*;
- import java.awt.image.VolatileImage;
- import java.awt.Graphics2D;
- import java.awt.peer.LightweightPeer;
- import java.awt.dnd.DropTarget;
- import java.beans.*;
- import java.applet.Applet;
- import java.io.Serializable;
- import java.io.ObjectOutputStream;
- import java.io.ObjectInputStream;
- import java.io.IOException;
- import java.io.ObjectInputValidation;
- import java.io.InvalidObjectException;
- import javax.swing.border.*;
- import javax.swing.event.*;
- import javax.swing.plaf.*;
- import javax.accessibility.*;
- /**
- * The base class for all Swing components except top-level containers.
- * To use a component that inherits from <code>JComponent</code>,
- * you must place the component in a containment hierarchy
- * whose root is a top-level Swing container.
- * Top-level Swing containers --
- * such as <code>JFrame</code>, <code>JDialog</code>,
- * and <code>JApplet</code> --
- * are specialized components
- * that provide a place for other Swing components to paint themselves.
- * For an explanation of containment hierarchies, see
- * <a
- href="http://java.sun.com/docs/books/tutorial/uiswing/overview/hierarchy.html">Swing Components and the Containment Hierarchy</a>,
- * a section in <em>The Java Tutorial</em>.
- *
- * <p>
- * The <code>JComponent</code> class provides:
- * <ul>
- * <li>The base class for both standard and custom components
- * that use the Swing architecture.
- * <li>A "pluggable look and feel" (L&F) that can be specified by the
- * programmer or (optionally) selected by the user at runtime.
- * The look and feel for each component is provided by a
- * <em>UI delegate</em> -- an object that descends from
- * {@link javax.swing.plaf.ComponentUI}.
- * See <a
- * href="http://java.sun.com/docs/books/tutorial/uiswing/misc/plaf.html">How
- * to Set the Look and Feel</a>
- * in <em>The Java Tutorial</em>
- * for more information.
- * <li>Comprehensive keystroke handling.
- * See the document <a
- * href="http://java.sun.com/products/jfc/tsc/special_report/kestrel/keybindings.html">Keyboard
- * Bindings in Swing</a>,
- * an article in <em>The Swing Connection</em>,
- * for more information.
- * <li>Support for tool tips --
- * short descriptions that pop up when the cursor lingers
- * over a component.
- * See <a
- * href="http://java.sun.com/docs/books/tutorial/uiswing/components/tooltip.html">How
- * to Use Tool Tips</a>
- * in <em>The Java Tutorial</em>
- * for more information.
- * <li>Support for accessibility.
- * <code>JComponent</code> contains all of the methods in the
- * <code>Accessible</code> interface,
- * but it doesn't actually implement the interface. That is the
- * responsibility of the individual classes
- * that extend <code>JComponent</code>.
- * <li>Support for component-specific properties.
- * With the {@link #putClientProperty}
- * and {@link #getClientProperty} methods,
- * you can associate name-object pairs
- * with any object that descends from <code>JComponent</code>.
- * <li>An infrastructure for painting
- * that includes double buffering and support for borders.
- * For more information see <a
- * href="http://java.sun.com/docs/books/tutorial/uiswing/overview/draw.html">Painting</a> and
- * <a href="http://java.sun.com/docs/books/tutorial/uiswing/misc/border.html">How
- * to Use Borders</a>,
- * both of which are sections in <em>The Java Tutorial</em>.
- * </ul>
- * For more information on these subjects, see the
- * <a href="package-summary.html#package_description">Swing package description</a>
- * and <em>The Java Tutorial</em> section
- * <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/jcomponent.html">The JComponent Class</a>.
- * <p>
- * <strong>Warning:</strong>
- * Serialized objects of this class will not be compatible with
- * future Swing releases. The current serialization support is
- * appropriate for short term storage or RMI between applications running
- * the same version of Swing. As of 1.4, support for long term storage
- * of all JavaBeans<sup><font size="-2">TM</font></sup>
- * has been added to the <code>java.beans</code> package.
- * Please see {@link java.beans.XMLEncoder}.
- *
- * @see KeyStroke
- * @see Action
- * @see #setBorder
- * @see #registerKeyboardAction
- * @see JOptionPane
- * @see #setDebugGraphicsOptions
- * @see #setToolTipText
- * @see #setAutoscrolls
- *
- * @version 2.130 07/09/99
- * @author Hans Muller
- * @author Arnaud Weber
- */
- public abstract class JComponent extends Container implements Serializable
- {
- /**
- * @see #getUIClassID
- * @see #writeObject
- */
- private static final String uiClassID = "ComponentUI";
- /**
- * @see ReadObjectCallback
- * @see #readObject
- */
- private static final Hashtable readObjectCallbacks = new Hashtable(1);
- /**
- * Keys to use for forward focus traversal when the JComponent is
- * managing focus.
- */
- private static Set managingFocusForwardTraversalKeys;
- /**
- * Keys to use for backward focus traversal when the JComponent is
- * managing focus.
- */
- private static Set managingFocusBackwardTraversalKeys;
- /**
- * Indicates if we should register a <code>DropTarget</code> for a
- * non-null <code>TransferHandler</code>. Use
- * <code>getSuppressDropTarget</code> to check.
- */
- private static boolean suppressDropSupport;
- /**
- * Indiciates if we've checked the system property for suppressing
- * drop support.
- */
- private static boolean checkedSuppressDropSupport;
- // Following are the possible return values from getObscuredState.
- private static final int NOT_OBSCURED = 0;
- private static final int PARTIALLY_OBSCURED = 1;
- private static final int COMPLETELY_OBSCURED = 2;
- /* The following fields support set methods for the corresponding
- * java.awt.Component properties.
- */
- private Dimension preferredSize;
- private Dimension minimumSize;
- private Dimension maximumSize;
- private Float alignmentX;
- private Float alignmentY;
- private AncestorNotifier ancestorNotifier;
- Rectangle _bounds = new Rectangle();
- /**
- * Backing store for JComponent properties and listeners
- */
- /** The look and feel delegate for this component. */
- protected transient ComponentUI ui;
- /** A list of event listeners for this component. */
- protected EventListenerList listenerList = new EventListenerList();
- private Hashtable clientProperties;
- private VetoableChangeSupport vetoableChangeSupport;
- private Autoscroller autoscroller;
- private Border border;
- private int flags;
- private TransferHandler transfer;
- /* Input verifier for this component */
- private InputVerifier inputVerifier = null;
- private boolean verifyInputWhenFocusTarget = true;
- /* A "scratch pad" rectangle used by the painting code.
- */
- private transient Rectangle tmpRect;
- /**
- * Set in <code>_paintImmediately</code>.
- * Will indicate the child that initiated the painting operation.
- * If <code>paintingChild</code> is opaque, no need to paint
- * any child components after <code>paintingChild</code>.
- * Test used in <code>paintChildren</code>.
- */
- transient Component paintingChild;
- /**
- * Constant used for <code>registerKeyboardAction</code> that
- * means that the command should be invoked when
- * the component has the focus.
- */
- public static final int WHEN_FOCUSED = 0;
- /**
- * Constant used for <code>registerKeyboardAction</code> that
- * means that the command should be invoked when the receiving
- * component is an ancestor of the focused component or is
- * itself the focused component.
- */
- public static final int WHEN_ANCESTOR_OF_FOCUSED_COMPONENT = 1;
- /**
- * Constant used for <code>registerKeyboardAction</code> that
- * means that the command should be invoked when
- * the receiving component is in the window that has the focus
- * or is itself the focused component.
- */
- public static final int WHEN_IN_FOCUSED_WINDOW = 2;
- /**
- * Constant used by some of the APIs to mean that no condition is defined.
- */
- public static final int UNDEFINED_CONDITION = -1;
- /**
- * The key used by <code>JComponent</code> to access keyboard bindings.
- */
- private static final String KEYBOARD_BINDINGS_KEY = "_KeyboardBindings";
- /**
- * An array of <code>KeyStroke</code>s used for
- * <code>WHEN_IN_FOCUSED_WINDOW</code> are stashed
- * in the client properties under this string.
- */
- private static final String WHEN_IN_FOCUSED_WINDOW_BINDINGS = "_WhenInFocusedWindow";
- /**
- * The comment to display when the cursor is over the component,
- * also known as a "value tip", "flyover help", or "flyover label".
- */
- public static final String TOOL_TIP_TEXT_KEY = "ToolTipText";
- private static final String NEXT_FOCUS = "nextFocus";
- /** Private flags **/
- private static final int IS_DOUBLE_BUFFERED = 0;
- private static final int ANCESTOR_USING_BUFFER = 1;
- private static final int IS_PAINTING_TILE = 2;
- private static final int IS_OPAQUE = 3;
- private static final int KEY_EVENTS_ENABLED = 4;
- private static final int FOCUS_INPUTMAP_CREATED = 5;
- private static final int ANCESTOR_INPUTMAP_CREATED = 6;
- private static final int WIF_INPUTMAP_CREATED = 7;
- private static final int ACTIONMAP_CREATED = 8;
- private static final int CREATED_DOUBLE_BUFFER = 9;
- // Bit 10 is free
- private static final int IS_PRINTING = 11;
- private static final int IS_PRINTING_ALL = 12;
- private static final int IS_REPAINTING = 13;
- /** Bits 14-21 are used to handle nested writeObject calls. **/
- private static final int WRITE_OBJ_COUNTER_FIRST = 14;
- private static final int RESERVED_1 = 15;
- private static final int RESERVED_2 = 16;
- private static final int RESERVED_3 = 17;
- private static final int RESERVED_4 = 18;
- private static final int RESERVED_5 = 19;
- private static final int RESERVED_6 = 20;
- private static final int WRITE_OBJ_COUNTER_LAST = 21;
- private static final int REQUEST_FOCUS_DISABLED = 22;
- /** Used for <code>WHEN_FOCUSED</code> bindings. */
- private InputMap focusInputMap;
- /** Used for <code>WHEN_ANCESTOR_OF_FOCUSED_COMPONENT</code> bindings. */
- private InputMap ancestorInputMap;
- /** Used for <code>WHEN_IN_FOCUSED_KEY</code> bindings. */
- private ComponentInputMap windowInputMap;
- /** ActionMap. */
- private ActionMap actionMap;
- /** Key used to store the default locale in an AppContext **/
- private static final String defaultLocale = "JComponent.defaultLocale";
- /**
- * Returns the Set of <code>KeyStroke</code>s to use if the component
- * is managing focus for forward focus traversal.
- */
- static Set getManagingFocusForwardTraversalKeys() {
- if (managingFocusForwardTraversalKeys == null) {
- managingFocusForwardTraversalKeys = new TreeSet();
- managingFocusForwardTraversalKeys.add(
- KeyStroke.getKeyStroke(KeyEvent.VK_TAB, InputEvent.CTRL_MASK));
- }
- return managingFocusForwardTraversalKeys;
- }
- /**
- * Returns the Set of <code>KeyStroke</code>s to use if the component
- * is managing focus for backward focus traversal.
- */
- static Set getManagingFocusBackwardTraversalKeys() {
- if (managingFocusBackwardTraversalKeys == null) {
- managingFocusBackwardTraversalKeys = new TreeSet();
- managingFocusBackwardTraversalKeys.add(
- KeyStroke.getKeyStroke(KeyEvent.VK_TAB,
- InputEvent.SHIFT_MASK |
- InputEvent.CTRL_MASK));
- }
- return managingFocusBackwardTraversalKeys;
- }
- /**
- * Returns true if <code>setTransferHandler</code> should install
- * a <code>DropTarget</code>.
- */
- private static boolean getSuppressDropTarget() {
- if (!checkedSuppressDropSupport) {
- Boolean b = (Boolean)java.security.AccessController.doPrivileged(
- new java.security.PrivilegedAction() {
- public Object run() {
- String value = System.getProperty(
- "suppressSwingDropSupport");
- if (value != null) {
- return Boolean.valueOf(value);
- }
- return Boolean.FALSE;
- }
- }
- );
- suppressDropSupport = b.booleanValue();
- checkedSuppressDropSupport = true;
- }
- return suppressDropSupport;
- }
- /**
- * Default <code>JComponent</code> constructor. This constructor does
- * very little initialization beyond calling the <code>Container</code>
- * constructor. For example, the initial layout manager is
- * <code>null</code>. It does, however, set the component's locale
- * property to the value returned by
- * <code>JComponent.getDefaultLocale</code>.
- *
- * @see #getDefaultLocale
- */
- public JComponent() {
- super();
- // We enable key events on all JComponents so that accessibility
- // bindings will work everywhere. This is a partial fix to BugID
- // 4282211.
- enableEvents(AWTEvent.KEY_EVENT_MASK);
- enableSerialization();
- if (isManagingFocus()) {
- setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
- getManagingFocusForwardTraversalKeys());
- setFocusTraversalKeys(KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS,
- getManagingFocusBackwardTraversalKeys());
- }
- super.setLocale( JComponent.getDefaultLocale() );
- }
- /**
- * Resets the UI property to a value from the current look and feel.
- * <code>JComponent</code> subclasses must override this method
- * like this:
- * <pre>
- * public void updateUI() {
- * setUI((SliderUI)UIManager.getUI(this);
- * }
- * </pre>
- *
- * @see #setUI
- * @see UIManager#getLookAndFeel
- * @see UIManager#getUI
- */
- public void updateUI() {}
- /**
- * Sets the look and feel delegate for this component.
- * <code>JComponent</code> subclasses generally override this method
- * to narrow the argument type. For example, in <code>JSlider</code>:
- * <pre>
- * public void setUI(SliderUI newUI) {
- * super.setUI(newUI);
- * }
- * </pre>
- * <p>
- * Additionally <code>JComponent</code> subclasses must provide a
- * <code>getUI</code> method that returns the correct type. For example:
- * <pre>
- * public SliderUI getUI() {
- * return (SliderUI)ui;
- * }
- * </pre>
- *
- * @param newUI the new UI delegate
- * @see #updateUI
- * @see UIManager#getLookAndFeel
- * @see UIManager#getUI
- * @beaninfo
- * bound: true
- * hidden: true
- * attribute: visualUpdate true
- * description: The component's look and feel delegate.
- */
- protected void setUI(ComponentUI newUI) {
- /* We do not check that the UI instance is different
- * before allowing the switch in order to enable the
- * same UI instance *with different default settings*
- * to be installed.
- */
- if (ui != null) {
- ui.uninstallUI(this);
- }
- ComponentUI oldUI = ui;
- ui = newUI;
- if (ui != null) {
- ui.installUI(this);
- }
- firePropertyChange("UI", oldUI, newUI);
- revalidate();
- repaint();
- }
- /**
- * Returns the <code>UIDefaults</code> key used to
- * look up the name of the <code>swing.plaf.ComponentUI</code>
- * class that defines the look and feel
- * for this component. Most applications will never need to
- * call this method. Subclasses of <code>JComponent</code> that support
- * pluggable look and feel should override this method to
- * return a <code>UIDefaults</code> key that maps to the
- * <code>ComponentUI</code> subclass that defines their look and feel.
- *
- * @return the <code>UIDefaults</code> key for a
- * <code>ComponentUI</code> subclass
- * @see UIDefaults#getUI
- * @beaninfo
- * expert: true
- * description: UIClassID
- */
- public String getUIClassID() {
- return uiClassID;
- }
- /**
- * Returns the graphics object used to paint this component.
- * If <code>DebugGraphics</code> is turned on we create a new
- * <code>DebugGraphics</code> object if necessary.
- * Otherwise we just configure the
- * specified graphics object's foreground and font.
- *
- * @param g the original <code>Graphics</code> object
- * @return a <code>Graphics</code> object configured for this component
- */
- protected Graphics getComponentGraphics(Graphics g) {
- Graphics componentGraphics = g;
- if (ui != null) {
- if ((DebugGraphics.debugComponentCount() != 0) &&
- (shouldDebugGraphics() != 0) &&
- !(g instanceof DebugGraphics)) {
- if(g instanceof SwingGraphics) {
- if(!(((SwingGraphics)g).subGraphics() instanceof DebugGraphics)) {
- Graphics dbgGraphics = new DebugGraphics(((SwingGraphics)g).subGraphics(),this);
- componentGraphics = SwingGraphics.createSwingGraphics(dbgGraphics);
- dbgGraphics.dispose();
- }
- } else {
- componentGraphics = new DebugGraphics(g,this);
- }
- }
- }
- componentGraphics.setColor(getForeground());
- componentGraphics.setFont(getFont());
- return componentGraphics;
- }
- /**
- * Calls the UI delegate's paint method, if the UI delegate
- * is non-<code>null</code>. We pass the delegate a copy of the
- * <code>Graphics</code> object to protect the rest of the
- * paint code from irrevocable changes
- * (for example, <code>Graphics.translate</code>).
- * <p>
- * If you override this in a subclass you should not make permanent
- * changes to the passed in <code>Graphics</code>. For example, you
- * should not alter the clip <code>Rectangle</code> or modify the
- * transform. If you need to do these operations you may find it
- * easier to create a new <code>Graphics</code> from the passed in
- * <code>Graphics</code> and manipulate it. Further, if you do not
- * invoker super's implementation you must honor the opaque property,
- * that is
- * if this component is opaque, you must completely fill in the background
- * in a non-opaque color. If you do not honor the opaque property you
- * will likely see visual artifacts.
- *
- * @param g the <code>Graphics</code> object to protect
- * @see #paint
- * @see ComponentUI
- */
- protected void paintComponent(Graphics g) {
- if (ui != null) {
- Graphics scratchGraphics = SwingGraphics.createSwingGraphics(g);
- try {
- ui.update(scratchGraphics, this);
- }
- finally {
- scratchGraphics.dispose();
- }
- }
- }
- /**
- * Paints this component's children.
- * If <code>shouldUseBuffer</code> is true,
- * no component ancestor has a buffer and
- * the component children can use a buffer if they have one.
- * Otherwise, one ancestor has a buffer currently in use and children
- * should not use a buffer to paint.
- * @param g the <code>Graphics</code> context in which to paint
- * @see #paint
- * @see java.awt.Container#paint
- */
- protected void paintChildren(Graphics g) {
- boolean isJComponent;
- Graphics sg = null;
- try {
- synchronized(getTreeLock()) {
- int i = getComponentCount() - 1;
- if (i < 0) {
- return;
- }
- sg = SwingGraphics.createSwingGraphics(g);
- // If we are only to paint to a specific child, determine
- // its index.
- if (paintingChild != null &&
- (paintingChild instanceof JComponent) &&
- ((JComponent)paintingChild).isOpaque()) {
- for (; i >= 0; i--) {
- if (getComponent(i) == paintingChild){
- break;
- }
- }
- }
- if(tmpRect == null) {
- tmpRect = new Rectangle();
- }
- boolean checkSiblings = (!isOptimizedDrawingEnabled() &&
- checkIfChildObscuredBySibling());
- Rectangle clipBounds = null;
- if (checkSiblings) {
- clipBounds = sg.getClipBounds();
- if (clipBounds == null) {
- clipBounds = new Rectangle(0, 0, _bounds.width,
- _bounds.height);
- }
- }
- boolean printing = getFlag(IS_PRINTING);
- for (; i >= 0 ; i--) {
- Component comp = getComponent(i);
- if (comp != null && isLightweightComponent(comp) &&
- (comp.isVisible() == true)) {
- Rectangle cr;
- isJComponent = (comp instanceof JComponent);
- if(isJComponent) {
- cr = tmpRect;
- ((JComponent)comp).getBounds(cr);
- } else {
- cr = comp.getBounds();
- }
- boolean hitClip = g.hitClip(cr.x, cr.y, cr.width, cr.height);
- if (hitClip) {
- if (checkSiblings && i > 0) {
- int x = cr.x;
- int y = cr.y;
- int width = cr.width;
- int height = cr.height;
- SwingUtilities.computeIntersection
- (clipBounds.x, clipBounds.y,
- clipBounds.width, clipBounds.height, cr);
- if(getObscuredState(i, cr.x, cr.y, cr.width,
- cr.height) == COMPLETELY_OBSCURED) {
- continue;
- }
- cr.x = x;
- cr.y = y;
- cr.width = width;
- cr.height = height;
- }
- Graphics cg = SwingGraphics.createSwingGraphics(
- sg, cr.x, cr.y, cr.width, cr.height);
- cg.setColor(comp.getForeground());
- cg.setFont(comp.getFont());
- boolean shouldSetFlagBack = false;
- try {
- if(isJComponent) {
- if(getFlag(ANCESTOR_USING_BUFFER)) {
- ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,true);
- shouldSetFlagBack = true;
- }
- if(getFlag(IS_PAINTING_TILE)) {
- ((JComponent)comp).setFlag(IS_PAINTING_TILE,true);
- shouldSetFlagBack = true;
- }
- if(!printing) {
- ((JComponent)comp).paint(cg);
- }
- else {
- if (!getFlag(IS_PRINTING_ALL)) {
- comp.print(cg);
- }
- else {
- comp.printAll(cg);
- }
- }
- } else {
- if (!printing) {
- comp.paint(cg);
- }
- else {
- if (!getFlag(IS_PRINTING_ALL)) {
- comp.print(cg);
- }
- else {
- comp.printAll(cg);
- }
- }
- }
- } finally {
- cg.dispose();
- if(shouldSetFlagBack) {
- ((JComponent)comp).setFlag(ANCESTOR_USING_BUFFER,false);
- ((JComponent)comp).setFlag(IS_PAINTING_TILE,false);
- }
- }
- }
- }
- }
- }
- } finally {
- if (sg != null) {
- sg.dispose();
- }
- }
- }
- /**
- * Paints the component's border.
- * <p>
- * If you override this in a subclass you should not make permanent
- * changes to the passed in <code>Graphics</code>. For example, you
- * should not alter the clip <code>Rectangle</code> or modify the
- * transform. If you need to do these operations you may find it
- * easier to create a new <code>Graphics</code> from the passed in
- * <code>Graphics</code> and manipulate it.
- *
- * @param g the <code>Graphics</code> context in which to paint
- *
- * @see #paint
- * @see #setBorder
- */
- protected void paintBorder(Graphics g) {
- Border border = getBorder();
- if (border != null) {
- border.paintBorder(this, g, 0, 0, getWidth(), getHeight());
- }
- }
- /**
- * Calls <code>paint</code>. Doesn't clear the background but see
- * <code>ComponentUI.update</code>, which is called by
- * <code>paintComponent</code>.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #paint
- * @see #paintComponent
- * @see javax.swing.plaf.ComponentUI
- */
- public void update(Graphics g) {
- paint(g);
- }
- /**
- * Invoked by Swing to draw components.
- * Applications should not invoke <code>paint</code> directly,
- * but should instead use the <code>repaint</code> method to
- * schedule the component for redrawing.
- * <p>
- * This method actually delegates the work of painting to three
- * protected methods: <code>paintComponent</code>,
- * <code>paintBorder</code>,
- * and <code>paintChildren</code>. They're called in the order
- * listed to ensure that children appear on top of component itself.
- * Generally speaking, the component and its children should not
- * paint in the insets area allocated to the border. Subclasses can
- * just override this method, as always. A subclass that just
- * wants to specialize the UI (look and feel) delegate's
- * <code>paint</code> method should just override
- * <code>paintComponent</code>.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #paintComponent
- * @see #paintBorder
- * @see #paintChildren
- * @see #getComponentGraphics
- * @see #repaint
- */
- public void paint(Graphics g) {
- boolean shouldClearPaintFlags = false;
- boolean paintCompleted = false;
- if ((getWidth() <= 0) || (getHeight() <= 0)) {
- return;
- }
- Graphics componentGraphics = getComponentGraphics(g);
- Graphics co = SwingGraphics.createSwingGraphics(componentGraphics);
- try {
- RepaintManager repaintManager = RepaintManager.currentManager(this);
- Rectangle clipRect = co.getClipBounds();
- int clipX;
- int clipY;
- int clipW;
- int clipH;
- if (clipRect == null) {
- clipX = clipY = 0;
- clipW = _bounds.width;
- clipH = _bounds.height;
- }
- else {
- clipX = clipRect.x;
- clipY = clipRect.y;
- clipW = clipRect.width;
- clipH = clipRect.height;
- }
- if(clipW > getWidth()) {
- clipW = getWidth();
- }
- if(clipH > getHeight()) {
- clipH = getHeight();
- }
- if(getParent() != null && !(getParent() instanceof JComponent)) {
- adjustPaintFlags();
- shouldClearPaintFlags = true;
- }
- int bw,bh;
- boolean printing = getFlag(IS_PRINTING);
- if(!printing && repaintManager.isDoubleBufferingEnabled() &&
- !getFlag(ANCESTOR_USING_BUFFER) && isDoubleBuffered()) {
- paintCompleted = paintDoubleBuffered(this, this, co, clipX, clipY, clipW, clipH);
- }
- if (!paintCompleted) {
- // Will ocassionaly happen in 1.2, especially when printing.
- if (clipRect == null) {
- co.setClip(clipX, clipY, clipW, clipH);
- }
- if (!rectangleIsObscured(clipX,clipY,clipW,clipH)) {
- if (!printing) {
- paintComponent(co);
- paintBorder(co);
- }
- else {
- printComponent(co);
- printBorder(co);
- }
- }
- if (!printing) {
- paintChildren(co);
- }
- else {
- printChildren(co);
- }
- }
- } finally {
- co.dispose();
- if(shouldClearPaintFlags) {
- setFlag(ANCESTOR_USING_BUFFER,false);
- setFlag(IS_PAINTING_TILE,false);
- setFlag(IS_PRINTING,false);
- setFlag(IS_PRINTING_ALL,false);
- }
- }
- }
- private void adjustPaintFlags() {
- JComponent jparent = null;
- Container parent;
- for(parent = getParent() ; parent != null ; parent =
- parent.getParent()) {
- if(parent instanceof JComponent) {
- jparent = (JComponent) parent;
- if(jparent.getFlag(ANCESTOR_USING_BUFFER))
- setFlag(ANCESTOR_USING_BUFFER, true);
- if(jparent.getFlag(IS_PAINTING_TILE))
- setFlag(IS_PAINTING_TILE, true);
- if(jparent.getFlag(IS_PRINTING))
- setFlag(IS_PRINTING, true);
- if(jparent.getFlag(IS_PRINTING_ALL))
- setFlag(IS_PRINTING_ALL, true);
- break;
- }
- }
- }
- /**
- * Invoke this method to print the component. This method invokes
- * <code>print</code> on the component.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #print
- * @see #printComponent
- * @see #printBorder
- * @see #printChildren
- */
- public void printAll(Graphics g) {
- setFlag(IS_PRINTING_ALL, true);
- try {
- print(g);
- }
- finally {
- setFlag(IS_PRINTING_ALL, false);
- }
- }
- /**
- * Invoke this method to print the component. This method will
- * result in invocations to <code>printComponent</code>,
- * <code>printBorder</code> and <code>printChildren</code>. It is
- * not recommended that you override this method, instead override
- * one of the previously mentioned methods. This method sets the
- * component's state such that the double buffer will not be used, eg
- * painting will be done directly on the passed in <code>Graphics</code>.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #printComponent
- * @see #printBorder
- * @see #printChildren
- */
- public void print(Graphics g) {
- setFlag(IS_PRINTING, true);
- try {
- paint(g);
- }
- finally {
- setFlag(IS_PRINTING, false);
- }
- }
- /**
- * This is invoked during a printing operation. This is implemented to
- * invoke <code>paintComponent</code> on the component. Override this
- * if you wish to add special painting behavior when printing.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #print
- * @since 1.3
- */
- protected void printComponent(Graphics g) {
- paintComponent(g);
- }
- /**
- * Prints this component's children. This is implemented to invoke
- * <code>paintChildren</code> on the component. Override this if you
- * wish to print the children differently than painting.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #print
- * @since 1.3
- */
- protected void printChildren(Graphics g) {
- paintChildren(g);
- }
- /**
- * Prints the component's border. This is implemented to invoke
- * <code>paintBorder</code> on the component. Override this if you
- * wish to print the border differently that it is painted.
- *
- * @param g the <code>Graphics</code> context in which to paint
- * @see #print
- * @since 1.3
- */
- protected void printBorder(Graphics g) {
- paintBorder(g);
- }
- /**
- * Returns true if the component is currently painting a tile.
- * If this method returns true, paint will be called again for another
- * tile. This method returns false if you are not painting a tile or
- * if the last tile is painted.
- * Use this method to keep some state you might need between tiles.
- *
- * @return true if the component is currently painting a tile,
- * false otherwise
- */
- public boolean isPaintingTile() {
- return getFlag(IS_PAINTING_TILE);
- }
- /**
- * Changes this <code>JComponent</code>'s focus traversal keys to
- * CTRL+TAB and CTRL+SHIFT+TAB. Also prevents
- * <code>SortingFocusTraversalPolicy</code> from considering descendants
- * of this JComponent when computing a focus traversal cycle.
- *
- * @see java.awt.Component#setFocusTraversalKeys
- * @see SortingFocusTraversalPolicy
- * @deprecated As of 1.4, replaced by
- * <code>Component.setFocusTraversalKeys(int, Set)</code> and
- * <code>Container.setFocusCycleRoot(boolean)</code>.
- */
- public boolean isManagingFocus() {
- return false;
- }
- private void registerNextFocusableComponent() {
- registerNextFocusableComponent(getNextFocusableComponent());
- }
- private void registerNextFocusableComponent(Component
- nextFocusableComponent) {
- if (nextFocusableComponent == null) {
- return;
- }
- Container nearestRoot =
- (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
- FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
- if (!(policy instanceof LegacyGlueFocusTraversalPolicy)) {
- policy = new LegacyGlueFocusTraversalPolicy(policy);
- nearestRoot.setFocusTraversalPolicy(policy);
- }
- ((LegacyGlueFocusTraversalPolicy)policy).
- setNextFocusableComponent(this, nextFocusableComponent);
- }
- private void deregisterNextFocusableComponent() {
- Component nextFocusableComponent = getNextFocusableComponent();
- if (nextFocusableComponent == null) {
- return;
- }
- Container nearestRoot =
- (isFocusCycleRoot()) ? this : getFocusCycleRootAncestor();
- if (nearestRoot == null) {
- return;
- }
- FocusTraversalPolicy policy = nearestRoot.getFocusTraversalPolicy();
- if (policy instanceof LegacyGlueFocusTraversalPolicy) {
- ((LegacyGlueFocusTraversalPolicy)policy).
- unsetNextFocusableComponent(this, nextFocusableComponent);
- }
- }
- /**
- * Overrides the default <code>FocusTraversalPolicy</code> for this
- * <code>JComponent</code>'s focus traversal cycle by unconditionally
- * setting the specified <code>Component</code> as the next
- * <code>Component</code> in the cycle, and this <code>JComponent</code>
- * as the specified <code>Component</code>'s previous
- * <code>Component</code> in the cycle.
- *
- * @param aComponent the <code>Component</code> that should follow this
- * <code>JComponent</code> in the focus traversal cycle
- *
- * @see #getNextFocusableComponent
- * @see java.awt.FocusTraversalPolicy
- * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>
- */
- public void setNextFocusableComponent(Component aComponent) {
- boolean displayable = isDisplayable();
- if (displayable) {
- deregisterNextFocusableComponent();
- }
- putClientProperty(NEXT_FOCUS, aComponent);
- if (displayable) {
- registerNextFocusableComponent(aComponent);
- }
- }
- /**
- * Returns the <code>Component</code> set by a prior call to
- * <code>setNextFocusableComponent(Component)</code> on this
- * <code>JComponent</code>.
- *
- * @return the <code>Component</code> that will follow this
- * <code>JComponent</code> in the focus traversal cycle, or
- * <code>null</code> if none has been explicitly specified
- *
- * @see #setNextFocusableComponent
- * @deprecated As of 1.4, replaced by <code>FocusTraversalPolicy</code>.
- */
- public Component getNextFocusableComponent() {
- return (Component)getClientProperty(NEXT_FOCUS);
- }
- /**
- * Provides a hint as to whether or not this <code>JComponent</code>
- * should get focus. This is only a hint, and it is up to consumers that
- * are requesting focus to honor this property. This is typically honored
- * for mouse operations, but not keyboard operations. For example, look
- * and feels could verify this property is true before requesting focus
- * during a mouse operation. This would often times be used if you did
- * not want a mouse press on a <code>JComponent</code> to steal focus,
- * but did want the <code>JComponent</code> to be traversable via the
- * keyboard. If you do not want this <code>JComponent</code> focusable at
- * all, use the <code>setFocusable</code> method instead.
- *
- * @param requestFocusEnabled Indicates if you want this JComponent to
- * be focusable or not
- * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus Specification</a>
- * @see java.awt.Component#setFocusable
- */
- public void setRequestFocusEnabled(boolean requestFocusEnabled) {
- setFlag(REQUEST_FOCUS_DISABLED, !requestFocusEnabled);
- }
- /**
- * Returns <code>true</code> if this <code>JComponent</code> should
- * get focus; otherwise returns <code>false</code>.
- *
- * @return <code>true</code> if this component should get focus,
- * otherwise returns <code>false</code>
- * @see #setRequestFocusEnabled
- * @see <a href="../../java/awt/doc-files/FocusSpec.html">Focus
- * Specification</a>
- * @see java.awt.Component#isFocusable
- */
- public boolean isRequestFocusEnabled() {
- return !getFlag(REQUEST_FOCUS_DISABLED);
- }
- private boolean runInputVerifier() {
- Component focusOwner =
- KeyboardFocusManager.getCurrentKeyboardFocusManager().
- getFocusOwner();
- if (focusOwner == this) {
- return true;
- }
- if (!getVerifyInputWhenFocusTarget()) {
- return true;
- }
- if (focusOwner == null || !(focusOwner instanceof JComponent)) {
- return true;
- }
- JComponent jFocusOwner = (JComponent)focusOwner;
- InputVerifier iv = jFocusOwner.getInputVerifier();
- if (iv == null) {
- return true;
- } else {
- return iv.shouldYieldFocus(jFocusOwner);
- }
- }
- public void requestFocus() {
- if (runInputVerifier()) {
- super.requestFocus();
- }
- }
- /**
- * <code>JComponent</code> overrides <code>requestFocus</code> solely
- * to make the method public so that UI implementations can cause
- * temporary focus changes. This method is not meant for general use,
- * instead developers are urged to call the noarg <code>requestFocus</code>
- * or <code>requestFocusInWindow</code> methods. If the
- * <code>JComponent</code> has an <code>InputVerifier</code>associated
- * with it, the <code>InputVerifier</code> will be messaged.
- * <p>
- * Refer to {@link java.awt.Component#requestFocus(boolean)
- * Component.requestFocus(boolean)} for a complete description
- * of this method.
- *
- * @param temporary boolean indicating if the focus change is temporary
- * @return <code>false</code> if the focus change request is guaranteed to
- * fail; <code>true</code> if it is likely to succeed
- * @see java.awt.Component#requestFocus()
- * @see java.awt.Component#requestFocusInWindow()
- * @see java.awt.Component#requestFocus(boolean)
- * @see java.awt.Component#requestFocusInWindow(boolean)
- * @since 1.4
- */
- public boolean requestFocus(boolean temporary) {
- return (runInputVerifier())
- ? super.requestFocus(temporary)
- : false;
- }
- public boolean requestFocusInWindow() {
- return (runInputVerifier())
- ? super.requestFocusInWindow()
- : false;
- }
- /**
- * <code>JComponent</code> overrides <code>requestFocusInWindow</code>
- * solely to make the method public so that UI implementations can cause
- * temporary focus changes. This method is not meant for general use,
- * instead developers are urged to call the noarg <code>requestFocus</code>
- * or <code>requestFocusInWindow</code> methods. If the
- * <code>JComponent</code> has an <code>InputVerifier</code>associated
- * with it, the <code>InputVerifier</code> will be messaged.
- * <p>
- * Refer to {@link java.awt.Component#requestFocusInWindow(boolean)
- * Component.requestFocusInWindow(boolean)} for a complete description of
- * this method.
- *
- * @param temporary boolean indicating if the focus change is temporary
- * @return <code>false</code> if the focus change request is guaranteed to
- * fail; <code>true</code> if it is likely to succeed
- * @see java.awt.Component#requestFocus()
- * @see java.awt.Component#requestFocusInWindow()
- * @see java.awt.Component#requestFocus(boolean)
- * @see java.awt.Component#requestFocusInWindow(boolean)
- * @since 1.4
- */
- protected boolean requestFocusInWindow(boolean temporary) {
- return (runInputVerifier())
- ? super.requestFocusInWindow(temporary)
- : false;
- }
- /**
- * Requests that this Component get the input focus, and that this
- * Component's top-level ancestor become the focused Window. This component
- * must be displayable, visible, and focusable for the request to be
- * granted.
- * <p>
- * This method is intended for use by focus implementations. Client code
- * should not use this method; instead, it should use
- * <code>requestFocus()</code>.
- *
- * @see #requestFocus()
- */
- public void grabFocus() {
- requestFocus();
- }
- /**
- * Sets the value to indicate whether input verifier for the
- * current focus owner will be called before this component requests
- * focus. The default is true. Set to false on components such as a
- * Cancel button or a scrollbar, which should activate even if the
- * input in the current focus owner is not "passed" by the input
- * verifier for that component.
- *
- * @param verifyInputWhenFocusTarget value for the
- * <code>verifyInputWhenFocusTarget</code> property
- * @see InputVerifier
- * @see #setInputVerifier
- * @see #getInputVerifier
- * @see #getVerifyInputWhenFocusTarget
- *
- * @since 1.3
- * @beaninfo
- * bound: true
- * description: Whether the Component verifies input before accepting
- * focus.
- */
- public void setVerifyInputWhenFocusTarget(boolean
- verifyInputWhenFocusTarget) {
- boolean oldVerifyInputWhenFocusTarget =
- this.verifyInputWhenFocusTarget;
- this.verifyInputWhenFocusTarget = verifyInputWhenFocusTarget;
- firePropertyChange("verifyInputWhenFocusTarget",
- oldVerifyInputWhenFocusTarget,
- verifyInputWhenFocusTarget);
- }
- /**
- * Returns the value that indicates whether the input verifier for the
- * current focus owner will be called before this component requests
- * focus.
- *
- * @return value of the <code>verifyInputWhenFocusTarget</code> property
- *
- * @see InputVerifier
- * @see #setInputVerifier
- * @see #getInputVerifier
- * @see #setVerifyInputWhenFocusTarget
- *
- * @since 1.3
- */
- public boolean getVerifyInputWhenFocusTarget() {
- return verifyInputWhenFocusTarget;
- }
- /**
- * Sets the preferred size of this component.
- * If <code>preferredSize</code> is <code>null</code>, the UI will
- * be asked for the preferred size.
- * @beaninfo
- * preferred: true
- * bound: true
- * description: The preferred size of the component.
- */
- public void setPreferredSize(Dimension preferredSize) {
- Dimension old = this.preferredSize;
- this.preferredSize = preferredSize;
- firePropertyChange("preferredSize", old, preferredSize);
- }
- /**
- * If the <code>preferredSize</code> has been set to a
- * non-<code>null</code> value just returns it.
- * If the UI delegate's <code>getPreferredSize</code>
- * method returns a non <code>null</code> value then return that;
- * otherwise defer to the component's layout manager.
- *
- * @return the value of the <code>preferredSize</code> property
- * @see #setPreferredSize
- * @see ComponentUI
- */
- public Dimension getPreferredSize() {
- if (preferredSize != null) {
- return preferredSize;
- }
- Dimension size = null;
- if (ui != null) {
- size = ui.getPreferredSize(this);
- }
- return (size != null) ? size : super.getPreferredSize();
- }
- /**
- * Sets the maximum size of this component to a constant
- * value. Subsequent calls to <code>getMaximumSize</code> will always
- * return this value; the component's UI will not be asked
- * to compute it. Setting the maximum size to <code>null</code>
- * restores the default behavior.
- *
- * @param maximumSize a <code>Dimension</code> containing the
- * desired maximum allowable size
- * @see #getMaximumSize
- * @beaninfo
- * bound: true
- * description: The maximum size of the component.
- */
- public void setMaximumSize(Dimension maximumSize) {
- Dimension old = this.maximumSize;
- this.maximumSize = maximumSize;
- firePropertyChange("maximumSize", old, maximumSize);
- }
- /**
- * If the maximum size has been set to a non-<code>null</code> value
- * just returns it. If the UI delegate's <code>getMaximumSize</code>
- * method returns a non-<code>null</code> value then return that;
- * otherwise defer to the component's layout manager.
- *
- * @return the value of the <code>maximumSize</code> property
- * @see #setMaximumSize
- * @see ComponentUI
- */
- public Dimension getMaximumSize() {
- if (maximumSize != null) {
- return maximumSize;
- }
- Dimension size = null;
- if (ui != null) {
- size = ui.getMaximumSize(this);
- }
- return (size != null) ? size : super.getMaximumSize();
- }
- /**
- * Sets the minimum size of this component to a constant
- * value. Subsequent calls to <code>getMinimumSize</code> will always
- * return this value; the component's UI will not be asked
- * to compute it. Setting the minimum size to <code>null</code>
- * restores the default behavior.
- *
- * @param minimumSize the new minimum size of this component
- * @see #getMinimumSize
- * @beaninfo
- * bound: true
- * description: The minimum size of the component.
- */
- public void setMinimumSize(Dimension minimumSize) {
- Dimension old = this.minimumSize;
- this.minimumSize = minimumSize;
- firePropertyChange("minimumSize", old, minimumSize);
- }
- /**
- * If the minimum size has been set to a non-<code>null</code> value
- * just returns it. If the UI delegate's <code>getMinimumSize</code>
- * method returns a non-<code>null</code> value then return that; otherwise
- * defer to the component's layout manager.
- *
- * @return the value of the <code>minimumSize</code> property
- * @see #setMinimumSize
- * @see ComponentUI
- */
- public Dimension getMinimumSize() {
- if (minimumSize != null) {
- return minimumSize;
- }
- Dimension size = null;
- if (ui != null) {
- size = ui.getMinimumSize(this);
- }
- return (size != null) ? size : super.getMinimumSize();
- }
- /**
- * Returns true if the minimum size has been set to a non-<code>null</code>
- * value otherwise returns false.
- *
- * @return true if <code>minimumSize</code> is non-<code>null</code>,
- * false otherwise
- * @since 1.3
- */
- public boolean isMinimumSizeSet() {
- return minimumSize != null;
- }
- /**
- * Returns true if the preferred size has been set to a
- * non-<code>null</code> value otherwise returns false.
- *
- * @return true if <code>preferredSize</code> is non-<code>null</code>,
- * false otherwise
- * @since 1.3
- */
- public boolean isPreferredSizeSet() {
- return preferredSize != null;
- }
- /**
- * Returns true if the maximum size has been set to a non-<code>null</code>
- * value otherwise returns false.
- *
- * @return true if <code>maximumSize</code> is non-<code>null</code>,
- * false otherwise
- * @since 1.3
- */
- public boolean isMaximumSizeSet() {
- return maximumSize != null;
- }
- /**
- * Gives the UI delegate an opportunity to define the precise
- * shape of this component for the sake of mouse processing.
- *
- * @return true if this component logically contains x,y
- * @see java.awt.Component#contains(int, int)
- * @see ComponentUI
- */
- public boolean contains(int x, int y) {
- return (ui != null) ? ui.contains(this, x, y) : super.contains(x, y);
- }
- /**
- * Sets the border of this component. The <code>Border</code> object is
- * responsible for defining the insets for the component
- * (overriding any insets set directly on the component) and
- * for optionally rendering any border decorations within the
- * bounds of those insets. Borders should be used (rather
- * than insets) for creating both decorative and non-decorative
- * (such as margins and padding) regions for a swing component.
- * Compound borders can be used to nest multiple borders within a
- * single component.
- * <p>
- * This is a bound property.
- *
- * @param border the border to be rendered for this component
- * @see Border
- * @see CompoundBorder
- * @beaninfo
- * bound: true
- * preferred: true
- * attribute: visualUpdate true
- * description: The component's border.
- */
- public void setBorder(Border border) {
- Border oldBorder = this.border;
- this.border = border;
- firePropertyChange("border", oldBorder, border);
- if (border != oldBorder) {
- if (border == null || oldBorder == null ||
- !(border.getBorderInsets(this).equals(oldBorder.getBorderInsets(this)))) {
- revalidate();
- }
- repaint();
- }
- }
- /**
- * Returns the border of this component or <code>null</code> if no
- * border is currently set.
- *
- * @return the border object for this component
- * @see #setBorder
- */
- public Border getBorder() {
- return border;
- }
- /**
- * If a border has been set on this component, returns the
- * border's insets; otherwise calls <code>super.getInsets</code>.
- *
- * @return the value of the insets property
- * @see #setBorder
- */
- public Insets getInsets() {
- if (border != null) {
- return border.getBorderInsets(this);
- }
- return super.getInsets();
- }
- /**
- * Returns an <code>Insets</code> object containing this component's inset
- * values. The passed-in <code>Insets</code> object will be reused
- * if possible.
- * Calling methods cannot assume that the same object will be returned,
- * however. All existing values within this object are overwritten.
- * If <code>insets</code> is null, this will allocate a new one.
- *
- * @param insets the <code>Insets</code> object, which can be reused
- * @return the <code>Insets</code> object
- * @see #getInsets
- * @beaninfo
- * expert: true
- */
- public Insets getInsets(Insets insets) {
- if (insets == null) {
- insets = new Insets(0, 0, 0, 0);
- }
- if (border != null) {
- if (border instanceof AbstractBorder) {
- return ((AbstractBorder)border).getBorderInsets(this, insets);
- } else {
- // Can't reuse border insets because the Border interface
- // can't be enhanced.
- return border.getBorderInsets(this);
- }
- } else {
- // super.getInsets() always returns an Insets object with
- // all of its value zeroed. No need for a new object here.
- insets.left = insets.top = insets.right = insets.bottom = 0;
- return insets;
- }
- }
- /**
- * Overrides <code>Container.getAlignmentY</code> to return
- * the horizontal alignment.
- *
- * @return the value of the <code>alignmentY</code> property
- * @see #setAlignmentY
- * @see java.awt.Component#getAlignmentY
- */
- public float getAlignmentY() {
- return (alignmentY != null) ? alignmentY.floatValue() : super.getAlignmentY();
- }
- /**
- * Sets the the horizontal alignment.
- *
- * @param alignmentY the new horizontal alignment
- * @see #getAlignmentY
- * @beaninfo
- * description: The preferred vertical alignment of the component.
- */
- public void setAlignmentY(float alignmentY) {
- this.alignmentY = new Float(alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY);
- }
- /**
- * Overrides