1 /* 2 * Copyright (c) 2011, 2012, 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.lwawt.macosx; 27 28 import java.awt.Component; 29 import java.lang.reflect.Field; 30 31 import javax.accessibility.Accessible; 32 import javax.accessibility.AccessibleContext; 33 import javax.swing.JProgressBar; 34 import javax.swing.JSlider; 35 import javax.swing.event.CaretEvent; 36 import javax.swing.event.CaretListener; 37 import javax.swing.event.ChangeEvent; 38 import javax.swing.event.ChangeListener; 39 import javax.swing.event.DocumentEvent; 40 import javax.swing.event.DocumentListener; 41 import javax.swing.text.JTextComponent; 42 43 44 class CAccessible extends CFRetainedResource implements Accessible { 45 static Field getNativeAXResourceField() { 46 try { 47 final Field field = AccessibleContext.class.getDeclaredField("nativeAXResource"); 48 field.setAccessible(true); 49 return field; 50 } catch (final Exception e) { 51 e.printStackTrace(); 52 return null; 53 } 54 } 55 56 private static Field nativeAXResourceField = getNativeAXResourceField(); 57 58 public static CAccessible getCAccessible(final Accessible a) { 59 if (a == null) return null; 60 AccessibleContext context = a.getAccessibleContext(); 61 try { 62 final CAccessible cachedCAX = (CAccessible) nativeAXResourceField.get(context); 63 if (cachedCAX != null) return cachedCAX; 64 65 final CAccessible newCAX = new CAccessible(a); 66 nativeAXResourceField.set(context, newCAX); 67 return newCAX; 68 } catch (final Exception e) { 69 e.printStackTrace(); 70 return null; 71 } 72 } 73 74 private static native void unregisterFromCocoaAXSystem(long ptr); 75 private static native void valueChanged(long ptr); 76 private static native void selectionChanged(long ptr); 77 78 private Accessible accessible; 79 80 private CAccessible(final Accessible accessible) { 81 super(0L, true); // real pointer will be poked in by native 82 83 if (accessible == null) throw new NullPointerException(); 84 this.accessible = accessible; 85 86 if (accessible instanceof Component) { 87 addNotificationListeners((Component)accessible); 88 } 89 } 90 91 @Override 92 protected synchronized void dispose() { 93 if (ptr != 0) unregisterFromCocoaAXSystem(ptr); 94 super.dispose(); 95 } 96 97 @Override 98 public AccessibleContext getAccessibleContext() { 99 return accessible.getAccessibleContext(); 100 } 101 102 // currently only supports text components 103 public void addNotificationListeners(Component c) { 104 if (c instanceof JTextComponent) { 105 JTextComponent tc = (JTextComponent) c; 106 AXTextChangeNotifier listener = new AXTextChangeNotifier(); 107 tc.getDocument().addDocumentListener(listener); 108 tc.addCaretListener(listener); 109 } 110 if (c instanceof JProgressBar) { 111 JProgressBar pb = (JProgressBar) c; 112 pb.addChangeListener(new AXProgressChangeNotifier()); 113 } else if (c instanceof JSlider) { 114 JSlider slider = (JSlider) c; 115 slider.addChangeListener(new AXProgressChangeNotifier()); 116 } 117 } 118 119 120 private class AXTextChangeNotifier implements DocumentListener, CaretListener { 121 @Override 122 public void changedUpdate(DocumentEvent e) { 123 if (ptr != 0) valueChanged(ptr); 124 } 125 126 @Override 127 public void insertUpdate(DocumentEvent e) { 128 if (ptr != 0) valueChanged(ptr); 129 } 130 131 @Override 132 public void removeUpdate(DocumentEvent e) { 133 if (ptr != 0) valueChanged(ptr); 134 } 135 136 @Override 137 public void caretUpdate(CaretEvent e) { 138 if (ptr != 0) selectionChanged(ptr); 139 } 140 } 141 142 private class AXProgressChangeNotifier implements ChangeListener { 143 public void stateChanged(ChangeEvent e) { 144 if (ptr != 0) valueChanged(ptr); 145 } 146 } 147 148 static Accessible getSwingAccessible(final Accessible a) { 149 return (a instanceof CAccessible) ? ((CAccessible)a).accessible : a; 150 } 151 }