How to implement GWT editors for subclasses of a type?

后端 未结 2 1441
不思量自难忘°
不思量自难忘° 2020-12-11 10:21

Let\'s say I have an object hierarchy like this:

Account > Site > Supply

An Account is an actual company, a Site is a building they have, an

相关标签:
2条回答
  • 2020-12-11 10:55

    I've already been in this case, and I've implemented the following solution :

    • First create an generic utilitary class named AbstractSubTypeEditor which will activate a specific editor when you edit one of your subclass object :

      import com.google.gwt.editor.client.CompositeEditor;
      import com.google.gwt.editor.client.Editor;
      import com.google.gwt.editor.client.EditorDelegate;
      import com.google.gwt.editor.client.LeafValueEditor;
      
      public abstract class AbstractSubTypeEditor<T, C extends T, E extends Editor<C>> implements CompositeEditor<T, C, E>, LeafValueEditor<T> {
              private EditorChain<C, E> chain;
              private T currentValue;
              private final E subEditor;
      
              /**
               * Construct an AbstractSubTypeEditor backed by the given sub-Editor.
               *
               * @param subEditor the sub-Editor that will be attached to the Editor
               *          hierarchy
               */
              public AbstractSubTypeEditor(E subEditor) {
                      this.subEditor = subEditor;
              }
      
              /**
               * Returns the sub-Editor that the OptionalFieldEditor was constructed
               * with.
               *
               * @return an {@link Editor} of type E
               */
              public E createEditorForTraversal() {
                      return subEditor;
              }
      
              public void flush() {
                      currentValue = chain.getValue(subEditor);
              }
      
              /**
               * Returns an empty string because there is only ever one sub-editor used.
               */
              public String getPathElement(E subEditor) {
                      return "";
              }
      
              public T getValue() {
                      return currentValue;
              }
      
              public void onPropertyChange(String... paths) {
              }
      
              public void setDelegate(EditorDelegate<T> delegate) {
              }
      
              public void setEditorChain(EditorChain<C, E> chain) {
                      this.chain = chain;
              }
      
              public void setValue(T value, boolean instanceOf) {
                      if (currentValue != null && value == null) {
                              chain.detach(subEditor);
                      }
                      currentValue = value;
                      if (value != null && instanceOf) {
                              chain.attach((C)value, subEditor);
                      }
              }
      }
      
    • Now you can create an Editor for Supply, containing two sub-editors and two AbstractSubTypeEditor (one for each of your subtypes) :

      public class SupplyEditor extends Composite implements Editor<Supply> {
      
              public class ElecSupplyEditor implements Editor<ElecSupply> {
                      public final TextBox profile = new TextBox();
                      public final TextBox mtc = new TextBox();
                      public final TextBox llf = new TextBox();
                      public final TextBox area = new TextBox();
                      public final TextBox core = new TextBox();
              }
              @Ignore
              final ElecSupplyEditor elecSupplyEditor = new ElecSupplyEditor();
              @Path("")
              final AbstractSubTypeEditor<Supply, ElecSupply, ElecSupplyEditor> elecSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, ElecSupply, SupplyEditor.ElecSupplyEditor>(elecSupplyEditor) {
                      @Override
                      public void setValue(final Supply value) {
                              setValue(value, value instanceof ElecSupply);
                              if (!(value instanceof ElecSupply)) {
                                      elecSupplyEditor.profile.setVisible(false);
                                      elecSupplyEditor.mtc.setVisible(false);
                                      elecSupplyEditor.llf.setVisible(false);
                                      elecSupplyEditor.area.setVisible(false);
                                      elecSupplyEditor.core.setVisible(false);
                              } else {
                                      elecSupplyEditor.profile.setVisible(true);
                                      elecSupplyEditor.mtc.setVisible(true);
                                      elecSupplyEditor.llf.setVisible(true);
                                      elecSupplyEditor.area.setVisible(true);
                                      elecSupplyEditor.core.setVisible(true);
                              }
                      }
              };
      
              public class GasSupplyEditor implements Editor<GasSupply> {
                      public final TextBox mpr = new TextBox();
              }
              @Ignore
              final GasSupplyEditor gasSupplyEditor = new GasSupplyEditor();
              @Path("")
              final AbstractSubTypeEditor<Supply, GasSupply, GasSupplyEditor> gasSupplyEditorWrapper = new AbstractSubTypeEditor<Supply, GasSupply, SupplyEditor.GasSupplyEditor>(gasSupplyEditor) {
                      @Override
                      public void setValue(final Supply value) {
                              setValue(value, value instanceof GasSupply);
                              if (!(value instanceof GasSupply)) {
                                      gasSupplyEditor.mpr.setVisible(false);
                              } else {
                                      gasSupplyEditor.mpr.setVisible(true);
                              }
                      }
              };
      
              public SupplyEditor () {
                      final VerticalPanel page = new VerticalPanel();
                      page.add(elecSupplyEditor.profile);
                      page.add(elecSupplyEditor.mtc);
                      page.add(elecSupplyEditor.llf);
                      page.add(elecSupplyEditor.area);
                      page.add(elecSupplyEditor.code);
                      page.add(gasSupplyEditor.mpr);
                      initWidget(page);
              }
      }
      

    This should show/hide your fields according to the subclass you are editing, and bind the properties to the good fields.

    0 讨论(0)
  • 2020-12-11 11:01

    You can have your SupplyEditor implement ValueAwareEditor<Supply>.

    This way, the editor framework will pass you the actual value being edited in the setValue(Supply supply); In the implementation of setValue(Supply supply) you can inspect the type of Supply and choose to show/hide any additional relevant fields.

    0 讨论(0)
提交回复
热议问题