| /* |
| * Copyright (c) 2011, 2013, Oracle and/or its affiliates. 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. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package sun.lwawt; |
| |
| import sun.awt.SunGraphicsCallback; |
| import sun.java2d.pipe.Region; |
| |
| import java.awt.Color; |
| import java.awt.Container; |
| import java.awt.Font; |
| import java.awt.Graphics; |
| import java.awt.Insets; |
| import java.awt.Rectangle; |
| import java.awt.peer.ContainerPeer; |
| import java.util.LinkedList; |
| import java.util.List; |
| |
| import javax.swing.JComponent; |
| |
| abstract class LWContainerPeer<T extends Container, D extends JComponent> |
| extends LWCanvasPeer<T, D> implements ContainerPeer { |
| |
| /** |
| * List of child peers sorted by z-order from bottom-most to top-most. |
| */ |
| private final List<LWComponentPeer<?, ?>> childPeers = new LinkedList<>(); |
| |
| LWContainerPeer(final T target, final PlatformComponent platformComponent) { |
| super(target, platformComponent); |
| } |
| |
| final void addChildPeer(final LWComponentPeer<?, ?> child) { |
| synchronized (getPeerTreeLock()) { |
| childPeers.add(childPeers.size(), child); |
| // TODO: repaint |
| } |
| } |
| |
| final void removeChildPeer(final LWComponentPeer<?, ?> child) { |
| synchronized (getPeerTreeLock()) { |
| childPeers.remove(child); |
| } |
| // TODO: repaint |
| } |
| |
| // Used by LWComponentPeer.setZOrder() |
| final void setChildPeerZOrder(final LWComponentPeer<?, ?> peer, |
| final LWComponentPeer<?, ?> above) { |
| synchronized (getPeerTreeLock()) { |
| childPeers.remove(peer); |
| int index = (above != null) ? childPeers.indexOf(above) : childPeers.size(); |
| if (index >= 0) { |
| childPeers.add(index, peer); |
| } else { |
| // TODO: log |
| } |
| } |
| // TODO: repaint |
| } |
| |
| // ---- PEER METHODS ---- // |
| |
| /* |
| * Overridden in LWWindowPeer. |
| */ |
| @Override |
| public Insets getInsets() { |
| return new Insets(0, 0, 0, 0); |
| } |
| |
| @Override |
| public final void beginValidate() { |
| // TODO: it seems that begin/endValidate() is only useful |
| // for heavyweight windows, when a batch movement for |
| // child windows occurs. That's why no-op |
| } |
| |
| @Override |
| public final void endValidate() { |
| // TODO: it seems that begin/endValidate() is only useful |
| // for heavyweight windows, when a batch movement for |
| // child windows occurs. That's why no-op |
| } |
| |
| @Override |
| public final void beginLayout() { |
| // Skip all painting till endLayout() |
| setLayouting(true); |
| } |
| |
| @Override |
| public final void endLayout() { |
| setLayouting(false); |
| |
| // Post an empty event to flush all the pending target paints |
| postPaintEvent(0, 0, 0, 0); |
| } |
| |
| // ---- PEER NOTIFICATIONS ---- // |
| |
| /** |
| * Returns a copy of the childPeer collection. |
| */ |
| @SuppressWarnings("unchecked") |
| final List<LWComponentPeer<?, ?>> getChildren() { |
| synchronized (getPeerTreeLock()) { |
| Object copy = ((LinkedList<?>) childPeers).clone(); |
| return (List<LWComponentPeer<?, ?>>) copy; |
| } |
| } |
| |
| @Override |
| final Region getVisibleRegion() { |
| return cutChildren(super.getVisibleRegion(), null); |
| } |
| |
| /** |
| * Removes bounds of children above specific child from the region. If above |
| * is null removes all bounds of children. |
| */ |
| final Region cutChildren(Region r, final LWComponentPeer<?, ?> above) { |
| boolean aboveFound = above == null; |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| if (!aboveFound && child == above) { |
| aboveFound = true; |
| continue; |
| } |
| if (aboveFound) { |
| if(child.isVisible()){ |
| final Rectangle cb = child.getBounds(); |
| final Region cr = child.getRegion(); |
| final Region tr = cr.getTranslatedRegion(cb.x, cb.y); |
| r = r.getDifference(tr.getIntersection(getContentSize())); |
| } |
| } |
| } |
| return r; |
| } |
| |
| // ---- UTILITY METHODS ---- // |
| |
| /** |
| * Finds a top-most visible component for the given point. The location is |
| * specified relative to the peer's parent. |
| */ |
| @Override |
| final LWComponentPeer<?, ?> findPeerAt(int x, int y) { |
| LWComponentPeer<?, ?> peer = super.findPeerAt(x, y); |
| final Rectangle r = getBounds(); |
| // Translate to this container's coordinates to pass to children |
| x -= r.x; |
| y -= r.y; |
| if (peer != null && getContentSize().contains(x, y)) { |
| synchronized (getPeerTreeLock()) { |
| for (int i = childPeers.size() - 1; i >= 0; --i) { |
| LWComponentPeer<?, ?> p = childPeers.get(i).findPeerAt(x, y); |
| if (p != null) { |
| peer = p; |
| break; |
| } |
| } |
| } |
| } |
| return peer; |
| } |
| |
| /* |
| * Called by the container when any part of this peer or child |
| * peers should be repainted |
| */ |
| @Override |
| final void repaintPeer(final Rectangle r) { |
| final Rectangle toPaint = getSize().intersection(r); |
| if (!isShowing() || toPaint.isEmpty()) { |
| return; |
| } |
| // First, post the PaintEvent for this peer |
| super.repaintPeer(toPaint); |
| // Second, handle all the children |
| // Use the straight order of children, so the bottom |
| // ones are painted first |
| repaintChildren(toPaint); |
| } |
| |
| /** |
| * Paints all the child peers in the straight z-order, so the |
| * bottom-most ones are painted first. |
| */ |
| private void repaintChildren(final Rectangle r) { |
| final Rectangle content = getContentSize(); |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| final Rectangle childBounds = child.getBounds(); |
| Rectangle toPaint = r.intersection(childBounds); |
| toPaint = toPaint.intersection(content); |
| toPaint.translate(-childBounds.x, -childBounds.y); |
| child.repaintPeer(toPaint); |
| } |
| } |
| |
| Rectangle getContentSize() { |
| return getSize(); |
| } |
| |
| @Override |
| public void setEnabled(final boolean e) { |
| super.setEnabled(e); |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| child.setEnabled(e && child.getTarget().isEnabled()); |
| } |
| } |
| |
| @Override |
| public void setBackground(final Color c) { |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| if (!child.getTarget().isBackgroundSet()) { |
| child.setBackground(c); |
| } |
| } |
| super.setBackground(c); |
| } |
| |
| @Override |
| public void setForeground(final Color c) { |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| if (!child.getTarget().isForegroundSet()) { |
| child.setForeground(c); |
| } |
| } |
| super.setForeground(c); |
| } |
| |
| @Override |
| public void setFont(final Font f) { |
| for (final LWComponentPeer<?, ?> child : getChildren()) { |
| if (!child.getTarget().isFontSet()) { |
| child.setFont(f); |
| } |
| } |
| super.setFont(f); |
| } |
| |
| @Override |
| public final void paint(final Graphics g) { |
| super.paint(g); |
| SunGraphicsCallback.PaintHeavyweightComponentsCallback.getInstance() |
| .runComponents(getTarget().getComponents(), g, |
| SunGraphicsCallback.LIGHTWEIGHTS |
| | SunGraphicsCallback.HEAVYWEIGHTS); |
| } |
| |
| @Override |
| public final void print(final Graphics g) { |
| super.print(g); |
| SunGraphicsCallback.PrintHeavyweightComponentsCallback.getInstance() |
| .runComponents(getTarget().getComponents(), g, |
| SunGraphicsCallback.LIGHTWEIGHTS |
| | SunGraphicsCallback.HEAVYWEIGHTS); |
| } |
| } |