LWContainerPeer.java 9.0 KB
Newer Older
1
/*
2
 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 * 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>
44
        extends LWCanvasPeer<T, D> implements ContainerPeer {
45

46 47 48 49 50 51 52
    /**
     * 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);
53 54
    }

55
    final void addChildPeer(final LWComponentPeer<?, ?> child) {
56
        synchronized (getPeerTreeLock()) {
57 58
            childPeers.add(childPeers.size(), child);
            // TODO: repaint
59 60 61
        }
    }

62
    final void removeChildPeer(final LWComponentPeer<?, ?> child) {
63 64 65 66 67 68 69
        synchronized (getPeerTreeLock()) {
            childPeers.remove(child);
        }
        // TODO: repaint
    }

    // Used by LWComponentPeer.setZOrder()
70 71
    final void setChildPeerZOrder(final LWComponentPeer<?, ?> peer,
                                  final LWComponentPeer<?, ?> above) {
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
        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
95
    public final void beginValidate() {
96 97 98 99
        // 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
    }
100

101
    @Override
102
    public final void endValidate() {
103 104 105 106 107 108
        // 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
109
    public final void beginLayout() {
110 111 112
        // Skip all painting till endLayout()
        setLayouting(true);
    }
113

114
    @Override
115
    public final void endLayout() {
116 117 118 119 120 121 122 123
        setLayouting(false);

        // Post an empty event to flush all the pending target paints
        postPaintEvent(0, 0, 0, 0);
    }

    // ---- PEER NOTIFICATIONS ---- //

124
    /**
125 126
     * Returns a copy of the childPeer collection.
     */
127 128
    @SuppressWarnings("unchecked")
    final List<LWComponentPeer<?, ?>> getChildren() {
129
        synchronized (getPeerTreeLock()) {
130 131
            Object copy = ((LinkedList<?>) childPeers).clone();
            return (List<LWComponentPeer<?, ?>>) copy;
132 133 134 135
        }
    }

    @Override
136
    final Region getVisibleRegion() {
137 138 139 140 141 142 143
        return cutChildren(super.getVisibleRegion(), null);
    }

    /**
     * Removes bounds of children above specific child from the region. If above
     * is null removes all bounds of children.
     */
144
    final Region cutChildren(Region r, final LWComponentPeer<?, ?> above) {
145
        boolean aboveFound = above == null;
146
        for (final LWComponentPeer<?, ?> child : getChildren()) {
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
            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
170 171
    final LWComponentPeer<?, ?> findPeerAt(int x, int y) {
        LWComponentPeer<?, ?> peer = super.findPeerAt(x, y);
172 173 174 175 176 177 178
        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) {
179
                    LWComponentPeer<?, ?> p = childPeers.get(i).findPeerAt(x, y);
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
                    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
195
    final void repaintPeer(final Rectangle r) {
196 197 198 199 200 201 202 203 204 205 206 207
        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);
    }

208 209 210 211
    /**
     * Paints all the child peers in the straight z-order, so the
     * bottom-most ones are painted first.
     */
212 213
    private void repaintChildren(final Rectangle r) {
        final Rectangle content = getContentSize();
214
        for (final LWComponentPeer<?, ?> child : getChildren()) {
215 216 217 218 219 220 221 222
            final Rectangle childBounds = child.getBounds();
            Rectangle toPaint = r.intersection(childBounds);
            toPaint = toPaint.intersection(content);
            toPaint.translate(-childBounds.x, -childBounds.y);
            child.repaintPeer(toPaint);
        }
    }

223
    Rectangle getContentSize() {
224 225 226 227 228 229
        return getSize();
    }

    @Override
    public void setEnabled(final boolean e) {
        super.setEnabled(e);
230
        for (final LWComponentPeer<?, ?> child : getChildren()) {
231 232 233 234 235 236
            child.setEnabled(e && child.getTarget().isEnabled());
        }
    }

    @Override
    public void setBackground(final Color c) {
237
        for (final LWComponentPeer<?, ?> child : getChildren()) {
238 239 240 241 242 243 244 245 246
            if (!child.getTarget().isBackgroundSet()) {
                child.setBackground(c);
            }
        }
        super.setBackground(c);
    }

    @Override
    public void setForeground(final Color c) {
247
        for (final LWComponentPeer<?, ?> child : getChildren()) {
248 249 250 251 252 253 254 255 256
            if (!child.getTarget().isForegroundSet()) {
                child.setForeground(c);
            }
        }
        super.setForeground(c);
    }

    @Override
    public void setFont(final Font f) {
257
        for (final LWComponentPeer<?, ?> child : getChildren()) {
258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
            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);
    }
}