01: /*
02: * Copyright 2006 Ethan Nicholas. All rights reserved.
03: * Use is subject to license terms.
04: */
05: package jaxx.runtime.swing;
06:
07: import java.lang.reflect.*;
08:
09: import javax.swing.*;
10: import javax.swing.text.*;
11:
12: public class Utils {
13: private static Field numReaders;
14: private static Field notifyingListeners;
15:
16: public static void setText(final JTextComponent c, final String text) {
17: try {
18: // AbstractDocument deadlocks if we try to acquire a write lock while a read lock is held by the current thread
19: // If there are any readers, dispatch an invokeLater. This should only happen in the event of circular bindings.
20: // Similarly, circular bindings can result in an "Attempt to mutate in notification" error, which we deal with
21: // by checking for the 'notifyingListeners' property.
22: AbstractDocument document = (AbstractDocument) c
23: .getDocument();
24: if (numReaders == null) {
25: numReaders = AbstractDocument.class
26: .getDeclaredField("numReaders");
27: numReaders.setAccessible(true);
28: }
29: if (notifyingListeners == null) {
30: notifyingListeners = AbstractDocument.class
31: .getDeclaredField("notifyingListeners");
32: notifyingListeners.setAccessible(true);
33: }
34:
35: if (notifyingListeners.get(document).equals(Boolean.TRUE))
36: return;
37:
38: if (((Integer) numReaders.get(document)).intValue() > 0) {
39: SwingUtilities.invokeLater(new Runnable() {
40: public void run() {
41: if (!c.getText().equals(text))
42: c.setText(text);
43: }
44: });
45: return;
46: }
47:
48: String oldText = c.getText();
49: if (oldText == null || !oldText.equals(text))
50: c.setText(text);
51: } catch (NoSuchFieldException e) {
52: throw new RuntimeException(e);
53: } catch (IllegalAccessException e) {
54: throw new RuntimeException(e);
55: } catch (SecurityException e) {
56: c.setText(text);
57: }
58: }
59: }
|