package org.nightlabs.jfire.trade.ui.overview; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.jdo.FetchPlan; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.jobs.IJobChangeEvent; import org.eclipse.core.runtime.jobs.JobChangeAdapter; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.SashForm; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Text; import org.nightlabs.base.ui.composite.XComposite; import org.nightlabs.base.ui.composite.XComposite.LayoutDataMode; import org.nightlabs.base.ui.composite.XComposite.LayoutMode; import org.nightlabs.base.ui.job.Job; import org.nightlabs.base.ui.notification.NotificationAdapterJob; import org.nightlabs.base.ui.table.AbstractTableComposite; import org.nightlabs.base.ui.toolkit.IToolkit; import org.nightlabs.base.ui.util.RCPUtil; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jfire.accounting.Currency; import org.nightlabs.jfire.accounting.Price; import org.nightlabs.jfire.accounting.PriceFragment; import org.nightlabs.jfire.accounting.PriceFragmentType; import org.nightlabs.jfire.base.jdo.notification.JDOLifecycleManager; import org.nightlabs.jfire.base.ui.config.ConfigUtil; import org.nightlabs.jfire.base.ui.overview.Entry; import org.nightlabs.jfire.base.ui.overview.search.JDOQuerySearchEntryViewer; import org.nightlabs.jfire.trade.ArticleContainer; import org.nightlabs.jfire.trade.PricedArticleContainer; import org.nightlabs.jfire.trade.config.SummedPriceFragmentTypeConfigModule; import org.nightlabs.jfire.trade.query.AbstractArticleContainerQuery; import org.nightlabs.l10n.NumberFormatter; import org.nightlabs.notification.NotificationEvent; import org.nightlabs.notification.NotificationListener; import org.nightlabs.progress.ProgressMonitor; import org.nightlabs.progress.SubProgressMonitor; /** * @author Daniel.Mazurek [at] NightLabs [dot] de * @author Marco Schulze - Marco at NightLabs dot de */ public abstract class ArticleContainerEntryViewer<R extends ArticleContainer, Q extends AbstractArticleContainerQuery> extends JDOQuerySearchEntryViewer<R, Q> { private Text footerTextTotal; private Text footerTextSelection; public ArticleContainerEntryViewer(Entry entry) { super(entry); } @Override protected void addResultTableListeners( final AbstractTableComposite<R> tableComposite) { super.addResultTableListeners(tableComposite); tableComposite.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { if (PricedArticleContainer.class.isAssignableFrom(getTargetType())) if (footerTextSelection != null && !footerTextSelection.isDisposed()) displayTotals(tableComposite.getSelectedElements(), footerTextSelection); } }); } private SummedPriceFragmentTypeConfigModule summedPriceFragmentTypeConfigModule; private XComposite footerComposite; private Label selectionLabel; private Label totalLabel; @Override public Composite createFooterComposite(final Composite parent) { //Checks if the target type is PricedArticleContainer or not... if (PricedArticleContainer.class.isAssignableFrom(getTargetType())) { loadConfigModuleJob.setPriority(Job.SHORT); loadConfigModuleJob.addJobChangeListener(new JobChangeAdapter() { @Override public void done(IJobChangeEvent event) { //Creates UIs getComposite().getDisplay().asyncExec(new Runnable() { @Override public void run() { if (footerComposite != null && !footerComposite.isDisposed()) { for (Control child : footerComposite.getChildren()) child.dispose(); footerComposite.dispose(); footerComposite = null; } if (!summedPriceFragmentTypeConfigModule.getSummedPriceFragmentTypeList().isEmpty()) { footerComposite = generateFooterComposite(parent); } setFooter(footerComposite); relayoutFooter(); } }); //Display }//done() }); loadConfigModuleJob.schedule(); } return footerComposite; } private XComposite generateFooterComposite(Composite parent) { XComposite footer = new XComposite(parent, SWT.NONE, LayoutMode.TOTAL_WRAPPER, LayoutDataMode.GRID_DATA_HORIZONTAL); footer.getGridLayout().numColumns = 4; IToolkit toolkit = XComposite.retrieveToolkit(footer); toolkit.adapt(footer); selectionLabel = toolkit.createLabel(footer, "Selection: ", SWT.RIGHT); GridData gridData = new GridData(GridData.FILL_VERTICAL); gridData.widthHint = 150; selectionLabel.setLayoutData(gridData); footerTextSelection = new Text(footer, SWT.RIGHT | SWT.MULTI); footerTextSelection.setEditable(false); gridData = new GridData(GridData.FILL_BOTH); gridData.widthHint = 450; footerTextSelection.setLayoutData(gridData); totalLabel = toolkit.createLabel(footer, "Total: ", SWT.RIGHT); gridData = new GridData(GridData.FILL_VERTICAL); gridData.widthHint = 150; totalLabel.setLayoutData(gridData); footerTextTotal = new Text(footer, SWT.RIGHT | SWT.MULTI); footerTextTotal.setEditable(false); gridData = new GridData(GridData.FILL_BOTH); gridData.widthHint = 450; footerTextTotal.setLayoutData(gridData); if (getListComposite().getElements().isEmpty()) { displayTotals((Collection<R>) Collections.EMPTY_SET, footerTextSelection); displayTotals((Collection<R>) Collections.EMPTY_SET, footerTextTotal); } else { displayTotals(getListComposite().getSelectedElements(), footerTextSelection); displayTotals(getListComposite().getElements(), footerTextTotal); } XComposite.retrieveToolkit(parent).adapt(footer); return footer; } private void relayoutFooter() { int numCurrency = currency2PriceFragmentTypeSumMap.keySet().size(); int numPriceFragmentType = summedPriceFragmentTypeConfigModule.getSummedPriceFragmentTypeList().size(); if (footerComposite != null && !footerComposite.isDisposed()) footerComposite.getGridData().heightHint = (RCPUtil.getFontHeight(footerTextSelection) * numPriceFragmentType * numCurrency); getComposite().getParent().layout(); ((SashForm)getComposite()).setWeights(calculateSashWeights(null)); } private Job loadConfigModuleJob = new Job("Loading config module") { @Override protected IStatus run(ProgressMonitor monitor) throws Exception { monitor.beginTask("Loading config module....", 100); //Loads config module summedPriceFragmentTypeConfigModule = ConfigUtil.getUserCfMod( SummedPriceFragmentTypeConfigModule.class, new String[] { FetchPlan.DEFAULT, SummedPriceFragmentTypeConfigModule.FETCH_GROUP_SUMMED_PRICE_FRAGMENT_TYPE_LIST, PriceFragmentType.FETCH_GROUP_NAME, }, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new SubProgressMonitor(monitor, 10) ); JDOLifecycleManager.sharedInstance().addNotificationListener(SummedPriceFragmentTypeConfigModule.class, configModuleChangeListener); return Status.OK_STATUS; } }; private NotificationListener configModuleChangeListener = new NotificationAdapterJob() { @Override public void notify(final NotificationEvent event) { loadConfigModuleJob.setPriority(Job.SHORT); loadConfigModuleJob.schedule(); } }; @Override protected void displaySearchResult(Object result) { super.displaySearchResult(result); if (footerTextTotal != null && !footerTextTotal.isDisposed()) { Collection<R> elements = getListComposite().getElements(); displayTotals(elements, footerTextTotal); relayoutFooter(); } } private Map<Currency, Map<PriceFragmentType, Long>> currency2PriceFragmentTypeSumMap = new HashMap<Currency, Map<PriceFragmentType,Long>>(); private void displayTotals(Collection<R> articleContainers, Text text) { List<PriceFragmentType> summedPriceFragmentTypes = summedPriceFragmentTypeConfigModule.getSummedPriceFragmentTypeList(); for (Map<PriceFragmentType, Long> priceFragmentTypeSumMap : currency2PriceFragmentTypeSumMap.values()) { priceFragmentTypeSumMap.clear(); } //For each article containers for (R articleContainer : articleContainers) { PricedArticleContainer pricedArticleContainer = (PricedArticleContainer) articleContainer; Price price = pricedArticleContainer.getPrice(); if (price != null) { Currency currency = price.getCurrency(); if (currency2PriceFragmentTypeSumMap.get(currency) == null) { //Initialises the map currency2PriceFragmentTypeSumMap.put(currency, new HashMap<PriceFragmentType, Long>()); } //For each summed price fragment types for (PriceFragmentType summedPriceFragmentType : summedPriceFragmentTypes) { PriceFragment priceFragment = price.getPriceFragment(summedPriceFragmentType.getPrimaryKey(), false); long amount = priceFragment == null ? 0 : priceFragment.getAmount(); Map<PriceFragmentType, Long> priceFragmentTypeSumMap = currency2PriceFragmentTypeSumMap.get(currency); Long totalAmount = priceFragmentTypeSumMap.get(summedPriceFragmentType); if (totalAmount == null) { totalAmount = 0L; } totalAmount += amount; priceFragmentTypeSumMap.put(summedPriceFragmentType, totalAmount); } } } StringBuilder sumString = new StringBuilder(""); for (Currency currency : currency2PriceFragmentTypeSumMap.keySet()) { Map<PriceFragmentType, Long> priceFragmentTypeSumMap = currency2PriceFragmentTypeSumMap.get(currency); for (PriceFragmentType priceFragmentType : summedPriceFragmentTypes) { sumString.append(priceFragmentType.getName().getText()); sumString.append(" = "); Long sum = priceFragmentTypeSumMap.get(priceFragmentType);; long longSum = (sum == null?0:sum); sumString.append(NumberFormatter.formatCurrency(longSum, currency)); sumString.append("\n "); } } text.setText(sumString.toString()); } // /** // * Returns Article containers' price // * @param ac // * @return // */ // private Price getACPrice(R ac) { // if (ac instanceof Offer) { // return ((Offer)ac).getPrice(); // } else if (ac instanceof Invoice) { // return ((Invoice) ac).getPrice(); // } // return null; // } // private void show // @Override // protected void optimizeSearchResults(Object result) // { // if (result instanceof Collection) { // Collection articleContainers = (Collection) result; // Set<AnchorID> anchorIDs = new HashSet<AnchorID>(articleContainers.size() * 2); // for (Object object : articleContainers) { // if (object instanceof ArticleContainer) { // ArticleContainer articleContainer = (ArticleContainer) object; // anchorIDs.add(articleContainer.getVendorID()); // anchorIDs.add(articleContainer.getCustomerID()); // } // } // String[] FETCH_GROUP_ARTICLE_CONTAINER_ANCHORS = new String[] { // LegalEntity.FETCH_GROUP_PERSON, // FetchPlan.DEFAULT // }; // // fetch the name of the customer and the vendor at once to add them to the cache // // what avoids afterwards multiple connections to the server in labelProvider // LegalEntityProvider.sharedInstance().getLegalEntities( // anchorIDs.toArray(new AnchorID[anchorIDs.size()]), // FETCH_GROUP_ARTICLE_CONTAINER_ANCHORS, // NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); // } // } }