src/macosx/classes/sun/lwawt/LWComponentPeer.java

Print this page




  64 
  65 import sun.lwawt.macosx.CDropTarget;
  66 
  67 import com.sun.java.swing.SwingUtilities3;
  68 
  69 public abstract class LWComponentPeer<T extends Component, D extends JComponent>
  70     implements ComponentPeer, DropTargetPeer
  71 {
  72     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");
  73 
  74     // State lock is to be used for modifications to this
  75     // peer's fields (e.g. bounds, background, font, etc.)
  76     // It should be the last lock in the lock chain
  77     private final Object stateLock =
  78             new StringBuilder("LWComponentPeer.stateLock");
  79 
  80     // The lock to operate with the peers hierarchy. AWT tree
  81     // lock is not used as there are many peers related ops
  82     // to be done on the toolkit thread, and we don't want to
  83     // depend on a public lock on this thread
  84     private final static Object peerTreeLock =
  85             new StringBuilder("LWComponentPeer.peerTreeLock");
  86 
  87     /**
  88      * A custom tree-lock used for the hierarchy of the delegate Swing
  89      * components.
  90      * The lock synchronizes access to the delegate
  91      * internal state. Think of it as a 'virtual EDT'.
  92      */
  93 //    private final Object delegateTreeLock =
  94 //        new StringBuilder("LWComponentPeer.delegateTreeLock");
  95 
  96     private T target;
  97 
  98     // Container peer. It may not be the peer of the target's direct
  99     // parent, for example, in the case of hw/lw mixing. However,
 100     // let's skip this scenario for the time being. We also assume
 101     // the container peer is not null, which might also be false if
 102     // addNotify() is called for a component outside of the hierarchy.
 103     // The exception is LWWindowPeers: their parents are always null
 104     private LWContainerPeer containerPeer;
 105 
 106     // Handy reference to the top-level window peer. Window peer is
 107     // borrowed from the containerPeer in constructor, and should also
 108     // be updated when the component is reparented to another container
 109     private LWWindowPeer windowPeer;
 110 
 111     private AtomicBoolean disposed = new AtomicBoolean(false);
 112 
 113     // Bounds are relative to parent peer
 114     private Rectangle bounds = new Rectangle();
 115     private Region region;
 116 
 117     // Component state. Should be accessed under the state lock
 118     private boolean visible = false;
 119     private boolean enabled = true;
 120 
 121     private Color background;
 122     private Color foreground;
 123     private Font font;
 124 
 125     // Paint area to coalesce all the paint events and store
 126     // the target dirty area
 127     private RepaintArea targetPaintArea;


 128 
 129     //   private volatile boolean paintPending;
 130     private volatile boolean isLayouting;
 131 
 132     private D delegate = null;
 133     private Container delegateContainer;
 134     private Component delegateDropTarget;
 135     private final Object dropTargetLock = new Object();
 136 
 137     private int fNumDropTargets = 0;
 138     private CDropTarget fDropTarget = null;
 139 
 140     private PlatformComponent platformComponent;
 141 
 142     private final class DelegateContainer extends Container {
 143         {
 144             enableEvents(0xFFFFFFFF);
 145         }
 146 
 147         DelegateContainer() {
 148             super();
 149         }
 150 
 151         @Override
 152         public boolean isLightweight() {
 153             return false;
 154         }
 155 
 156         @Override
 157         public Point getLocation() {
 158             return getLocationOnScreen();
 159         }
 160 
 161         @Override
 162         public Point getLocationOnScreen() {
 163             return LWComponentPeer.this.getLocationOnScreen();
 164         }
 165 
 166         @Override
 167         public int getX() {
 168             return getLocation().x;
 169         }
 170 
 171         @Override
 172         public int getY() {
 173             return getLocation().y;
 174         }
 175     }
 176 
 177     public LWComponentPeer(T target, PlatformComponent platformComponent) {

 178         this.target = target;
 179         this.platformComponent = platformComponent;
 180 
 181         initializeContainerPeer();
 182         // Container peer is always null for LWWindowPeers, so
 183         // windowPeer is always null for them as well. On the other
 184         // hand, LWWindowPeer shouldn't use windowPeer at all
 185         if (containerPeer != null) {
 186             windowPeer = containerPeer.getWindowPeerOrSelf();
 187         }
 188         // don't bother about z-order here as updateZOrder()
 189         // will be called from addNotify() later anyway
 190         if (containerPeer != null) {
 191             containerPeer.addChildPeer(this);
 192         }
 193 
 194         // the delegate must be created after the target is set
 195         AWTEventListener toolkitListener = null;
 196         synchronized (Toolkit.getDefaultToolkit()) {
 197             try {
 198                 toolkitListener = getToolkitAWTEventListener();
 199                 setToolkitAWTEventListener(null);
 200 
 201                 synchronized (getDelegateLock()) {
 202                     delegate = createDelegate();
 203                     if (delegate != null) {

 204                         delegateContainer = new DelegateContainer();
 205                         delegateContainer.add(delegate);
 206                         delegateContainer.addNotify();
 207                         delegate.addNotify();


 208                     } else {
 209                         return;
 210                     }
 211                 }
 212 
 213             } finally {
 214                 setToolkitAWTEventListener(toolkitListener);
 215             }
 216 
 217             // todo swing: later on we will probably have one global RM
 218             SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
 219                 @Override
 220                 public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
 221                     repaintPeer(SwingUtilities.convertRectangle(
 222                             c, new Rectangle(x, y, w, h), getDelegate()));
 223                 }
 224             });
 225         }
 226     }
 227 


 261     }
 262 
 263     /**
 264      * This method is called under getDelegateLock().
 265      * Overridden in subclasses.
 266      */
 267     protected D createDelegate() {
 268         return null;
 269     }
 270 
 271     protected final D getDelegate() {
 272         synchronized (getStateLock()) {
 273             return delegate;
 274         }
 275     }
 276 
 277     protected Component getDelegateFocusOwner() {
 278         return getDelegate();
 279     }
 280 
 281     /*
 282      * Initializes this peer by fetching all the properties from the target.
 283      * The call to initialize() is not placed to LWComponentPeer ctor to
 284      * let the subclass ctor to finish completely first. Instead, it's the
 285      * LWToolkit object who is responsible for initialization.
 286      */
 287     public void initialize() {
 288         platformComponent.initialize(target, this, getPlatformWindow());
 289         targetPaintArea = new LWRepaintArea();
 290         if (getDelegate() != null) {
 291             synchronized (getDelegateLock()) {
 292                 resetColorsAndFont(delegate);
 293                 getDelegate().setOpaque(true);
 294             }
 295         }






 296         setBackground(target.getBackground());
 297         setForeground(target.getForeground());
 298         setFont(target.getFont());
 299         setBounds(target.getBounds());
 300         setEnabled(target.isEnabled());
 301         setVisible(target.isVisible());
 302     }
 303 
 304     private static void resetColorsAndFont(final Container c) {
 305         c.setBackground(null);
 306         c.setForeground(null);
 307         c.setFont(null);
 308         for (int i = 0; i < c.getComponentCount(); i++) {
 309             resetColorsAndFont((Container) c.getComponent(i));
 310         }
 311     }
 312 
 313     final Object getStateLock() {
 314         return stateLock;
 315     }
 316 
 317     // Synchronize all operations with the Swing delegates under
 318     // AWT tree lock, using a new separate lock to synchronize
 319     // access to delegates may lead deadlocks




 320     final Object getDelegateLock() {
 321         //return delegateTreeLock;
 322         return getTarget().getTreeLock();
 323     }
 324 
 325     protected final static Object getPeerTreeLock() {
 326         return peerTreeLock;
 327     }
 328 
 329     final T getTarget() {
 330         return target;
 331     }
 332 
 333     // Just a helper method
 334     // Returns the window peer or null if this is a window peer
 335     protected final LWWindowPeer getWindowPeer() {
 336         return windowPeer;
 337     }
 338 
 339     // Returns the window peer or 'this' if this is a window peer
 340     protected LWWindowPeer getWindowPeerOrSelf() {
 341         return getWindowPeer();
 342     }
 343 
 344     // Just a helper method
 345     protected final LWContainerPeer getContainerPeer() {


 741 
 742         final D delegate = getDelegate();
 743 
 744         if (delegate != null) {
 745             synchronized (getDelegateLock()) {
 746                 delegate.setEnabled(status);
 747             }
 748         } else {
 749             repaintPeer();
 750         }
 751     }
 752 
 753     // Helper method
 754     public final boolean isEnabled() {
 755         synchronized (getStateLock()) {
 756             return enabled;
 757         }
 758     }
 759 
 760     @Override
 761     public void setVisible(boolean v) {
 762         synchronized (getStateLock()) {
 763             if (visible == v) {
 764                 return;
 765             }
 766             visible = v;
 767         }


 768 

 769         final D delegate = getDelegate();
 770 
 771         if (delegate != null) {
 772             synchronized (getDelegateLock()) {
 773                 delegate.setVisible(v);
 774             }
 775         }
 776         if (visible) {
 777             repaintPeer();
 778         } else {
 779             repaintParent(getBounds());
 780         }
 781     }
 782 
 783     // Helper method
 784     public final boolean isVisible() {
 785         synchronized (getStateLock()) {
 786             return visible;
 787         }
 788     }


1338     public final void repaintPeer() {
1339         repaintPeer(getSize());
1340     }
1341 
1342     public void repaintPeer(final Rectangle r) {
1343         final Rectangle toPaint = getSize().intersection(r);
1344         if (!isShowing() || toPaint.isEmpty()) {
1345             return;
1346         }
1347 
1348         postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
1349     }
1350 
1351     /**
1352      * Determines whether this peer is showing on screen. This means that the
1353      * peer must be visible, and it must be in a container that is visible and
1354      * showing.
1355      *
1356      * @see #isVisible()
1357      */
1358     protected boolean isShowing() {
1359         synchronized (getPeerTreeLock()) {
1360             if (isVisible()) {
1361                 final LWContainerPeer container = getContainerPeer();
1362                 return (container == null) || container.isShowing();
1363             }
1364         }
1365         return false;
1366     }
1367 
1368     /**
1369      * Paints the peer. Overridden in subclasses to delegate the actual painting
1370      * to Swing components.
1371      */
1372     protected final void paintPeer(final Graphics g) {
1373         final D delegate = getDelegate();
1374         if (delegate != null) {
1375             if (!SwingUtilities.isEventDispatchThread()) {
1376                 throw new InternalError("Painting must be done on EDT");
1377             }
1378             synchronized (getDelegateLock()) {




  64 
  65 import sun.lwawt.macosx.CDropTarget;
  66 
  67 import com.sun.java.swing.SwingUtilities3;
  68 
  69 public abstract class LWComponentPeer<T extends Component, D extends JComponent>
  70     implements ComponentPeer, DropTargetPeer
  71 {
  72     private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer");
  73 
  74     // State lock is to be used for modifications to this
  75     // peer's fields (e.g. bounds, background, font, etc.)
  76     // It should be the last lock in the lock chain
  77     private final Object stateLock =
  78             new StringBuilder("LWComponentPeer.stateLock");
  79 
  80     // The lock to operate with the peers hierarchy. AWT tree
  81     // lock is not used as there are many peers related ops
  82     // to be done on the toolkit thread, and we don't want to
  83     // depend on a public lock on this thread
  84     private static final Object peerTreeLock =
  85             new StringBuilder("LWComponentPeer.peerTreeLock");
  86 
  87     private final T target;









  88 
  89     // Container peer. It may not be the peer of the target's direct
  90     // parent, for example, in the case of hw/lw mixing. However,
  91     // let's skip this scenario for the time being. We also assume
  92     // the container peer is not null, which might also be false if
  93     // addNotify() is called for a component outside of the hierarchy.
  94     // The exception is LWWindowPeers: their parents are always null
  95     private LWContainerPeer containerPeer;
  96 
  97     // Handy reference to the top-level window peer. Window peer is
  98     // borrowed from the containerPeer in constructor, and should also
  99     // be updated when the component is reparented to another container
 100     private LWWindowPeer windowPeer;
 101 
 102     private final AtomicBoolean disposed = new AtomicBoolean(false);
 103 
 104     // Bounds are relative to parent peer
 105     private final Rectangle bounds = new Rectangle();
 106     private Region region;
 107 
 108     // Component state. Should be accessed under the state lock
 109     private boolean visible = false;
 110     private boolean enabled = true;
 111 
 112     private Color background;
 113     private Color foreground;
 114     private Font font;
 115 
 116     /**
 117      * Paint area to coalesce all the paint events and store the target dirty
 118      * area.
 119      */
 120     private final RepaintArea targetPaintArea;
 121 
 122     //   private volatile boolean paintPending;
 123     private volatile boolean isLayouting;
 124 
 125     private D delegate = null;
 126     private Container delegateContainer;
 127     private Component delegateDropTarget;
 128     private final Object dropTargetLock = new Object();
 129 
 130     private int fNumDropTargets = 0;
 131     private CDropTarget fDropTarget = null;
 132 
 133     private final PlatformComponent platformComponent;
 134 
 135     private final class DelegateContainer extends Container {
 136         {
 137             enableEvents(0xFFFFFFFF);
 138         }
 139 
 140         DelegateContainer() {
 141             super();
 142         }
 143 
 144         @Override
 145         public boolean isLightweight() {
 146             return false;
 147         }
 148 
 149         @Override
 150         public Point getLocation() {
 151             return getLocationOnScreen();
 152         }
 153 
 154         @Override
 155         public Point getLocationOnScreen() {
 156             return LWComponentPeer.this.getLocationOnScreen();
 157         }
 158 
 159         @Override
 160         public int getX() {
 161             return getLocation().x;
 162         }
 163 
 164         @Override
 165         public int getY() {
 166             return getLocation().y;
 167         }
 168     }
 169 
 170     public LWComponentPeer(T target, PlatformComponent platformComponent) {
 171         targetPaintArea = new LWRepaintArea();
 172         this.target = target;
 173         this.platformComponent = platformComponent;
 174 
 175         initializeContainerPeer();
 176         // Container peer is always null for LWWindowPeers, so
 177         // windowPeer is always null for them as well. On the other
 178         // hand, LWWindowPeer shouldn't use windowPeer at all
 179         if (containerPeer != null) {
 180             windowPeer = containerPeer.getWindowPeerOrSelf();
 181         }
 182         // don't bother about z-order here as updateZOrder()
 183         // will be called from addNotify() later anyway
 184         if (containerPeer != null) {
 185             containerPeer.addChildPeer(this);
 186         }
 187 
 188         // the delegate must be created after the target is set
 189         AWTEventListener toolkitListener = null;
 190         synchronized (Toolkit.getDefaultToolkit()) {
 191             try {
 192                 toolkitListener = getToolkitAWTEventListener();
 193                 setToolkitAWTEventListener(null);
 194 
 195                 synchronized (getDelegateLock()) {
 196                     delegate = createDelegate();
 197                     if (delegate != null) {
 198                         delegate.setVisible(false);
 199                         delegateContainer = new DelegateContainer();
 200                         delegateContainer.add(delegate);
 201                         delegateContainer.addNotify();
 202                         delegate.addNotify();
 203                         resetColorsAndFont(delegate);
 204                         delegate.setOpaque(true);
 205                     } else {
 206                         return;
 207                     }
 208                 }
 209 
 210             } finally {
 211                 setToolkitAWTEventListener(toolkitListener);
 212             }
 213 
 214             // todo swing: later on we will probably have one global RM
 215             SwingUtilities3.setDelegateRepaintManager(delegate, new RepaintManager() {
 216                 @Override
 217                 public void addDirtyRegion(final JComponent c, final int x, final int y, final int w, final int h) {
 218                     repaintPeer(SwingUtilities.convertRectangle(
 219                             c, new Rectangle(x, y, w, h), getDelegate()));
 220                 }
 221             });
 222         }
 223     }
 224 


 258     }
 259 
 260     /**
 261      * This method is called under getDelegateLock().
 262      * Overridden in subclasses.
 263      */
 264     protected D createDelegate() {
 265         return null;
 266     }
 267 
 268     protected final D getDelegate() {
 269         synchronized (getStateLock()) {
 270             return delegate;
 271         }
 272     }
 273 
 274     protected Component getDelegateFocusOwner() {
 275         return getDelegate();
 276     }
 277 
 278     /**
 279      * Initializes this peer. The call to initialize() is not placed to
 280      * LWComponentPeer ctor to let the subclass ctor to finish completely first.
 281      * Instead, it's the LWToolkit object who is responsible for initialization.
 282      * Note that we call setVisible() at the end of initialization.
 283      */
 284     public final void initialize() {
 285         platformComponent.initialize(target, this, getPlatformWindow());
 286         initializeImpl();
 287         setVisible(target.isVisible());




 288     }
 289 
 290     /**
 291      * Fetching general properties from the target. Should be overridden in
 292      * subclasses to initialize specific peers properties.
 293      */
 294     void initializeImpl() {
 295         setBackground(target.getBackground());
 296         setForeground(target.getForeground());
 297         setFont(target.getFont());
 298         setBounds(target.getBounds());
 299         setEnabled(target.isEnabled());

 300     }
 301 
 302     private static void resetColorsAndFont(final Container c) {
 303         c.setBackground(null);
 304         c.setForeground(null);
 305         c.setFont(null);
 306         for (int i = 0; i < c.getComponentCount(); i++) {
 307             resetColorsAndFont((Container) c.getComponent(i));
 308         }
 309     }
 310 
 311     final Object getStateLock() {
 312         return stateLock;
 313     }
 314 
 315     /**
 316      * Synchronize all operations with the Swing delegates under AWT tree lock,
 317      * using a new separate lock to synchronize access to delegates may lead
 318      * deadlocks. Think of it as a 'virtual EDT'.
 319      *
 320      * @return DelegateLock
 321      */
 322     final Object getDelegateLock() {

 323         return getTarget().getTreeLock();
 324     }
 325 
 326     protected static final Object getPeerTreeLock() {
 327         return peerTreeLock;
 328     }
 329 
 330     final T getTarget() {
 331         return target;
 332     }
 333 
 334     // Just a helper method
 335     // Returns the window peer or null if this is a window peer
 336     protected final LWWindowPeer getWindowPeer() {
 337         return windowPeer;
 338     }
 339 
 340     // Returns the window peer or 'this' if this is a window peer
 341     protected LWWindowPeer getWindowPeerOrSelf() {
 342         return getWindowPeer();
 343     }
 344 
 345     // Just a helper method
 346     protected final LWContainerPeer getContainerPeer() {


 742 
 743         final D delegate = getDelegate();
 744 
 745         if (delegate != null) {
 746             synchronized (getDelegateLock()) {
 747                 delegate.setEnabled(status);
 748             }
 749         } else {
 750             repaintPeer();
 751         }
 752     }
 753 
 754     // Helper method
 755     public final boolean isEnabled() {
 756         synchronized (getStateLock()) {
 757             return enabled;
 758         }
 759     }
 760 
 761     @Override
 762     public void setVisible(final boolean v) {
 763         synchronized (getStateLock()) {
 764             if (visible == v) {
 765                 return;
 766             }
 767             visible = v;
 768         }
 769         setVisibleImpl(v);
 770     }
 771 
 772     protected void setVisibleImpl(final boolean v) {
 773         final D delegate = getDelegate();
 774 
 775         if (delegate != null) {
 776             synchronized (getDelegateLock()) {
 777                 delegate.setVisible(v);
 778             }
 779         }
 780         if (visible) {
 781             repaintPeer();
 782         } else {
 783             repaintParent(getBounds());
 784         }
 785     }
 786 
 787     // Helper method
 788     public final boolean isVisible() {
 789         synchronized (getStateLock()) {
 790             return visible;
 791         }
 792     }


1342     public final void repaintPeer() {
1343         repaintPeer(getSize());
1344     }
1345 
1346     public void repaintPeer(final Rectangle r) {
1347         final Rectangle toPaint = getSize().intersection(r);
1348         if (!isShowing() || toPaint.isEmpty()) {
1349             return;
1350         }
1351 
1352         postPaintEvent(toPaint.x, toPaint.y, toPaint.width, toPaint.height);
1353     }
1354 
1355     /**
1356      * Determines whether this peer is showing on screen. This means that the
1357      * peer must be visible, and it must be in a container that is visible and
1358      * showing.
1359      *
1360      * @see #isVisible()
1361      */
1362     protected final boolean isShowing() {
1363         synchronized (getPeerTreeLock()) {
1364             if (isVisible()) {
1365                 final LWContainerPeer container = getContainerPeer();
1366                 return (container == null) || container.isShowing();
1367             }
1368         }
1369         return false;
1370     }
1371 
1372     /**
1373      * Paints the peer. Overridden in subclasses to delegate the actual painting
1374      * to Swing components.
1375      */
1376     protected final void paintPeer(final Graphics g) {
1377         final D delegate = getDelegate();
1378         if (delegate != null) {
1379             if (!SwingUtilities.isEventDispatchThread()) {
1380                 throw new InternalError("Painting must be done on EDT");
1381             }
1382             synchronized (getDelegateLock()) {