1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /* @test
  25    @bug 8139581
  26    @summary AWT components are not drawn after removal and addition to a container
  27    @author Anton Litvinov
  28  */
  29 
  30 import java.awt.Button;
  31 import java.awt.Color;
  32 import java.awt.Canvas;
  33 import java.awt.Frame;
  34 import java.awt.Graphics;
  35 import java.awt.Panel;
  36 import java.util.ArrayList;
  37 
  38 public class ComponentIsNotDrawnAfterRemoveAddTest {
  39     private final Frame frame;
  40     private final Panel panel;
  41     private final ArrayList<Testable> compList = new ArrayList<Testable>();
  42 
  43     public ComponentIsNotDrawnAfterRemoveAddTest() {
  44         frame = new Frame("ComponentIsNotDrawnAfterRemoveAddTest");
  45         frame.setSize(500, 500);
  46         frame.setLocation(200, 200);
  47         frame.setLayout(null);
  48         frame.setBackground(Color.RED);
  49 
  50         panel = new Panel();
  51         panel.setLayout(null);
  52         panel.setBounds(25, 100, 455, 295);
  53         panel.setBackground(Color.GREEN);
  54 
  55         for (int i = 0; i < 10; i++) {
  56             TestCanvas canv1 = new TestCanvas();
  57             canv1.setBounds(i * 45 + 5, 15, 30 + i, 30 + i);
  58             panel.add(canv1);
  59             compList.add(canv1);
  60 
  61             TestButton btn1 = new TestButton();
  62             btn1.setBounds(i * 45 + 5, 60, 30 + i, 30 + i);
  63             panel.add(btn1);
  64             compList.add(btn1);
  65 
  66             TestCanvas canv2 = new TestCanvas();
  67             canv2.setBounds(i * 45 + 5, 105, 30 + i, 30 + i);
  68             panel.add(canv2);
  69             compList.add(canv2);
  70 
  71             TestButton btn2 = new TestButton();
  72             btn2.setBounds(i * 45 + 5, 150, 30 + i, 30 + i);
  73             panel.add(btn2);
  74             compList.add(btn2);
  75 
  76             TestCanvas canv3 = new TestCanvas();
  77             canv3.setBounds(i * 45 + 5, 195, 30 + i, 30 + i);
  78             panel.add(canv3);
  79             compList.add(canv3);
  80 
  81             TestButton btn3 = new TestButton();
  82             btn3.setBounds(i * 45 + 5, 240, 30 + i, 30 + i);
  83             panel.add(btn3);
  84             compList.add(btn3);
  85         }
  86 
  87         frame.add(panel);
  88         frame.setVisible(true);
  89     }
  90 
  91     private void runTest() {
  92         try {
  93             doSleep(1500);
  94             checkTestableComponents();
  95 
  96             for (int i = 0; i < 5; i++) {
  97                 System.err.println(String.format("Test iteration #%d:", i));
  98 
  99                 frame.remove(panel);
 100                 frame.invalidate();
 101                 frame.validate();
 102                 frame.add(panel);
 103 
 104                 doSleep(1500);
 105                 checkTestableComponents();
 106             }
 107         } finally {
 108             frame.dispose();
 109         }
 110     }
 111 
 112     private void doSleep(long millis) {
 113         try {
 114             Thread.sleep(millis);
 115         } catch (InterruptedException ie) {
 116             ie.printStackTrace();
 117         }
 118     }
 119 
 120     private void checkTestableComponents() throws RuntimeException {
 121         int notDrawnCompsCount = 0;
 122         for (Testable comp : compList) {
 123             if (!comp.wasPaintCalled()) {
 124                 notDrawnCompsCount++;
 125             } else {
 126                 comp.resetPaintCalledFlag();
 127             }
 128         }
 129         if (notDrawnCompsCount > 0) {
 130             throw new RuntimeException(String.format(
 131                 "'paint' method of %d components was not called.", notDrawnCompsCount));
 132         }
 133     }
 134 
 135     private interface Testable {
 136         boolean wasPaintCalled();
 137         void resetPaintCalledFlag();
 138     }
 139 
 140     private static class TestCanvas extends Canvas implements Testable {
 141         private volatile boolean paintWasCalled = false;
 142 
 143         @Override
 144         public void paint(Graphics g) {
 145             paintWasCalled = true;
 146             super.paint(g);
 147             g.setColor(Color.BLUE);
 148             g.fillRect(0, 0, getWidth(), getHeight());
 149         }
 150 
 151         @Override
 152         public boolean wasPaintCalled() {
 153             return paintWasCalled;
 154         }
 155 
 156         @Override
 157         public void resetPaintCalledFlag() {
 158             paintWasCalled = false;
 159         }
 160     }
 161 
 162     private static class TestButton extends Button implements Testable {
 163         private volatile boolean paintWasCalled = false;
 164 
 165         @Override
 166         public void paint(Graphics g) {
 167             paintWasCalled = true;
 168             super.paint(g);
 169             g.setColor(Color.YELLOW);
 170             g.fillRect(0, 0, 15, 15);
 171         }
 172 
 173         @Override
 174         public boolean wasPaintCalled() {
 175             return paintWasCalled;
 176         }
 177 
 178         @Override
 179         public void resetPaintCalledFlag() {
 180             paintWasCalled = false;
 181         }
 182     }
 183 
 184     public static void main(String[] args) {
 185         new ComponentIsNotDrawnAfterRemoveAddTest().runTest();
 186     }
 187 }