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