前回はMaster
パッケージ・クラスの構造の整理
今までは
パッケージの分割
まず、
パッケージ名 | 説明 | 所属するファイル |
---|---|---|
plugin | プラグイン全体で使用するクラスを配置する | Activator. |
model | モデルクラスを配置する | Field. |
ui | ユーザーインタフェースに関係するクラスを配置する | FormDesignerEditor. |

Master(一覧)のクラス化
現在のフォームデザイナーのソースコードの中で一番複雑なのは、
マニフェストエディターの
FieldsMasterSectionPartクラスでウィジェットの生成・
public class FieldsMasterSectionPart extends SectionPart {
public FieldsMasterSectionPart(Composite parent, IManagedForm managedForm) {
super(parent,
managedForm.getToolkit(),
Section.TITLE_BAR | Section.DESCRIPTION);
initialize(managedForm);
createContents(getSection(), managedForm.getToolkit());
}
private void createContents(Section section, FormToolkit toolkit) {
section.setText("フィールド一覧");
section.setDescription("編集するフィールドを選択してください。");
Composite composite = toolkit.createComposite(section);
composite.setLayout(new GridLayout(2, false));
Table table = toolkit.createTable(
composite,
SWT.SINGLE | SWT.FULL_SELECTION);
table.setHeaderVisible(true);
table.setLinesVisible(true);
GridData layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
layoutData.verticalAlignment = GridData.FILL;
layoutData.grabExcessHorizontalSpace = true;
layoutData.grabExcessVerticalSpace = true;
table.setLayoutData(layoutData);
TableColumn column1 = new TableColumn(table, SWT.NULL);
column1.setText("フィールド名");
column1.setWidth(100);
TableColumn column2 = new TableColumn(table, SWT.NULL);
column2.setText("説明");
column2.setWidth(100);
TableViewer viewer = new TableViewer(table);
viewer.setContentProvider(new ArrayContentProvider());
viewer.setLabelProvider(new ITableLabelProvider() {
public Image getColumnImage(Object element, int columnIndex) {
return null;
}
public String getColumnText(Object element, int columnIndex) {
if (element == null) {
return "";
}
if (!(element instanceof Field)) {
return "";
}
Field field = (Field) element;
if (columnIndex == 0) {
return field.getName();
} else if (columnIndex == 1) {
return field.getDescription();
}
return "";
}
public void addListener(ILabelProviderListener listener) {
}
public void dispose() {
}
public boolean isLabelProperty(Object element, String property) {
return false;
}
public void removeListener(ILabelProviderListener listener) {
}
});
final SectionPart part = new SectionPart(section);
viewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
FieldsMasterSectionPart.this.getManagedForm().fireSelectionChanged(
part,
event.getSelection());
}
});
Composite buttons = toolkit.createComposite(composite);
layoutData = new GridData();
layoutData.verticalAlignment = GridData.FILL;
buttons.setLayoutData(layoutData);
buttons.setLayout(new GridLayout());
Button addButton = toolkit.createButton(buttons, "追加(&A)...", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
addButton.setLayoutData(layoutData);
Button delButton = toolkit.createButton(buttons, "削除(&D)...", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
delButton.setLayoutData(layoutData);
Button upButton = toolkit.createButton(buttons, "上へ", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
upButton.setLayoutData(layoutData);
Button downButton = toolkit.createButton(buttons, "下へ", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
downButton.setLayoutData(layoutData);
section.setClient(composite);
viewer.setInput(createSample());
}
private List createSample() {
List fields = new ArrayList();
Field field1 = new Field("name");
field1.setDescription("名前");
field1.setRequired(true);
field1.setMessage("名前は必須です。");
fields.add(field1);
Field field2 = new Field("phone");
field2.setDescription("電話番号");
field2.setRequired(true);
field2.setMessage("電話番号は必須です。");
fields.add(field2);
Field field3 = new Field("address");
field3.setDescription("住所");
field3.setRequired(false);
fields.add(field3);
return fields;
}
}
private class FieldsBlock extends MasterDetailsBlock {
@Override
protected void createMasterPart(
final IManagedForm managedForm,
final Composite parent) {
new FieldsMasterSectionPart(parent, managedForm);
}
@Override
protected void createToolBarActions(IManagedForm managedForm) {
}
@Override
protected void registerPages(DetailsPart detailsPart) {
...
}
}
ここまで実装できたら、
Details(詳細)のクラス化
続いて、
public class FieldDetailsPage implements IDetailsPage {
...
(ソースコードはFieldsBlockクラスのregisterPages()メソッドのIDetailsPageインタフェースの無名クラスをそのまま移動してきます。)
...
}
private class FieldsBlock extends MasterDetailsBlock {
@Override
protected void createMasterPart(
final IManagedForm managedForm,
final Composite parent) {
new FieldsMasterSectionPart(parent, managedForm);
}
@Override
protected void createToolBarActions(IManagedForm managedForm) {
}
@Override
protected void registerPages(DetailsPart detailsPart) {
detailsPart.registerPage(Field.class, new FieldDetailsPage());
}
}
ここまで実装できたら、
ボタンの実装
ソースコードはだいぶ整理できましたので、
[追加]ボタン
[追加]
private void createContents(Section section, FormToolkit toolkit) {
...
final TableViewer viewer = new TableViewer(table);
...
final Composite buttons = toolkit.createComposite(composite);
...
Button addButton = toolkit.createButton(buttons, "追加(&A)...", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
addButton.setLayoutData(layoutData);
addButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
InputDialog dialog = new InputDialog(
buttons.getShell(),
"フィールド名入力",
"フィールド名を入力してください。",
null,
null);
dialog.open();
Field field = new Field(dialog.getValue());
viewer.add(field);
viewer.setSelection(new StructuredSelection(field));
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
...
}
widgetSelected()メソッドの中でviewerとbuttonsを使用するので、
それでは実行してみましょう。
![[追加]ボタンをクリックするとフィールド名の入力を促すダイアログが表示される [追加]ボタンをクリックするとフィールド名の入力を促すダイアログが表示される](/assets/images/dev/serial/01/eclipse-plugin/0009/thumb/TH800_0009-02.png)
[削除]ボタン
削除は選択されているFieldオブジェクトを取得し、
private void createContents(Section section, FormToolkit toolkit) {
...
Button delButton = toolkit.createButton(buttons, "削除(&D)...", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
delButton.setLayoutData(layoutData);
delButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
Field field =
(Field) ((IStructuredSelection) viewer.getSelection())
.getFirstElement();
viewer.remove(field);
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
}
それでは実行してみましょう。Master
[上へ][下へ]ボタン
最後に
private void createContents(Section section, FormToolkit toolkit) {
...
Button upButton = toolkit.createButton(buttons, "上へ", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
upButton.setLayoutData(layoutData);
upButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
int index = viewer.getTable().getSelectionIndex();
if (index == 0) {
return;
}
Field tmpField = (Field) viewer.getElementAt(index - 1);
viewer.replace(viewer.getElementAt(index), index - 1);
viewer.replace(tmpField, index);
viewer.setSelection(
new StructuredSelection((Field) viewer.getElementAt(index - 1)));
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
Button downButton = toolkit.createButton(buttons, "下へ", SWT.PUSH);
layoutData = new GridData();
layoutData.horizontalAlignment = GridData.FILL;
downButton.setLayoutData(layoutData);
downButton.addSelectionListener(new SelectionListener() {
public void widgetSelected(SelectionEvent e) {
int index = viewer.getTable().getSelectionIndex();
if (index + 1 == viewer.getTable().getItemCount()) {
return;
}
Field tmpField = (Field) viewer.getElementAt(index + 1);
viewer.replace(viewer.getElementAt(index), index + 1);
viewer.replace(tmpField, index);
viewer.setSelection(
new StructuredSelection((Field) viewer.getElementAt(index + 1)));
}
public void widgetDefaultSelected(SelectionEvent e) {
}
});
...
}
それでは実行してみましょう。Master
![[上へ]ボタン、[下へ]ボタンに合わせてフィールドが上下に移動する [上へ]ボタン、[下へ]ボタンに合わせてフィールドが上下に移動する](/assets/images/dev/serial/01/eclipse-plugin/0009/thumb/TH400_0009-03.png)
Details(詳細)の変更の反映
Master
ManagedFormクラスのfireSelectionChanged()メソッドの実装を見るとわかるのですが、
IPartSelectionListenerインタフェースはselectionChanged()メソッドを定義しているので、
public class FieldsMasterSectionPart extends SectionPart implements IPartSelectionListener {
private TableViewer fViewer;
...
private void createContents(Section section, FormToolkit toolkit) {
...
fViewer = new TableViewer(table);
...
fViewer.addSelectionChangedListener(new ISelectionChangedListener() {
public void selectionChanged(SelectionChangedEvent event) {
FieldsMasterSectionPart.this.getManagedForm().fireSelectionChanged(
FieldsMasterSectionPart.this,
event.getSelection());
}
});
...
section.setClient(composite);
getManagedForm().addPart(this);
fViewer.setInput(createSample());
}
...
public void selectionChanged(IFormPart part, ISelection selection) {
if (part == this) {
return;
}
if (!(selection instanceof IStructuredSelection)) {
return;
}
fViewer.refresh((Field) ((IStructuredSelection) selection).getFirstElement());
}
}
次に変更を通知するDetails
public class FieldDetailsPage implements IDetailsPage {
private Field fField;
private SectionPart fSectionPart;
...
public void createContents(Composite parent) {
...
layoutData = new GridData();
layoutData.grabExcessHorizontalSpace = true;
layoutData.horizontalAlignment = GridData.FILL;
composite.setLayoutData(layoutData);
fSectionPart = new SectionPart(section);
FocusListener focusListener = new FocusListener() {
public void focusGained(FocusEvent e) {
}
public void focusLost(FocusEvent event) {
if (fNameText == event.widget) {
fField.setName(fNameText.getText());
} else if (fDescriptionText == event.widget) {
fField.setDescription(fDescriptionText.getText());
} else if (fRequiredYesButton == event.widget
|| fRequiredNoButton == event.widget) {
fField.setRequired(fRequiredYesButton.getSelection());
} else if (fMessageText == event.widget) {
fField.setMessage(fMessageText.getText());
}
fForm.fireSelectionChanged(
fSectionPart,
new StructuredSelection(fField));
}
};
toolkit.createLabel(composite, "フィールド名");
...
fNameText.addFocusListener(focusListener);
toolkit.createLabel(composite, "概要");
...
fDescriptionText.addFocusListener(focusListener);
toolkit.createLabel(composite, "必須");
...
fRequiredYesButton.addFocusListener(focusListener);
fRequiredNoButton.addFocusListener(focusListener);
toolkit.createLabel(composite, "メッセージ");
...
fMessageText.addFocusListener(focusListener);
section.setClient(composite);
}
...
public void selectionChanged(IFormPart part,
ISelection selection) {
if (fSectionPart == part) {
return;
}
...
fField = field;
}
}
それでは実行してみましょう。フィールド名や概要を変更して、

おわりに
今回はテーブル、
次回はバリデータ定義フォームの実装を説明します。