Created
January 22, 2015 07:07
-
-
Save jmini/31b768f00e9a48da3f48 to your computer and use it in GitHub Desktop.
AbstractTableWithDetail template: implementation of the master/detail pattern.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* Copyright (c) 2015 BSI Business Systems Integration AG. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* BSI Business Systems Integration AG - initial API and implementation | |
******************************************************************************/ | |
import java.util.List; | |
import org.eclipse.scout.commons.annotations.Order; | |
import org.eclipse.scout.commons.exception.ProcessingException; | |
import org.eclipse.scout.rt.client.ui.basic.table.AbstractTable; | |
import org.eclipse.scout.rt.client.ui.basic.table.ITableRow; | |
import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractColumn; | |
import org.eclipse.scout.rt.shared.data.form.fields.tablefield.AbstractTableFieldBeanData; | |
/** | |
* Specific {@link AbstractTable} to support master/detail pattern | |
*/ | |
public abstract class AbstractTableWithDetail<DETAIL_TYPE> extends AbstractTable { | |
private ITableRow m_previousSelection; | |
protected abstract Class<DETAIL_TYPE> getConfiguredDetailDataType(); | |
public DetailDataColumn getDetailDataColumn() { | |
@SuppressWarnings("unchecked") | |
DetailDataColumn column = getColumnSet().getColumnByClass(DetailDataColumn.class); | |
return column; | |
} | |
@Order(0.0) | |
public class DetailDataColumn extends AbstractColumn<DETAIL_TYPE> { | |
@Override | |
protected boolean getConfiguredDisplayable() { | |
return false; | |
} | |
@Override | |
public Class<DETAIL_TYPE> getDataType() { | |
return getConfiguredDetailDataType(); | |
} | |
} | |
@Override | |
protected boolean getConfiguredMultiSelect() { | |
return false; | |
} | |
@Override | |
protected final void execRowsSelected(List<? extends ITableRow> rows) throws ProcessingException { | |
savePreviousSelection(); | |
if (rows.size() == 1) { | |
ITableRow selection = rows.get(0); | |
execSelectionNew(selection); | |
m_previousSelection = selection; | |
} | |
else { | |
execSelectionNo(); | |
m_previousSelection = null; | |
} | |
super.execRowsSelected(rows); | |
} | |
@Override | |
public void exportToTableBeanData(AbstractTableFieldBeanData target) throws ProcessingException { | |
savePreviousSelection(); | |
super.exportToTableBeanData(target); | |
} | |
@Override | |
public void importFromTableBeanData(AbstractTableFieldBeanData source) throws ProcessingException { | |
execSelectionNo(); | |
super.importFromTableBeanData(source); | |
} | |
private void savePreviousSelection() throws ProcessingException { | |
if (m_previousSelection != null) { | |
boolean changed = execSelectionSave(m_previousSelection); | |
if (changed && m_previousSelection.getStatus() == ITableRow.STATUS_NON_CHANGED) { | |
m_previousSelection.setStatusUpdated(); | |
} | |
m_previousSelection = null; | |
} | |
} | |
/** | |
* Called when the content of the detail group box needs to be put in the {@link #getDetailDataColumn()} for the | |
* selectionRow. | |
* | |
* @param selectionRow | |
* @return a boolean indicating if the content was changed or not | |
* @throws ProcessingException | |
*/ | |
protected boolean execSelectionSave(ITableRow selectionRow) throws ProcessingException { | |
return false; | |
} | |
/** | |
* Called when there is one new selection. The content of the {@link #getDetailDataColumn()} for the selectionRow | |
* should be imported on the detail group box. | |
* | |
* @param selectionRow | |
* @throws ProcessingException | |
*/ | |
protected void execSelectionNew(ITableRow selectionRow) throws ProcessingException { | |
} | |
/** | |
* Called when there is no selection. Can be used to disable or to hide the detail group box. | |
* | |
* @throws ProcessingException | |
*/ | |
protected void execSelectionNo() throws ProcessingException { | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/******************************************************************************* | |
* Copyright (c) 2015 BSI Business Systems Integration AG. | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* BSI Business Systems Integration AG - initial API and implementation | |
******************************************************************************/ | |
package m4test.client.core; | |
import java.util.Set; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.CancelButton; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.DetailsBox; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.DetailsBox.ChildrenField; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.DetailsBox.FirstNameField; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.DetailsBox.LastNameField; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.DetailsBox.UzdCodeField; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.OkButton; | |
import m4test.client.core.WithMasterDetailTableForm.MainBox.PersonsTableField; | |
import m4test.shared.core.IWithMasterDetailTableService; | |
import m4test.shared.core.PersonDetailBean; | |
import m4test.shared.core.UpdateWithMasterDetailTablePermission; | |
import m4test.shared.core.WithMasterDetailTableFormData; | |
import org.eclipse.scout.commons.CollectionUtility; | |
import org.eclipse.scout.commons.CompareUtility; | |
import org.eclipse.scout.commons.annotations.FormData; | |
import org.eclipse.scout.commons.annotations.Order; | |
import org.eclipse.scout.commons.exception.ProcessingException; | |
import org.eclipse.scout.rt.client.ui.action.menu.IMenuType; | |
import org.eclipse.scout.rt.client.ui.action.menu.TableMenuType; | |
import org.eclipse.scout.rt.client.ui.basic.table.ITableRow; | |
import org.eclipse.scout.rt.client.ui.basic.table.columns.AbstractStringColumn; | |
import org.eclipse.scout.rt.client.ui.form.AbstractForm; | |
import org.eclipse.scout.rt.client.ui.form.AbstractFormHandler; | |
import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractCancelButton; | |
import org.eclipse.scout.rt.client.ui.form.fields.button.AbstractOkButton; | |
import org.eclipse.scout.rt.client.ui.form.fields.groupbox.AbstractGroupBox; | |
import org.eclipse.scout.rt.client.ui.form.fields.integerfield.AbstractIntegerField; | |
import org.eclipse.scout.rt.client.ui.form.fields.stringfield.AbstractStringField; | |
import org.eclipse.scout.rt.client.ui.form.fields.tablefield.AbstractTableField; | |
import org.eclipse.scout.rt.extension.client.ui.action.menu.AbstractExtensibleMenu; | |
import org.eclipse.scout.rt.shared.TEXTS; | |
import org.eclipse.scout.service.SERVICES; | |
/** | |
* @author jbr | |
*/ | |
@FormData(value = WithMasterDetailTableFormData.class, sdkCommand = FormData.SdkCommand.CREATE) | |
public class WithMasterDetailTableForm extends AbstractForm { | |
/** | |
* @throws org.eclipse.scout.commons.exception.ProcessingException | |
*/ | |
public WithMasterDetailTableForm() throws ProcessingException { | |
super(); | |
} | |
@Override | |
protected String getConfiguredTitle() { | |
return TEXTS.get("FormWithMasterDetailTable"); | |
} | |
/** | |
* @throws org.eclipse.scout.commons.exception.ProcessingException | |
*/ | |
public void startModify() throws ProcessingException { | |
startInternal(new ModifyHandler()); | |
} | |
/** | |
* @throws org.eclipse.scout.commons.exception.ProcessingException | |
*/ | |
public void startNew() throws ProcessingException { | |
startInternal(new NewHandler()); | |
} | |
/** | |
* @return the CancelButton | |
*/ | |
public CancelButton getCancelButton() { | |
return getFieldByClass(CancelButton.class); | |
} | |
/** | |
* @return the ChildrenField | |
*/ | |
public ChildrenField getChildrenField() { | |
return getFieldByClass(ChildrenField.class); | |
} | |
/** | |
* @return the DetailsBox | |
*/ | |
public DetailsBox getDetailsBox() { | |
return getFieldByClass(DetailsBox.class); | |
} | |
/** | |
* @return the FirstNameField | |
*/ | |
public FirstNameField getFirstNameField() { | |
return getFieldByClass(FirstNameField.class); | |
} | |
/** | |
* @return the LastNameField | |
*/ | |
public LastNameField getLastNameField() { | |
return getFieldByClass(LastNameField.class); | |
} | |
/** | |
* @return the MainBox | |
*/ | |
public MainBox getMainBox() { | |
return getFieldByClass(MainBox.class); | |
} | |
/** | |
* @return the OkButton | |
*/ | |
public OkButton getOkButton() { | |
return getFieldByClass(OkButton.class); | |
} | |
/** | |
* @return the PersonsTableField | |
*/ | |
public PersonsTableField getPersonsTableField() { | |
return getFieldByClass(PersonsTableField.class); | |
} | |
/** | |
* @return the UzdCodeField | |
*/ | |
public UzdCodeField getUzdCodeField() { | |
return getFieldByClass(UzdCodeField.class); | |
} | |
@Order(1000.0) | |
public class MainBox extends AbstractGroupBox { | |
@Order(1000.0) | |
public class PersonsTableField extends AbstractTableField<PersonsTableField.Table> { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("Persons"); | |
} | |
@Override | |
protected int getConfiguredGridH() { | |
return 5; | |
} | |
@Override | |
protected int getConfiguredGridW() { | |
return 2; | |
} | |
@Order(1000.0) | |
public class Table extends AbstractTableWithDetail<PersonDetailBean> { | |
@Override | |
protected Class<PersonDetailBean> getConfiguredDetailDataType() { | |
return PersonDetailBean.class; | |
} | |
public FirstNameColumn getFirstNameColumn() { | |
return getColumnSet().getColumnByClass(FirstNameColumn.class); | |
} | |
public LastNameColumn getLastNameColumn() { | |
return getColumnSet().getColumnByClass(LastNameColumn.class); | |
} | |
@Override | |
protected boolean execSelectionSave(ITableRow selectionRow) throws ProcessingException { | |
boolean hasChanged = false; | |
PersonDetailBean detailBean = getDetailDataColumn().getValue(selectionRow); | |
if (detailBean == null) { | |
detailBean = new PersonDetailBean(); | |
getDetailDataColumn().setValue(selectionRow, detailBean); | |
} | |
if (CompareUtility.notEquals(getFirstNameField().getValue(), getFirstNameColumn().getValue(selectionRow))) { | |
hasChanged = true; | |
getFirstNameColumn().setValue(selectionRow, getFirstNameField().getValue()); | |
} | |
if (CompareUtility.notEquals(getLastNameField().getValue(), getLastNameColumn().getValue(selectionRow))) { | |
hasChanged = true; | |
getLastNameColumn().setValue(selectionRow, getLastNameField().getValue()); | |
} | |
if (CompareUtility.notEquals(getUzdCodeField().getValue(), detailBean.getUzdCode())) { | |
hasChanged = true; | |
detailBean.setUzdCode(getUzdCodeField().getValue()); | |
} | |
if (CompareUtility.notEquals(getChildrenField().getValue(), detailBean.getChildren())) { | |
hasChanged = true; | |
detailBean.setChildren(getChildrenField().getValue()); | |
} | |
return hasChanged; | |
} | |
@Override | |
protected void execSelectionNew(ITableRow selectionRow) throws ProcessingException { | |
PersonDetailBean detailBean = getDetailDataColumn().getValue(selectionRow); | |
if (detailBean == null) { | |
detailBean = new PersonDetailBean(); | |
} | |
getFirstNameField().setValue(getFirstNameColumn().getValue(selectionRow)); | |
getLastNameField().setValue(getLastNameColumn().getValue(selectionRow)); | |
getUzdCodeField().setValue(detailBean.getUzdCode()); | |
getChildrenField().setValue(detailBean.getChildren()); | |
getDetailsBox().setEnabled(true); | |
getFirstNameField().requestFocus(); | |
} | |
@Override | |
protected void execSelectionNo() throws ProcessingException { | |
getFirstNameField().setValue(null); | |
getLastNameField().setValue(null); | |
getUzdCodeField().setValue(null); | |
getChildrenField().setValue(null); | |
getDetailsBox().setEnabled(false); | |
getDetailsBox().requestFocus(); | |
} | |
@Order(1000.0) | |
public class FirstNameColumn extends AbstractStringColumn { | |
@Override | |
protected String getConfiguredHeaderText() { | |
return TEXTS.get("FirstName"); | |
} | |
@Override | |
protected int getConfiguredWidth() { | |
return 120; | |
} | |
} | |
@Order(2000.0) | |
public class LastNameColumn extends AbstractStringColumn { | |
@Override | |
protected String getConfiguredHeaderText() { | |
return TEXTS.get("LastName"); | |
} | |
@Override | |
protected int getConfiguredWidth() { | |
return 120; | |
} | |
} | |
@Order(1000.0) | |
public class NewPersonMenu extends AbstractExtensibleMenu { | |
@Override | |
protected Set<? extends IMenuType> getConfiguredMenuTypes() { | |
return CollectionUtility.<IMenuType> hashSet(TableMenuType.EmptySpace); | |
} | |
@Override | |
protected String getConfiguredText() { | |
return TEXTS.get("NewPerson"); | |
} | |
@Override | |
protected void execAction() throws ProcessingException { | |
ITableRow row = createRow(); | |
row = addRow(row); | |
selectRow(row); | |
} | |
} | |
@Order(2000.0) | |
public class DeletePersonMenu extends AbstractExtensibleMenu { | |
@Override | |
protected String getConfiguredText() { | |
return TEXTS.get("DeletePerson"); | |
} | |
@Override | |
protected void execAction() throws ProcessingException { | |
getSelectedRow().delete(); | |
} | |
} | |
} | |
} | |
@Order(2000.0) | |
public class DetailsBox extends AbstractGroupBox { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("DetailsForTheSelectedPerson"); | |
} | |
@Order(1000.0) | |
@FormData(sdkCommand = FormData.SdkCommand.IGNORE) | |
public class FirstNameField extends AbstractStringField { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("FirstName"); | |
} | |
@Override | |
protected boolean execIsSaveNeeded() throws ProcessingException { | |
return false; | |
} | |
} | |
@Order(2000.0) | |
@FormData(sdkCommand = FormData.SdkCommand.IGNORE) | |
public class LastNameField extends AbstractStringField { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("LastName"); | |
} | |
@Override | |
protected boolean execIsSaveNeeded() throws ProcessingException { | |
return false; | |
} | |
} | |
@Order(3000.0) | |
@FormData(sdkCommand = FormData.SdkCommand.IGNORE) | |
public class UzdCodeField extends AbstractStringField { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("CodeUDZ"); | |
} | |
@Override | |
protected boolean execIsSaveNeeded() throws ProcessingException { | |
return false; | |
} | |
} | |
@Order(4000.0) | |
@FormData(sdkCommand = FormData.SdkCommand.IGNORE) | |
public class ChildrenField extends AbstractIntegerField { | |
@Override | |
protected String getConfiguredLabel() { | |
return TEXTS.get("NumberOfChildren"); | |
} | |
@Override | |
protected boolean execIsSaveNeeded() throws ProcessingException { | |
return false; | |
} | |
} | |
} | |
@Order(100000.0) | |
public class OkButton extends AbstractOkButton { | |
} | |
@Order(101000.0) | |
public class CancelButton extends AbstractCancelButton { | |
} | |
} | |
public class ModifyHandler extends AbstractFormHandler { | |
@Override | |
protected void execLoad() throws ProcessingException { | |
IWithMasterDetailTableService service = SERVICES.getService(IWithMasterDetailTableService.class); | |
WithMasterDetailTableFormData formData = new WithMasterDetailTableFormData(); | |
exportFormData(formData); | |
formData = service.load(formData); | |
importFormData(formData); | |
setEnabledPermission(new UpdateWithMasterDetailTablePermission()); | |
} | |
@Override | |
protected void execStore() throws ProcessingException { | |
IWithMasterDetailTableService service = SERVICES.getService(IWithMasterDetailTableService.class); | |
WithMasterDetailTableFormData formData = new WithMasterDetailTableFormData(); | |
exportFormData(formData); | |
formData = service.store(formData); | |
} | |
} | |
public class NewHandler extends AbstractFormHandler { | |
@Override | |
protected void execLoad() throws ProcessingException { | |
IWithMasterDetailTableService service = SERVICES.getService(IWithMasterDetailTableService.class); | |
WithMasterDetailTableFormData formData = new WithMasterDetailTableFormData(); | |
exportFormData(formData); | |
formData = service.prepareCreate(formData); | |
importFormData(formData); | |
} | |
@Override | |
protected void execStore() throws ProcessingException { | |
IWithMasterDetailTableService service = SERVICES.getService(IWithMasterDetailTableService.class); | |
WithMasterDetailTableFormData formData = new WithMasterDetailTableFormData(); | |
exportFormData(formData); | |
formData = service.create(formData); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
See also the corresponding description in the Eclipse Scout Forum.