/*
 * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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.
/** * 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); } }