/**
  * The value of the given child entry has changed. Therefore we must set this change into our
  * value objects.
  *
  * <p>We must inform our parent so that it can update its value objects
  *
  * <p>Subclasses may override to set the property value in some custom way.
  *
  * @param the child entry that changed its value
  */
 protected void valueChanged(PropertySheetEntry child) {
   for (int i = 0; i < values.length; i++) {
     IPropertySource source = getPropertySource(values[i]);
     source.setPropertyValue(child.getDescriptor().getId(), child.getEditValue(i));
   } // inform our parent
   if (parent != null) parent.valueChanged(this);
 }
 /**
  * Update our value objects. We ask our parent for the property values based on our descriptor.
  */
 private void refreshValues() {
   // get our parent's value objects
   Object[] sources = parent.getValues();
   // loop through the objects getting our property value from each
   Object[] newValues = new Object[sources.length];
   for (int i = 0; i < sources.length; i++) {
     IPropertySource source = parent.getPropertySource(sources[i]);
     newValues[i] = source.getPropertyValue(descriptor.getId());
   } // set our new values
   setValues(newValues);
 } /* (non-Javadoc)
 /** Create our child entries. */
 private void createChildEntries() {
   // get the current descriptors
   List descriptors = computeMergedPropertyDescriptors();
   // rebuild child entries using old when possible
   childEntries = new PropertySheetEntry[descriptors.size()];
   for (int i = 0; i < descriptors.size(); i++) {
     IPropertyDescriptor d = (IPropertyDescriptor) descriptors.get(i);
     // create new entry
     PropertySheetEntry entry = new PropertySheetEntry();
     entry.setDescriptor(d);
     entry.setParent(this);
     entry.setPropertySourceProvider(propertySourceProvider);
     entry.refreshValues();
     childEntries[i] = entry;
   }
 } /* (non-Javadoc)
 /**
  * Set the value for this entry.
  *
  * <p>We set the given value as the value for all our value objects. We then call our parent to
  * update the property we represent with the given value. We then trigger a model refresh.
  *
  * <p>
  *
  * @param newValue the new value
  */
 private void setValue(Object newValue) { // Set the value
   for (int i = 0; i < values.length; i++) {
     values[i] = newValue;
   } // Inform our parent
   parent.valueChanged(this);
   // Refresh the model
   refreshFromRoot();
 }
 public void resetPropertyValue() {
   if (parent == null) // root does not have a default value
   return;
   //	Use our parent's values to reset our values.
   boolean change = false;
   Object[] objects = parent.getValues();
   for (int i = 0; i < objects.length; i++) {
     IPropertySource source = getPropertySource(objects[i]);
     if (source.isPropertySet(descriptor.getId())) {
       source.resetPropertyValue(descriptor.getId());
       change = true;
     }
   }
   if (change) refreshValues();
 }
  /**
   * Update our child entries. This implementation tries to reuse child entries if possible (if the
   * id of the new descriptor matches the descriptor id of the old entry).
   */
  private void refreshChildEntries() {
    if (childEntries == null) // no children to refresh
    return;
    // get the current descriptors
    List descriptors = computeMergedPropertyDescriptors();
    // cache old entries by their descriptor id
    Map entryCache = new HashMap(childEntries.length * 2 + 1);
    for (int i = 0; i < childEntries.length; i++) {
      entryCache.put(childEntries[i].getDescriptor().getId(), childEntries[i]);
    } // create a list of entries to dispose
    List entriesToDispose = new ArrayList(Arrays.asList(childEntries));
    // rebuild child entries using old when possible
    childEntries = new PropertySheetEntry[descriptors.size()];
    boolean entriesChanged = descriptors.size() != entryCache.size();
    for (int i = 0; i < descriptors.size(); i++) {
      IPropertyDescriptor d = (IPropertyDescriptor) descriptors.get(i);
      // see if we have an entry matching this descriptor
      PropertySheetEntry entry = (PropertySheetEntry) entryCache.get(d.getId());
      if (entry != null) { // reuse old entry
        entry.setDescriptor(d);
        entriesToDispose.remove(entry);
      } else { // create new entry
        entry = new PropertySheetEntry();
        entry.setDescriptor(d);
        entry.setParent(this);
        entry.setPropertySourceProvider(propertySourceProvider);
        entriesChanged = true;
      }
      entry.refreshValues();
      childEntries[i] = entry;
    }

    if (entriesChanged) fireChildEntriesChanged();
    // Dispose of entries which are no longer needed
    for (int i = 0; i < entriesToDispose.size(); i++) {
      ((IPropertySheetEntry) entriesToDispose.get(i)).dispose();
    }
  }
 /** Refresh the entry tree from the root down */
 private void refreshFromRoot() {
   if (parent == null) refreshChildEntries();
   else parent.refreshFromRoot();
 }