001 /**
002 * Copyright (c) 2009, Piet Blok
003 * All rights reserved.
004 *
005 * Redistribution and use in source and binary forms, with or without
006 * modification, are permitted provided that the following conditions
007 * are met:
008 *
009 * * Redistributions of source code must retain the above copyright
010 * notice, this list of conditions and the following disclaimer.
011 * * Redistributions in binary form must reproduce the above
012 * copyright notice, this list of conditions and the following
013 * disclaimer in the documentation and/or other materials provided
014 * with the distribution.
015 * * Neither the name of the copyright holder nor the names of the
016 * contributors may be used to endorse or promote products derived
017 * from this software without specific prior written permission.
018 *
019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
020 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
021 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
022 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
023 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
024 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
025 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
026 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
027 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
028 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
029 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
030 */
031
032 package org.pbjar.jxlayer.repaint;
033
034 import java.awt.Component;
035 import java.awt.Font;
036 import java.awt.event.ActionEvent;
037 import java.io.PrintWriter;
038 import java.io.StringWriter;
039
040 import javax.swing.AbstractAction;
041 import javax.swing.Action;
042 import javax.swing.JComponent;
043 import javax.swing.JOptionPane;
044 import javax.swing.JTextPane;
045 import javax.swing.RepaintManager;
046
047 import org.jdesktop.swingx.ForwardingRepaintManager;
048
049 /**
050 * Utility class that ensures that a correct {@link RepaintManager} is set.
051 *
052 * @author Piet Blok
053 */
054 public class RepaintManagerUtils {
055
056 private static class DisplayAction extends AbstractAction {
057
058 private static final long serialVersionUID = 1L;
059
060 public DisplayAction() {
061 super("RPM tree");
062 }
063
064 @Override
065 public void actionPerformed(ActionEvent e) {
066 JComponent c = (JComponent) e.getSource();
067 StringWriter sw = new StringWriter();
068 PrintWriter pw = new PrintWriter(sw);
069 pw.println("The tree for the current RepaintManager:");
070 pw.println();
071 RepaintManager manager = RepaintManager.currentManager(c);
072 appendDelegates(pw, manager);
073 pw.close();
074 String text = sw.toString();
075 JTextPane message = new JTextPane();
076 message.setFont(Font.decode(Font.MONOSPACED));
077 message.setContentType("text/plain");
078 message.setText(text);
079 message.setEditable(false);
080 JOptionPane.showMessageDialog(c, message,
081 "The RepaintManager tree", JOptionPane.INFORMATION_MESSAGE);
082 }
083
084 private void appendClass(PrintWriter writer, Object obj) {
085 Class<?> clazz = obj.getClass();
086 String prefix = "Class: ";
087 while (clazz != null) {
088 writer.println(prefix + clazz.getName());
089 clazz = clazz.getSuperclass();
090 prefix = "Extends: ";
091 }
092 }
093
094 private void appendDelegates(PrintWriter writer, Object rp) {
095 appendClass(writer, rp);
096 RepaintManager delegate;
097 if (rp instanceof WrappedRepaintManager) {
098 delegate = ((WrappedRepaintManager) rp).getDelegateManager();
099 } else if (swingX) {
100 if (rp instanceof ForwardingRepaintManager) {
101 delegate = ((ForwardingRepaintManager) rp)
102 .getDelegateManager();
103 } else {
104 delegate = null;
105 }
106 } else {
107 delegate = null;
108 }
109 if (delegate != null) {
110 writer.println();
111 writer.println("Delegate:");
112 appendDelegates(writer, delegate);
113 }
114 }
115
116 }
117
118 /**
119 * Indicates the availability of SwingX on the class path.
120 */
121 private static final boolean swingX = isSwingXAvalable();
122
123 /**
124 * Create and return an {@link Action} that will display the delegate
125 * structure of the current {@link RepaintManager}.
126 *
127 * @return an {@link Action} object
128 */
129 public static Action createRPDisplayAction() {
130 return new DisplayAction();
131 }
132
133 /**
134 * Ensure that a specific {@link RepaintManager} is set according to the
135 * requirements of the {@link RepaintManagerProvider}.
136 *
137 * @param c
138 * a component from which the current repaint manager can be
139 * obtained.
140 * @param provider
141 * the provider
142 */
143 public static void ensureRepaintManagerSet(Component c,
144 RepaintManagerProvider provider) {
145 ensureImpl(RepaintManager.currentManager(c), provider);
146 }
147
148 /**
149 * Ensure that a specific {@link RepaintManager} is set according to the
150 * requirements of the {@link RepaintManagerProvider}.
151 *
152 * @param c
153 * a component from which the current repaint manager can be
154 * obtained.
155 * @param provider
156 * the provider
157 */
158 public static void ensureRepaintManagerSet(JComponent c,
159 RepaintManagerProvider provider) {
160 ensureImpl(RepaintManager.currentManager(c), provider);
161 }
162
163 private static RepaintManager createManager(
164 Class<? extends RepaintManager> clazz, RepaintManager delegate) {
165 try {
166 RepaintManager newManager = (RepaintManager) clazz.getConstructor(
167 RepaintManager.class).newInstance(delegate);
168 System.out.println("Created "+ newManager.getClass().getName());
169 return newManager;
170 } catch (Throwable t) {
171 throw new RuntimeException("Cannot instantiate " + clazz.getName(),
172 t);
173 }
174 }
175
176 /**
177 * The actual implementation of ensure.
178 *
179 * @param delegate
180 * a delegate RepaintManager
181 * @param provider
182 * the provider that provides for the type and implementation of
183 * a delegated RepaintManager
184 */
185 private static void ensureImpl(RepaintManager delegate,
186 RepaintManagerProvider provider) {
187 /*
188 * Setup a traversal variable.
189 */
190 RepaintManager manager = delegate;
191
192 while (!provider.isAdequate(manager.getClass())) {
193 if (swingX) {
194 if (manager instanceof ForwardingRepaintManager) {
195 manager = ((ForwardingRepaintManager) manager)
196 .getDelegateManager();
197 } else {
198 RepaintManager.setCurrentManager(createManager(provider
199 .getForwardingRepaintManagerClass(), delegate));
200 break;
201 }
202 } else {
203 if (manager instanceof WrappedRepaintManager) {
204 manager = ((WrappedRepaintManager) manager)
205 .getDelegateManager();
206 } else {
207 RepaintManager.setCurrentManager(createManager(provider
208 .getWrappedRepaintManagerClass(), delegate));
209 break;
210 }
211 }
212 }
213 }
214
215 /**
216 * Detect the availability of the ForwardingRepaintManager class.
217 *
218 * @return {@code} true if available, {@code false} otherwise
219 */
220 private static boolean isSwingXAvalable() {
221 try {
222 Class<?> clazz = ForwardingRepaintManager.class;
223 System.out.println("SwingX is available");
224 return clazz != null;
225 } catch (Throwable t) {
226 System.out.println("SwingX is not available");
227 return false;
228 }
229 }
230
231 private RepaintManagerUtils() {
232
233 }
234
235 }