/* ***************************************************************************** * 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.ui.articlecontainer.detail.offer; import java.util.Date; import javax.jdo.JDOHelper; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ControlAdapter; import org.eclipse.swt.events.ControlEvent; import org.eclipse.swt.events.DisposeEvent; import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.FocusAdapter; import org.eclipse.swt.events.FocusEvent; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.RowData; import org.eclipse.swt.layout.RowLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Label; import org.nightlabs.base.ui.composite.DateTimeControl; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.job.Job; import org.nightlabs.base.ui.notification.NotificationAdapterJob; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jfire.base.JFireEjb3Factory; import org.nightlabs.jfire.base.jdo.notification.JDOLifecycleManager; import org.nightlabs.jfire.base.login.ui.Login; import org.nightlabs.jfire.jbpm.ui.state.CurrentStateComposite; import org.nightlabs.jfire.jbpm.ui.transition.next.NextTransitionComposite; import org.nightlabs.jfire.jbpm.ui.transition.next.SignalEvent; import org.nightlabs.jfire.jbpm.ui.transition.next.SignalListener; import org.nightlabs.jfire.trade.Offer; import org.nightlabs.jfire.trade.TradeManagerRemote; import org.nightlabs.jfire.trade.dao.OfferDAO; import org.nightlabs.jfire.trade.id.OfferID; import org.nightlabs.jfire.trade.ui.articlecontainer.detail.ArticleContainerEditComposite; import org.nightlabs.jfire.trade.ui.articlecontainer.detail.HeaderComposite; import org.nightlabs.jfire.trade.ui.articlecontainer.detail.HeaderVendorCustomerComposite; import org.nightlabs.jfire.trade.ui.resource.Messages; import org.nightlabs.l10n.IDateFormatter; import org.nightlabs.notification.NotificationEvent; import org.nightlabs.notification.NotificationListener; import org.nightlabs.progress.ProgressMonitor; import org.nightlabs.progress.SubProgressMonitor; /** * @author Marco Schulze - marco at nightlabs dot de */ public class OfferHeaderComposite extends HeaderComposite { private volatile Offer offer; private final CurrentStateComposite currentStateComposite; private final NextTransitionComposite nextTransitionComposite; private XComposite expiryTimestampContainerComp; private XComposite expiryTimestampUnfinalizedComp; private DateTimeControl expiryTimestampUnfinalized; private Button expiryTimestampUnfinalizedAutoManaged; private XComposite expiryTimestampFinalizedComp; private DateTimeControl expiryTimestampFinalized; private Button expiryTimestampFinalizedAutoManaged; private final HeaderVendorCustomerComposite headerVendorCustomerComposite; protected OfferID getOfferID() { return (OfferID) JDOHelper.getObjectId(offer); } private final RowData headerVendorCustomerCompositeRowData; private int getHeaderVendorCustomerCompositeRowDataWidth() { final RowLayout rowLayout = (RowLayout)getLayout(); return getClientArea().width - rowLayout.marginLeft - rowLayout.marginRight - rowLayout.marginWidth; } public OfferHeaderComposite(final ArticleContainerEditComposite articleContainerEditComposite, final Offer offer) { super(articleContainerEditComposite, articleContainerEditComposite, offer); this.offer = offer; this.setLayout(new RowLayout()); headerVendorCustomerComposite = new HeaderVendorCustomerComposite(this); headerVendorCustomerCompositeRowData = new RowData(getHeaderVendorCustomerCompositeRowDataWidth(), headerVendorCustomerComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT).y); headerVendorCustomerComposite.setLayoutData(headerVendorCustomerCompositeRowData); addControlListener(new ControlAdapter() { @Override public void controlResized(final ControlEvent e) { headerVendorCustomerCompositeRowData.width = getHeaderVendorCustomerCompositeRowDataWidth(); } }); currentStateComposite = new CurrentStateComposite(this, SWT.NONE); currentStateComposite.setStatable(offer); currentStateComposite.setLayoutData(null); nextTransitionComposite = new NextTransitionComposite(this, SWT.NONE); nextTransitionComposite.setStatable(offer); nextTransitionComposite.setLayoutData(new RowData(260, SWT.DEFAULT)); nextTransitionComposite.addSignalListener(new SignalListener() { @Override public void signal(final SignalEvent event) { signalNextTransition(event); } }); if (!offer.isFinalized()) { if (expiryTimestampContainerComp == null) expiryTimestampContainerComp = new XComposite(this, SWT.NONE, LayoutMode.TOP_BOTTOM_WRAPPER, LayoutDataMode.NONE); expiryTimestampUnfinalizedComp = new XComposite(expiryTimestampContainerComp, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.NONE); expiryTimestampUnfinalizedComp.setLayoutData(null); expiryTimestampUnfinalizedComp.getGridLayout().numColumns = 2; new Label(expiryTimestampUnfinalizedComp, SWT.NONE).setText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.label.expiry.unfinalized")); //$NON-NLS-1$ expiryTimestampUnfinalized = new DateTimeControl(expiryTimestampUnfinalizedComp, SWT.NONE, IDateFormatter.FLAGS_DATE_SHORT_TIME_HM); new Label(expiryTimestampUnfinalizedComp, SWT.NONE); expiryTimestampUnfinalizedAutoManaged = new Button(expiryTimestampUnfinalizedComp, SWT.CHECK); expiryTimestampUnfinalizedAutoManaged.setText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.button.text.manageAutomatically")); //$NON-NLS-1$ expiryTimestampUnfinalizedAutoManaged.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.button.tooltip.manageAutomatically")); //$NON-NLS-1$ expiryTimestampUnfinalized.setDate(offer.getExpiryTimestampUnfinalized()); expiryTimestampUnfinalizedAutoManaged.setSelection(offer.isExpiryTimestampUnfinalizedAutoManaged()); expiryTimestampUnfinalizedAutoManaged.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { saveExpiryTimestamp(); } }); expiryTimestampUnfinalized.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { expiryTimestampUnfinalizedAutoManaged.setSelection(false); saveExpiryTimestamp(); } }); expiryTimestampUnfinalized.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent event) { expiryTimestampModifiedNeedsSaveOnFocusLost = true; expiryTimestampUnfinalizedAutoManaged.setSelection(false); } }); expiryTimestampUnfinalized.addFocusListener(new FocusAdapter() { @Override public void focusLost(final FocusEvent e) { if (expiryTimestampModifiedNeedsSaveOnFocusLost) { expiryTimestampModifiedNeedsSaveOnFocusLost = false; saveExpiryTimestamp(); } } }); } if (!offer.getOfferLocal().isAccepted()) { if (expiryTimestampContainerComp == null) expiryTimestampContainerComp = new XComposite(this, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.NONE); expiryTimestampFinalizedComp = new XComposite(expiryTimestampContainerComp, SWT.NONE, LayoutMode.TIGHT_WRAPPER, LayoutDataMode.NONE); expiryTimestampFinalizedComp.setLayoutData(null); expiryTimestampFinalizedComp.getGridLayout().numColumns = 2; new Label(expiryTimestampFinalizedComp, SWT.NONE).setText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.label.expiry.finalized")); //$NON-NLS-1$ expiryTimestampFinalized = new DateTimeControl(expiryTimestampFinalizedComp, SWT.NONE, IDateFormatter.FLAGS_DATE_SHORT_TIME_HM); new Label(expiryTimestampFinalizedComp, SWT.NONE); expiryTimestampFinalizedAutoManaged = new Button(expiryTimestampFinalizedComp, SWT.CHECK); expiryTimestampFinalizedAutoManaged.setText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.button.text.manageAutomatically")); //$NON-NLS-1$ expiryTimestampFinalizedAutoManaged.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.button.tooltip.manageAutomatically")); //$NON-NLS-1$ expiryTimestampFinalized.setDate(offer.getExpiryTimestampFinalized()); expiryTimestampFinalizedAutoManaged.setSelection(offer.isExpiryTimestampFinalizedAutoManaged()); expiryTimestampFinalizedAutoManaged.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { saveExpiryTimestamp(); } }); expiryTimestampFinalized.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(final SelectionEvent e) { expiryTimestampFinalizedAutoManaged.setSelection(false); saveExpiryTimestamp(); } }); expiryTimestampFinalized.addModifyListener(new ModifyListener() { @Override public void modifyText(final ModifyEvent event) { expiryTimestampModifiedNeedsSaveOnFocusLost = true; expiryTimestampFinalizedAutoManaged.setSelection(false); } }); expiryTimestampFinalized.addFocusListener(new FocusAdapter() { @Override public void focusLost(final FocusEvent e) { if (expiryTimestampModifiedNeedsSaveOnFocusLost) { expiryTimestampModifiedNeedsSaveOnFocusLost = false; saveExpiryTimestamp(); } } }); if (offer.isFinalized()) expiryTimestampFinalizedComp.setEnabled(false); } if (expiryTimestampContainerComp != null) expiryTimestampContainerComp.getGridLayout().numColumns = 2; createArticleContainerContextMenu(); JDOLifecycleManager.sharedInstance().addNotificationListener(Offer.class, offerChangedListener); addDisposeListener(new DisposeListener() { public void widgetDisposed(final DisposeEvent e) { JDOLifecycleManager.sharedInstance().removeNotificationListener(Offer.class, offerChangedListener); } }); getDisplay().asyncExec(new Runnable() { public void run() { if (isDisposed()) return; getShell().layout(true, true); getDisplay().asyncExec(new Runnable() { public void run() { if (isDisposed()) return; getShell().layout(true, true); } }); } }); } private boolean expiryTimestampModifiedNeedsSaveOnFocusLost = false; private void saveExpiryTimestamp() { final Date _expiryTimestampUnfinalized = expiryTimestampUnfinalized == null ? offer.getExpiryTimestampUnfinalized() : expiryTimestampUnfinalized.getDate(); final boolean _expiryTimestampUnfinalizedAutoManaged = expiryTimestampUnfinalizedAutoManaged == null ? offer.isExpiryTimestampUnfinalizedAutoManaged() : expiryTimestampUnfinalizedAutoManaged.getSelection(); final Date _expiryTimestampFinalized = expiryTimestampFinalized == null ? offer.getExpiryTimestampFinalized() : expiryTimestampFinalized.getDate(); final boolean _expiryTimestampFinalizedAutoManaged = expiryTimestampFinalizedAutoManaged == null ? offer.isExpiryTimestampFinalizedAutoManaged() : expiryTimestampFinalizedAutoManaged.getSelection(); final org.nightlabs.base.ui.job.Job job = new org.nightlabs.base.ui.job.Job(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.job.name.savingExpiryTimeStamp")) { //$NON-NLS-1$ @Override protected IStatus run(final ProgressMonitor monitor) throws Exception { monitor.beginTask(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.job.name.savingExpiryTimeStamp"), 2); //$NON-NLS-1$ try { final Offer _offer = OfferDAO.sharedInstance().setOfferExpiry( getOfferID(), _expiryTimestampUnfinalized, _expiryTimestampUnfinalizedAutoManaged, _expiryTimestampFinalized, _expiryTimestampFinalizedAutoManaged, true, ArticleContainerEditComposite.FETCH_GROUPS_ARTICLE_CONTAINER_WITHOUT_ARTICLES, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new SubProgressMonitor(monitor, 1)); onOfferModified(_offer, new SubProgressMonitor(monitor, 1)); } finally { monitor.done(); } return Status.OK_STATUS; } }; job.setPriority(Job.INTERACTIVE); job.setUser(true); job.schedule(); } private void onOfferModified(final Offer offer, final ProgressMonitor monitor) { monitor.beginTask(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.job.task.name.updateUI"), 100); //$NON-NLS-1$ try { this.offer = offer; currentStateComposite.setStatable(offer, new SubProgressMonitor(monitor, 1)); nextTransitionComposite.setStatable(offer, new SubProgressMonitor(monitor, 1)); getDisplay().asyncExec(new Runnable() { public void run() { if (expiryTimestampUnfinalizedComp != null && offer.isFinalized()) { expiryTimestampUnfinalizedComp.dispose(); expiryTimestampUnfinalizedComp = null; expiryTimestampUnfinalized = null; expiryTimestampUnfinalizedAutoManaged = null; } if (expiryTimestampFinalizedComp != null && (offer.getOfferLocal().isAccepted() || offer.getOfferLocal().isRejected())) { expiryTimestampFinalizedComp.dispose(); expiryTimestampFinalizedComp = null; expiryTimestampFinalized = null; expiryTimestampFinalizedAutoManaged = null; } if (expiryTimestampUnfinalizedComp == null && expiryTimestampFinalizedComp == null && expiryTimestampContainerComp != null) { expiryTimestampContainerComp.dispose(); expiryTimestampContainerComp = null; } if (expiryTimestampUnfinalized != null) { expiryTimestampUnfinalized.setDate(offer.getExpiryTimestampUnfinalized()); expiryTimestampUnfinalizedAutoManaged.setSelection(offer.isExpiryTimestampUnfinalizedAutoManaged()); } if (expiryTimestampFinalized != null) { expiryTimestampFinalized.setDate(offer.getExpiryTimestampFinalized()); expiryTimestampFinalizedAutoManaged.setSelection(offer.isExpiryTimestampFinalizedAutoManaged()); if (offer.isFinalized()) expiryTimestampFinalizedComp.setEnabled(false); } getShell().layout(true, true); } }); } finally { monitor.done(); } } private final NotificationListener offerChangedListener = new NotificationAdapterJob(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.loadOfferJob.name")) { //$NON-NLS-1$ public void notify(final NotificationEvent notificationEvent) { final ProgressMonitor monitor = getProgressMonitor(); monitor.beginTask( Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.loadOfferMonitor.task.name"), //$NON-NLS-1$ 3 ); final Offer _offer = OfferDAO.sharedInstance().getOffer( (OfferID) JDOHelper.getObjectId(offer), // ArticleContainerEditComposite.FETCH_GROUPS_OFFER_WITH_ARTICLES, // it's fine to use these fetch groups here, because we'll get it out of the cache - hence it's even better to load it with more fetch groups than only with the ones we need in this composite // After a change, it does NOT load the ArticleContainer *with* articles, but *WITHOUT*! // Therefore, it's a bad idea to load them with articles! Marco. ArticleContainerEditComposite.FETCH_GROUPS_ARTICLE_CONTAINER_WITHOUT_ARTICLES, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new SubProgressMonitor(monitor, 1)); onOfferModified(_offer, new SubProgressMonitor(monitor, 2)); monitor.done(); } }; private void signalNextTransition(final SignalEvent event) { final Job job = new Job(Messages.getString("org.nightlabs.jfire.trade.ui.articlecontainer.detail.offer.OfferHeaderComposite.performTransitionJob.name")) { //$NON-NLS-1$ @Override protected IStatus run(final ProgressMonitor monitor) { try { final TradeManagerRemote tm = JFireEjb3Factory.getRemoteBean(TradeManagerRemote.class, Login.getLogin().getInitialContextProperties()); tm.signalOffer((OfferID)JDOHelper.getObjectId(offer), event.getTransition().getJbpmTransitionName()); } catch (final Exception x) { throw new RuntimeException(x); } return Status.OK_STATUS; } }; job.setPriority(Job.SHORT); job.setUser(true); job.schedule(); } @Override public void refresh() { headerVendorCustomerComposite.setArticleContainer(getArticleContainer()); } }