1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.swing; 27 28 import java.awt.BorderLayout; 29 import java.awt.Color; 30 import java.awt.Component; 31 import java.awt.Container; 32 import java.awt.EventQueue; 33 import java.awt.Graphics; 34 import java.awt.Graphics2D; 35 import java.awt.Rectangle; 36 import java.awt.image.BufferedImage; 37 import java.awt.image.DataBufferInt; 38 39 import javax.swing.JLayeredPane; 40 import javax.swing.JPanel; 41 import javax.swing.JRootPane; 42 import javax.swing.RootPaneContainer; 43 44 import sun.awt.LightweightFrame; 45 46 /** 47 * The frame serves as a lightweight container which paints its content to an offscreen image 48 * and provides access to the image's data via the {@link LightweightContent} interface. 49 * Note, that it may not be shown as a standalone toplevel frame. Its purpose is to provide 50 * functionality for lightweight embedding. 51 * 52 * @author Artem Ananiev 53 * @author Anton Tarasov 54 */ 55 public final class JLightweightFrame extends LightweightFrame implements RootPaneContainer { 56 57 private final JRootPane rootPane = new JRootPane(); 58 59 private LightweightContent content; 60 61 private Component component; 62 private JPanel contentPane; 63 64 private BufferedImage bbImage; 65 66 /** 67 * Constructs a new, initially invisible {@code JLightweightFrame} instance. 68 */ 69 public JLightweightFrame() { 70 super(); 71 add(rootPane, BorderLayout.CENTER); 72 setBackground(new Color(0, 0, 0, 0)); 73 } 74 75 /** 76 * Sets the {@link LightweightContent} instance for this frame. 77 * The {@code JComponent} object returned by the {@link LightweightContent#getComponent()} 78 * method is immediately added to the frame's content pane. 79 * 80 * @param content the {@link LightweightContent} instance 81 */ 82 public void setContent(LightweightContent content) { 83 this.content = content; 84 this.component = content.getComponent(); 85 86 initInterior(); 87 } 88 89 @Override 90 public Graphics getGraphics() { 91 if (bbImage == null) return null; 92 93 Graphics2D g = bbImage.createGraphics(); 94 g.setBackground(getBackground()); 95 g.setColor(getForeground()); 96 g.setFont(getFont()); 97 return g; 98 } 99 100 @Override 101 public void grabFocus() { 102 super.grabFocus(); 103 if (content != null) { 104 content.focusGrabbed(); 105 } 106 } 107 108 @Override 109 public void ungrabFocus(boolean postEvent) { 110 super.ungrabFocus(postEvent); 111 if (content != null) { 112 content.focusUngrabbed(); 113 } 114 } 115 116 private void initInterior() { 117 contentPane = new JPanel() { 118 @Override 119 public void paint(Graphics g) { 120 content.paintLock(); 121 try { 122 super.paint(g); 123 124 final Rectangle clip = g.getClipBounds() != null ? 125 g.getClipBounds() : new Rectangle(0, 0, contentPane.getWidth(), contentPane.getHeight()); 126 127 clip.x = Math.max(0, clip.x); 128 clip.y = Math.max(0, clip.y); 129 clip.width = Math.min(contentPane.getWidth(), clip.width); 130 clip.height = Math.min(contentPane.getHeight(), clip.height); 131 132 EventQueue.invokeLater(new Runnable() { 133 @Override 134 public void run() { 135 content.imageUpdated(clip.x, clip.y, clip.width, clip.height); 136 } 137 }); 138 } finally { 139 content.paintUnlock(); 140 } 141 } 142 @Override 143 protected boolean isPaintingOrigin() { 144 return true; 145 } 146 }; 147 contentPane.setLayout(new BorderLayout()); 148 contentPane.add(component); 149 setContentPane(contentPane); 150 } 151 152 @SuppressWarnings("deprecation") 153 @Override public void reshape(int x, int y, int width, int height) { 154 super.reshape(x, y, width, height); 155 156 if (width == 0 || height == 0) { 157 return; 158 } 159 160 content.paintLock(); 161 try { 162 if ((bbImage == null) || (width != bbImage.getWidth()) || (height != bbImage.getHeight())) { 163 boolean createBB = true; 164 int newW = width; 165 int newH = height; 166 if (bbImage != null) { 167 int oldW = bbImage.getWidth(); 168 int oldH = bbImage.getHeight(); 169 if ((oldW >= newW) && (oldH >= newH)) { 170 createBB = false; 171 } else { 172 if (oldW >= newW) { 173 newW = oldW; 174 } else { 175 newW = Math.max((int)(oldW * 1.2), width); 176 } 177 if (oldH >= newH) { 178 newH = oldH; 179 } else { 180 newH = Math.max((int)(oldH * 1.2), height); 181 } 182 } 183 } 184 if (createBB) { 185 BufferedImage oldBB = bbImage; 186 bbImage = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_ARGB_PRE); 187 if (oldBB != null) { 188 Graphics g = bbImage.getGraphics(); 189 try { 190 g.drawImage(oldBB, 0, 0, newW, newH, null); 191 } finally { 192 g.dispose(); 193 oldBB.flush(); 194 } 195 } 196 DataBufferInt dataBuf = (DataBufferInt)bbImage.getRaster().getDataBuffer(); 197 content.imageBufferReset(dataBuf.getData(), 0, 0, width, height, bbImage.getWidth()); 198 } else { 199 content.imageReshaped(0, 0, width, height); 200 } 201 } 202 } finally { 203 content.paintUnlock(); 204 } 205 } 206 207 @Override 208 public JRootPane getRootPane() { 209 return rootPane; 210 } 211 212 @Override 213 public void setContentPane(Container contentPane) { 214 getRootPane().setContentPane(contentPane); 215 } 216 217 @Override 218 public Container getContentPane() { 219 return getRootPane().getContentPane(); 220 } 221 222 @Override 223 public void setLayeredPane(JLayeredPane layeredPane) { 224 getRootPane().setLayeredPane(layeredPane); 225 } 226 227 @Override 228 public JLayeredPane getLayeredPane() { 229 return getRootPane().getLayeredPane(); 230 } 231 232 @Override 233 public void setGlassPane(Component glassPane) { 234 getRootPane().setGlassPane(glassPane); 235 } 236 237 @Override 238 public Component getGlassPane() { 239 return getRootPane().getGlassPane(); 240 } 241 }