/**
  * Builds the set of FocusKey objects for all focusable components on the form. A FocusKey allows
  * us to store a reference to a focusable component and later find that component when a form has
  * been de-serialized. We don't use the component name to reference the component because we don't
  * want to keep track of when the user changes the name.
  */
 public void buildFocusKeys(
     HashSet currentFocusSet,
     HashMap focus_key_map,
     FormComponent form,
     CompositeFocusKey compositeKey) {
   for (int row = 1; row <= form.getRowCount(); row++) {
     for (int col = 1; col <= form.getColumnCount(); col++) {
       GridComponent gc = form.getGridComponent(col, row);
       if (gc instanceof StandardComponent) {
         Component comp = gc.getBeanDelegate();
         if (comp != null) {
           if (currentFocusSet.contains(comp)) {
             CompositeFocusKey ckey = (CompositeFocusKey) compositeKey.clone();
             ckey.add(new FormCellFocusKey(row, col, comp));
             focus_key_map.put(comp, ckey);
           } else {
             /**
              * This comp must be a container that contains components that are in the focus policy
              * This can happen for Java Beans that are also panels which contain other components.
              */
             if (comp instanceof Container) {
               CompositeFocusKey ckey = (CompositeFocusKey) compositeKey.clone();
               ckey.add(new FormCellFocusKey(row, col, comp));
               buildContainerFocusKeys(currentFocusSet, focus_key_map, (Container) comp, ckey);
             } else {
               // ignore because this could be a component like
               // a JLabel which does not need focus
             }
           }
         }
       } else if (gc instanceof FormComponent) {
         FormComponent childform = (FormComponent) gc;
         CompositeFocusKey ckey = (CompositeFocusKey) compositeKey.clone();
         ckey.add(new FormCellFocusKey(row, col, gc));
         buildFocusKeys(currentFocusSet, focus_key_map, childform, ckey);
       } else {
         if (gc != null) {
           System.out.println(
               "FormFocusManager.buildDefaultPolicyFailed  found unknown comp: " + gc.getClass());
         }
       }
     }
   }
 }
  /**
   * Builds a list of components (Component) for a form that are ordered in the default focus order.
   */
  public static LinkedHashSet buildDefaultFocusPolicy(FormComponent fc) {
    System.out.println("buildDefaultFocusPolicy  form: " + fc.getId());

    final FormComponent theform = fc;
    LinkedHashSet default_policy = new LinkedHashSet();
    LayoutFocusTraversalPolicy policy =
        new LayoutFocusTraversalPolicy() {
          protected boolean accept(Component aComponent) {
            if (aComponent instanceof StandardComponent) {
              if (((StandardComponent) aComponent).getBeanDelegate() == null) return false;
            }

            if (aComponent == theform) return super.accept(aComponent);

            if (aComponent instanceof FormComponent) {
              if (((FormComponent) aComponent).isTopLevelForm()) return false;
            }

            if (aComponent instanceof JTabbedPane) return true;

            if (aComponent != null) {
              /** handle the case for embedded focus cycle roots such as JTabbedPane forms */
              Container cc = aComponent.getParent();
              while (cc != null && cc != theform) {
                if (cc instanceof FormContainerComponent) {
                  return false;
                }

                cc = cc.getParent();
              }
            }
            return super.accept(aComponent);
          }
        };
    Component comp = policy.getFirstComponent(fc);
    Component last_comp = policy.getLastComponent(fc);
    while (true) {

      /** Don't add scroll pane in design mode since the scroll bars might not be visible */
      if (FormUtils.isDesignMode()) {
        if (!(comp instanceof JScrollPane) && !(comp instanceof JScrollBar)) {
          default_policy.add(comp);
        }
      } else {
        default_policy.add(comp);
      }

      if (comp == last_comp) break;

      System.out.println("FormFocusManager.getComponentAfter: " + comp.getClass());
      comp = policy.getComponentAfter(fc, comp);
    }

    return default_policy;
  }
  /** @return the parent form of the given child form. */
  public FormComponent getParentForm(FormComponent comp) {
    Component parent = comp.getParent();
    while (parent != null) {
      if (parent instanceof FormComponent) return (FormComponent) parent;
      else if (parent instanceof FormEditor) return null;
      else if (parent instanceof javax.swing.JFrame) return null;

      parent = parent.getParent();
    }
    return null;
  }
 /**
  * Builds an list of components that are ordered in the focus order previously set by a user for a
  * given form. The form may have changed (components might have been deleted or moved), so we need
  * to delete those components from the focus order that don't match the current state of the form.
  */
 ArrayList buildStoredFocusList(FormComponent form) {
   ArrayList focus_list = new ArrayList();
   FocusPolicyMemento memento = form.getFocusPolicy();
   if (memento != null) {
     Collection fkeys = memento.getFocusPolicyKeys();
     Iterator iter = fkeys.iterator();
     while (iter.hasNext()) {
       FocusKey fkey = (FocusKey) iter.next();
       Component comp = fkey.getComponent(form);
       if (comp != null) {
         focus_list.add(comp);
       }
     }
   }
   return focus_list;
 }
  /** ctor */
  public FormFocusManager(FormComponent fc) {
    /** now set the focusCycleRoot to false for any child forms. */
    disableChildFocusCycleRoots(fc);
    fc.setFocusCycleRoot(true);

    m_form = fc;

    /**
     * First get all valid components from the stored focus policy. This list was created when the
     * developer set the focus policy in the designer and stored the result.
     */
    ArrayList stored_focus_set = buildStoredFocusList(fc);

    /** Now get the default focus policy which is assigned by Swing. */
    LinkedHashSet default_focus_set = buildDefaultFocusPolicy(fc);

    /**
     * Now we want to reconcile what has been stored versus the default policy because the form may
     * have changed since the last time the focus policy was saved.
     */

    /**
     * now remove any elements from the stored policy that are not found in the default focus policy
     */
    Iterator iter = stored_focus_set.iterator();
    while (iter.hasNext()) {
      Component comp = (Component) iter.next();
      if (!default_focus_set.contains(comp)) {
        iter.remove();
      }
    }

    /** used for quick lookups */
    HashSet stored_lookup = new HashSet();
    stored_lookup.addAll(stored_focus_set);

    /**
     * now iterate over the default focus policy. Any components not found in the stored focus
     * policy are added at the default position
     */
    Component prev_comp = null;
    iter = default_focus_set.iterator();
    while (iter.hasNext()) {
      Component comp = (Component) iter.next();
      if (!stored_lookup.contains(comp)) {
        stored_lookup.add(comp);
        if (prev_comp == null) {
          stored_focus_set.add(0, comp);
        } else {
          int pos = stored_focus_set.indexOf(prev_comp);
          assert (pos >= 0);
          if (pos >= 0) {
            stored_focus_set.add(pos + 1, comp);
          }
        }
      }
      prev_comp = comp;
    }

    /** now the stored_focus_set has the correct focus order */
    m_focus_list = stored_focus_set;
  }