Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [albireo-dev] size/layout management

Hi Gordon,

> > Still, I haven't understood the handleSetBounds and setAWTSize methods.
> 
> These mainly just pass on a newly set size to the embedded component.

What I meant, was why handleSetBounds was written in a timing-dependent
way: If the AWT thread succeeded to create and layout the Swing component
quickly, before computeSize was called, handleSetBounds would propagate
the size to the AWT side. If, however, the SWT thread was quicker than the
AWT thread, the size would be thrown away.

> > Also, is the 'computeSizeDefault' variable really needed? Why not use
> > '!cachedSizesInitialized' instead? Or equivalently, why is the initial
> > value of 'computeSizeDefault' false?
> 
> Sorry about that. It was an unnecessary hack to remember the state of 
> the cache when computeSize() was actually called. There is a small 
> chance for this sequence of events:
> 
> 1) computeSize() called
> 2) AWT cache initialized from AWT thread
> 3) setBounds() called
> 
> In this rare case, if we rely on the cachedSizesInitialized field, 
> setBounds() could pass on a bad (zero) size to AWT. But, after thinking 
> about it more, this is a very unlikely case, and the only harm is a 
> little extra flicker as far as I know. So I'm removing the field, and 
> using cachedSizesInitialzed instead.

Nevertheless, it is possible to avoid the flickering in this condition.
I'm applying this patch, which - I believe - also fixes the problem
mentioned above.

Bruno


Index: src/org/eclipse/albireo/core/SwingControl.java
===================================================================
RCS file: /cvsroot/technology/org.eclipse.albireo/org.eclipse.albireo.core/src/org/eclipse/albireo/core/SwingControl.java,v
retrieving revision 1.21
diff -c -3 -r1.21 SwingControl.java
*** src/org/eclipse/albireo/core/SwingControl.java	8 Feb 2008 20:55:20 -0000	1.21
--- src/org/eclipse/albireo/core/SwingControl.java	8 Feb 2008 22:05:09 -0000
***************
*** 343,350 ****
      private Dimension cachedMaxSize = new Dimension(0,0);
      // Since the swingComponent is not already initialized in the constructor,   
      // this control initially has no notion of what its preferred size could
!     // be.
!     private boolean cachedSizesInitialized = false;
  
      // We have bidirectional size propagation, from AWT to SWT, and from
      // SWT to AWT. To avoid endless recursion in weird cases (for example,
--- 343,353 ----
      private Dimension cachedMaxSize = new Dimension(0,0);
      // Since the swingComponent is not already initialized in the constructor,   
      // this control initially has no notion of what its preferred size could
!     // be. This variable is
!     // - 0 initially,
!     // - 1 after the sizes have been set from the AWT side,
!     // - 2 after these sizes have been taken into account by the SWT side.
!     private int cachedSizesInitialized = 0;
  
      // We have bidirectional size propagation, from AWT to SWT, and from
      // SWT to AWT. To avoid endless recursion in weird cases (for example,
***************
*** 364,376 ****
          boolean mustNotify;
  
          synchronized (this) {
!             mustNotify = !cachedSizesInitialized;
              if (!mustNotify) {
                  mustNotify = !(min.equals(cachedMinSize)
                                 && pref.equals(cachedPrefSize)
                                 && max.equals(cachedMaxSize));
              }
!             cachedSizesInitialized = true;
              cachedMinSize = min;
              cachedPrefSize = pref;
              cachedMaxSize = max;
--- 367,380 ----
          boolean mustNotify;
  
          synchronized (this) {
!             mustNotify = (cachedSizesInitialized == 0);
              if (!mustNotify) {
                  mustNotify = !(min.equals(cachedMinSize)
                                 && pref.equals(cachedPrefSize)
                                 && max.equals(cachedMaxSize));
              }
!             if (cachedSizesInitialized == 0)
!               cachedSizesInitialized = 1;
              cachedMinSize = min;
              cachedPrefSize = pref;
              cachedMaxSize = max;
***************
*** 382,388 ****
              // sizes can be taken into account.
              ThreadingHandler.getInstance().asyncExec(display, new Runnable() {
                  public void run() {
!                     // System.out.println("Laying out after first size update");
                      if (!isDisposed()) {
                          try {
                              inhibitSizePropagationToAWT = true;
--- 386,392 ----
              // sizes can be taken into account.
              ThreadingHandler.getInstance().asyncExec(display, new Runnable() {
                  public void run() {
!                     // System.out.println("Laying out after size update");
                      if (!isDisposed()) {
                          try {
                              inhibitSizePropagationToAWT = true;
***************
*** 407,413 ****
       */
      protected boolean getCachedAWTSizes(Dimension min, Dimension pref, Dimension max) {
          synchronized(this) {
!             if (cachedSizesInitialized) {
                  min.setSize(cachedMinSize);
                  pref.setSize(cachedPrefSize);
                  max.setSize(cachedMaxSize);
--- 411,417 ----
       */
      protected boolean getCachedAWTSizes(Dimension min, Dimension pref, Dimension max) {
          synchronized(this) {
!             if (cachedSizesInitialized >= 1) {
                  min.setSize(cachedMinSize);
                  pref.setSize(cachedPrefSize);
                  max.setSize(cachedMaxSize);
***************
*** 419,424 ****
--- 423,429 ----
      }
  
      protected void setAWTSize(final int width, final int height) {
+         assert Display.getCurrent() != null;     // On SWT event thread
          // System.out.println("Setting size from SWT: " + width + " x " + height + " for " + swingComponent);
          EventQueue.invokeLater(
              new Runnable() {
***************
*** 437,451 ****
      protected void handleSetBounds(int width, int height) {
          assert Display.getCurrent() != null;     // On SWT event thread
          checkPopulated();
!         // pass on the desired size to the embedded component, but only if it could 
!         // be reasonably calculated (i.e. we have cached preferred sizes).
          synchronized (this) {
!             // Note: in rare cases it is possible that the cachedSizesInitialized flag may have changed 
!             // since computeSize was called. If so, we'll be passing a bad size to the embedded
!             // component. This is not a big problem because the component will be resized again 
!             // very quickly (with, possibly, some flicker). 
!             if (cachedSizesInitialized && !inhibitSizePropagationToAWT) {
!                 setAWTSize(width, height);
              }
          }
      }
--- 442,463 ----
      protected void handleSetBounds(int width, int height) {
          assert Display.getCurrent() != null;     // On SWT event thread
          checkPopulated();
!         // Pass on the desired size to the embedded component, but only if it could 
!         // be reasonably calculated (i.e. we have cached preferred sizes) and if
!         // computeSize took it into account.
!         // If, however, the SWT side specifies a size for the component while
!         // cachedSizesInitialized < 2 (i.e. usually, before the Swing component
!         // is created), it is tempting to store the size given here and use it
!         // when the Swing component is created later. But this leads to
!         // flickering: If the size could not been reasonably calculated or if
!         // computeSize did not take it into account, the values are always
!         // derived from the default size 64x64 of SWT Composites. Ignore these
!         // values then! It is better than to use them.
          synchronized (this) {
!             if (cachedSizesInitialized >= 2) {
!                 if (!inhibitSizePropagationToAWT) {
!                     setAWTSize(width, height);
!                 }
              }
          }
      }
***************
*** 464,473 ****
          Dimension max = new Dimension();
          boolean initialized = getCachedAWTSizes(min, pref, max);
  
!         if ((!initialized)) {
              // System.out.println("Uninitialized AWT sizes for " + swingComponent);
              return super.computeSize(widthHint, heightHint, changed);
          } else {
              int width =
                  (widthHint == SWT.DEFAULT ? pref.width :
                   widthHint < min.width ? min.width :
--- 476,489 ----
          Dimension max = new Dimension();
          boolean initialized = getCachedAWTSizes(min, pref, max);
  
!         if (!initialized) {
              // System.out.println("Uninitialized AWT sizes for " + swingComponent);
              return super.computeSize(widthHint, heightHint, changed);
          } else {
+             assert cachedSizesInitialized >= 1;
+             synchronized (this) {
+                 cachedSizesInitialized = 2;
+             }
              int width =
                  (widthHint == SWT.DEFAULT ? pref.width :
                   widthHint < min.width ? min.width :


Back to the top