1/* 2 * Copyright (c) 2011, 2013, 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package sun.lwawt; 27 28import sun.awt.SunGraphicsCallback; 29import sun.java2d.pipe.Region; 30 31import java.awt.Color; 32import java.awt.Container; 33import java.awt.Font; 34import java.awt.Graphics; 35import java.awt.Insets; 36import java.awt.Rectangle; 37import java.awt.peer.ContainerPeer; 38import java.util.LinkedList; 39import java.util.List; 40 41import javax.swing.JComponent; 42 43abstract class LWContainerPeer<T extends Container, D extends JComponent> 44 extends LWCanvasPeer<T, D> implements ContainerPeer { 45 46 /** 47 * List of child peers sorted by z-order from bottom-most to top-most. 48 */ 49 private final List<LWComponentPeer<?, ?>> childPeers = new LinkedList<>(); 50 51 LWContainerPeer(final T target, final PlatformComponent platformComponent) { 52 super(target, platformComponent); 53 } 54 55 final void addChildPeer(final LWComponentPeer<?, ?> child) { 56 synchronized (getPeerTreeLock()) { 57 childPeers.add(childPeers.size(), child); 58 // TODO: repaint 59 } 60 } 61 62 final void removeChildPeer(final LWComponentPeer<?, ?> child) { 63 synchronized (getPeerTreeLock()) { 64 childPeers.remove(child); 65 } 66 // TODO: repaint 67 } 68 69 // Used by LWComponentPeer.setZOrder() 70 final void setChildPeerZOrder(final LWComponentPeer<?, ?> peer, 71 final LWComponentPeer<?, ?> above) { 72 synchronized (getPeerTreeLock()) { 73 childPeers.remove(peer); 74 int index = (above != null) ? childPeers.indexOf(above) : childPeers.size(); 75 if (index >= 0) { 76 childPeers.add(index, peer); 77 } else { 78 // TODO: log 79 } 80 } 81 // TODO: repaint 82 } 83 84 // ---- PEER METHODS ---- // 85 86 /* 87 * Overridden in LWWindowPeer. 88 */ 89 @Override 90 public Insets getInsets() { 91 return new Insets(0, 0, 0, 0); 92 } 93 94 @Override 95 public final void beginValidate() { 96 // TODO: it seems that begin/endValidate() is only useful 97 // for heavyweight windows, when a batch movement for 98 // child windows occurs. That's why no-op 99 } 100 101 @Override 102 public final void endValidate() { 103 // TODO: it seems that begin/endValidate() is only useful 104 // for heavyweight windows, when a batch movement for 105 // child windows occurs. That's why no-op 106 } 107 108 @Override 109 public final void beginLayout() { 110 // Skip all painting till endLayout() 111 setLayouting(true); 112 } 113 114 @Override 115 public final void endLayout() { 116 setLayouting(false); 117 118 // Post an empty event to flush all the pending target paints 119 postPaintEvent(0, 0, 0, 0); 120 } 121 122 // ---- PEER NOTIFICATIONS ---- // 123 124 /** 125 * Returns a copy of the childPeer collection. 126 */ 127 @SuppressWarnings("unchecked") 128 final List<LWComponentPeer<?, ?>> getChildren() { 129 synchronized (getPeerTreeLock()) { 130 Object copy = ((LinkedList<?>) childPeers).clone(); 131 return (List<LWComponentPeer<?, ?>>) copy; 132 } 133 } 134 135 @Override 136 final Region getVisibleRegion() { 137 return cutChildren(super.getVisibleRegion(), null); 138 } 139 140 /** 141 * Removes bounds of children above specific child from the region. If above 142 * is null removes all bounds of children. 143 */ 144 final Region cutChildren(Region r, final LWComponentPeer<?, ?> above) { 145 boolean aboveFound = above == null; 146 for (final LWComponentPeer<?, ?> child : getChildren()) { 147 if (!aboveFound && child == above) { 148 aboveFound = true; 149 continue; 150 } 151 if (aboveFound) { 152 if(child.isVisible()){ 153 final Rectangle cb = child.getBounds(); 154 final Region cr = child.getRegion(); 155 final Region tr = cr.getTranslatedRegion(cb.x, cb.y); 156 r = r.getDifference(tr.getIntersection(getContentSize())); 157 } 158 } 159 } 160 return r; 161 } 162 163 // ---- UTILITY METHODS ---- // 164 165 /** 166 * Finds a top-most visible component for the given point. The location is 167 * specified relative to the peer's parent. 168 */ 169 @Override 170 final LWComponentPeer<?, ?> findPeerAt(int x, int y) { 171 LWComponentPeer<?, ?> peer = super.findPeerAt(x, y); 172 final Rectangle r = getBounds(); 173 // Translate to this container's coordinates to pass to children 174 x -= r.x; 175 y -= r.y; 176 if (peer != null && getContentSize().contains(x, y)) { 177 synchronized (getPeerTreeLock()) { 178 for (int i = childPeers.size() - 1; i >= 0; --i) { 179 LWComponentPeer<?, ?> p = childPeers.get(i).findPeerAt(x, y); 180 if (p != null) { 181 peer = p; 182 break; 183 } 184 } 185 } 186 } 187 return peer; 188 } 189 190 /* 191 * Called by the container when any part of this peer or child 192 * peers should be repainted 193 */ 194 @Override 195 final void repaintPeer(final Rectangle r) { 196 final Rectangle toPaint = getSize().intersection(r); 197 if (!isShowing() || toPaint.isEmpty()) { 198 return; 199 } 200 // First, post the PaintEvent for this peer 201 super.repaintPeer(toPaint); 202 // Second, handle all the children 203 // Use the straight order of children, so the bottom 204 // ones are painted first 205 repaintChildren(toPaint); 206 } 207 208 /** 209 * Paints all the child peers in the straight z-order, so the 210 * bottom-most ones are painted first. 211 */ 212 private void repaintChildren(final Rectangle r) { 213 final Rectangle content = getContentSize(); 214 for (final LWComponentPeer<?, ?> child : getChildren()) { 215 final Rectangle childBounds = child.getBounds(); 216 Rectangle toPaint = r.intersection(childBounds); 217 toPaint = toPaint.intersection(content); 218 toPaint.translate(-childBounds.x, -childBounds.y); 219 child.repaintPeer(toPaint); 220 } 221 } 222 223 Rectangle getContentSize() { 224 return getSize(); 225 } 226 227 @Override 228 public void setEnabled(final boolean e) { 229 super.setEnabled(e); 230 for (final LWComponentPeer<?, ?> child : getChildren()) { 231 child.setEnabled(e && child.getTarget().isEnabled()); 232 } 233 } 234 235 @Override 236 public void setBackground(final Color c) { 237 for (final LWComponentPeer<?, ?> child : getChildren()) { 238 if (!child.getTarget().isBackgroundSet()) { 239 child.setBackground(c); 240 } 241 } 242 super.setBackground(c); 243 } 244 245 @Override 246 public void setForeground(final Color c) { 247 for (final LWComponentPeer<?, ?> child : getChildren()) { 248 if (!child.getTarget().isForegroundSet()) { 249 child.setForeground(c); 250 } 251 } 252 super.setForeground(c); 253 } 254 255 @Override 256 public void setFont(final Font f) { 257 for (final LWComponentPeer<?, ?> child : getChildren()) { 258 if (!child.getTarget().isFontSet()) { 259 child.setFont(f); 260 } 261 } 262 super.setFont(f); 263 } 264 265 @Override 266 public final void paint(final Graphics g) { 267 super.paint(g); 268 SunGraphicsCallback.PaintHeavyweightComponentsCallback.getInstance() 269 .runComponents(getTarget().getComponents(), g, 270 SunGraphicsCallback.LIGHTWEIGHTS 271 | SunGraphicsCallback.HEAVYWEIGHTS); 272 } 273 274 @Override 275 public final void print(final Graphics g) { 276 super.print(g); 277 SunGraphicsCallback.PrintHeavyweightComponentsCallback.getInstance() 278 .runComponents(getTarget().getComponents(), g, 279 SunGraphicsCallback.LIGHTWEIGHTS 280 | SunGraphicsCallback.HEAVYWEIGHTS); 281 } 282} 283