alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (LWComponentPeer.java)

This example Java source code file (LWComponentPeer.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

awt, awtevent, awteventlistener, color, dimension, graphics, gui, image, java2d, keyevent, lwcomponentpeer, lwcontainerpeer, lwwindowpeer, object, override, point, rectangle, region, security, swing

The LWComponentPeer.java Java example source code

/*
 * 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 java.awt.*;

import java.awt.dnd.DropTarget;
import java.awt.dnd.peer.DropTargetPeer;
import java.awt.event.*;

import java.awt.image.ColorModel;
import java.awt.image.ImageObserver;
import java.awt.image.ImageProducer;
import java.awt.image.VolatileImage;

import java.awt.peer.ComponentPeer;
import java.awt.peer.ContainerPeer;

import java.awt.peer.KeyboardFocusManagerPeer;
import java.util.concurrent.atomic.AtomicBoolean;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;

import sun.awt.*;

import sun.awt.event.IgnorePaintEvent;

import sun.awt.image.SunVolatileImage;
import sun.awt.image.ToolkitImage;

import sun.java2d.SunGraphics2D;
import sun.java2d.opengl.OGLRenderQueue;
import sun.java2d.pipe.Region;

import sun.util.logging.PlatformLogger;

import javax.swing.JComponent;
import javax.swing.SwingUtilities;
import javax.swing.RepaintManager;

import sun.lwawt.macosx.CDropTarget;

import com.sun.java.swing.SwingUtilities3;

public abstract class LWComponentPeer<T extends Component, D extends JComponent>
    implements ComponentPeer, DropTargetPeer
{
    private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");

    /**
     * State lock is to be used for modifications to this peer's fields (e.g.
     * bounds, background, font, etc.) It should be the last lock in the lock
     * chain
     */
    private final Object stateLock = new Object();

    /**
     * The lock to operate with the peers hierarchy. AWT tree lock is not used
     * as there are many peers related ops to be done on the toolkit thread, and
     * we don't want to depend on a public lock on this thread
     */
    private static final Object peerTreeLock = new Object();

    /**
     * The associated AWT object.
     */
    private final T target;

    /**
     * Container peer. It may not be the peer of the target's direct parent, for
     * example, in the case of hw/lw mixing. However, let's skip this scenario
     * for the time being. We also assume the container peer is not null, which
     * might also be false if addNotify() is called for a component outside of
     * the hierarchy. The exception is LWWindowPeers: their containers are
     * always null
     */
    private final LWContainerPeer<?, ?> containerPeer;

    /**
     * Handy reference to the top-level window peer. Window peer is borrowed
     * from the containerPeer in constructor, and should also be updated when
     * the component is reparented to another container
     */
    private final LWWindowPeer windowPeer;

    private final AtomicBoolean disposed = new AtomicBoolean(false);

    // Bounds are relative to parent peer
    private final Rectangle bounds = new Rectangle();
    private Region region;

    // Component state. Should be accessed under the state lock
    private boolean visible = false;
    private boolean enabled = true;

    private Color background;
    private Color foreground;
    private Font font;

    /**
     * Paint area to coalesce all the paint events and store the target dirty
     * area.
     */
    private final RepaintArea targetPaintArea;

    //   private volatile boolean paintPending;
    private volatile boolean isLayouting;

    private final D delegate;
    private Container delegateContainer;
    private Component delegateDropTarget;
    private final Object dropTargetLock = new Object();

    private int fNumDropTargets = 0;
    private CDropTarget fDropTarget = null;

    private final PlatformComponent platformComponent;

    /**
     * Character with reasonable value between the minimum width and maximum.
     */
    static final char WIDE_CHAR = '0';

    /**
     * The back buffer provide user with a BufferStrategy.
     */
    private Image backBuffer;

    /**
     * All Swing delegates use delegateContainer as a parent. This container
     * intentionally do not use parent of the peer.
     */
    @SuppressWarnings("serial")// Safe: outer class is non-serializable.
    private final class DelegateContainer extends Container {
        {
            enableEvents(0xFFFFFFFF);
        }

        // Empty non private constructor was added because access to this
        // class shouldn't be emulated by a synthetic accessor method.
        DelegateContainer() {
            super();
        }

        @Override
        public boolean isLightweight() {
            return false;
        }

        @Override
        public Point getLocation() {
            return getLocationOnScreen();
        }

        @Override
        public Point getLocationOnScreen() {
            return LWComponentPeer.this.getLocationOnScreen();
        }

        @Override
        public int getX() {
            return getLocation().x;
        }

        @Override
        public int getY() {
            return getLocation().y;
        }
    }

    LWComponentPeer(final T target, final PlatformComponent platformComponent) {
        targetPaintArea = new LWRepaintArea();
        this.target = target;
        this.platformComponent = platformComponent;

        // Container peer is always null for LWWindowPeers, so
        // windowPeer is always null for them as well. On the other
        // hand, LWWindowPeer shouldn't use windowPeer at all
        final Container container = SunToolkit.getNativeContainer(target);
        containerPeer = (LWContainerPeer) LWToolkit.targetToPeer(container);
        windowPeer = containerPeer != null ? containerPeer.getWindowPeerOrSelf()
                                           : null;
        // don't bother about z-order here as updateZOrder()
        // will be called from addNotify() later anyway
        if (containerPeer != null) {
            containerPeer.addChildPeer(this);
        }

        // the delegate must be created after the target is set
        AWTEventListener toolkitListener = null;
        synchronized (Toolkit.getDefaultToolkit()) {
            try {
                toolkitListener = getToolkitAWTEventListener();
                setToolkitAWTEventListener(null);

                synchronized (getDelegateLock()) {
                    delegate = createDelegate();
                    if (delegate != null) {
                        delegate.setVisible(false);
                        delegateContainer = new DelegateContainer();
                        delegateContainer.add(delegate);
                        delegateContainer.addNotify();
                        delegate.addNotify();
                        resetColorsAndFont(delegate);
                        delegate.setOpaque(true);
                    } else {
                        return;
                    }
                }

            } finally {
                setToolkitAWTEventListener(toolkitListener);
            }

            // todo swing: later on we will probably have one global RM
            SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
                @Override
                public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
                    repaintPeer(SwingUtilities.convertRectangle(
                            c, new Rectangle(x, y, w, h), getDelegate()));
                }
            });
        }
    }

    /**
     * This method must be called under Toolkit.getDefaultToolkit() lock
     * and followed by setToolkitAWTEventListener()
     */
    protected final AWTEventListener getToolkitAWTEventListener() {
        return AccessController.doPrivileged(new PrivilegedAction<AWTEventListener>() {
            public AWTEventListener run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                try {
                    Field field = Toolkit.class.getDeclaredField("eventListener");
                    field.setAccessible(true);
                    return (AWTEventListener) field.get(toolkit);
                } catch (Exception e) {
                    throw new InternalError(e.toString());
                }
            }
        });
    }

    protected final void setToolkitAWTEventListener(final AWTEventListener listener) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                try {
                    Field field = Toolkit.class.getDeclaredField("eventListener");
                    field.setAccessible(true);
                    field.set(toolkit, listener);
                } catch (Exception e) {
                    throw new InternalError(e.toString());
                }
                return null;
            }
        });
    }

    /**
     * This method is called under getDelegateLock().
     * Overridden in subclasses.
     */
    D createDelegate() {
        return null;
    }

    final D getDelegate() {
        return delegate;
    }

    /**
     * This method should be called under getDelegateLock().
     */
    Component getDelegateFocusOwner() {
        return getDelegate();
    }

    /**
     * Initializes this peer. The call to initialize() is not placed to
     * LWComponentPeer ctor to let the subclass ctor to finish completely first.
     * Instead, it's the LWToolkit object who is responsible for initialization.
     * Note that we call setVisible() at the end of initialization.
     */
    public final void initialize() {
        platformComponent.initialize(getPlatformWindow());
        initializeImpl();
        setVisible(target.isVisible());
    }

    /**
     * Fetching general properties from the target. Should be overridden in
     * subclasses to initialize specific peers properties.
     */
    void initializeImpl() {
        setBackground(target.getBackground());
        setForeground(target.getForeground());
        setFont(target.getFont());
        setBounds(target.getBounds());
        setEnabled(target.isEnabled());
    }

    private static void resetColorsAndFont(final Container c) {
        c.setBackground(null);
        c.setForeground(null);
        c.setFont(null);
        for (int i = 0; i < c.getComponentCount(); i++) {
            resetColorsAndFont((Container) c.getComponent(i));
        }
    }

    final Object getStateLock() {
        return stateLock;
    }

    /**
     * Synchronize all operations with the Swing delegates under AWT tree lock,
     * using a new separate lock to synchronize access to delegates may lead
     * deadlocks. Think of it as a 'virtual EDT'.
     *
     * @return DelegateLock
     */
    final Object getDelegateLock() {
        return getTarget().getTreeLock();
    }

    protected static final Object getPeerTreeLock() {
        return peerTreeLock;
    }

    public final T getTarget() {
        return target;
    }

    // Just a helper method
    // Returns the window peer or null if this is a window peer
    protected final LWWindowPeer getWindowPeer() {
        return windowPeer;
    }

    // Returns the window peer or 'this' if this is a window peer
    protected LWWindowPeer getWindowPeerOrSelf() {
        return getWindowPeer();
    }

    // Just a helper method
    protected final LWContainerPeer<?, ?> getContainerPeer() {
        return containerPeer;
    }

    public PlatformWindow getPlatformWindow() {
        LWWindowPeer windowPeer = getWindowPeer();
        return windowPeer.getPlatformWindow();
    }

    // ---- PEER METHODS ---- //

    // Just a helper method
    public LWToolkit getLWToolkit() {
        return LWToolkit.getLWToolkit();
    }

    @Override
    public final void dispose() {
        if (disposed.compareAndSet(false, true)) {
            disposeImpl();
        }
    }

    protected void disposeImpl() {
        destroyBuffers();
        LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            cp.removeChildPeer(this);
        }
        platformComponent.dispose();
        LWToolkit.targetDisposedPeer(getTarget(), this);
    }

    public final boolean isDisposed() {
        return disposed.get();
    }

    /*
     * GraphicsConfiguration is borrowed from the parent peer. The
     * return value must not be null.
     *
     * Overridden in LWWindowPeer.
     */
    @Override
    public GraphicsConfiguration getGraphicsConfiguration() {
        // Don't check windowPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        return getWindowPeer().getGraphicsConfiguration();
    }


    // Just a helper method
    public final LWGraphicsConfig getLWGC() {
        return (LWGraphicsConfig) getGraphicsConfiguration();
    }

    /*
     * Overridden in LWWindowPeer to replace its surface
     * data and back buffer.
     */
    @Override
    public boolean updateGraphicsData(GraphicsConfiguration gc) {
        // TODO: not implemented
//        throw new RuntimeException("Has not been implemented yet.");
        return false;
    }

    @Override
    public Graphics getGraphics() {
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            synchronized (getPeerTreeLock()){
                applyConstrain(g);
            }
        }
        return g;
    }

    /*
     * Peer Graphics is borrowed from the parent peer, while
     * foreground and background colors and font are specific to
     * this peer.
     */
    public final Graphics getOnscreenGraphics() {
        final LWWindowPeer wp = getWindowPeerOrSelf();
        return wp.getOnscreenGraphics(getForeground(), getBackground(),
                                      getFont());

    }

    private void applyConstrain(final Graphics g) {
        final SunGraphics2D sg2d = (SunGraphics2D) g;
        final Rectangle size = localToWindow(getSize());
        sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion());
    }

    Region getVisibleRegion() {
        return computeVisibleRect(this, getRegion());
    }

    static final Region computeVisibleRect(final LWComponentPeer<?, ?> c,
                                           Region region) {
        final LWContainerPeer<?, ?> p = c.getContainerPeer();
        if (p != null) {
            final Rectangle r = c.getBounds();
            region = region.getTranslatedRegion(r.x, r.y);
            region = region.getIntersection(p.getRegion());
            region = region.getIntersection(p.getContentSize());
            region = p.cutChildren(region, c);
            region = computeVisibleRect(p, region);
            region = region.getTranslatedRegion(-r.x, -r.y);
        }
        return region;
    }

    @Override
    public ColorModel getColorModel() {
        // Is it a correct implementation?
        return getGraphicsConfiguration().getColorModel();
    }

    public boolean isTranslucent() {
        // Translucent windows of the top level are supported only
        return false;
    }

    @Override
    public final void createBuffers(int numBuffers, BufferCapabilities caps)
            throws AWTException {
        getLWGC().assertOperationSupported(numBuffers, caps);
        final Image buffer = getLWGC().createBackBuffer(this);
        synchronized (getStateLock()) {
            backBuffer = buffer;
        }
    }

    @Override
    public final Image getBackBuffer() {
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                return backBuffer;
            }
        }
        throw new IllegalStateException("Buffers have not been created");
    }

    @Override
    public final void flip(int x1, int y1, int x2, int y2,
                     BufferCapabilities.FlipContents flipAction) {
        getLWGC().flip(this, getBackBuffer(), x1, y1, x2, y2, flipAction);
    }

    @Override
    public final void destroyBuffers() {
        final Image oldBB;
        synchronized (getStateLock()) {
            oldBB = backBuffer;
            backBuffer = null;
        }
        getLWGC().destroyBackBuffer(oldBB);
    }

    // Helper method
    public void setBounds(Rectangle r) {
        setBounds(r.x, r.y, r.width, r.height, SET_BOUNDS);
    }

    /**
     * This method could be called on the toolkit thread.
     */
    @Override
    public void setBounds(int x, int y, int w, int h, int op) {
        setBounds(x, y, w, h, op, true, false);
    }

    protected void setBounds(int x, int y, int w, int h, int op, boolean notify,
                             final boolean updateTarget) {
        Rectangle oldBounds;
        synchronized (getStateLock()) {
            oldBounds = new Rectangle(bounds);
            if ((op & (SET_LOCATION | SET_BOUNDS)) != 0) {
                bounds.x = x;
                bounds.y = y;
            }
            if ((op & (SET_SIZE | SET_BOUNDS)) != 0) {
                bounds.width = w;
                bounds.height = h;
            }
        }
        boolean moved = (oldBounds.x != x) || (oldBounds.y != y);
        boolean resized = (oldBounds.width != w) || (oldBounds.height != h);
        if (!moved && !resized) {
            return;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegateContainer.setBounds(0, 0, w, h);
                delegate.setBounds(delegateContainer.getBounds());
                // TODO: the following means that the delegateContainer NEVER gets validated. That's WRONG!
                delegate.validate();
            }
        }

        final Point locationInWindow = localToWindow(0, 0);
        platformComponent.setBounds(locationInWindow.x, locationInWindow.y, w,
                                    h);
        if (notify) {
            repaintOldNewBounds(oldBounds);
            if (resized) {
                handleResize(w, h, updateTarget);
            }
            if (moved) {
                handleMove(x, y, updateTarget);
            }
        }
    }

    public final Rectangle getBounds() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return bounds.getBounds();
        }
    }

    public final Rectangle getSize() {
        synchronized (getStateLock()) {
            // Return a copy to prevent subsequent modifications
            return new Rectangle(bounds.width, bounds.height);
        }
    }

    @Override
    public Point getLocationOnScreen() {
        Point windowLocation = getWindowPeer().getLocationOnScreen();
        Point locationInWindow = localToWindow(0, 0);
        return new Point(windowLocation.x + locationInWindow.x,
                windowLocation.y + locationInWindow.y);
    }

    /**
     * Returns the cursor of the peer, which is cursor of the target by default,
     * but peer can override this behavior.
     *
     * @param p Point relative to the peer.
     * @return Cursor of the peer or null if default cursor should be used.
     */
    Cursor getCursor(final Point p) {
        return getTarget().getCursor();
    }

    @Override
    public void setBackground(final Color c) {
        final Color oldBg = getBackground();
        if (oldBg == c || (oldBg != null && oldBg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            background = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setBackground(c);
            }
        } else {
            repaintPeer();
        }
    }

    public final Color getBackground() {
        synchronized (getStateLock()) {
            return background;
        }
    }

    @Override
    public void setForeground(final Color c) {
        final Color oldFg = getForeground();
        if (oldFg == c || (oldFg != null && oldFg.equals(c))) {
            return;
        }
        synchronized (getStateLock()) {
            foreground = c;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setForeground(c);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Color getForeground() {
        synchronized (getStateLock()) {
            return foreground;
        }
    }

    @Override
    public void setFont(final Font f) {
        final Font oldF = getFont();
        if (oldF == f || (oldF != null && oldF.equals(f))) {
            return;
        }
        synchronized (getStateLock()) {
            font = f;
        }
        final D delegate = getDelegate();
        if (delegate != null) {
            synchronized (getDelegateLock()) {
                // delegate will repaint the target
                delegate.setFont(f);
            }
        } else {
            repaintPeer();
        }
    }

    protected final Font getFont() {
        synchronized (getStateLock()) {
            return font;
        }
    }

    @Override
    public FontMetrics getFontMetrics(final Font f) {
        // Borrow the metrics from the top-level window
//        return getWindowPeer().getFontMetrics(f);
        // Obtain the metrics from the offscreen window where this peer is
        // mostly drawn to.
        // TODO: check for "use platform metrics" settings
        final Graphics g = getOnscreenGraphics();
        if (g != null) {
            try {
                return g.getFontMetrics(f);
            } finally {
                g.dispose();
            }
        }
        synchronized (getDelegateLock()) {
            return delegateContainer.getFontMetrics(f);
        }
    }

    @Override
    public void setEnabled(final boolean e) {
        boolean status = e;
        final LWComponentPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            status &= cp.isEnabled();
        }
        synchronized (getStateLock()) {
            if (enabled == status) {
                return;
            }
            enabled = status;
        }

        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setEnabled(status);
            }
        } else {
            repaintPeer();
        }
    }

    // Helper method
    public final boolean isEnabled() {
        synchronized (getStateLock()) {
            return enabled;
        }
    }

    @Override
    public void setVisible(final boolean v) {
        synchronized (getStateLock()) {
            if (visible == v) {
                return;
            }
            visible = v;
        }
        setVisibleImpl(v);
    }

    protected void setVisibleImpl(final boolean v) {
        final D delegate = getDelegate();

        if (delegate != null) {
            synchronized (getDelegateLock()) {
                delegate.setVisible(v);
            }
        }
        if (visible) {
            repaintPeer();
        } else {
            repaintParent(getBounds());
        }
    }

    // Helper method
    public final boolean isVisible() {
        synchronized (getStateLock()) {
            return visible;
        }
    }

    @Override
    public void paint(final Graphics g) {
        getTarget().paint(g);
    }

    @Override
    public void print(final Graphics g) {
        getTarget().print(g);
    }

    @Override
    public void reparent(ContainerPeer newContainer) {
        // TODO: not implemented
        throw new UnsupportedOperationException("ComponentPeer.reparent()");
    }

    @Override
    public boolean isReparentSupported() {
        // TODO: not implemented
        return false;
    }

    @Override
    public void setZOrder(final ComponentPeer above) {
        LWContainerPeer<?, ?> cp = getContainerPeer();
        // Don't check containerPeer for null as it can only happen
        // for windows, but this method is overridden in
        // LWWindowPeer and doesn't call super()
        cp.setChildPeerZOrder(this, (LWComponentPeer<?, ?>) above);
    }

    @Override
    public void coalescePaintEvent(PaintEvent e) {
        if (!(e instanceof IgnorePaintEvent)) {
            Rectangle r = e.getUpdateRect();
            if ((r != null) && !r.isEmpty()) {
                targetPaintArea.add(r, e.getID());
            }
        }
    }

    /*
     * Should be overridden in subclasses which use complex Swing components.
     */
    @Override
    public void layout() {
        // TODO: not implemented
    }

    @Override
    public boolean isObscured() {
        // TODO: not implemented
        return false;
    }

    @Override
    public boolean canDetermineObscurity() {
        // TODO: not implemented
        return false;
    }

    /**
     * Determines the preferred size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getPreferredSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getPreferredSize();
        }
        return validateSize(size);
    }

    /**
     * Determines the minimum size of the component. By default forwards the
     * request to the Swing helper component. Should be overridden in subclasses
     * if required.
     */
    @Override
    public Dimension getMinimumSize() {
        final Dimension size;
        synchronized (getDelegateLock()) {
            size = getDelegate().getMinimumSize();
        }
        return validateSize(size);
    }

    /**
     * In some situations delegates can return empty minimum/preferred size.
     * (For example: empty JLabel, etc), but awt components never should be
     * empty. In the XPeers or WPeers we use some magic constants, but here we
     * try to use something more useful,
     */
    private Dimension validateSize(final Dimension size) {
        if (size.width == 0 || size.height == 0) {
            final FontMetrics fm = getFontMetrics(getFont());
            size.width = fm.charWidth(WIDE_CHAR);
            size.height = fm.getHeight();
        }
        return size;
    }

    @Override
    public void updateCursorImmediately() {
        getLWToolkit().getCursorManager().updateCursor();
    }

    @Override
    public boolean isFocusable() {
        // Overridden in focusable subclasses like buttons
        return false;
    }

    @Override
    public boolean requestFocus(Component lightweightChild, boolean temporary,
                                boolean focusedWindowChangeAllowed, long time,
                                CausedFocusEvent.Cause cause)
    {
        if (focusLog.isLoggable(PlatformLogger.Level.FINEST)) {
            focusLog.finest("lightweightChild=" + lightweightChild + ", temporary=" + temporary +
                            ", focusedWindowChangeAllowed=" + focusedWindowChangeAllowed +
                            ", time= " + time + ", cause=" + cause);
        }
        if (LWKeyboardFocusManagerPeer.processSynchronousLightweightTransfer(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time)) {
            return true;
        }

        int result = LWKeyboardFocusManagerPeer.shouldNativelyFocusHeavyweight(
                getTarget(), lightweightChild, temporary,
                focusedWindowChangeAllowed, time, cause);
        switch (result) {
            case LWKeyboardFocusManagerPeer.SNFH_FAILURE:
                return false;
            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_PROCEED:
                Window parentWindow = SunToolkit.getContainingWindow(getTarget());
                if (parentWindow == null) {
                    focusLog.fine("request rejected, parentWindow is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }
                final LWWindowPeer parentPeer =
                        (LWWindowPeer) AWTAccessor.getComponentAccessor()
                                                  .getPeer(parentWindow);
                if (parentPeer == null) {
                    focusLog.fine("request rejected, parentPeer is null");
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                // A fix for 7145768. Ensure the parent window is currently natively focused.
                // The more evident place to perform this check is in KFM.shouldNativelyFocusHeavyweight,
                // however that is the shared code and this particular problem's reproducibility has
                // platform specifics. So, it was decided to narrow down the fix to lwawt (OSX) in
                // current release. TODO: consider fixing it in the shared code.
                if (!focusedWindowChangeAllowed) {
                    LWWindowPeer decoratedPeer = parentPeer.isSimpleWindow() ?
                        LWWindowPeer.getOwnerFrameDialog(parentPeer) : parentPeer;

                    if (decoratedPeer == null || !decoratedPeer.getPlatformWindow().isActive()) {
                        if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                            focusLog.fine("request rejected, focusedWindowChangeAllowed==false, " +
                                          "decoratedPeer is inactive: " + decoratedPeer);
                        }
                        LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                        return false;
                    }
                }

                boolean res = parentPeer.requestWindowFocus(cause);
                // If parent window can be made focused and has been made focused (synchronously)
                // then we can proceed with children, otherwise we retreat
                if (!res || !parentWindow.isFocused()) {
                    if (focusLog.isLoggable(PlatformLogger.Level.FINE)) {
                        focusLog.fine("request rejected, res= " + res + ", parentWindow.isFocused()=" +
                                      parentWindow.isFocused());
                    }
                    LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget());
                    return false;
                }

                KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
                Component focusOwner = kfmPeer.getCurrentFocusOwner();
                return LWKeyboardFocusManagerPeer.deliverFocus(lightweightChild,
                        getTarget(), temporary,
                        focusedWindowChangeAllowed,
                        time, cause, focusOwner);

            case LWKeyboardFocusManagerPeer.SNFH_SUCCESS_HANDLED:
                return true;
        }

        return false;
    }

    @Override
    public final Image createImage(final ImageProducer producer) {
        return new ToolkitImage(producer);
    }

    @Override
    public final Image createImage(final int width, final int height) {
        return getLWGC().createAcceleratedImage(getTarget(), width, height);
    }

    @Override
    public final VolatileImage createVolatileImage(final int w, final int h) {
        return new SunVolatileImage(getTarget(), w, h);
    }

    @Override
    public boolean prepareImage(Image img, int w, int h, ImageObserver o) {
        // TODO: is it a right/complete implementation?
        return Toolkit.getDefaultToolkit().prepareImage(img, w, h, o);
    }

    @Override
    public int checkImage(Image img, int w, int h, ImageObserver o) {
        // TODO: is it a right/complete implementation?
        return Toolkit.getDefaultToolkit().checkImage(img, w, h, o);
    }

    @Override
    public boolean handlesWheelScrolling() {
        // TODO: not implemented
        return false;
    }

    @Override
    public final void applyShape(final Region shape) {
        synchronized (getStateLock()) {
            if (region == shape || (region != null && region.equals(shape))) {
                return;
            }
        }
        applyShapeImpl(shape);
    }

    void applyShapeImpl(final Region shape) {
        synchronized (getStateLock()) {
            if (shape != null) {
                region = Region.WHOLE_REGION.getIntersection(shape);
            } else {
                region = null;
            }
        }
        repaintParent(getBounds());
    }

    protected final Region getRegion() {
        synchronized (getStateLock()) {
            return isShaped() ? region : Region.getInstance(getSize());
        }
    }

    public boolean isShaped() {
        synchronized (getStateLock()) {
            return region != null;
        }
    }

    // DropTargetPeer Method
    @Override
    public void addDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to register the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.addDropTarget(dt);
        } else {
            synchronized (dropTargetLock) {
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (++fNumDropTargets == 1) {
                    // Having a non-null drop target would be an error but let's check just in case:
                    if (fDropTarget != null)
                        System.err.println("CComponent.addDropTarget(): current drop target is non-null.");

                    // Create a new drop target:
                    fDropTarget = CDropTarget.createDropTarget(dt, target, this);
                }
            }
        }
    }

    // DropTargetPeer Method
    @Override
    public void removeDropTarget(DropTarget dt) {
        LWWindowPeer winPeer = getWindowPeerOrSelf();
        if (winPeer != null && winPeer != this) {
            // We need to unregister the DropTarget in the
            // peer of the window ancestor of the component
            winPeer.removeDropTarget(dt);
        } else {
            synchronized (dropTargetLock){
                // 10-14-02 VL: Windows WComponentPeer would add (or remove) the drop target only
                // if it's the first (or last) one for the component. Otherwise this call is a no-op.
                if (--fNumDropTargets == 0) {
                    // Having a null drop target would be an error but let's check just in case:
                    if (fDropTarget != null) {
                        // Dispose of the drop target:
                        fDropTarget.dispose();
                        fDropTarget = null;
                    } else
                        System.err.println("CComponent.removeDropTarget(): current drop target is null.");
                }
            }
        }
    }

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

    /**
     * Called when this peer's location has been changed either as a result
     * of target.setLocation() or as a result of user actions (window is
     * dragged with mouse).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleMove(final int x, final int y,
                                    final boolean updateTarget) {
        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setLocation(getTarget(), x, y);
        }
        postEvent(new ComponentEvent(getTarget(),
                                     ComponentEvent.COMPONENT_MOVED));
    }

    /**
     * Called when this peer's size has been changed either as a result of
     * target.setSize() or as a result of user actions (window is resized).
     *
     * This method could be called on the toolkit thread.
     */
    protected final void handleResize(final int w, final int h,
                                      final boolean updateTarget) {
        Image oldBB = null;
        synchronized (getStateLock()) {
            if (backBuffer != null) {
                oldBB = backBuffer;
                backBuffer = getLWGC().createBackBuffer(this);
            }
        }
        getLWGC().destroyBackBuffer(oldBB);

        if (updateTarget) {
            AWTAccessor.getComponentAccessor().setSize(getTarget(), w, h);
        }
        postEvent(new ComponentEvent(getTarget(),
                                     ComponentEvent.COMPONENT_RESIZED));
    }

    protected final void repaintOldNewBounds(final Rectangle oldB) {
        repaintParent(oldB);
        repaintPeer(getSize());
    }

    protected final void repaintParent(final Rectangle oldB) {
        final LWContainerPeer<?, ?> cp = getContainerPeer();
        if (cp != null) {
            // Repaint unobscured part of the parent
            cp.repaintPeer(cp.getContentSize().intersection(oldB));
        }
    }

    // ---- EVENTS ---- //

    /**
     * Post an event to the proper Java EDT.
     */
    public void postEvent(final AWTEvent event) {
        LWToolkit.postEvent(event);
    }

    protected void postPaintEvent(int x, int y, int w, int h) {
        // TODO: call getIgnoreRepaint() directly with the right ACC
        if (AWTAccessor.getComponentAccessor().getIgnoreRepaint(target)) {
            return;
        }
        PaintEvent event = PaintEventDispatcher.getPaintEventDispatcher().
                createPaintEvent(getTarget(), x, y, w, h);
        if (event != null) {
            postEvent(event);
        }
    }

    /*
     * Gives a chance for the peer to handle the event after it's been
     * processed by the target.
     */
    @Override
    public void handleEvent(AWTEvent e) {
        if ((e instanceof InputEvent) && ((InputEvent) e).isConsumed()) {
            return;
        }
        switch (e.getID()) {
            case FocusEvent.FOCUS_GAINED:
            case FocusEvent.FOCUS_LOST:
                handleJavaFocusEvent((FocusEvent) e);
                break;
            case PaintEvent.PAINT:
                // Got a native paint event
//                paintPending = false;
                // fall through to the next statement
            case PaintEvent.UPDATE:
                handleJavaPaintEvent();
                break;
            case MouseEvent.MOUSE_PRESSED:
                handleJavaMouseEvent((MouseEvent)e);
        }

        sendEventToDelegate(e);
    }

    protected void sendEventToDelegate(final AWTEvent e) {
        if (getDelegate() == null || !isShowing() || !isEnabled()) {
            return;
        }
        synchronized (getDelegateLock()) {
            AWTEvent delegateEvent = createDelegateEvent(e);
            if (delegateEvent != null) {
                AWTAccessor.getComponentAccessor()
                        .processEvent((Component) delegateEvent.getSource(),
                                delegateEvent);
                if (delegateEvent instanceof KeyEvent) {
                    KeyEvent ke = (KeyEvent) delegateEvent;
                    SwingUtilities.processKeyBindings(ke);
                }
            }
        }
    }

    /**
     * Changes the target of the AWTEvent from awt component to appropriate
     * swing delegate.
     */
    private AWTEvent createDelegateEvent(final AWTEvent e) {
        // TODO modifiers should be changed to getModifiers()|getModifiersEx()?
        AWTEvent delegateEvent = null;
        if (e instanceof MouseWheelEvent) {
            MouseWheelEvent me = (MouseWheelEvent) e;
            delegateEvent = new MouseWheelEvent(
                    delegate, me.getID(), me.getWhen(),
                    me.getModifiers(),
                    me.getX(), me.getY(),
                    me.getClickCount(),
                    me.isPopupTrigger(),
                    me.getScrollType(),
                    me.getScrollAmount(),
                    me.getWheelRotation());
        } else if (e instanceof MouseEvent) {
            MouseEvent me = (MouseEvent) e;

            Component eventTarget = SwingUtilities.getDeepestComponentAt(delegate, me.getX(), me.getY());

            if (me.getID() == MouseEvent.MOUSE_DRAGGED) {
                if (delegateDropTarget == null) {
                    delegateDropTarget = eventTarget;
                } else {
                    eventTarget = delegateDropTarget;
                }
            }
            if (me.getID() == MouseEvent.MOUSE_RELEASED && delegateDropTarget != null) {
                eventTarget = delegateDropTarget;
                delegateDropTarget = null;
            }
            if (eventTarget == null) {
                eventTarget = delegate;
            }
            delegateEvent = SwingUtilities.convertMouseEvent(getTarget(), me, eventTarget);
        } else if (e instanceof KeyEvent) {
            KeyEvent ke = (KeyEvent) e;
            delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(),
                    ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation());
            AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent,
                    ke.getExtendedKeyCode());
        } else if (e instanceof FocusEvent) {
            FocusEvent fe = (FocusEvent) e;
            delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary());
        }
        return delegateEvent;
    }

    protected void handleJavaMouseEvent(MouseEvent e) {
        Component target = getTarget();
        assert (e.getSource() == target);

        if (!target.isFocusOwner() && LWKeyboardFocusManagerPeer.shouldFocusOnClick(target)) {
            LWKeyboardFocusManagerPeer.requestFocusFor(target, CausedFocusEvent.Cause.MOUSE_EVENT);
        }
    }

    /**
     * Handler for FocusEvents.
     */
    void handleJavaFocusEvent(final FocusEvent e) {
        // Note that the peer receives all the FocusEvents from
        // its lightweight children as well
        KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance();
        kfmPeer.setCurrentFocusOwner(e.getID() == FocusEvent.FOCUS_GAINED ? getTarget() : null);
    }

    /**
     * All peers should clear background before paint.
     *
     * @return false on components that DO NOT require a clearRect() before
     *         painting.
     */
    protected final boolean shouldClearRectBeforePaint() {
        // TODO: sun.awt.noerasebackground
        return true;
    }

    /**
     * Handler for PAINT and UPDATE PaintEvents.
     */
    private void handleJavaPaintEvent() {
        // Skip all painting while layouting and all UPDATEs
        // while waiting for native paint
//        if (!isLayouting && !paintPending) {
        if (!isLayouting()) {
            targetPaintArea.paint(getTarget(), shouldClearRectBeforePaint());
        }
    }

    // ---- UTILITY METHODS ---- //

    /**
     * Finds a top-most visible component for the given point. The location is
     * specified relative to the peer's parent.
     */
    LWComponentPeer<?, ?> findPeerAt(final int x, final int y) {
        final Rectangle r = getBounds();
        final Region sh = getRegion();
        final boolean found = isVisible() && sh.contains(x - r.x, y - r.y);
        return found ? this : null;
    }

    /*
     * Translated the given point in Window coordinates to the point in
     * coordinates local to this component. The given window peer must be
     * the window where this component is in.
     */
    public Point windowToLocal(int x, int y, LWWindowPeer wp) {
        return windowToLocal(new Point(x, y), wp);
    }

    public Point windowToLocal(Point p, LWWindowPeer wp) {
        LWComponentPeer<?, ?> cp = this;
        while (cp != wp) {
            Rectangle cpb = cp.getBounds();
            p.x -= cpb.x;
            p.y -= cpb.y;
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle windowToLocal(Rectangle r, LWWindowPeer wp) {
        Point p = windowToLocal(r.getLocation(), wp);
        return new Rectangle(p, r.getSize());
    }

    public Point localToWindow(int x, int y) {
        return localToWindow(new Point(x, y));
    }

    public Point localToWindow(Point p) {
        LWComponentPeer<?, ?> cp = getContainerPeer();
        Rectangle r = getBounds();
        while (cp != null) {
            p.x += r.x;
            p.y += r.y;
            r = cp.getBounds();
            cp = cp.getContainerPeer();
        }
        // Return a copy to prevent subsequent modifications
        return new Point(p);
    }

    public Rectangle localToWindow(Rectangle r) {
        Point p = localToWindow(r.getLocation());
        return new Rectangle(p, r.getSize());
    }

    public final void repaintPeer() {
        repaintPeer(getSize());
    }

    void repaintPeer(final Rectangle r) {
        final Rectangle toPaint = getSize().intersection(r);
        if (!isShowing() || toPaint.isEmpty()) {
            return;
        }

        postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
    }

    /**
     * Determines whether this peer is showing on screen. This means that the
     * peer must be visible, and it must be in a container that is visible and
     * showing.
     *
     * @see #isVisible()
     */
    protected final boolean isShowing() {
        synchronized (getPeerTreeLock()) {
            if (isVisible()) {
                final LWContainerPeer<?, ?> container = getContainerPeer();
                return (container == null) || container.isShowing();
            }
        }
        return false;
    }

    /**
     * Paints the peer. Delegate the actual painting to Swing components.
     */
    protected final void paintPeer(final Graphics g) {
        final D delegate = getDelegate();
        if (delegate != null) {
            if (!SwingUtilities.isEventDispatchThread()) {
                throw new InternalError("Painting must be done on EDT");
            }
            synchronized (getDelegateLock()) {
                // JComponent.print() is guaranteed to not affect the double buffer
                getDelegate().print(g);
            }
        }
    }

    protected static final void flushOnscreenGraphics(){
        final OGLRenderQueue rq = OGLRenderQueue.getInstance();
        rq.lock();
        try {
            rq.flushNow();
        } finally {
            rq.unlock();
        }
    }

    /**
     * Used by ContainerPeer to skip all the paint events during layout.
     *
     * @param isLayouting layouting state.
     */
    protected final void setLayouting(final boolean isLayouting) {
        this.isLayouting = isLayouting;
    }

    /**
     * Returns layouting state. Used by ComponentPeer to skip all the paint
     * events during layout.
     *
     * @return true during layout, false otherwise.
     */
    private final boolean isLayouting() {
        return isLayouting;
    }
}

Other Java examples (source code examples)

Here is a short list of links related to this Java LWComponentPeer.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.