1 /* 2 * Copyright (c) 2002, 2010, 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 com.sun.java.swing; 27 28 import sun.awt.EventQueueDelegate; 29 import sun.awt.AppContext; 30 import sun.awt.SunToolkit; 31 32 import java.util.Collections; 33 import java.util.Map; 34 import java.util.WeakHashMap; 35 import java.util.concurrent.Callable; 36 import java.applet.Applet; 37 import java.awt.AWTEvent; 38 import java.awt.EventQueue; 39 import java.awt.Component; 40 import java.awt.Container; 41 import java.awt.Window; 42 import javax.swing.JComponent; 43 import javax.swing.RepaintManager; 44 45 /** 46 * A collection of utility methods for Swing. 47 * <p> 48 * <b>WARNING:</b> While this class is public, it should not be treated as 49 * public API and its API may change in incompatable ways between dot dot 50 * releases and even patch releases. You should not rely on this class even 51 * existing. 52 * 53 * This is a second part of sun.swing.SwingUtilities2. It is required 54 * to provide services for JavaFX applets. 55 * 56 */ 57 public class SwingUtilities3 { 58 /** 59 * The {@code clientProperty} key for delegate {@code RepaintManager} 60 */ 61 private static final Object DELEGATE_REPAINT_MANAGER_KEY = 62 new StringBuilder("DelegateRepaintManagerKey"); 63 64 /** 65 * Registers delegate RepaintManager for {@code JComponent}. 66 */ 67 public static void setDelegateRepaintManager(JComponent component, 68 RepaintManager repaintManager) { 69 /* setting up flag in AppContext to speed up lookups in case 70 * there are no delegate RepaintManagers used. 71 */ 72 AppContext.getAppContext().put(DELEGATE_REPAINT_MANAGER_KEY, 73 Boolean.TRUE); 74 75 component.putClientProperty(DELEGATE_REPAINT_MANAGER_KEY, 76 repaintManager); 77 } 78 79 private static final Map<Container, Boolean> vsyncedMap = 80 Collections.synchronizedMap(new WeakHashMap<Container, Boolean>()); 81 82 /** 83 * Sets vsyncRequested state for the {@code rootContainer}. If 84 * {@code isRequested} is {@code true} then vsynced 85 * {@code BufferStrategy} is enabled for this {@code rootContainer}. 86 * 87 * Note: requesting vsynced painting does not guarantee one. The outcome 88 * depends on current RepaintManager's RepaintManager.PaintManager 89 * and on the capabilities of the graphics hardware/software and what not. 90 * 91 * @param rootContainer topmost container. Should be either {@code Window} 92 * or {@code Applet} 93 * @param isRequested the value to set vsyncRequested state to 94 */ 95 public static void setVsyncRequested(Container rootContainer, 96 boolean isRequested) { 97 assert (rootContainer instanceof Applet) || (rootContainer instanceof Window); 98 if (isRequested) { 99 vsyncedMap.put(rootContainer, Boolean.TRUE); 100 } else { 101 vsyncedMap.remove(rootContainer); 102 } 103 } 104 105 /** 106 * Checks if vsync painting is requested for {@code rootContainer} 107 * 108 * @param rootContainer topmost container. Should be either Window or Applet 109 * @return {@code true} if vsync painting is requested for {@code rootContainer} 110 */ 111 public static boolean isVsyncRequested(Container rootContainer) { 112 assert (rootContainer instanceof Applet) || (rootContainer instanceof Window); 113 return Boolean.TRUE == vsyncedMap.get(rootContainer); 114 } 115 116 /** 117 * Returns delegate {@code RepaintManager} for {@code component} hierarchy. 118 */ 119 public static RepaintManager getDelegateRepaintManager(Component 120 component) { 121 RepaintManager delegate = null; 122 if (Boolean.TRUE == SunToolkit.targetToAppContext(component) 123 .get(DELEGATE_REPAINT_MANAGER_KEY)) { 124 while (delegate == null && component != null) { 125 while (component != null 126 && ! (component instanceof JComponent)) { 127 component = component.getParent(); 128 } 129 if (component != null) { 130 delegate = (RepaintManager) 131 ((JComponent) component) 132 .getClientProperty(DELEGATE_REPAINT_MANAGER_KEY); 133 component = component.getParent(); 134 } 135 136 } 137 } 138 return delegate; 139 } 140 141 /* 142 * We use maps to avoid reflection. Hopefully it should perform better 143 * this way. 144 */ 145 public static void setEventQueueDelegate( 146 Map<String, Map<String, Object>> map) { 147 EventQueueDelegate.setDelegate(new EventQueueDelegateFromMap(map)); 148 } 149 150 private static class EventQueueDelegateFromMap 151 implements EventQueueDelegate.Delegate { 152 private final AWTEvent[] afterDispatchEventArgument; 153 private final Object[] afterDispatchHandleArgument; 154 private final Callable<Void> afterDispatchCallable; 155 156 private final AWTEvent[] beforeDispatchEventArgument; 157 private final Callable<Object> beforeDispatchCallable; 158 159 private final EventQueue[] getNextEventEventQueueArgument; 160 private final Callable<AWTEvent> getNextEventCallable; 161 162 @SuppressWarnings("unchecked") 163 public EventQueueDelegateFromMap(Map<String, Map<String, Object>> objectMap) { 164 Map<String, Object> methodMap = objectMap.get("afterDispatch"); 165 afterDispatchEventArgument = (AWTEvent[]) methodMap.get("event"); 166 afterDispatchHandleArgument = (Object[]) methodMap.get("handle"); 167 afterDispatchCallable = (Callable<Void>) methodMap.get("method"); 168 169 methodMap = objectMap.get("beforeDispatch"); 170 beforeDispatchEventArgument = (AWTEvent[]) methodMap.get("event"); 171 beforeDispatchCallable = (Callable<Object>) methodMap.get("method"); 172 173 methodMap = objectMap.get("getNextEvent"); 174 getNextEventEventQueueArgument = 175 (EventQueue[]) methodMap.get("eventQueue"); 176 getNextEventCallable = (Callable<AWTEvent>) methodMap.get("method"); 177 } 178 179 @Override 180 public void afterDispatch(AWTEvent event, Object handle) throws InterruptedException { 181 afterDispatchEventArgument[0] = event; 182 afterDispatchHandleArgument[0] = handle; 183 try { 184 afterDispatchCallable.call(); 185 } catch (InterruptedException e) { 186 throw e; 187 } catch (RuntimeException e) { 188 throw e; 189 } catch (Exception e) { 190 throw new RuntimeException(e); 191 } 192 } 193 194 @Override 195 public Object beforeDispatch(AWTEvent event) throws InterruptedException { 196 beforeDispatchEventArgument[0] = event; 197 try { 198 return beforeDispatchCallable.call(); 199 } catch (InterruptedException e) { 200 throw e; 201 } catch (RuntimeException e) { 202 throw e; 203 } catch (Exception e) { 204 throw new RuntimeException(e); 205 } 206 } 207 208 @Override 209 public AWTEvent getNextEvent(EventQueue eventQueue) throws InterruptedException { 210 getNextEventEventQueueArgument[0] = eventQueue; 211 try { 212 return getNextEventCallable.call(); 213 } catch (InterruptedException e) { 214 throw e; 215 } catch (RuntimeException e) { 216 throw e; 217 } catch (Exception e) { 218 throw new RuntimeException(e); 219 } 220 } 221 } 222 }