|
|||||||||||||||||||
| Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
| AbstractComponentDecorator.java | 50% | 71.1% | 80% | 68.3% |
|
||||||||||||||
| 1 |
package abbot.editor.widgets;
|
|
| 2 |
|
|
| 3 |
import java.awt.*;
|
|
| 4 |
import java.awt.event.*;
|
|
| 5 |
import javax.swing.*;
|
|
| 6 |
import java.lang.ref.*;
|
|
| 7 |
import java.util.*;
|
|
| 8 |
|
|
| 9 |
import abbot.Log;
|
|
| 10 |
|
|
| 11 |
/** Provide a method for consistently painting over a given component.
|
|
| 12 |
This implementation uses an invisible, added componenet in order to insert
|
|
| 13 |
code at the appropriate time in the painting process.
|
|
| 14 |
*/
|
|
| 15 |
// cf CellRendererPane
|
|
| 16 |
public abstract class AbstractComponentDecorator { |
|
| 17 |
private Container component;
|
|
| 18 |
private Renderer renderer;
|
|
| 19 |
private boolean inViewport; |
|
| 20 |
|
|
| 21 |
/** Create a decorator for the given component. */
|
|
| 22 | 5 |
public AbstractComponentDecorator(Container c) {
|
| 23 | 5 |
if (c instanceof JViewport |
| 24 |
&& c.getComponentCount() != 0 |
|
| 25 |
&& c.getComponents()[0] instanceof Container) {
|
|
| 26 | 0 |
c = (Container)c.getComponents()[0]; |
| 27 |
// Viewports only support a single child, so instead add to the
|
|
| 28 |
// child, and use the viewport's graphics to paint any areas
|
|
| 29 |
// outside the child.
|
|
| 30 | 0 |
inViewport = true;
|
| 31 |
} |
|
| 32 | 5 |
else if (c instanceof RootPaneContainer) { |
| 33 | 0 |
c = ((RootPaneContainer)c).getLayeredPane(); |
| 34 |
} |
|
| 35 | 5 |
else if (c instanceof JRootPane) { |
| 36 | 0 |
c = ((JRootPane)c).getLayeredPane(); |
| 37 |
} |
|
| 38 | 5 |
component = c; |
| 39 | 5 |
renderer = new Renderer();
|
| 40 |
// FIXME never add anything to JViewport
|
|
| 41 | 5 |
component.add(renderer); |
| 42 | 5 |
component.repaint(); |
| 43 |
// don't repaint the viewport here, or any custom painting
|
|
| 44 |
// will be wiped out.
|
|
| 45 |
} |
|
| 46 |
|
|
| 47 | 0 |
protected Container getComponent() { return component; } |
| 48 |
|
|
| 49 |
/** Stop decorating. */
|
|
| 50 | 2 |
public void dispose() { |
| 51 | 2 |
Runnable action = new Runnable() {
|
| 52 | 2 |
public void run() { |
| 53 | 2 |
component.remove(renderer); |
| 54 | 2 |
component.repaint(); |
| 55 | 2 |
if (inViewport)
|
| 56 | 0 |
component.getParent().repaint(); |
| 57 | 2 |
synchronized(AbstractComponentDecorator.this) { |
| 58 | 2 |
renderer = null;
|
| 59 | 2 |
component = null;
|
| 60 |
} |
|
| 61 |
} |
|
| 62 |
}; |
|
| 63 | 2 |
if (SwingUtilities.isEventDispatchThread()) {
|
| 64 | 0 |
action.run(); |
| 65 |
} |
|
| 66 |
else {
|
|
| 67 | 2 |
SwingUtilities.invokeLater(action); |
| 68 |
} |
|
| 69 |
} |
|
| 70 |
|
|
| 71 |
public abstract void paint(Graphics g); |
|
| 72 |
|
|
| 73 |
private class Renderer extends JComponent { |
|
| 74 | 5 |
public Renderer() {
|
| 75 | 5 |
setOpaque(false);
|
| 76 |
} |
|
| 77 | 5 |
public void invalidate() { } |
| 78 | 9 |
public boolean isVisible() { return true; } |
| 79 | 0 |
public boolean isShowing() { return true; } |
| 80 | 6 |
public Rectangle getBounds(Rectangle b) {
|
| 81 |
// Pretend to have the same bounds as the component
|
|
| 82 | 6 |
b = component.getBounds(b); |
| 83 | 6 |
b.x = 0; |
| 84 | 6 |
b.y = 0; |
| 85 | 6 |
Log.debug("bounds: " + b);
|
| 86 | 6 |
return b;
|
| 87 |
} |
|
| 88 |
// must use the paint method; paintComponent will not work here
|
|
| 89 | 6 |
public void paint(Graphics g) { |
| 90 | 6 |
synchronized(AbstractComponentDecorator.this) { |
| 91 | 6 |
if (inViewport) {
|
| 92 | 0 |
Log.debug("painting viewport");
|
| 93 | 0 |
Graphics g2 = component.getParent().getGraphics(); |
| 94 | 0 |
AbstractComponentDecorator.this.paint(g2);
|
| 95 |
} |
|
| 96 | 6 |
Log.debug("painting component");
|
| 97 | 6 |
AbstractComponentDecorator.this.paint(g);
|
| 98 |
} |
|
| 99 |
// NOTE: see paintComponent from CellRendererPane
|
|
| 100 |
// setBounds(-width,-height,0,0) to avoid getting any input
|
|
| 101 |
} |
|
| 102 |
} |
|
| 103 |
} |
|
| 104 |
|
|
||||||||||