Package org.jnode.awt.swingpeers

Source Code of org.jnode.awt.swingpeers.AWTInvocationLock

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
package org.jnode.awt.swingpeers;

import java.awt.AWTError;
import java.awt.AWTEvent;
import java.awt.Button;
import java.awt.Canvas;
import java.awt.Checkbox;
import java.awt.CheckboxMenuItem;
import java.awt.Choice;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dialog;
import java.awt.EventQueue;
import java.awt.FileDialog;
import java.awt.Font;
import java.awt.Frame;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Insets;
import java.awt.Label;
import java.awt.Menu;
import java.awt.MenuBar;
import java.awt.MenuItem;
import java.awt.Panel;
import java.awt.Point;
import java.awt.PopupMenu;
import java.awt.Rectangle;
import java.awt.ScrollPane;
import java.awt.Scrollbar;
import java.awt.Shape;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.dnd.DragGestureEvent;
import java.awt.dnd.peer.DragSourceContextPeer;
import java.awt.event.InvocationEvent;
import java.awt.image.BufferedImage;
import java.awt.peer.ButtonPeer;
import java.awt.peer.CanvasPeer;
import java.awt.peer.CheckboxMenuItemPeer;
import java.awt.peer.CheckboxPeer;
import java.awt.peer.ChoicePeer;
import java.awt.peer.ComponentPeer;
import java.awt.peer.DialogPeer;
import java.awt.peer.FileDialogPeer;
import java.awt.peer.FramePeer;
import java.awt.peer.LabelPeer;
import java.awt.peer.LightweightPeer;
import java.awt.peer.ListPeer;
import java.awt.peer.MenuBarPeer;
import java.awt.peer.MenuItemPeer;
import java.awt.peer.MenuPeer;
import java.awt.peer.PanelPeer;
import java.awt.peer.PopupMenuPeer;
import java.awt.peer.ScrollPanePeer;
import java.awt.peer.ScrollbarPeer;
import java.awt.peer.TextAreaPeer;
import java.awt.peer.TextFieldPeer;
import java.awt.peer.WindowPeer;
import java.beans.PropertyVetoException;
import java.util.WeakHashMap;
import java.lang.reflect.Method;
import java.lang.reflect.Field;
import java.security.AccessController;
import java.security.PrivilegedAction;
import javax.swing.JComponent;
import javax.swing.JInternalFrame;
import javax.swing.JMenuBar;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
import javax.swing.plaf.metal.MetalLookAndFeel;
import javax.swing.plaf.metal.OceanTheme;
import org.jnode.awt.JNodeAwtContext;
import org.jnode.awt.JNodeToolkit;
import org.jnode.annotation.SharedStatics;
import sun.awt.AWTAutoShutdown;
import sun.awt.AppContext;
import sun.awt.SunToolkit;

/**
* AWT toolkit implemented entirely with JFC peers, thus allowing a lightweight
* simulation of the operating system desktop.
*
* @author Levente S\u00e1ntha
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
@SharedStatics
public final class SwingToolkit extends JNodeToolkit {

    /**
     * An empty border
     */
    static final Border EMPTY_BORDER = new EmptyBorder(0, 0, 0, 0);

    /**
     * My repaint manager.  Only valid between onInitialize and onClose
     */
    private RepaintManager repaintManager;

    public static void add(Component component, JComponent peer) {
        final ISwingContainerPeer containerPeer = getContainerPeer(component);
        if (containerPeer != null) {
            containerPeer.addAWTComponent(component, peer);
        }
    }

    /**
     * Copies the generic component properties from the AWT component into the
     * peer.
     *
     * @param awtComponent
     * @param peer
     */
    static void copyAwtProperties(Component awtComponent, Component peer) {
        Color c;
        Font f;
        if ((c = awtComponent.getForeground()) != null) {
            peer.setForeground(c);
        }
        if ((c = awtComponent.getBackground()) != null) {
            peer.setBackground(c);
        }
        if ((f = awtComponent.getFont()) != null) {
            peer.setFont(f);
        }
    }

    @SuppressWarnings("deprecation")
    private static ISwingContainerPeer getContainerPeer(Component component) {
        final Component parent = component.getParent();
        if (parent == null) {
            return null;
        } else {
            final ComponentPeer parentPeer = parent.getPeer();
            if (parentPeer instanceof ISwingContainerPeer) {
                return (ISwingContainerPeer) parentPeer;
            } else {
                return getContainerPeer(parent);
            }
        }
    }

    /**
     * Paint all the lightweight children of the given container.
     *
     * @param awtContainer
     * @param g
     */
    public static void paintLightWeightChildren(Container awtContainer,
                                                Graphics g, int dx, int dy) {
        final Shape oldClip = g.getClip();
        try {
            final Component[] comps = awtContainer.getComponents();
            final int cnt = comps.length;
            for (int i = 0; i < cnt; i++) {
                final Component child = comps[i];
                if (child.isVisible() && child.isLightweight()) {
                    final int x = child.getX() - dx;
                    final int y = child.getY() - dy;
                    final int width = child.getWidth();
                    final int height = child.getHeight();
                    g.setClip(x, y, width, height);
                    g.translate(x, y);
                    try {
                        child.paint(g);
                    } finally {
                        g.translate(-x, -y);
                    }
                }
            }
        } finally {
            g.setClip(oldClip);
        }
    }

    private DesktopFrame desktopFrame;

    /**
     * Initialize this instance.
     */
    public SwingToolkit() {
    }

    // Peers

    protected ButtonPeer createButton(Button target) {
        return new SwingButtonPeer(this, target);
    }

    protected CanvasPeer createCanvas(Canvas target) {
        // return super.createCanvas( target );
        return new SwingCanvasPeer(this, target);
    }

    protected CheckboxPeer createCheckbox(Checkbox target) {
        return new SwingCheckboxPeer(this, target);
    }

    protected CheckboxMenuItemPeer createCheckboxMenuItem(
        CheckboxMenuItem target) {
        return new SwingCheckboxMenuItemPeer(this, target);
    }

    protected ChoicePeer createChoice(Choice target) {
        return new SwingChoicePeer(this, target);
    }

    protected LightweightPeer createComponent(Component target) {
        //todo investigate the idea used in super for applying here
        if (target instanceof Container)
            return new SwingLightweightContainerPeer(this, (Container) target);
        else
            return new SwingLightweightPeer(this, target);
    }

    protected DialogPeer createDialog(Dialog target) {
        return new SwingDialogPeer(this, target);
    }

    public DragSourceContextPeer createDragSourceContextPeer(
        DragGestureEvent dge) {
        return null;
    }

    protected FileDialogPeer createFileDialog(FileDialog target) {
        return null;
    }

    protected FramePeer createFrame(final Frame target) {
        final FramePeer[] ret = new FramePeer[1];

        final Runnable run = new Runnable() {
            public void run() {

                if (!isGuiActive()) {
                    //throw new AWTError("AWT is currently not available");
                    initGui();
                }
                if (target instanceof DesktopFrame) {
                    setTop(target);
                    log.debug("createFrame:desktopFramePeer(" + target + ")");
                    // Only desktop is real frame
                    //return new DesktopFramePeer(SwingToolkit.this, (DesktopFrame) target);
                    synchronized (ret) {
                        ret[0] = new DesktopFramePeer(SwingToolkit.this, (DesktopFrame) target);
                        try {
                            Method method = AWTAutoShutdown.class.getDeclaredMethod("registerPeer",
                                Object.class, Object.class);
                            method.setAccessible(true);
                            method.invoke(AWTAutoShutdown.getInstance(), target, ret[0]);
                        } catch (Exception x) {
                            x.printStackTrace();
                        }
                    }
                } else /*if (target instanceof JFrame) */ {
                    if (!isGuiActive()) {
                        throw new AWTError("Gui is not active");
                    }
                    log.debug("createFrame:normal(" + target + ")");
                    // Other frames are emulated
                    //return new SwingFramePeer(SwingToolkit.this, target);
                    synchronized (ret) {
                        ret[0] = new SwingFramePeer(SwingToolkit.this, target);
                    }
                } /*else {
            if (!isGuiActive()) {
                throw new AWTError("Gui is not active");
            }
            log.debug("createFrame:normal(" + target + ")");
            // Other frames are emulated
            return new SwingJFramePeer(this, target);
        }   */
            }
        };
        AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {


                //peer frames should be created in the same app context where the desktop is
                //todo refactor this into a generic inter-appcontext invoke and wait
                AppContext ac = SunToolkit.targetToAppContext(target);
                if (ac != null) {
                    EventQueue eq = (EventQueue) ac.get(sun.awt.AppContext.EVENT_QUEUE_KEY);
                    if (eq != null) {
                        try {
                            Method met = EventQueue.class.getDeclaredMethod("initDispatchThread");
                            met.setAccessible(true);
                            met.invoke(eq);
                        } catch (Exception x) {
                            x.printStackTrace();
                        }
                    }
                }

                // invoke and wait --
                EventQueue eq = getMainEventQueue();

                if (eq == getSystemEventQueueImpl()) {
                    run.run();
                    synchronized (ret) {
                        return ret[0];
                    }
                }

                try {
                    Field field = EventQueue.class.getField("dispatchThread");
                    field.setAccessible(true);
                    Thread edt = (Thread) field.get(eq);
                    if (Thread.currentThread() == edt) {
                        run.run();
                        synchronized (ret) {
                            return ret[0];
                        }
                    }
                } catch (Exception x) {
                    throw new RuntimeException(x);
                }

                class AWTInvocationLock {
                }
                Object lock = new AWTInvocationLock();

                InvocationEvent event = new InvocationEvent(Toolkit.getDefaultToolkit(), run, lock, true);

                try {
                    synchronized (lock) {
                        eq.postEvent(event);
                        lock.wait();
                    }
                } catch (Exception x) {
                    throw new RuntimeException(x);
                }

                Throwable eventThrowable = event.getThrowable();
                if (eventThrowable != null) {
                    throw new RuntimeException(eventThrowable);
                }

                 // --invoke and wait


                return null;
            }
        });



        synchronized (ret) {
            return ret[0];
        }
    }

    protected LabelPeer createLabel(Label target) {
        return new SwingLabelPeer(this, target);
    }

    protected ListPeer createList(java.awt.List target) {
        return new SwingListPeer(this, target);
    }

    protected MenuPeer createMenu(Menu target) {
        return new SwingMenuPeer(this, target);
    }

    protected MenuBarPeer createMenuBar(MenuBar target) {
        return new SwingMenuBarPeer(this, target);
    }

    protected MenuItemPeer createMenuItem(MenuItem target) {
        return new SwingMenuItemPeer(this, target);
    }

    protected PanelPeer createPanel(Panel target) {
        return new SwingPanelPeer(this, target);
    }

    protected PopupMenuPeer createPopupMenu(PopupMenu target) {
        return new SwingPopupMenuPeer(this, target);
    }

    protected ScrollbarPeer createScrollbar(Scrollbar target) {
        return new SwingScrollbarPeer(this, target);
    }

    protected ScrollPanePeer createScrollPane(ScrollPane target) {
        return new SwingScrollPanePeer(this, target);
    }

    protected TextAreaPeer createTextArea(TextArea target) {
        return new SwingTextAreaPeer(this, target);
    }

    protected TextFieldPeer createTextField(TextField target) {
        return new SwingTextFieldPeer(this, target);
    }

    protected WindowPeer createWindow(Window target) {
        return new SwingWindowPeer(this, target);
    }

    public JNodeAwtContext getAwtContext() {
        return desktopFrame;
    }

    /**
     * @see org.jnode.awt.JNodeToolkit#refresh()
     */
    protected void refresh() {
        log.info("Refresh");
        final JNodeAwtContext ctx = getAwtContext();
        if (ctx == null) {
            log.info("Refresh: no AWT context");
            return;
        }
        final Container root = ctx.getAwtRoot();
        if (root != null) {
            root.repaint();
        } else {
            log.info("Refresh: no AWT root");
        }
    }

    public Component getTopComponentAt(int x, int y) {
        if (desktopFrame == null) {
            //no AWT yet, drop the event
            return null;
        }
        Component comp = desktopFrame.getComponentAt(x, y);
        if (comp instanceof SwingBaseWindow) {
            SwingBaseWindow<?, ?> base = (SwingBaseWindow<?, ?>) comp;
            if (base.isShowing()) {
                Window w = base.getAWTComponent();
                if (w instanceof Frame) {
                    MenuBar mb = ((Frame) w).getMenuBar();
                    if (mb != null) {
                        JMenuBar jmb = ((SwingMenuBarPeer) mb.getPeer()).jComponent;
                        Point p = new Point(x, y);
                        SwingUtilities.convertPointFromScreen(p, jmb);
                        comp = SwingUtilities.getDeepestComponentAt(jmb, p.x, p.y);
                        if (comp != null && (comp != jmb || jmb.contains(p.x, p.y))) {
                            return comp;
                        }
                    }
                }
                Point p = new Point(x, y);
                SwingUtilities.convertPointFromScreen(p, w);
                comp = SwingUtilities.getDeepestComponentAt(w, p.x, p.y);
                if (comp == w) {
                    p = new Point(x, y);
                    SwingUtilities.convertPointFromScreen(p, base);
                    comp = SwingUtilities.getDeepestComponentAt(base, p.x, p.y);
                }
            }
        } else {
            comp = super.getTopComponentAt(x, y);
            SwingBaseWindow<?, ?> window = (SwingBaseWindow<?, ?>) SwingUtilities.
                getAncestorOfClass(SwingBaseWindow.class, comp);
            if (window != null) {
                Rectangle r = window.getBounds();
                Insets ins = window.getSwingPeer().getInsets();
                r.x = r.x + ins.left;
                r.y = r.y + ins.top;
                r.width = r.width - ins.left - ins.right;
                r.height = r.height - ins.top - ins.bottom;
                if (r.contains(x, y)) {
                    Component c = window.getAWTComponent().findComponentAt(x - r.x + ins.left, y - r.y + ins.top);
                    if (c != null) {
                        comp = c;
                    }
                }
            }
        }
        return comp;
    }

    public void activateWindow(Component comp) {
        if (comp == null) return;

        Window w = SwingUtilities.getWindowAncestor(comp);
        if (w == null) return;

        WindowPeer p = (WindowPeer) w.getPeer();
        if (p instanceof SwingBaseWindowPeer) {
            JInternalFrame f = (JInternalFrame) ((SwingBaseWindowPeer<?, ?>) p).peerComponent;
            if (f.isShowing() && !f.isSelected()) {
                try {
                    f.setSelected(true);
                } catch (PropertyVetoException pve) {
                    //ignore
                }
            }
        }
    }

    /**
     * @see org.jnode.awt.JNodeToolkit#onClose()
     */
    protected void onClose() {
        log.debug("onClose");
        // Stop the repaint manager
        if (repaintManager != null) {
            //repaintManager.shutdown();
            repaintManager = null;
        }

        // sometime when the start of wat has failed, desktopFrame can be null
        // so, we must check it is not null
        if (desktopFrame != null) {
            // Close the desktop
            desktopFrame.dispose();
            desktopFrame = null;
        }
    }

    // /////////////////////////////////////////////////////////////////////////////////////
    // Private

    final void onDisposeFrame(SwingBaseWindowPeer<?, ?> windowPeer) {
        // Nothing to do
    }

    /**
     * @see org.jnode.awt.JNodeToolkit#onInitialize()
     */
    protected void onInitialize() {
        log.debug("onInitialize");

        // Set the repaint manager

        RepaintManager.setCurrentManager(repaintManager = new RepaintManager() {
            private WeakHashMap<Component, BufferedImage> bufferMap = new WeakHashMap<Component, BufferedImage>();
            @SuppressWarnings("unused")
            private final Component DEFA_KEY = new Component() {
                private static final long serialVersionUID = 1L;
            };

            @Override
            public Image getOffscreenBuffer(Component c, int proposedWidth, int proposedHeight) {
                BufferedImage buffer = bufferMap.get(c);
                if (buffer == null || buffer.getWidth() < proposedWidth || buffer.getHeight() < proposedHeight) {
                    buffer = new BufferedImage(proposedWidth, proposedHeight, BufferedImage.TYPE_INT_ARGB);
                    bufferMap.put(c, buffer);
                }

                return buffer;
            }
        });

        try {
            MetalLookAndFeel.setCurrentTheme(new OceanTheme());
            UIManager.setLookAndFeel(new MetalLookAndFeel());
        } catch (Exception x) {
            log.warn("Look And Feel not found: ", x);
        }
        // Create the desktop
        desktopFrame = new DesktopFrame(getScreenSize());
        desktopFrame.show();
    }

    protected void onResize() {
        //nothing to do here yet
    }

    public boolean isWindow(Component comp) {
        return comp instanceof SwingWindow;
    }

    /**
     * Sets the source of the event to the given component.
     */
    static <T extends AWTEvent> T convertEvent(T event, Component awtComponent) {
        event.setSource(awtComponent);
        return event;
    }

    /**
     * Run the runnable now, if the current thread is the event dispatch thread,
     * otherwise invoke it on the event thread.
     */
    public static void invokeNowOrLater(final Runnable runnable) {
        if (SwingUtilities.isEventDispatchThread()) {
            runnable.run();
        } else {
            SwingUtilities.invokeLater(runnable);
        }
    }

    /*
     * Modality
     */
    public boolean isModalityTypeSupported(Dialog.ModalityType modalityType) {
        //todo implement it
        return true;
    }

}
TOP

Related Classes of org.jnode.awt.swingpeers.AWTInvocationLock

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.