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