/* ***************************************************************************** * JFire - it's hot - Free ERP System - http://jfire.org * * Copyright (C) 2004-2005 NightLabs - http://NightLabs.org * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin St, Fifth Floor, * * Boston, MA 02110-1301 USA * * * * Or get it online : * * http://opensource.org/licenses/lgpl-license.php * * * * * ******************************************************************************/ package org.nightlabs.jfire.trade.admin.ui.producttype; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jdo.JDOHelper; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.notification.IDirtyStateManager; import org.nightlabs.base.ui.util.RCPUtil; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jfire.base.JFireEjb3Factory; import org.nightlabs.jfire.base.login.ui.Login; import org.nightlabs.jfire.store.ProductType; import org.nightlabs.jfire.store.StoreManagerRemote; import org.nightlabs.jfire.store.id.ProductTypeID; import org.nightlabs.jfire.trade.admin.ui.resource.Messages; import org.nightlabs.util.CollectionUtil; import org.nightlabs.util.NLLocale; /** * With this composite the user can control the sale status of every * product type. Currently, this is only the published and saleable * flags, but on the long run, access rights can be managed via Authority * assignment and manipulation of the Authority. * * @author Marco Schulze - marco at nightlabs dot de */ public class SaleAccessControlComposite extends XComposite { public static final String STATUS_CONTROL_ID_PUBLISHED = "published"; //$NON-NLS-1$ public static final String STATUS_CONTROL_ID_CONFIRMED = "confirmed"; //$NON-NLS-1$ public static final String STATUS_CONTROL_ID_SALEABLE = "saleable"; //$NON-NLS-1$ public static final String STATUS_CONTROL_ID_CLOSED = "closed"; //$NON-NLS-1$ private Label productTypeLabel; private ProductType productType; private Map<String, Control> statusControlID2statusControl = new HashMap<String, Control>(); private Button publishedCheckBox; private Button confirmedCheckBox; private Button saleableCheckBox; private Button closedCheckBox; private SaleAccessControlHelper saleAccessControlHelper; private boolean showProductTypeLabel = true; private IDirtyStateManager dirtyStateManager; /** * @param parent SWT parent composite (into which this composite will be added as child). * @param style SWT style * @param fetchGroupsProductType Can be null. * @param saleAccessControlHelper Must not be null. */ public SaleAccessControlComposite(Composite parent, int style, SaleAccessControlHelper saleAccessControlHelper) { this(parent, style, saleAccessControlHelper, true, null); } /** * @param parent SWT parent composite (into which this composite will be added as child). * @param style SWT style * @param fetchGroupsProductType Can be null. * @param _saleAccessControlHelper Must not be null. * @param showProductTypeLabel determines if the the name of the productType should be displayed * or not */ public SaleAccessControlComposite(Composite parent, int style, SaleAccessControlHelper _saleAccessControlHelper, boolean showProductTypeLabel, IDirtyStateManager dirtyStateManager) { super(parent, style, LayoutMode.TIGHT_WRAPPER); // super(parent, style); this.dirtyStateManager = dirtyStateManager; this.showProductTypeLabel = showProductTypeLabel; // Set fetchGroups = _saleAccessControlHelper.getFetchGroupsProductType(); // if (fetchGroups.isEmpty()) // this.fetchGroupsProductType = FETCH_GROUPS_PRODUCT_TYPE_MIN; // else { // fetchGroups.addAll(Utils.array2ArrayList(FETCH_GROUPS_PRODUCT_TYPE_MIN)); // this.fetchGroupsProductType = (String[]) Utils.collection2TypedArray(fetchGroups, String.class); // } if (_saleAccessControlHelper == null) throw new NullPointerException("saleAccessControlHelper"); //$NON-NLS-1$ this.saleAccessControlHelper = _saleAccessControlHelper; if (showProductTypeLabel) { productTypeLabel = new Label(this, SWT.BORDER); productTypeLabel.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); } XComposite statusComp = new XComposite(this, SWT.NONE, LayoutMode.TIGHT_WRAPPER); statusComp.getGridData().grabExcessVerticalSpace = false; createStatusControlsForStatusComposite(statusComp, CollectionUtil.array2ArrayList(new String[] { STATUS_CONTROL_ID_PUBLISHED, STATUS_CONTROL_ID_CONFIRMED, STATUS_CONTROL_ID_SALEABLE, STATUS_CONTROL_ID_CLOSED })); statusComp.getGridLayout().numColumns = statusComp.getChildren().length; // JDOLifecycleManager.sharedInstance().addNotificationListener(ProductType.class, productTypeChangedListener); // addDisposeListener(new DisposeListener(){ // public void widgetDisposed(DisposeEvent e) // { // JDOLifecycleManager.sharedInstance().removeNotificationListener(ProductType.class, productTypeChangedListener); // } // }); setProductType(null); } protected void createStatusControlsForStatusComposite(Composite parent, List<String> statusControlIDs) { for (String statusControlID : statusControlIDs) { Control control = createStatusControl(parent, statusControlID); addStatusControl(statusControlID, control); } } protected Control getStatusControl(String statusControlID) { return statusControlID2statusControl.get(statusControlID); } protected void addStatusControl(String statusControlID, Control control) { if (control != null) statusControlID2statusControl.put(statusControlID, control); } protected Control createStatusControl(Composite parent, String statusControlID) { if (STATUS_CONTROL_ID_PUBLISHED.equals(statusControlID)) { publishedCheckBox = new Button(parent, SWT.CHECK); publishedCheckBox.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.publishedCheckBox.text")); //$NON-NLS-1$ publishedCheckBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { publishedCheckBoxChanged(); } }); return publishedCheckBox; } else if (STATUS_CONTROL_ID_CONFIRMED.equals(statusControlID)) { confirmedCheckBox = new Button(parent, SWT.CHECK); confirmedCheckBox.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.confirmedCheckBox.text")); //$NON-NLS-1$ confirmedCheckBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { confirmedCheckBoxChanged(); } }); return confirmedCheckBox; } else if (STATUS_CONTROL_ID_SALEABLE.equals(statusControlID)) { saleableCheckBox = new Button(parent, SWT.CHECK); saleableCheckBox.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.saleableCheckBox.text")); //$NON-NLS-1$ saleableCheckBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { saleableCheckBoxChanged(saleableCheckBox.getSelection()); } }); return saleableCheckBox; } else if (STATUS_CONTROL_ID_CLOSED.equals(statusControlID)) { closedCheckBox = new Button(parent, SWT.CHECK); closedCheckBox.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.closedCheckBox.text")); //$NON-NLS-1$ closedCheckBox.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { closedCheckBoxChanged(); } }); return closedCheckBox; } else return null; } protected void updateControlsEnabled() { if (productType == null) return; saleableCheckBox.setEnabled(confirmedCheckBox.getSelection()); closedCheckBox.setEnabled(productType.isConfirmed()); } protected void publishedCheckBoxChanged() { try { if (publishedCheckBox.getSelection()) { boolean flag = saleAccessControlHelper.canPublish(false); if (flag) { flag = MessageDialog.openConfirm( RCPUtil.getActiveShell(), Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.publishDialog.title"), //$NON-NLS-1$ Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.publishDialog.message")); //$NON-NLS-1$ } if (!flag) publishedCheckBox.setSelection(false); } else { if (productType.isPublished()) { MessageDialog.openError( RCPUtil.getActiveWorkbenchShell(), Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.publishDialog.undo.title"), //$NON-NLS-1$ Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.publishDialog.undo.message")); //$NON-NLS-1$ publishedCheckBox.setSelection(true); } } } catch (Throwable t) { publishedCheckBox.setSelection(!publishedCheckBox.getSelection()); throw new RuntimeException(t); } updateControlsEnabled(); calculateChanged(); if (dirtyStateManager != null) { if (isChanged()) dirtyStateManager.markDirty(); } } protected void confirmedCheckBoxChanged() { try { if (confirmedCheckBox.getSelection()) { boolean flag = saleAccessControlHelper.canConfirm(false); if (flag) { flag = MessageDialog.openConfirm( RCPUtil.getActiveShell(), Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.confirmDialog.title"), //$NON-NLS-1$ Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.confirmDialog.message")); //$NON-NLS-1$ } if (!flag) confirmedCheckBox.setSelection(false); else { if (!saleableCheckBox.isEnabled()) { saleableCheckBox.setSelection(true); saleableCheckBoxChanged(saleableCheckBox.getSelection()); } } } else { if (productType.isConfirmed()) { MessageDialog.openError( RCPUtil.getActiveShell(), Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.undoConfirmDialog.title"), //$NON-NLS-1$ Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.undoConfirmDialog.message")); //$NON-NLS-1$ confirmedCheckBox.setSelection(true); } else saleableCheckBox.setSelection(false); } } catch (Throwable t) { confirmedCheckBox.setSelection(!confirmedCheckBox.getSelection()); throw new RuntimeException(t); } updateControlsEnabled(); calculateChanged(); if (dirtyStateManager != null) { if (isChanged()) dirtyStateManager.markDirty(); } } /** * Set the saleable state. Call this method from a subclass to set the saleable state. * * @param saleable whether or not to make it saleable. */ protected final void setSaleable(boolean saleable) { if (saleable == saleableCheckBox.getSelection()) return; saleableCheckBox.setSelection(saleable); saleableCheckBoxChanged(saleableCheckBox.getSelection()); } protected void saleableCheckBoxChanged(boolean checked) { try { if (checked) { boolean flag = saleAccessControlHelper.canSetSaleable(false, saleableCheckBox.getSelection()); if (!flag) saleableCheckBox.setSelection(!saleableCheckBox.getSelection()); } else { // nothing } } catch (Throwable t) { saleableCheckBox.setSelection(!saleableCheckBox.getSelection()); throw new RuntimeException(t); } updateControlsEnabled(); calculateChanged(); if (dirtyStateManager != null) { if (isChanged()) dirtyStateManager.markDirty(); } } protected IDirtyStateManager getDirtyStateManager() { return dirtyStateManager; } protected void closedCheckBoxChanged() { try { if (closedCheckBox.getSelection()) { boolean flag = saleAccessControlHelper.canClose(false); if (flag) { flag = MessageDialog.openConfirm( RCPUtil.getActiveShell(), Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.closeDialog.title"), //$NON-NLS-1$ Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.closeDialog.message")); //$NON-NLS-1$ } if (!flag) closedCheckBox.setSelection(false); saleableCheckBox.setSelection(false); } else { // nothing saleableCheckBox.setSelection(true); } } catch (Throwable t) { closedCheckBox.setSelection(!closedCheckBox.getSelection()); throw new RuntimeException(t); } updateControlsEnabled(); calculateChanged(); if (dirtyStateManager != null) { if (isChanged()) dirtyStateManager.markDirty(); } } private boolean published = false; public boolean isPublished() { return published; } private boolean confirmed = false; public boolean isConfirmed() { return confirmed; } private boolean saleable = false; public boolean isSaleable() { return saleable; } private boolean closed = false; public boolean isClosed() { return closed; } private void calculateChanged() { changed = (publishedCheckBox.getSelection() != productType.isPublished()) || (confirmedCheckBox.getSelection() != productType.isConfirmed()) || (saleableCheckBox.getSelection() != productType.isSaleable()) || (closedCheckBox.getSelection() != productType.isClosed()); published = publishedCheckBox.getSelection(); confirmed = confirmedCheckBox.getSelection(); saleable = saleableCheckBox.getSelection(); closed = closedCheckBox.getSelection(); } // I think this is set by the surrounding composite/editor // protected NotificationListener productTypeChangedListener = new NotificationAdapterJob(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.loadProductTypesJob.name")) { //$NON-NLS-1$ // public void notify(NotificationEvent notificationEvent) // { // DirtyObjectID dirtyObjectID = (DirtyObjectID) notificationEvent.getFirstSubject(); // ProductTypeID productTypeID = (ProductTypeID) dirtyObjectID.getObjectID(); // if (productTypeID == null || !productTypeID.equals(JDOHelper.getObjectId(productType))) // return; // We have none or another object open and are not interested in this change. // // try { // setProductTypeID(productTypeID); // } catch (ModuleException e) { // throw new RuntimeException(e); // } // } // }; public SaleAccessControlHelper getSaleAccessControlHelper() { return saleAccessControlHelper; } private String[] fetchGroupsProductType; public String[] getFetchGroupsProductType() { return fetchGroupsProductType; } // protected static String[] FETCH_GROUPS_PRODUCT_TYPE_MIN = new String[] { // FetchPlan.DEFAULT, // ProductType.FETCH_GROUP_NAME}; // /** // * @deprecated should not be used anymore, call {@link SaleAccessControlComposite#setProductType(ProductType)} instead // * // * @param productTypeID the {@link ProductTypeID} of the {@link ProductType} to load // * @throws ModuleException if something during loading the productType went wrong // */ // @Deprecated // public void setProductTypeID(ProductTypeID productTypeID) // throws ModuleException // { // try { // if (productTypeID == null) { // Display.getDefault().asyncExec(new Runnable() { // public void run() { // setProductType(null); // } // }); // return; // } // // StoreManager sm = JFireEjbFactory.getBean(StoreManager.class, Login.getLogin().getInitialContextProperties()); // final ProductType productType = sm.getProductType( // productTypeID, fetchGroupsProductType, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); // // if (Thread.currentThread() == Display.getDefault().getThread()) // setProductType(productType); // else { // Display.getDefault().asyncExec(new Runnable() { // public void run() { // setProductType(productType); // } // }); // } // } catch (Exception x) { // throw new ModuleException(x); // } // } /** * @param productType The selected ProductType. */ public void setProductType(ProductType productType) { if (isDisposed()) return; saleAccessControlHelper.setProductType(productType); productType = saleAccessControlHelper.getProductType(); this.productType = productType; if (productType == null) { setEnabled(false); if (showProductTypeLabel) productTypeLabel.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.producttype.SaleAccessControlComposite.productTypeLabel.text_nothingSelected")); //$NON-NLS-1$ publishedCheckBox.setSelection(false); confirmedCheckBox.setSelection(false); saleableCheckBox.setSelection(false); closedCheckBox.setSelection(false); } else { if (showProductTypeLabel) productTypeLabel.setText(productType.getName().getText(NLLocale.getDefault().getLanguage())); publishedCheckBox.setSelection(productType.isPublished()); confirmedCheckBox.setSelection(productType.isConfirmed()); saleableCheckBox.setSelection(productType.isSaleable()); closedCheckBox.setSelection(productType.isClosed()); setEnabled(true); updateControlsEnabled(); } changed = false; published = publishedCheckBox.getSelection(); confirmed = confirmedCheckBox.getSelection(); saleable = saleableCheckBox.getSelection(); closed = closedCheckBox.getSelection(); } private boolean changed = false; public boolean isChanged() { return changed; } /** * @deprecated should not be called any more, but productType should be saved * somewhere else e.g. by a controller * * Submit all the settings to the server. */ @Deprecated public void submit() { if (productType == null) return; if (!isChanged()) return; try { ProductTypeID productTypeID = (ProductTypeID) JDOHelper.getObjectId(productType); boolean make_published = published && !productType.isPublished(); boolean make_confirmed = confirmed && !productType.isConfirmed(); boolean make_saleable_true = saleable && !productType.isSaleable(); boolean make_saleable_false = !saleable && productType.isSaleable();; boolean make_closed = closed && !productType.isClosed(); // setEnabled(false); StoreManagerRemote storeManager = JFireEjb3Factory.getRemoteBean(StoreManagerRemote.class, Login.getLogin().getInitialContextProperties()); if (make_published) storeManager.setProductTypeStatus_published(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); if (make_confirmed) storeManager.setProductTypeStatus_confirmed(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); if (make_saleable_true || make_saleable_false) storeManager.setProductTypeStatus_saleable(productTypeID, make_saleable_true, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); if (make_closed) storeManager.setProductTypeStatus_closed(productTypeID, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); } catch (Exception e) { throw new RuntimeException(e); } } // public Composite getStatusComposite() { // return statusComposite; // } }