前回でMaster
プラグインプロジェクトのダウンロード
今回はポイントを絞って解説するために、
画面とクラスの関係
今回の実装でフォームデザイナーの画面が完成しました。画面とそれを実装しているクラスの関係を示します。なお、

Details
以下のソースコードはFieldDetailsPageクラスのselectionChanged()メソッドです。この実装ではフィールドが選択された場合に、
public class FieldDetailsPage implements IDetailsPage {
...
public void selectionChanged(IFormPart part,
ISelection selection) {
boolean fieldChange = true;
if (fSections != null) {
for (AbstractFieldDetailsSection section : fSections) {
if (section.getSectionPart() == part) {
fieldChange = false;
}
}
}
if (fieldChange) {
if (fSections != null) {
for (AbstractFieldDetailsSection section : fSections) {
section.getSectionPart().getSection().dispose();
}
fSections.removeAll(
new ArrayList<AbstractFieldDetailsSection>());
}
fSections = new ArrayList<AbstractFieldDetailsSection>();
fSections.add(new FieldDetailsGeneralSection());
fSections.add(new FieldDetailsValidatorSection());
for (AbstractFieldDetailsSection section : fSections) {
section.createContents(
fManagedForm.getToolkit().createSection(
fParent, Section.TITLE_BAR),
fManagedForm);
}
fParent.pack();
}
for (AbstractFieldDetailsSection section : fSections) {
section.selectionChanged(part, selection);
}
}
}
定義されたバリデータを表すDefinedValidatorクラス
フォームデザイナーはPHPのバリデーションフレームワークPiece_
ひとつのバリデータ定義にはひとつ以上のルールを設定する必要があります。例えば、
List<DefinedRule> emailRules = new ArrayList<DefinedRule>();
emailRules.add(new DefinedRule(
"allowDotBeforeAtmark",
DefinedRule.WidgetType.YesNo,
"false"));
DefinedValidator emailValidator = new DefinedValidator(
"Email",
"メールアドレス",
emailRules));
DefinedValidatorクラスはコンストラクタをプライベートとして定義し、
Piece_
ルールごとのウィジェットの定義
ルールには先ほどEmailバリデータのallowDotBeforeAtmarkルールのように
バリデータ定義フォームの実装
いよいよ今回の主な機能であるバリデータ定義フォームの実装を解説します。バリデータ定義フォームは今までMaster
バリデータ選択ダイアログ
まず最初に定義されたバリデータの一覧から追加するバリデータを選択するバリデータ一覧ダイアログを作成します。Eclipseでは一覧からデータを選択するためのダイアログとしてElementListSelectionDialogクラスが用意されているので、
ElementListSelectionDialogクラスを継承することで、
public class ValidatorSelectionDialog extends ElementListSelectionDialog {
public ValidatorSelectionDialog(Shell parent) {
super(parent, new ILabelProvider() {
public Image getImage(Object element) {
return null;
}
public String getText(Object element) {
assert (element instanceof DefinedValidator);
return ((DefinedValidator) element).getDisplayName();
}
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
});
setTitle("バリデータ選択");
setMessage("使用するバリデータを選択してください。");
setHelpAvailable(false);
setMultipleSelection(false);
setElements(DefinedValidator.getList().toArray());
}
}

ValidatorUIクラス
Master
そこで、
public class FieldDetailsValidatorSection extends AbstractFieldDetailsSection {
private class ValidatorUI {
private DefinedValidator fDefinedValidator;
private Validator fValidator;
ValidatorUI(DefinedValidator definedValidator) {
fDefinedValidator = definedValidator;
fValidator = fDefinedValidator.create();
}
ValidatorUI(Validator validator) {
fValidator = validator;
fDefinedValidator = DefinedValidator.getDefinedValidator(
fValidator);
}
public DefinedValidator getDefinedValidator() {
return fDefinedValidator;
}
public Validator getValidator() {
return fValidator;
}
}
...
}
さらにこのクラスではDefinedValidatorオブジェクト、
バリデータごとのウィジェットの生成
バリデータはそれぞれひとつ以のルールを保持するので、
public class FieldDetailsValidatorSection extends AbstractFieldDetailsSection {
...
private void createValidatorDetailsWidget(
final Composite composite,
final ValidatorUI validatorUI) {
FocusListener focusListener = new FocusListener() {
...
};
FormToolkit toolkit = getManagedForm().getToolkit();
if (fValidatorDetails != null) {
for (Control control : fValidatorDetails.getChildren()) {
control.dispose();
}
} else {
fValidatorDetails = toolkit.createComposite(composite);
fValidatorDetails.setLayout(new GridLayout(2, false));
GridData layoutData = new GridData();
layoutData.horizontalSpan = 2;
layoutData.grabExcessHorizontalSpace = true;
layoutData.grabExcessVerticalSpace = true;
layoutData.horizontalAlignment = GridData.FILL;
layoutData.verticalAlignment =
GridData.HORIZONTAL_ALIGN_BEGINNING;
fValidatorDetails.setLayoutData(layoutData);
}
Label nameLabel = toolkit.createLabel(
fValidatorDetails,
validatorUI.getDefinedValidator().getDisplayName());
GridData layoutData = new GridData();
layoutData.horizontalSpan = 2;
layoutData.grabExcessHorizontalSpace = true;
layoutData.horizontalAlignment = GridData.FILL;
nameLabel.setLayoutData(layoutData);
fMessageText = createLabelAndText(fValidatorDetails, "メッセージ");
fMessageText.addFocusListener(focusListener);
fRuleWidgets = new HashMap<DefinedRule, Widget[]>();
for (DefinedRule definedRule
: validatorUI.getDefinedValidator().getRules()) {
createRuleWidget(
fValidatorDetails,
definedRule,
focusListener);
}
layoutData = (GridData) fViewer.getTable().getLayoutData();
layoutData.minimumWidth = fViewer.getTable().getSize().x
- fViewer.getTable().getLocation().x
+ 5;
composite.getParent().pack();
layoutData.minimumWidth = 0;
}
...
}
すべてのウィジェットを再生成したあと、
また各ルールのウィジェットはDefinedRuleオブジェクトのWidgetTypeに合わせて生成され、
public class FieldDetailsValidatorSection extends AbstractFieldDetailsSection {
...
private void createRuleWidget(
final Composite parent,
final DefinedRule definedRule,
final FocusListener focusListener) {
if (definedRule.getWidgetType() == DefinedRule.WidgetType.Text) {
Text text = createLabelAndText(parent, definedRule.getName());
text.addFocusListener(focusListener);
fRuleWidgets.put(
definedRule,
new Widget[]{text});
} else if (definedRule.getWidgetType()
== DefinedRule.WidgetType.YesNo) {
Button[] radioButtons = createLabelAndRadioButton(
parent,
definedRule.getName());
for (Button radioButton : radioButtons) {
radioButton.addFocusListener(focusListener);
}
fRuleWidgets.put(
definedRule,
new Widget[]{radioButtons[0], radioButtons[1]});
} else {
assert (false);
}
}
...
}
変更通知
バリデータの詳細で行われた変更通知は、
public class FieldDetailsValidatorSection extends AbstractFieldDetailsSection {
...
private void createValidatorDetailsWidget(
final Composite composite,
final ValidatorUI validatorUI) {
FocusListener focusListener = new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent event) {
Validator validator =
((ValidatorUI) ((IStructuredSelection) fViewer
.getSelection()).getFirstElement()).getValidator();
if (fMessageText == event.widget) {
validator.setMessage(fMessageText.getText());
} else {
Iterator<DefinedRule> iterator =
fRuleWidgets.keySet().iterator();
while (iterator.hasNext()) {
DefinedRule definedRule = iterator.next();
Widget[] widgets = fRuleWidgets.get(definedRule);
if (definedRule.getWidgetType()
== DefinedRule.WidgetType.Text
&& widgets[0] == event.widget) {
validator.setRule(
definedRule.getName(),
((Text) widgets[0]).getText());
} else if (definedRule.getWidgetType()
== DefinedRule.WidgetType.YesNo
&& (widgets[0] == event.widget
|| widgets[1] == event.widget)) {
if (((Button) widgets[0]).getSelection()) {
validator.setRule(
definedRule.getName(), "true");
} else {
validator.setRule(
definedRule.getName(), "false");
}
} else {
assert (false);
}
}
}
getManagedForm().fireSelectionChanged(
getSectionPart(),
new StructuredSelection(getField()));
}
};
...
}
...
}
おわりに
今回はバリデータ定義フォームの実装について解説しました。前回までで説明した基礎をもとにした応用といった感じでしたが、
次回はYAMLファイルの読み書きを実装します。