[can be deleted] Component.invalidate() typo?

I know this is a tad offtopic for JGO, so I posted it in this section.

When trying to debug my AWT / layoutmanager code, I stumbled into this sourcecode of java.awt.Component:

    public void invalidate() {
        synchronized (getTreeLock()) {
            /* Nullify cached layout and size information.
             * For efficiency, propagate invalidate() upwards only if
             * some other component hasn't already done so first.
             */
            valid = false;
            if (!isPreferredSizeSet()) {
                prefSize = null;
            }
            if (!isMinimumSizeSet()) {
                minSize = null;
            }
            if (!isMaximumSizeSet()) {
                maxSize = null;
            }
            if (parent != null && parent.valid) {
                parent.invalidate();
            }
        }
    }

What this does:

            if (!isPreferredSizeSet()) {
                prefSize = null;
            }

is basicly:

if(prefSize==null) prefSize = null;

Obviously it should have been: if (isPreferredSizeSet()) (without the “!”)

because of this the invalidate() method is not working properly, as it does NOT reset the cached values for prefSize/minSize/maxSize.

Did I miss something, or did I find a bug… (created in Java 1.5, as isPreferedSizeSet() is a 1.5 method)

My workaround:


      Component c = ...;
      Component cOrg = c;

      // reset cached sizes
      do
      {
         c.setPreferredSize(null);
         c.setMinimumSize(null);
         c.setMaximumSize(null);
      }
      while ((c = c.getParent()) != null);

      cOrg.invalidate(); // travels component hierarchy

Well,
preferredSize management has 3 states :

  • not set : return the peer’s computed preferred size (based on layout)
  • set : return always this value
  • set to null : revert to “not set”

the prefSize field is cached from getPreferredSize(), wether this is the “set” or “not set” value, so as soon as getPreferredSize() is called, prefSize contains something not null.

invalidate() just flushes the cached value to let it be recomputed at the next getPreferredSize()

So there’s no bug here…

Lilian :slight_smile:

Please read more carefully (look who’s talking :-[), it does NOT flush the cache, as it only flushes the cache when it’s already null:


if (!isPreferredSizeSet()) {
   // equals to: !(prefSize != null)
   // equals to: prefSize == null
                prefSize = null; // only gets here if prefSize is already null
            }

It should have been:


if (isPreferredSizeSet()) {
   // equals to: (prefSize != null)
   // equals to: prefSize != null
                prefSize = null; // only gets here if prefSize is not null
            }

no,

the cache can hold two values :

  1. a size coming from setPreferredSize()
  2. a computed size from the peer (this one needs to be cached to avoid recomputing each time)

case 1 must not be flushed as it’s what the developer wants, so “if isPreferredSizeSet() don’t flush the cache”

case 2 must be flushed, because we’re invalidating the component.

merge the two and you’ll have “if setPreferredSize(s) hasn’t been called by the user, flush the prefSize cache”
or “if !isPreferredSizeSet() prefSize - null” if you prefer it more java-like

Lilian

Hm…

I guess then my LayoutManager violates from contract by manipulating pref/min/max.

Thanks for your explaination, and I’ll change my LayoutManager accordingly.