/* *****************************************************************************
* 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;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import javax.jdo.JDOHelper;
import org.eclipse.core.runtime.ListenerList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.nightlabs.base.ui.wizard.DynamicPathWizardDialog;
import org.nightlabs.jfire.accounting.Invoice;
import org.nightlabs.jfire.store.DeliveryNote;
import org.nightlabs.jfire.trade.Article;
import org.nightlabs.jfire.trade.ArticleCarrier;
import org.nightlabs.jfire.trade.ArticleContainer;
import org.nightlabs.jfire.trade.ArticleProductTypeClassGroup;
import org.nightlabs.jfire.trade.Offer;
import org.nightlabs.jfire.trade.id.ArticleID;
import org.nightlabs.jfire.trade.ui.articlecontainer.detail.action.changetariff.ChangeTariffWizard;
/**
* @author Marco Schulze - marco at nightlabs dot de
*/
public abstract class AbstractArticleEdit implements ArticleEdit
{
private ArticleEditFactory articleEditFactory;
private SegmentEdit segmentEdit;
private ArticleProductTypeClassGroup articleProductTypeClassGroup;
/**
* Because this ArticleEdit might only manage a subset of the <code>Article</code>s managed
* by the {@link #articleProductTypeClassGroup}, we need to store them again. This holds instances
* of {@link ArticleCarrier}.
*/
private Set<ArticleCarrier> articleCarriers;
public void init(ArticleEditFactory articleEditFactory,
SegmentEdit segmentEdit, ArticleProductTypeClassGroup articleProductTypeClassGroup, Set<ArticleCarrier> articleCarriers)
{
this.articleEditFactory = articleEditFactory;
this.segmentEdit = segmentEdit;
this.articleCarriers = articleCarriers;
this.articleProductTypeClassGroup = articleProductTypeClassGroup;
for (ArticleCarrier articleCarrier : articleCarriers) {
if (this.articleProductTypeClassGroup != articleCarrier.getArticleProductTypeClassGroup()) {
StringBuffer sb = new StringBuffer("All ArticleCarriers need to belong to the passed ArticleProductTypeClassGroup!"); //$NON-NLS-1$
for (ArticleCarrier ac : articleCarriers) {
sb.append("\n articlePK=\""); //$NON-NLS-1$
sb.append(ac.getArticle().getPrimaryKey());
sb.append("\" article.productTypePK=\""); //$NON-NLS-1$
sb.append(ac.getArticle().getProductType().getPrimaryKey());
sb.append("\" articleCarrier.articleProductTypeClassGroup=\""); //$NON-NLS-1$
sb.append(ac.getArticleProductTypeClassGroup());
sb.append("\" articleSegmentGroup=\""); //$NON-NLS-1$
sb.append(ac.getArticleProductTypeClassGroup().getArticleSegmentGroup());
sb.append("\" articleSegmentGroups=\""); //$NON-NLS-1$
sb.append(ac.getArticleProductTypeClassGroup().getArticleSegmentGroup().getArticleSegmentGroupSet());
sb.append("\""); //$NON-NLS-1$
}
throw new IllegalArgumentException(sb.toString());
}
}
}
public ArticleEditFactory getArticleEditFactory()
{
return articleEditFactory;
}
public SegmentEdit getSegmentEdit()
{
return segmentEdit;
}
public ArticleProductTypeClassGroup getArticleProductTypeClassGroup()
{
return articleProductTypeClassGroup;
}
/**
* When extending this class and implementing {@link ArticleEdit#addArticles(Set)},
* you <b>must</b> call this method with all {@link ArticleCarrier}s you want to accept
* and refresh your GUI afterwards.
*
* @param articles The articles to be added.
* @return Returns instances of {@link ArticleCarrier} wrapping the given <code>articles</code>.
*/
protected void _addArticleCarriers(Collection<? extends ArticleCarrier> articleCarriers)
{
// Collection<ArticleCarrier> res = getArticleProductTypeClassGroup().getArticleCarriers(articles);
// this.articleCarriers.addAll(res);
// return res;
this.articleCarriers.addAll(articleCarriers);
}
/*
* (non-Javadoc)
* @see org.nightlabs.jfire.trade.ui.articlecontainer.detail.ArticleEdit#removeArticles(java.util.Collection)
*/
@Override
public Collection<ArticleCarrier> removeArticles(Collection<ArticleCarrier> articleCarriers) {
for (Iterator<ArticleCarrier> it = articleCarriers.iterator(); it.hasNext(); ) {
if (this.articleCarriers.remove(it.next()))
it.remove();
}
return articleCarriers;
}
// /**
// * Note, that you must call {@link #_removeArticles(Set)} in your implementation
// * of this method!
// * <br/><br/>
// *
// * {@inheritDoc}
// */
// public abstract void removeArticles(Set<? extends Article> articles);
//
// /**
// * When extending this class and implementing {@link ArticleEdit#removeArticles(Set)},
// * you <b>must</b> call this method and refresh your GUI afterwards.
// *
// * @param articles
// */
// protected void _removeArticles(Set<? extends Article> articles)
// {
//// getArticleProductTypeClassGroup().removeArticles(articles);
// for (Iterator it = articleCarriers.iterator(); it.hasNext();) {
// ArticleCarrier articleCarrier = (ArticleCarrier) it.next();
// if (articles.contains(articleCarrier.getArticle()))
// it.remove();
// }
// }
//// public void removeArticles(Collection articles)
//// {
//// // TODO
//// articles = null;
//// }
//
// /**
// * Cache for {@link Article}s. Is created and populated by {@link #getArticles()}.
// */
// private Set articles = null;
public Set<? extends Article> getArticles()
{
// if (articles == null) {
Set<Article> s = new HashSet<Article>(articleCarriers.size());
for (ArticleCarrier articleCarrier : articleCarriers) {
s.add(articleCarrier.getArticle());
}
return Collections.unmodifiableSet(s);
// articles = Collections.unmodifiableSet(s);
// }
//
// return articles;
}
public Set<? extends ArticleCarrier> getArticleCarriers()
{
return Collections.unmodifiableSet(articleCarriers);
}
/**
* {@link #createComposite(Composite)} initializes this field and
* {@link #dispose()} the <tt>Composite</tt> if it is existing.
*/
private Composite composite = null;
// /**
// * The parent of the composite
// */
// private Composite parent = null;
private boolean ctrlKeyDown = false;
/**
* Find out whether the "Ctrl" key is currently pressed down.
* <p>
* It's urgently recommended to take the Ctrl key into account when selecting articles in an <code>ArticleEdit</code>'s composite. If this key is not pressed
* down, all other currently selected articles (in all other <code>ArticleEdit</code> s should be deselected.
* </p>
*
* @return <code>true</code>, if the Ctrl key is currently down.
*/
public boolean isCtrlKeyDown()
{
return ctrlKeyDown;
}
private Listener ctrlKeyDownListener = new Listener() {
public void handleEvent(Event event)
{
if (event.keyCode == SWT.CTRL)
ctrlKeyDown = true;
}
};
private Listener ctrlKeyUpListener = new Listener() {
public void handleEvent(Event event)
{
if (event.keyCode == SWT.CTRL)
ctrlKeyDown = false;
}
};
/**
* Important: Do NOT overwrite/extend this method, but implement {@link #_createComposite(Composite)} instead!
*
* @see org.nightlabs.jfire.trade.ui.articlecontainer.detail.ArticleEdit#createComposite(org.eclipse.swt.widgets.Composite)
*/
public Composite createComposite(Composite parent)
{
// this.parent = parent;
if (composite != null)
throw new IllegalStateException("createComposite(...) has already been called! Have already a composite!"); //$NON-NLS-1$
composite = _createComposite(parent);
Display.getDefault().addFilter(SWT.KeyDown, ctrlKeyDownListener);
Display.getDefault().addFilter(SWT.KeyUp, ctrlKeyUpListener);
composite.addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e)
{
Display.getDefault().removeFilter(SWT.KeyDown, ctrlKeyDownListener);
Display.getDefault().removeFilter(SWT.KeyUp, ctrlKeyUpListener);
((Composite)e.getSource()).removeDisposeListener(this);
onDispose();
}
});
return composite;
}
public Composite getComposite()
{
return composite;
}
/**
* This method is called by {@link #createComposite(Composite)}. Implement it and return a new instance
* of <tt>Composite</tt>.
*
* @param parent The parent <tt>Composite</tt> for the new <tt>Composite</tt>.
* @return The newly created <tt>Composite</tt>.
*/
protected abstract Composite _createComposite(Composite parent);
public void onDispose()
{
composite = null;
}
public void dispose()
{
if (composite != null)
composite.dispose();
}
private ListenerList articleEditArticleSelectionListeners = new ListenerList();
public void addArticleEditArticleSelectionListener(ArticleEditArticleSelectionListener listener)
{
articleEditArticleSelectionListeners.add(listener);
}
public void removeArticleEditArticleSelectionListener(ArticleEditArticleSelectionListener listener)
{
articleEditArticleSelectionListeners.remove(listener);
}
/**
* Your implementation must call this method on the SWT GUI thread, whenever the selection of
* {@link org.nightlabs.jfire.trade.ui.Article}s
* changed.
*/
public void fireArticleEditArticleSelectionEvent()
{
if (Display.getCurrent().getThread() != Thread.currentThread())
throw new IllegalStateException("You must call this method on the GUI thread!"); //$NON-NLS-1$
ArticleEditArticleSelectionEvent event = null;
Object[] listeners = articleEditArticleSelectionListeners.getListeners();
for (int i = 0; i < listeners.length; ++i) {
ArticleEditArticleSelectionListener listener = (ArticleEditArticleSelectionListener) listeners[i];
if (event == null)
event = new ArticleEditArticleSelectionEvent(this);
listener.selected(event);
}
}
/* (non-Javadoc)
* @see org.nightlabs.jfire.trade.ui.articlecontainer.detail.ArticleEdit#changeTariffForSelectedArticles()
*/
@Override
public void changeTariffForSelectedArticles() {
Set<ArticleID> selectedArticleIDs = new HashSet<ArticleID>();
// check if articles are allocated because only for those can the tariff be changes
for (Article article : getSelectedArticles()) {
if (article.isAllocated()) {
selectedArticleIDs.add((ArticleID)JDOHelper.getObjectId(article));
}
}
if (!selectedArticleIDs.isEmpty()) {
ChangeTariffWizard changeTariffWizard = new ChangeTariffWizard(selectedArticleIDs);
DynamicPathWizardDialog dialog = new DynamicPathWizardDialog(changeTariffWizard);
dialog.open();
}
}
/**
* This method checks of the Article Container has been finalized and if so it returns True.
*
* @return Boolean value if it has been finalized or no.
*/
public boolean isNonOrderArticleContainerFinalized() {
ArticleContainer ac = getSegmentEdit().getArticleContainer();
if (ac instanceof Offer) {
return ((Offer) ac).isFinalized();
} else if (ac instanceof Invoice) {
return ((Invoice) ac).isFinalized();
} else if (ac instanceof DeliveryNote) {
return ((DeliveryNote) ac).isFinalized();
} // TODO: Handle ReceptionNotes
return false;
}
// public boolean isInOrder()
// {
// return Order.class.getName().equals(getSegmentEdit().getArticleContainerClass());
// }
// public boolean isInOffer()
// {
// return Offer.class.equals(getSegmentEdit().getArticleContainerClass());
// }
// public boolean isInInvoice()
// {
// return Invoice.class.equals(getSegmentEdit().getArticleContainerClass());
// }
// public boolean isInDeliveryNote()
// {
// return DeliveryNote.class.equals(getSegmentEdit().getArticleContainerClass());
// }
// public boolean isInReceptionNote()
// {
// return ReceptionNote.class.equals(getSegmentEdit().getArticleContainerClass());
// }
}