001    package org.pbjar.jxlayer.repaint;
002    
003    import java.awt.Graphics;
004    import java.awt.event.ActionEvent;
005    import java.awt.event.ActionListener;
006    import java.lang.reflect.Constructor;
007    import java.lang.reflect.Field;
008    
009    import javax.swing.JCheckBoxMenuItem;
010    import javax.swing.JFrame;
011    import javax.swing.JMenu;
012    import javax.swing.JMenuBar;
013    import javax.swing.JMenuItem;
014    import javax.swing.JScrollPane;
015    import javax.swing.JTextArea;
016    import javax.swing.RepaintManager;
017    import javax.swing.SwingUtilities;
018    
019    import org.pbjar.jxlayer.plaf.ext.transform.TransformRPMFallBack;
020    import org.pbjar.jxlayer.plaf.ext.transform.TransformRPMImpl;
021    
022    public class RepaintManagerTest {
023    
024        private final Class<RepaintManager> rpmClass = RepaintManager.class;
025    
026        private final JMenu optionsMenu = new JMenu("Options");
027    
028        private final JCheckBoxMenuItem newRmItem = new JCheckBoxMenuItem(
029                "new RepaintManager Hacked");
030    
031        private final JCheckBoxMenuItem newWrappedItem = new JCheckBoxMenuItem(
032                "new WrappedRepaintManager (also hacked)");
033    
034        private final JCheckBoxMenuItem doubleBufItem = new JCheckBoxMenuItem(
035                "DoubleBuffering off and on");
036    
037        private RepaintManager oldManager;
038    
039        private void createGui() {
040    
041            optionsMenu.add(newWrappedItem);
042            newWrappedItem.addActionListener(new ActionListener() {
043    
044                @Override
045                public void actionPerformed(ActionEvent e) {
046                    SwingUtilities.invokeLater(new Runnable() {
047    
048                        @Override
049                        public void run() {
050                            oldManager = RepaintManager.currentManager(null);
051                            RepaintManager newManager = new TransformRPMFallBack(
052                                    oldManager);
053                            RepaintManager.setCurrentManager(newManager);
054                            newWrappedItem.setEnabled(false);
055                        }
056                    });
057                }
058            });
059    
060            optionsMenu.add(newRmItem);
061            newRmItem.addActionListener(new ActionListener() {
062                public void actionPerformed(ActionEvent e) {
063                    SwingUtilities.invokeLater(new Runnable() {
064                        public void run() {
065                            oldManager = RepaintManager.currentManager(null);
066                            RepaintManager newManager;
067                            try {
068                                /*
069                                 * Ensure that the new RepaintManager has the same
070                                 * bufferStrategyType as the original.
071                                 */
072                                Field bufferStrategyType = rpmClass
073                                        .getDeclaredField("bufferStrategyType");
074                                bufferStrategyType.setAccessible(true);
075                                short strategyType = (Short) bufferStrategyType
076                                        .get(oldManager);
077                                bufferStrategyType.setAccessible(false);
078                                switch (strategyType) {
079                                case (0):
080                                    System.out
081                                            .println("bufferStrategyType: BUFFER_STRATEGY_NOT_SPECIFIED");
082                                    break;
083                                case (1):
084                                    System.out
085                                            .println("bufferStrategyType: BUFFER_STRATEGY_SPECIFIED_ON");
086                                    break;
087                                case (2):
088                                    System.out
089                                            .println("bufferStrategyType: BUFFER_STRATEGY_SPECIFIED_OFF");
090                                    break;
091                                default:
092                                    System.out.println("bufferStrategyType: "
093                                            + strategyType);
094                                }
095                                /*
096                                 * Construct a new RepaintManager with its private
097                                 * constructor and the same bufferStrategyType.
098                                 */
099                                Constructor<RepaintManager> constructor = rpmClass
100                                        .getDeclaredConstructor(short.class);
101                                constructor.setAccessible(true);
102                                newManager = constructor.newInstance(strategyType);
103                                constructor.setAccessible(false);
104                                /*
105                                 * This is not enough. Now we need to copy the
106                                 * PaintManager from the original RepaintManager
107                                 * into the new RepaintManager.
108                                 */
109                                Field paintManager = rpmClass
110                                        .getDeclaredField("paintManager");
111                                paintManager.setAccessible(true);
112                                Object paintManagerInstance = paintManager
113                                        .get(oldManager);
114                                System.out
115                                        .println("PaintManager is of type: "
116                                                + paintManagerInstance.getClass()
117                                                        .getName());
118                                paintManager.set(newManager, paintManagerInstance);
119                                paintManager.setAccessible(false);
120                            } catch (Throwable t) {
121                                t.printStackTrace();
122                                newManager = oldManager;
123                            }
124    
125                            RepaintManager.setCurrentManager(newManager);
126                        }
127                    });
128                    newRmItem.setEnabled(false);
129                }
130            });
131    
132            optionsMenu.add(doubleBufItem);
133    
134            doubleBufItem.addActionListener(new ActionListener() {
135                public void actionPerformed(ActionEvent e) {
136                    SwingUtilities.invokeLater(new Runnable() {
137                        public void run() {
138                            RepaintManager rm = RepaintManager.currentManager(null);
139                            rm.setDoubleBufferingEnabled(false);
140                            rm.setDoubleBufferingEnabled(true);
141                        }
142                    });
143    
144                    doubleBufItem.setEnabled(false);
145                }
146            });
147    
148            optionsMenu.addSeparator();
149            JMenuItem clearItem = new JMenuItem("Clear textArea");
150            optionsMenu.add(clearItem);
151    
152            JMenuBar bar = new JMenuBar();
153            bar.add(optionsMenu);
154    
155            final JTextArea textArea = new JTextArea();
156            textArea.setEditable(false);
157            textArea.setWrapStyleWord(true);
158            textArea.setFont(textArea.getFont().deriveFont(20f));
159    
160            clearItem.addActionListener(new ActionListener() {
161                public void actionPerformed(ActionEvent e) {
162                    textArea.setText("");
163                }
164            });
165    
166            final JFrame frame = new JFrame("RM test") {
167    
168                private static final long serialVersionUID = 1L;
169    
170                public void paint(Graphics g) {
171                    super.paint(g);
172                    String newLine = System.currentTimeMillis()
173                            + " JFrame.paint()\n";
174                    textArea.setText(textArea.getText() + newLine);
175                }
176            };
177    
178            frame.add(new JScrollPane(textArea));
179            frame.setJMenuBar(bar);
180            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
181            frame.setSize(300, 300);
182            frame.setLocationRelativeTo(null);
183            frame.setVisible(true);
184        }
185    
186        public static void main(String[] args) throws Exception {
187            TransformRPMImpl.hack = true;
188            SwingUtilities.invokeLater(new Runnable() {
189                public void run() {
190                    new RepaintManagerTest().createGui();
191                }
192            });
193        }
194    }