/******************************************************************************* * Copyright (c) 2011 Softberries Krzysztof Grajek. * 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: * Softberries Krzysztof Grajek - initial API and implementation ******************************************************************************/ package com.softberries.klerk.gui.editors; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import org.eclipse.core.databinding.validation.IValidator; import org.eclipse.core.databinding.validation.ValidationStatus; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IEditorSite; import org.eclipse.ui.ISaveablePart; import org.eclipse.ui.PartInitException; import org.eclipse.ui.forms.events.ExpansionAdapter; import org.eclipse.ui.forms.events.ExpansionEvent; import org.eclipse.ui.forms.widgets.ExpandableComposite; import org.eclipse.ui.forms.widgets.Section; import org.eclipse.ui.forms.widgets.TableWrapData; import org.eclipse.ui.forms.widgets.TableWrapLayout; import org.eclipse.ui.statushandlers.StatusManager; import com.softberries.klerk.Activator; import com.softberries.klerk.LogUtil; import com.softberries.klerk.dao.ProductDao; import com.softberries.klerk.dao.to.Product; import com.softberries.klerk.gui.helpers.Messages; import com.softberries.klerk.gui.helpers.table.ProductsModelProvider; import com.softberries.klerk.gui.validators.FieldNotEmptyValidator; public class SingleProductEditor extends SingleObjectEditor { public static final String ID = "com.softberries.klerk.gui.editors.SingleProduct"; //$NON-NLS-1$ /** * Default constructor */ public SingleProductEditor() { } /** * Keeps a reference to the edited {@link Product} (if in editing mode) */ private Product product; /** * Keeps a reference to the original {@code Product} code set while opening this editor, * this way we can skip saving the {@code Product} if the modified {@code Product} code is the same as the original * one. */ private String oldProductCode; /** * Keeps a reference to the current {@code Product} code value, we are checking this value before saving to * make sure its filled with correct value */ private Text codeTxt; /** * Keeps a ref to the {@code Product} name to ensure upon saving that we are going to store correct values * in the database */ private String currentProductName = ""; //$NON-NLS-1$ /** * If the validator for the {@code Product} code property returns false this member variable prevents saving the * modified product */ private boolean codeInvalid; /** * Enable save conditionally, if the {@code dirty} - drt argument is set to true, this * method tries to enable save on the editor, before save can be enabled we are checking if * all the required fields for {@code Product} are filled with correct values * * @param drt - stands for 'dirty' like in standard Eclipse RCP editor */ @Override protected void enableSave(boolean drt) { //check if code and product name is filled with value and check if the code is valid if(drt && !codeTxt.getText().isEmpty() && !currentProductName.isEmpty() && !codeInvalid){ dirty = drt; //notify editor that its dirty/not dirty firePropertyChange(ISaveablePart.PROP_DIRTY); }else{ dirty = false; firePropertyChange(ISaveablePart.PROP_DIRTY); } } /** * Saves current {@code Product} either new or edited one * by using {@link ProductDao} */ @Override public void doSave(IProgressMonitor monitor) { ProductDao dao = new ProductDao(GenericKlerkEditor.DB_FOLDER_PATH); product.setCode(prepareProductCode(product.getCode().toUpperCase())); try { //if {@value product} doesn't have id set it means that its a new product //otherwise we are editing exising {@code Product} if(product.getId() == null){ dao.create(product); ProductsModelProvider.INSTANCE.getProducts().add(product); }else{ LogUtil.logInfo("Updating product: " + product.getId()); //$NON-NLS-1$ dao.update(product); } } catch (SQLException e) { IStatus status = new Status(IStatus.ERROR, Activator.PLUGIN_ID, 0, Messages.SingleProductEditor_cannotUpdateError, e); StatusManager.getManager().handle(status, StatusManager.SHOW); } enableSave(false); } /** * Remove special characters for the {@link Product} code * @param code * @return formatted code */ private String prepareProductCode(String code) { code = code.toUpperCase(); code = code.replaceAll("[^a-zA-Z0-9]", ""); //$NON-NLS-1$ //$NON-NLS-2$ return code; } @Override public void init(IEditorSite site, IEditorInput input) throws PartInitException { setSite(site); setInput(input); product = (Product) input.getAdapter(Product.class); this.oldProductCode = product.getCode(); this.currentProductName = product.getName(); setPartName(product.getName()); } /** * Creates all user interface controls */ @Override public void createPartControl(Composite parent) { form = toolkit.createScrolledForm(parent); form.setText(Messages.SingleProductEditor_PRODUCT + this.product.getName()); TableWrapLayout twlayout = new TableWrapLayout(); twlayout.numColumns = 2; form.getBody().setLayout(twlayout); // general section Section sectionGeneral = toolkit.createSection(form.getBody(), Section.DESCRIPTION | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED); sectionGeneral.setText(Messages.SingleProductEditor_Main); sectionGeneral.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { form.reflow(true); } }); toolkit.createCompositeSeparator(sectionGeneral); createSectionToolbar(sectionGeneral, toolkit); sectionGeneral.setDescription(Messages.SingleProductEditor_Product_main_properties); Composite sectionGeneralClient = toolkit .createComposite(sectionGeneral); TableWrapLayout twLayoutSectionGeneral = new TableWrapLayout(); twLayoutSectionGeneral.numColumns = 4; sectionGeneralClient.setLayout(twLayoutSectionGeneral); // product code final Label codeLbl = toolkit.createLabel(sectionGeneralClient, Messages.SingleProductEditor_code); codeTxt = toolkit.createText(sectionGeneralClient, this.product.getCode(), SWT.BORDER); bindValidator(codeTxt, product, "code", new IValidator(){ //$NON-NLS-1$ List<String> productCodes = getProductCodes(); @Override public IStatus validate(Object value) { String s = String.valueOf(value); for(String p : productCodes){ if(p.equalsIgnoreCase(s) && !p.equalsIgnoreCase(oldProductCode)){ codeInvalid = true; return ValidationStatus.error(Messages.SingleProductEditor_productCode + s + Messages.SingleProductEditor_alreadyExists); } } codeInvalid = false; return ValidationStatus.ok(); } }); bindValidator(codeTxt, product, "code", new FieldNotEmptyValidator(Messages.SingleProductEditor_fieldCannotBeEmpty)); //$NON-NLS-1$ codeTxt.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { enableSave(true); } }); TableWrapData twd_codeTxt = new TableWrapData(TableWrapData.FILL_GRAB); twd_codeTxt.colspan = 3; twd_codeTxt.indent = 5; codeTxt.setLayoutData(twd_codeTxt); // product title final Label nameLbl = toolkit.createLabel(sectionGeneralClient, Messages.SingleProductEditor_Name); final Text nameTxt = toolkit.createText(sectionGeneralClient, this.product.getName(), SWT.BORDER); bindValidator(nameTxt, product, "name",new FieldNotEmptyValidator(Messages.SingleProductEditor_fieldCannotBeEmpty)); //$NON-NLS-1$ nameTxt.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { product.setName(nameTxt.getText()); currentProductName = product.getName(); form.setText(Messages.SingleProductEditor_PRODUCT + product.getName()); setPartName(product.getName()); enableSave(true); } }); TableWrapData twd_titleTxt = new TableWrapData(TableWrapData.FILL_GRAB); twd_titleTxt.colspan = 3; twd_titleTxt.indent = 5; nameTxt.setLayoutData(twd_titleTxt); sectionGeneral.setClient(sectionGeneralClient); TableWrapData data = new TableWrapData(TableWrapData.FILL_GRAB); data.colspan = 2; sectionGeneral.setLayoutData(data); // product description section Section sectionDescription = toolkit.createSection(form.getBody(), Section.DESCRIPTION | ExpandableComposite.TWISTIE | ExpandableComposite.EXPANDED); sectionDescription.setText(Messages.SingleProductEditor_Description); sectionDescription.addExpansionListener(new ExpansionAdapter() { @Override public void expansionStateChanged(ExpansionEvent e) { form.reflow(true); } }); toolkit.createCompositeSeparator(sectionDescription); sectionDescription.setDescription(Messages.SingleProductEditor_Product_Description); Composite sectionDescClient = toolkit.createComposite(sectionDescription); TableWrapLayout twLayoutSectionDesc = new TableWrapLayout(); twLayoutSectionDesc.numColumns = 1; sectionDescClient.setLayout(twLayoutSectionDesc); final Text descTxt = toolkit.createText(sectionDescClient, this.product.getDescription(), SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI); descTxt.addModifyListener(new ModifyListener() { @Override public void modifyText(ModifyEvent e) { product.setDescription(descTxt.getText()); enableSave(true); } }); TableWrapData twd_descTxt = new TableWrapData(TableWrapData.FILL_GRAB); twd_descTxt.heightHint = 180; twd_descTxt.grabVertical = true; twd_descTxt.colspan = 1; descTxt.setLayoutData(twd_descTxt); sectionDescription.setClient(sectionDescClient); data = new TableWrapData(TableWrapData.FILL_GRAB); data.colspan = 2; sectionDescription.setLayoutData(data); } /** * Converts list of {@code Product} objects into corresponding * {@code java.util.List} of their codes * * @return {@link java.util.List} of {@link Product} codes */ private List<String> getProductCodes() { List<String> strs = new ArrayList<String>(); for(Product p : ProductsModelProvider.INSTANCE.getProducts()){ strs.add(p.getCode()); } return strs; } }