我有一个值类型Commission
,它是更大的编辑器图表的一部分:
public class Commission implements Serializable
{
private CommissionType commissionType; // enum
private Money value; // custom type, backed by BigDecimal
private Integer multiplier;
private Integer contractMonths;
// ...
}
我想要实现的是最初只显示commissionType
枚举的下拉列表,然后选择适当的子编辑器来根据所选值编辑其余字段:
我之前使用 an实现了多个子类型编辑器(请参阅此处的问题AbstractSubTypeEditor
),但这种情况略有不同,因为我没有编辑子类,它们都编辑相同的基本Commission
类型,并且由于某种原因,相同的方法似乎不适用于多个编辑器编辑相同的具体类型。
我目前有两个子编辑器(实现Editor<Commission>
和IsWidget
通过自定义界面IsCommissionEditorWidget
),但它们本身有不同的子编辑器,因为Money
可以是便士或英镑,乘数可以代表天或月,以及其他变化。
委员会编辑
我已经查看了这个问题中的类似问题,并尝试创建一个CompositeEditor<Commission, Commission, Editor<Commission>>
.
这就是我到目前为止所得到的(注意注释掉的部分是通过实现和LeafValueEditor<Commission>
手动调用setValue()
and getValue()
onamount
和来获得我想要的功能的黑客方式):multiplier
contractMonths
public class CommissionEditor extends Composite implements CompositeEditor<Commission, Commission, Editor<Commission>>, //LeafValueEditor<Commission>
{
interface Binder extends UiBinder<HTMLPanel, CommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
CommissionTypeEditor commissionType;
@UiField
Panel subEditorPanel;
private EditorChain<Commission, Editor<Commission>> chain;
private IsCommissionEditorWidget subEditor = null;
private Commission value = new Commission();
public CommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
commissionType.box.addValueChangeHandler(event -> setValue(new Commission(event.getValue())));
}
@Override
public void setValue(Commission value)
{
Log.warn("CommissionEditor -> setValue(): value is " + value);
chain.detach(subEditor);
commissionType.setValue(value.getCommissionType());
if(value.getCommissionType() != null)
{
switch(value.getCommissionType())
{
case UNIT_RATE:
Log.info("UNIT_RATE");
subEditor = new UnitRateCommissionEditor();
break;
case STANDING_CHARGE:
Log.info("STANDING_CHARGE");
subEditor = new StandingChargeCommissionEditor();
break;
case PER_MWH:
Log.info("PER_MWH");
// TODO
break;
case SINGLE_PAYMENT:
Log.info("SINGLE_PAYMENT");
// TODO
break;
}
this.value = value;
subEditorPanel.clear();
// subEditor.setValue(value);
subEditorPanel.add(subEditor);
chain.attach(value, subEditor);
}
}
// @Override
// public Commission getValue()
// {
// if(subEditor != null)
// {
// return subEditor.getValue();
// }
// else
// {
// return value;
// }
// }
@Override
public void flush()
{
this.value = chain.getValue(subEditor);
}
@Override
public void setEditorChain(EditorChain<Commission, Editor<Commission>> chain)
{
this.chain = chain;
}
@Override
public Editor<Commission> createEditorForTraversal()
{
return subEditor;
}
@Override
public String getPathElement(Editor<Commission> commissionEditor)
{
return "";
}
@Override
public void onPropertyChange(String... strings)
{
}
@Override
public void setDelegate(EditorDelegate<Commission> editorDelegate)
{
}
}
这是IsCommissionEditorWidget
定义每个子编辑器的合同的界面,也可以添加到面板中:
public interface IsCommissionEditorWidget extends Editor<Commission>, IsWidget
{
}
UnitRateCommissionEditor
当用户选择CommissionType.UNIT_RATE
时,我想将其添加到编辑器链中以应用于剩余的 3 个字段:
public class UnitRateCommissionEditor extends Composite implements IsCommissionEditorWidget
{
interface Binder extends UiBinder<Widget, UnitRateCommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
MoneyPenceBox amount;
@UiField
IntegerBox multiplier;
@UiField
IntegerBox contractMonths;
public UnitRateCommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
// @Override
// public void setValue(Commission commission)
// {
// amount.setValue(commission.getAmount());
// multiplier.setValue(commission.getMultiplier());
// contractMonths.setValue(commission.getContractMonths());
// }
//
// @Override
// public Commission getValue()
// {
// return new Commission(CommissionType.UNIT_RATE, amount.getValue(), multiplier.getValue(), contractMonths.getValue());
// }
}
常设收费委员会编辑
什么时候CommissionType.STANDING_CHARGE
选择我想要这个(UiBinders 也有点不同,但主要区别是MoneyPoundsBox
不是MoneyPenceBox
):
public class StandingChargeCommissionEditor extends Composite implements IsCommissionEditorWidget
{
interface Binder extends UiBinder<Widget, StandingChargeCommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
MoneyPoundsBox amount;
@UiField
IntegerBox multiplier;
@UiField
IntegerBox contractMonths;
public StandingChargeCommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
// @Override
// public void setValue(Commission commission)
// {
// amount.setValue(commission.getAmount());
// multiplier.setValue(commission.getMultiplier());
// contractMonths.setValue(commission.getContractMonths());
// }
//
// @Override
// public Commission getValue()
// {
// return new Commission(CommissionType.STANDING_CHARGE, amount.getValue(), multiplier.getValue(), contractMonths.getValue());
// }
}
目前flush()
,父类型的 (正在编辑的包含 的类型Commission
)返回一个带有未定义amount
和multiplier
的佣金contractMonths
。我可以让这些值传入和传出的唯一方法是手动将其编码(注释代码)。
- 我的副编辑器
EditorChain
是否正确附加?
编辑 1:提出的解决方案
我决定创建一个新的中间类,分别包装每个子类型的佣金,就像AbstractSubTypeEditor
我在这个问题中所做的那样。
委员会编辑
仍然是 a CompositeEditor
,但它只有一个或零个子编辑器,它只会是 a CommissionSubtypeEditor
:
public class CommissionEditor extends Composite implements CompositeEditor<Commission, Commission, CommissionSubtypeEditor>, LeafValueEditor<Commission>
{
interface Binder extends UiBinder<HTMLPanel, CommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
@Ignore
CommissionTypeEditor commissionType;
@UiField
Panel subEditorPanel;
private EditorChain<Commission, CommissionSubtypeEditor> chain;
@Ignore
@Path("")
CommissionSubtypeEditor subEditor = new CommissionSubtypeEditor();
private Commission value;
public CommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
commissionType.box.addValueChangeHandler(event -> setValue(new Commission(event.getValue())));
}
@Override
public void setValue(Commission value)
{
Log.warn("CommissionEditor -> setValue(): value is " + value);
commissionType.setValue(value.getCommissionType());
if(value.getCommissionType() != null)
{
this.value = value;
subEditorPanel.clear();
subEditorPanel.add(subEditor);
chain.attach(value, subEditor);
}
}
@Override
public Commission getValue()
{
Log.info("CommissionEditor -> getValue: " + value);
return value;
}
@Override
public void flush()
{
chain.getValue(subEditor);
}
@Override
public void setEditorChain(EditorChain<Commission, CommissionSubtypeEditor> chain)
{
this.chain = chain;
}
@Override
public CommissionSubtypeEditor createEditorForTraversal()
{
return subEditor;
}
@Override
public String getPathElement(CommissionSubtypeEditor commissionEditor)
{
return "";
}
@Override
public void onPropertyChange(String... strings)
{
}
@Override
public void setDelegate(EditorDelegate<Commission> editorDelegate)
{
}
}
AbstractSubTypeEditor
这门课归功于 Florent Bayle 。我不认为我可以在没有多态子类型的情况下使用它,但它似乎工作得很好。本质上允许包装子编辑器,如下所示CommissionSubtypeEditor
。
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;
public AbstractSubTypeEditor(E subEditor)
{
this.subEditor = subEditor;
}
@Override
public E createEditorForTraversal()
{
return subEditor;
}
@Override
public void flush()
{
currentValue = chain.getValue(subEditor);
}
@Override
public String getPathElement(E subEditor)
{
return "";
}
@Override
public T getValue()
{
return currentValue;
}
@Override
public void onPropertyChange(String... paths)
{
}
@Override
public void setDelegate(EditorDelegate<T> delegate)
{
}
@Override
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);
}
}
}
佣金子类型编辑器
public class CommissionSubtypeEditor extends Composite implements Editor<Commission>
{
interface Binder extends UiBinder<HTMLPanel, CommissionSubtypeEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
Panel subEditorPanel;
@Ignore
final UnitRateCommissionEditor unitRateCommissionEditor = new UnitRateCommissionEditor();
@Path("")
final AbstractSubTypeEditor<Commission, Commission, UnitRateCommissionEditor> unitRateWrapper = new AbstractSubTypeEditor<Commission, Commission,
UnitRateCommissionEditor>(unitRateCommissionEditor)
{
@Override
public void setValue(Commission value)
{
if(value.getCommissionType() == CommissionType.UNIT_RATE)
{
Log.info("unitRateWrapper setValue");
setValue(value, true);
subEditorPanel.clear();
subEditorPanel.add(unitRateCommissionEditor);
}
}
};
@Ignore
final StandingChargeCommissionEditor standingChargeCommissionEditor = new StandingChargeCommissionEditor();
@Path("")
final AbstractSubTypeEditor<Commission, Commission, StandingChargeCommissionEditor> standingChargeWrapper = new AbstractSubTypeEditor<Commission,
Commission, StandingChargeCommissionEditor>(standingChargeCommissionEditor)
{
@Override
public void setValue(Commission value)
{
if(value.getCommissionType() == CommissionType.STANDING_CHARGE)
{
Log.info("standingChargeWrapper setValue");
setValue(value, true);
subEditorPanel.clear();
subEditorPanel.add(standingChargeCommissionEditor);
}
}
};
public CommissionSubtypeEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
}
UnitRateCommissionEditor 和 StandingChargeCommissionEditor
既简单又实用Editor<Commission>
:
public class UnitRateCommissionEditor extends Composite implements Editor<Commission>
{
interface Binder extends UiBinder<Widget, UnitRateCommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
MoneyPenceBox amount;
@UiField
IntegerBox multiplier;
@UiField
IntegerBox contractMonths;
public UnitRateCommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
}
差不多好了...
public class StandingChargeCommissionEditor extends Composite implements Editor<Commission>
{
interface Binder extends UiBinder<Widget, StandingChargeCommissionEditor>
{
}
private static Binder uiBinder = GWT.create(Binder.class);
@UiField
MoneyPoundsBox amount;
@UiField
IntegerBox multiplier;
@UiField
IntegerBox contractMonths;
public StandingChargeCommissionEditor()
{
initWidget(uiBinder.createAndBindUi(this));
}
}
这确实有效,并且类似于我很早就尝试使用AbstractSubtypeEditor
sCompositeEditor
本身时尝试的方法。我认为那里的问题是编辑无法自行调用setValue()
。我对吗?