mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-24 04:54:40 +02:00
6852592: invalidate() must be smarter
Introduce validate roots in AWT Reviewed-by: alexp, art, dcherepanov
This commit is contained in:
parent
a77b6a72e0
commit
b50342c24e
13 changed files with 355 additions and 114 deletions
|
@ -229,6 +229,21 @@ public class Applet extends Panel {
|
|||
resize(d.width, d.height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this container is a validate root.
|
||||
* <p>
|
||||
* {@code Applet} objects are the validate roots, and, therefore, they
|
||||
* override this method to return {@code true}.
|
||||
*
|
||||
* @return {@code true}
|
||||
* @since 1.7
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests that the argument string be displayed in the
|
||||
* "status window". Many browsers and applet viewers
|
||||
|
|
|
@ -2764,8 +2764,11 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
|||
}
|
||||
|
||||
/**
|
||||
* Ensures that this component has a valid layout. This method is
|
||||
* primarily intended to operate on instances of <code>Container</code>.
|
||||
* Validates this component.
|
||||
* <p>
|
||||
* The meaning of the term <i>validating</i> is defined by the ancestors of
|
||||
* this class. See {@link Container#validate} for more details.
|
||||
*
|
||||
* @see #invalidate
|
||||
* @see #doLayout()
|
||||
* @see LayoutManager
|
||||
|
@ -2794,12 +2797,24 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
|||
}
|
||||
|
||||
/**
|
||||
* Invalidates this component. This component and all parents
|
||||
* above it are marked as needing to be laid out. This method can
|
||||
* be called often, so it needs to execute quickly.
|
||||
* Invalidates this component and its ancestors.
|
||||
* <p>
|
||||
* All the ancestors of this component up to the nearest validate root are
|
||||
* marked invalid also. If there is no a validate root container for this
|
||||
* component, all of its ancestors up to the root of the hierarchy are
|
||||
* marked invalid as well. Marking a container <i>invalid</i> indicates
|
||||
* that the container needs to be laid out.
|
||||
* <p>
|
||||
* This method is called automatically when any layout-related information
|
||||
* changes (e.g. setting the bounds of the component, or adding the
|
||||
* component to a container).
|
||||
* <p>
|
||||
* This method might be called often, so it should work fast.
|
||||
*
|
||||
* @see #validate
|
||||
* @see #doLayout
|
||||
* @see LayoutManager
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
* @since JDK1.0
|
||||
*/
|
||||
public void invalidate() {
|
||||
|
@ -2818,11 +2833,20 @@ public abstract class Component implements ImageObserver, MenuContainer,
|
|||
if (!isMaximumSizeSet()) {
|
||||
maxSize = null;
|
||||
}
|
||||
invalidateParent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the parent of this component if any.
|
||||
*
|
||||
* This method MUST BE invoked under the TreeLock.
|
||||
*/
|
||||
void invalidateParent() {
|
||||
if (parent != null) {
|
||||
parent.invalidateIfValid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Invalidates the component unless it is already invalid.
|
||||
*/
|
||||
|
|
|
@ -1492,20 +1492,59 @@ public class Container extends Component {
|
|||
}
|
||||
|
||||
/**
|
||||
* Invalidates the container. The container and all parents
|
||||
* above it are marked as needing to be laid out. This method can
|
||||
* be called often, so it needs to execute quickly.
|
||||
* Indicates if this container is a <i>validate root</i>.
|
||||
* <p>
|
||||
* Layout-related changes, such as bounds of the validate root descendants,
|
||||
* do not affect the layout of the validate root parent. This peculiarity
|
||||
* enables the {@code invalidate()} method to stop invalidating the
|
||||
* component hierarchy when the method encounters a validate root.
|
||||
* <p>
|
||||
* If a component hierarchy contains validate roots, the {@code validate()}
|
||||
* method must be invoked on the validate root of a previously invalidated
|
||||
* component, rather than on the top-level container (such as a {@code
|
||||
* Frame} object) to restore the validity of the hierarchy later.
|
||||
* <p>
|
||||
* The {@code Window} class and the {@code Applet} class are the validate
|
||||
* roots in AWT. Swing introduces more validate roots.
|
||||
*
|
||||
* <p> If the {@code LayoutManager} installed on this container is
|
||||
* an instance of {@code LayoutManager2}, then
|
||||
* {@link LayoutManager2#invalidateLayout(Container)} is invoked on
|
||||
* it supplying this {@code Container} as the argument.
|
||||
* @return whether this container is a validate root
|
||||
* @see #invalidate
|
||||
* @see java.awt.Component#invalidate
|
||||
* @see javax.swing.JComponent#isValidateRoot
|
||||
* @see javax.swing.JComponent#revalidate
|
||||
* @since 1.7
|
||||
*/
|
||||
public boolean isValidateRoot() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the parent of the container unless the container
|
||||
* is a validate root.
|
||||
*/
|
||||
@Override
|
||||
void invalidateParent() {
|
||||
if (!isValidateRoot()) {
|
||||
super.invalidateParent();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates the container.
|
||||
* <p>
|
||||
* If the {@code LayoutManager} installed on this container is an instance
|
||||
* of the {@code LayoutManager2} interface, then
|
||||
* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
|
||||
* on it supplying this {@code Container} as the argument.
|
||||
* <p>
|
||||
* Afterwards this method marks this container invalid, and invalidates its
|
||||
* ancestors. See the {@link Component#invalidate} method for more details.
|
||||
*
|
||||
* @see #validate
|
||||
* @see #layout
|
||||
* @see LayoutManager
|
||||
* @see LayoutManager2#invalidateLayout(Container)
|
||||
* @see LayoutManager2
|
||||
*/
|
||||
@Override
|
||||
public void invalidate() {
|
||||
LayoutManager layoutMgr = this.layoutMgr;
|
||||
if (layoutMgr instanceof LayoutManager2) {
|
||||
|
@ -1518,35 +1557,39 @@ public class Container extends Component {
|
|||
/**
|
||||
* Validates this container and all of its subcomponents.
|
||||
* <p>
|
||||
* The <code>validate</code> method is used to cause a container
|
||||
* to lay out its subcomponents again. It should be invoked when
|
||||
* this container's subcomponents are modified (added to or
|
||||
* removed from the container, or layout-related information
|
||||
* changed) after the container has been displayed.
|
||||
*
|
||||
* <p>If this {@code Container} is not valid, this method invokes
|
||||
* Validating a container means laying out its subcomponents.
|
||||
* Layout-related changes, such as setting the bounds of a component, or
|
||||
* adding a component to the container, invalidate the container
|
||||
* automatically. Note that the ancestors of the container may be
|
||||
* invalidated also (see {@link Component#invalidate} for details.)
|
||||
* Therefore, to restore the validity of the hierarchy, the {@code
|
||||
* validate()} method should be invoked on a validate root of an
|
||||
* invalidated component, or on the top-most container if the hierarchy
|
||||
* does not contain validate roots.
|
||||
* <p>
|
||||
* Validating the container may be a quite time-consuming operation. For
|
||||
* performance reasons a developer may postpone the validation of the
|
||||
* hierarchy till a set of layout-related operations completes, e.g. after
|
||||
* adding all the children to the container.
|
||||
* <p>
|
||||
* If this {@code Container} is not valid, this method invokes
|
||||
* the {@code validateTree} method and marks this {@code Container}
|
||||
* as valid. Otherwise, no action is performed.
|
||||
* <p>
|
||||
* Note that the {@code invalidate()} method may invalidate not only the
|
||||
* component it is called upon, but also the parents of the component.
|
||||
* Therefore, to restore the validity of the hierarchy, the {@code
|
||||
* validate()} method must be invoked on the top-most invalid container of
|
||||
* the hierarchy. For performance reasons a developer may postpone the
|
||||
* validation of the hierarchy till a bunch of layout-related operations
|
||||
* completes, e.g. after adding all the children to the container.
|
||||
*
|
||||
* @see #add(java.awt.Component)
|
||||
* @see #invalidate
|
||||
* @see Container#isValidateRoot
|
||||
* @see javax.swing.JComponent#revalidate()
|
||||
* @see #validateTree
|
||||
*/
|
||||
public void validate() {
|
||||
/* Avoid grabbing lock unless really necessary. */
|
||||
if (!isValid()) {
|
||||
if (!isValid() || descendUnconditionallyWhenValidating) {
|
||||
boolean updateCur = false;
|
||||
synchronized (getTreeLock()) {
|
||||
if (!isValid() && peer != null) {
|
||||
if ((!isValid() || descendUnconditionallyWhenValidating)
|
||||
&& peer != null)
|
||||
{
|
||||
ContainerPeer p = null;
|
||||
if (peer instanceof ContainerPeer) {
|
||||
p = (ContainerPeer) peer;
|
||||
|
@ -1557,16 +1600,53 @@ public class Container extends Component {
|
|||
validateTree();
|
||||
if (p != null) {
|
||||
p.endValidate();
|
||||
// Avoid updating cursor if this is an internal call.
|
||||
// See validateUnconditionally() for details.
|
||||
if (!descendUnconditionallyWhenValidating) {
|
||||
updateCur = isVisible();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updateCur) {
|
||||
updateCursorImmediately();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether valid containers should also traverse their
|
||||
* children and call the validateTree() method on them.
|
||||
*
|
||||
* Synchronization: TreeLock.
|
||||
*
|
||||
* The field is allowed to be static as long as the TreeLock itself is
|
||||
* static.
|
||||
*
|
||||
* @see #validateUnconditionally()
|
||||
*/
|
||||
private static boolean descendUnconditionallyWhenValidating = false;
|
||||
|
||||
/**
|
||||
* Unconditionally validate the component hierarchy.
|
||||
*/
|
||||
final void validateUnconditionally() {
|
||||
boolean updateCur = false;
|
||||
synchronized (getTreeLock()) {
|
||||
descendUnconditionallyWhenValidating = true;
|
||||
|
||||
validate();
|
||||
if (peer instanceof ContainerPeer) {
|
||||
updateCur = isVisible();
|
||||
}
|
||||
|
||||
descendUnconditionallyWhenValidating = false;
|
||||
}
|
||||
if (updateCur) {
|
||||
updateCursorImmediately();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively descends the container tree and recomputes the
|
||||
* layout for any subtrees marked as needing it (those marked as
|
||||
|
@ -1578,16 +1658,20 @@ public class Container extends Component {
|
|||
*/
|
||||
protected void validateTree() {
|
||||
checkTreeLock();
|
||||
if (!isValid()) {
|
||||
if (!isValid() || descendUnconditionallyWhenValidating) {
|
||||
if (peer instanceof ContainerPeer) {
|
||||
((ContainerPeer)peer).beginLayout();
|
||||
}
|
||||
if (!isValid()) {
|
||||
doLayout();
|
||||
}
|
||||
for (int i = 0; i < component.size(); i++) {
|
||||
Component comp = component.get(i);
|
||||
if ( (comp instanceof Container)
|
||||
&& !(comp instanceof Window)
|
||||
&& !comp.isValid()) {
|
||||
&& (!comp.isValid() ||
|
||||
descendUnconditionallyWhenValidating))
|
||||
{
|
||||
((Container)comp).validateTree();
|
||||
} else {
|
||||
comp.validate();
|
||||
|
|
|
@ -767,7 +767,7 @@ public class Window extends Container implements Accessible {
|
|||
isPacked = true;
|
||||
}
|
||||
|
||||
validate();
|
||||
validateUnconditionally();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -943,7 +943,7 @@ public class Window extends Container implements Accessible {
|
|||
if (peer == null) {
|
||||
addNotify();
|
||||
}
|
||||
validate();
|
||||
validateUnconditionally();
|
||||
|
||||
isInShow = true;
|
||||
if (visible) {
|
||||
|
@ -2599,6 +2599,21 @@ public class Window extends Container implements Accessible {
|
|||
super.addPropertyChangeListener(propertyName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this container is a validate root.
|
||||
* <p>
|
||||
* {@code Window} objects are the validate roots, and, therefore, they
|
||||
* override this method to return {@code true}.
|
||||
*
|
||||
* @return {@code true}
|
||||
* @since 1.7
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches an event to this window or one of its sub components.
|
||||
* @param e the event
|
||||
|
|
|
@ -4878,7 +4878,9 @@ public abstract class JComponent extends Container implements Serializable,
|
|||
* @see #revalidate
|
||||
* @see java.awt.Component#invalidate
|
||||
* @see java.awt.Container#validate
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -725,8 +725,10 @@ public class JRootPane extends JComponent implements Accessible {
|
|||
* because both classes override <code>isValidateRoot</code> to return true.
|
||||
*
|
||||
* @see JComponent#isValidateRoot
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
* @return true
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -453,10 +453,12 @@ public class JScrollPane extends JComponent implements ScrollPaneConstants, Acce
|
|||
* @see java.awt.Container#validate
|
||||
* @see JComponent#revalidate
|
||||
* @see JComponent#isValidateRoot
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*
|
||||
* @beaninfo
|
||||
* hidden: true
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -947,10 +947,12 @@ public class JSplitPane extends JComponent implements Accessible
|
|||
*
|
||||
* @return true
|
||||
* @see JComponent#revalidate
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*
|
||||
* @beaninfo
|
||||
* hidden: true
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -288,7 +288,9 @@ public class JTextField extends JTextComponent implements SwingConstants {
|
|||
*
|
||||
* @see JComponent#revalidate
|
||||
* @see JComponent#isValidateRoot
|
||||
* @see java.awt.Container#isValidateRoot
|
||||
*/
|
||||
@Override
|
||||
public boolean isValidateRoot() {
|
||||
return SwingUtilities2.getViewport(this) == null;
|
||||
}
|
||||
|
|
|
@ -469,49 +469,12 @@ public class JViewport extends JComponent implements Accessible
|
|||
* is the synchronous version of a <code>revalidate</code>.
|
||||
*/
|
||||
private void validateView() {
|
||||
Component validateRoot = null;
|
||||
Component validateRoot = SwingUtilities.getValidateRoot(this, false);
|
||||
|
||||
/* Find the first JComponent ancestor of this component whose
|
||||
* isValidateRoot() method returns true.
|
||||
*/
|
||||
for(Component c = this; c != null; c = c.getParent()) {
|
||||
if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
|
||||
return;
|
||||
}
|
||||
if ((c instanceof JComponent) &&
|
||||
(((JComponent)c).isValidateRoot())) {
|
||||
validateRoot = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no validateRoot, nothing to validate from.
|
||||
if (validateRoot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure all ancestors are visible.
|
||||
Component root = null;
|
||||
|
||||
for(Component c = validateRoot; c != null; c = c.getParent()) {
|
||||
// We don't check isVisible here, otherwise if the component
|
||||
// is contained in something like a JTabbedPane when the
|
||||
// component is made visible again it won't have scrolled
|
||||
// to the correct location.
|
||||
if (c.getPeer() == null) {
|
||||
return;
|
||||
}
|
||||
if ((c instanceof Window) || (c instanceof Applet)) {
|
||||
root = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure there is a Window ancestor.
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate the root.
|
||||
validateRoot.validate();
|
||||
|
||||
|
|
|
@ -310,47 +310,13 @@ public class RepaintManager
|
|||
delegate.addInvalidComponent(invalidComponent);
|
||||
return;
|
||||
}
|
||||
Component validateRoot = null;
|
||||
Component validateRoot =
|
||||
SwingUtilities.getValidateRoot(invalidComponent, true);
|
||||
|
||||
/* Find the first JComponent ancestor of this component whose
|
||||
* isValidateRoot() method returns true.
|
||||
*/
|
||||
for(Component c = invalidComponent; c != null; c = c.getParent()) {
|
||||
if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
|
||||
return;
|
||||
}
|
||||
if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
|
||||
validateRoot = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* There's no validateRoot to apply validate to, so we're done.
|
||||
*/
|
||||
if (validateRoot == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* If the validateRoot and all of its ancestors aren't visible
|
||||
* then we don't do anything. While we're walking up the tree
|
||||
* we find the root Window or Applet.
|
||||
*/
|
||||
Component root = null;
|
||||
|
||||
for(Component c = validateRoot; c != null; c = c.getParent()) {
|
||||
if (!c.isVisible() || (c.getPeer() == null)) {
|
||||
return;
|
||||
}
|
||||
if ((c instanceof Window) || (c instanceof Applet)) {
|
||||
root = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (root == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Lazily create the invalidateComponents vector and add the
|
||||
* validateRoot if it's not there already. If this validateRoot
|
||||
* is already in the vector, we're done.
|
||||
|
|
|
@ -1967,4 +1967,54 @@ public class SwingUtilities implements SwingConstants
|
|||
SwingUtilities.updateComponentTreeUI(component);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the validate root of a given container.
|
||||
*
|
||||
* If the container is contained within a {@code CellRendererPane}, this
|
||||
* method returns {@code null} due to the synthetic nature of the {@code
|
||||
* CellRendererPane}.
|
||||
* <p>
|
||||
* The component hierarchy must be displayable up to the toplevel component
|
||||
* (either a {@code Frame} or an {@code Applet} object.) Otherwise this
|
||||
* method returns {@code null}.
|
||||
* <p>
|
||||
* If the {@code visibleOnly} argument is {@code true}, the found validate
|
||||
* root and all its parents up to the toplevel component must also be
|
||||
* visible. Otherwise this method returns {@code null}.
|
||||
*
|
||||
* @return the validate root of the given container or null
|
||||
* @see java.awt.Component#isDisplayable()
|
||||
* @see java.awt.Component#isVisible()
|
||||
* @since 1.7
|
||||
*/
|
||||
static Container getValidateRoot(Container c, boolean visibleOnly) {
|
||||
Container root = null;
|
||||
|
||||
for (; c != null; c = c.getParent())
|
||||
{
|
||||
if (!c.isDisplayable() || c instanceof CellRendererPane) {
|
||||
return null;
|
||||
}
|
||||
if (c.isValidateRoot()) {
|
||||
root = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (root == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (; c != null; c = c.getParent()) {
|
||||
if (!c.isDisplayable() || (visibleOnly && !c.isVisible())) {
|
||||
return null;
|
||||
}
|
||||
if (c instanceof Window || c instanceof Applet) {
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
@test
|
||||
@bug 6852592
|
||||
@summary invalidate() must stop when it encounters a validate root
|
||||
@author anthony.petrov@sun.com
|
||||
@run main InvalidateMustRespectValidateRoots
|
||||
*/
|
||||
|
||||
import javax.swing.*;
|
||||
import java.awt.event.*;
|
||||
|
||||
public class InvalidateMustRespectValidateRoots {
|
||||
private static volatile JRootPane rootPane;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
// The JRootPane is a validate root. We'll check if
|
||||
// invalidate() stops on the root pane, or goes further
|
||||
// up to the frame.
|
||||
JFrame frame = new JFrame();
|
||||
final JButton button = new JButton();
|
||||
|
||||
frame.add(button);
|
||||
|
||||
// To enable running the test manually: use the Ctrl-Shift-F1
|
||||
// to print the component hierarchy to the console
|
||||
button.addActionListener(new ActionListener() {
|
||||
public void actionPerformed(ActionEvent ev) {
|
||||
if (button.isValid()) {
|
||||
button.invalidate();
|
||||
} else {
|
||||
button.revalidate();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
rootPane = frame.getRootPane();
|
||||
|
||||
// Now the component hierarchy looks like:
|
||||
// frame
|
||||
// --> rootPane
|
||||
// --> layered pane
|
||||
// --> content pane
|
||||
// --> button
|
||||
|
||||
// Make all components valid first via showing the frame
|
||||
// We have to make the frame visible. Otherwise revalidate() is
|
||||
// useless (see RepaintManager.addInvalidComponent()).
|
||||
frame.pack(); // To enable running this test manually
|
||||
frame.setVisible(true);
|
||||
|
||||
if (!frame.isValid()) {
|
||||
throw new RuntimeException(
|
||||
"setVisible(true) failed to validate the frame");
|
||||
}
|
||||
|
||||
// Now invalidate the button
|
||||
button.invalidate();
|
||||
|
||||
// Check if the 'valid' status is what we expect it to be
|
||||
if (rootPane.isValid()) {
|
||||
throw new RuntimeException(
|
||||
"invalidate() failed to invalidate the root pane");
|
||||
}
|
||||
|
||||
if (!frame.isValid()) {
|
||||
throw new RuntimeException(
|
||||
"invalidate() invalidated the frame");
|
||||
}
|
||||
|
||||
// Now validate the hierarchy again
|
||||
button.revalidate();
|
||||
|
||||
// Now let the validation happen on the EDT
|
||||
}
|
||||
});
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
SwingUtilities.invokeAndWait(new Runnable() {
|
||||
public void run() {
|
||||
// Check if the root pane finally became valid
|
||||
if (!rootPane.isValid()) {
|
||||
throw new RuntimeException(
|
||||
"revalidate() failed to validate the hierarchy");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue