/** Copyright (c) 2013, 2017, 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.swing;import java.awt.*;import java.awt.dnd.DragGestureEvent;import java.awt.dnd.DragGestureListener;import java.awt.dnd.DragGestureRecognizer;import java.awt.dnd.DragSource;import java.awt.dnd.DropTarget;import java.awt.dnd.InvalidDnDOperationException;import java.awt.dnd.peer.DragSourceContextPeer;import java.awt.event.ContainerEvent;import java.awt.event.ContainerListener;import java.awt.geom.AffineTransform;import java.awt.image.BufferedImage;import java.awt.image.DataBufferInt;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.security.AccessController;import javax.swing.JComponent;import javax.swing.JLayeredPane;import javax.swing.JPanel;import javax.swing.JRootPane;import javax.swing.LayoutFocusTraversalPolicy;import javax.swing.RepaintManager;import javax.swing.RootPaneContainer;import javax.swing.SwingUtilities;import sun.awt.AWTAccessor;import sun.awt.DisplayChangedListener;import sun.awt.LightweightFrame;import sun.awt.OverrideNativeWindowHandle;import sun.security.action.GetPropertyAction;import sun.swing.SwingUtilities2.RepaintListener;/*** The frame serves as a lightweight container which paints its content* to an offscreen image and provides access to the image's data via the* {@link LightweightContent} interface. Note, that it may not be shown* as a standalone toplevel frame. Its purpose is to provide functionality* for lightweight embedding.** @author Artem Ananiev* @author Anton Tarasov*/@SuppressWarnings("serial") // JDK-implementation classpublic final class JLightweightFrame extends LightweightFrame implements RootPaneContainer {private final JRootPane rootPane = new JRootPane();private LightweightContent content;private Component component;private JPanel contentPane;private BufferedImage bbImage;private volatile double scaleFactorX;private volatile double scaleFactorY;/*** {@code copyBufferEnabled}, true by default, defines the following strategy.* A duplicating (copy) buffer is created for the original pixel buffer.* The copy buffer is synchronized with the original buffer every time the* latter changes. {@code JLightweightFrame} passes the copy buffer array* to the {@link LightweightContent#imageBufferReset} method. The code spot* which synchronizes two buffers becomes the only critical section guarded* by the lock (managed with the {@link LightweightContent#paintLock()},* {@link LightweightContent#paintUnlock()} methods).*/private static boolean copyBufferEnabled;private int[] copyBuffer;private PropertyChangeListener layoutSizeListener;private RepaintListener repaintListener;static {SwingAccessor.setJLightweightFrameAccessor(new SwingAccessor.JLightweightFrameAccessor() {@Overridepublic void updateCursor(JLightweightFrame frame) {frame.updateClientCursor();}});copyBufferEnabled = "true".equals(AccessController.doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));}/*** Constructs a new, initially invisible {@code JLightweightFrame}* instance.*/public JLightweightFrame() {super();AffineTransform defaultTransform =getGraphicsConfiguration().getDefaultTransform();scaleFactorX = defaultTransform.getScaleX();scaleFactorY = defaultTransform.getScaleY();copyBufferEnabled = "true".equals(AccessController.doPrivileged(new GetPropertyAction("swing.jlf.copyBufferEnabled", "true")));add(rootPane, BorderLayout.CENTER);setFocusTraversalPolicy(new LayoutFocusTraversalPolicy());if (getGraphicsConfiguration().isTranslucencyCapable()) {setBackground(new Color(0, 0, 0, 0));}layoutSizeListener = new PropertyChangeListener() {@Overridepublic void propertyChange(PropertyChangeEvent e) {Dimension d = (Dimension)e.getNewValue();if ("preferredSize".equals(e.getPropertyName())) {content.preferredSizeChanged(d.width, d.height);} else if ("maximumSize".equals(e.getPropertyName())) {content.maximumSizeChanged(d.width, d.height);} else if ("minimumSize".equals(e.getPropertyName())) {content.minimumSizeChanged(d.width, d.height);}}};repaintListener = (JComponent c, int x, int y, int w, int h) -> {Window jlf = SwingUtilities.getWindowAncestor(c);if (jlf != JLightweightFrame.this) {return;}Point p = SwingUtilities.convertPoint(c, x, y, jlf);Rectangle r = new Rectangle(p.x, p.y, w, h).intersection(new Rectangle(0, 0,(int)Math.round(bbImage.getWidth() / scaleFactorX),(int)Math.round(bbImage.getHeight() / scaleFactorY)));if (!r.isEmpty()) {notifyImageUpdated(r.x, r.y, r.width, r.height);}};SwingAccessor.getRepaintManagerAccessor().addRepaintListener(RepaintManager.currentManager(this), repaintListener);}@Overridepublic void dispose() {SwingAccessor.getRepaintManagerAccessor().removeRepaintListener(RepaintManager.currentManager(this), repaintListener);super.dispose();}/*** Sets the {@link LightweightContent} instance for this frame.* The {@code JComponent} object returned by the* {@link LightweightContent#getComponent()} method is immediately* added to the frame's content pane.** @param content the {@link LightweightContent} instance*/public void setContent(final LightweightContent content) {if (content == null) {System.err.println("JLightweightFrame.setContent: content may not be null!");return;}this.content = content;this.component = content.getComponent();Dimension d = this.component.getPreferredSize();content.preferredSizeChanged(d.width, d.height);d = this.component.getMaximumSize();content.maximumSizeChanged(d.width, d.height);d = this.component.getMinimumSize();content.minimumSizeChanged(d.width, d.height);initInterior();}@Overridepublic Graphics getGraphics() {if (bbImage == null) return null;Graphics2D g = bbImage.createGraphics();g.setBackground(getBackground());g.setColor(getForeground());g.setFont(getFont());g.scale(scaleFactorX, scaleFactorY);return g;}/*** {@inheritDoc}** @see LightweightContent#focusGrabbed()*/@Overridepublic void grabFocus() {if (content != null) content.focusGrabbed();}/*** {@inheritDoc}** @see LightweightContent#focusUngrabbed()*/@Overridepublic void ungrabFocus() {if (content != null) content.focusUngrabbed();}@Override@SuppressWarnings("deprecation")public int getScaleFactor() {return (int)scaleFactorX;}@Overridepublic double getScaleFactorX() {return scaleFactorX;}@Overridepublic double getScaleFactorY() {return scaleFactorY;}@Override@SuppressWarnings("deprecation")public void notifyDisplayChanged(final int scaleFactor) {notifyDisplayChanged(scaleFactor, scaleFactor);}@Overridepublic void notifyDisplayChanged(final double scaleFactorX,final double scaleFactorY) {if (Double.compare(scaleFactorX, this.scaleFactorX) != 0 ||Double.compare(scaleFactorY, this.scaleFactorY) != 0) {if (!copyBufferEnabled) content.paintLock();try {if (bbImage != null) {resizeBuffer(getWidth(), getHeight(), scaleFactorX,scaleFactorY);}} finally {if (!copyBufferEnabled) content.paintUnlock();}this.scaleFactorX = scaleFactorX;this.scaleFactorY = scaleFactorY;if(isVisible()) {final Object peer =AWTAccessor.getComponentAccessor().getPeer(this);if (peer instanceof DisplayChangedListener) {((DisplayChangedListener) peer).displayChanged();}repaint();}}}@Overridepublic void addNotify() {super.addNotify();final Object peer = AWTAccessor.getComponentAccessor().getPeer(this);if (peer instanceof DisplayChangedListener) {((DisplayChangedListener) peer).displayChanged();}}private void syncCopyBuffer(boolean reset, int x, int y, int w, int h,double scaleX, double scaleY) {content.paintLock();try {int[] srcBuffer = ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();if (reset) {copyBuffer = new int[srcBuffer.length];}int linestride = bbImage.getWidth();int startX = (int)Math.floor(x * scaleX);int startY = (int)Math.floor(y * scaleY);int width = (int)Math.ceil((x + w) * scaleX) - startX;int height = (int)Math.ceil((y + h) * scaleY) - startY;if (startX + width > linestride) {width = linestride - startX;}if (startY + height > bbImage.getHeight()) {height = bbImage.getHeight() - startY;}for (int i = 0; i < height; i++) {int from = (startY + i) * linestride + startX;System.arraycopy(srcBuffer, from, copyBuffer, from, width);}} finally {content.paintUnlock();}}private void notifyImageUpdated(int x, int y, int width, int height) {if (copyBufferEnabled) {syncCopyBuffer(false, x, y, width, height, scaleFactorX,scaleFactorY);}content.imageUpdated(x, y, width, height);}@SuppressWarnings("serial") // anonymous class insideprivate void initInterior() {contentPane = new JPanel() {@Overridepublic void paint(Graphics g) {if (!copyBufferEnabled) {content.paintLock();}try {super.paint(g);final Rectangle clip = g.getClipBounds() != null ?g.getClipBounds() :new Rectangle(0, 0, contentPane.getWidth(), contentPane.getHeight());clip.x = Math.max(0, clip.x);clip.y = Math.max(0, clip.y);clip.width = Math.min(contentPane.getWidth(), clip.width);clip.height = Math.min(contentPane.getHeight(), clip.height);EventQueue.invokeLater(new Runnable() {@Overridepublic void run() {Rectangle c = contentPane.getBounds().intersection(clip);notifyImageUpdated(c.x, c.y, c.width, c.height);}});} finally {if (!copyBufferEnabled) {content.paintUnlock();}}}@Overrideprotected boolean isPaintingOrigin() {return true;}};contentPane.setLayout(new BorderLayout());contentPane.add(component);if ("true".equals(AccessController.doPrivileged(new GetPropertyAction("swing.jlf.contentPaneTransparent", "false")))){contentPane.setOpaque(false);}setContentPane(contentPane);contentPane.addContainerListener(new ContainerListener() {@Overridepublic void componentAdded(ContainerEvent e) {Component c = JLightweightFrame.this.component;if (e.getChild() == c) {c.addPropertyChangeListener("preferredSize", layoutSizeListener);c.addPropertyChangeListener("maximumSize", layoutSizeListener);c.addPropertyChangeListener("minimumSize", layoutSizeListener);}}@Overridepublic void componentRemoved(ContainerEvent e) {Component c = JLightweightFrame.this.component;if (e.getChild() == c) {c.removePropertyChangeListener(layoutSizeListener);}}});}@SuppressWarnings("deprecation")@Override public void reshape(int x, int y, int width, int height) {super.reshape(x, y, width, height);if (width == 0 || height == 0) {return;}if (!copyBufferEnabled) {content.paintLock();}try {boolean createBB = (bbImage == null);int newW = width;int newH = height;if (bbImage != null) {int imgWidth = (int)Math.round(bbImage.getWidth() /scaleFactorX);int imgHeight = (int)Math.round(bbImage.getHeight() /scaleFactorY);if (width != imgWidth || height != imgHeight) {createBB = true;if (bbImage != null) {int oldW = imgWidth;int oldH = imgHeight;if ((oldW >= newW) && (oldH >= newH)) {createBB = false;} else {if (oldW >= newW) {newW = oldW;} else {newW = Math.max((int)(oldW * 1.2), width);}if (oldH >= newH) {newH = oldH;} else {newH = Math.max((int)(oldH * 1.2), height);}}}}}if (createBB) {resizeBuffer(newW, newH, scaleFactorX, scaleFactorY);return;}content.imageReshaped(0, 0, width, height);} finally {if (!copyBufferEnabled) {content.paintUnlock();}}}private void resizeBuffer(int width, int height, double newScaleFactorX,double newScaleFactorY) {bbImage = new BufferedImage((int)Math.round(width * newScaleFactorX),(int)Math.round(height * newScaleFactorY),BufferedImage.TYPE_INT_ARGB_PRE);int[] pixels= ((DataBufferInt)bbImage.getRaster().getDataBuffer()).getData();if (copyBufferEnabled) {syncCopyBuffer(true, 0, 0, width, height, newScaleFactorX,newScaleFactorY);pixels = copyBuffer;}content.imageBufferReset(pixels, 0, 0, width, height,bbImage.getWidth(), newScaleFactorX, newScaleFactorY);}@Overridepublic JRootPane getRootPane() {return rootPane;}@Overridepublic void setContentPane(Container contentPane) {getRootPane().setContentPane(contentPane);}@Overridepublic Container getContentPane() {return getRootPane().getContentPane();}@Overridepublic void setLayeredPane(JLayeredPane layeredPane) {getRootPane().setLayeredPane(layeredPane);}@Overridepublic JLayeredPane getLayeredPane() {return getRootPane().getLayeredPane();}@Overridepublic void setGlassPane(Component glassPane) {getRootPane().setGlassPane(glassPane);}@Overridepublic Component getGlassPane() {return getRootPane().getGlassPane();}/** Notifies client toolkit that it should change a cursor.** Called from the peer via SwingAccessor, because the* Component.updateCursorImmediately method is final* and could not be overridden.*/private void updateClientCursor() {PointerInfo pointerInfo = MouseInfo.getPointerInfo();if (pointerInfo == null) {/** This can happen when multiple graphics device cannot decide* which graphics device contains the current mouse position* or on systems without a mouse*/return;}Point p = pointerInfo.getLocation();SwingUtilities.convertPointFromScreen(p, this);Component target = SwingUtilities.getDeepestComponentAt(this, p.x, p.y);if (target != null) {content.setCursor(target.getCursor());}}//Called by reflection by SwingNodepublic void overrideNativeWindowHandle(long handle, Runnable closeWindow) {final Object peer = AWTAccessor.getComponentAccessor().getPeer(this);if (peer instanceof OverrideNativeWindowHandle) {((OverrideNativeWindowHandle) peer).overrideWindowHandle(handle);}if (closeWindow != null) {closeWindow.run();}}public <T extends DragGestureRecognizer> T createDragGestureRecognizer(Class<T> abstractRecognizerClass,DragSource ds, Component c, int srcActions,DragGestureListener dgl){return content == null ? null : content.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl);}public DragSourceContextPeer createDragSourceContextPeer(DragGestureEvent dge) throws InvalidDnDOperationException {return content == null ? null : content.createDragSourceContextPeer(dge);}public void addDropTarget(DropTarget dt) {if (content == null) return;content.addDropTarget(dt);}public void removeDropTarget(DropTarget dt) {if (content == null) return;content.removeDropTarget(dt);}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。