/* ***************************************************************************** * 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.moneyflow; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import javax.jdo.FetchPlan; import javax.jdo.JDOHelper; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerDropAdapter; import org.eclipse.swt.SWT; import org.eclipse.swt.dnd.DND; import org.eclipse.swt.dnd.DragSourceEvent; import org.eclipse.swt.dnd.DragSourceListener; import org.eclipse.swt.dnd.TransferData; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Tree; import org.eclipse.swt.widgets.TreeColumn; import org.eclipse.swt.widgets.TreeItem; import org.nightlabs.base.ui.table.TableLabelProvider; import org.nightlabs.base.ui.tree.AbstractTreeComposite; import org.nightlabs.base.ui.tree.TreeContentProvider; import org.nightlabs.jdo.NLJDOHelper; import org.nightlabs.jfire.accounting.Account; import org.nightlabs.jfire.accounting.AccountType; import org.nightlabs.jfire.accounting.book.LocalAccountantDelegate; import org.nightlabs.jfire.accounting.book.id.LocalAccountantDelegateID; import org.nightlabs.jfire.accounting.book.mappingbased.MappingBasedAccountantDelegate; import org.nightlabs.jfire.accounting.book.mappingbased.MoneyFlowMapping; import org.nightlabs.jfire.accounting.dao.LocalAccountantDelegateDAO; import org.nightlabs.jfire.store.ProductType; import org.nightlabs.jfire.store.ProductTypeLocal; import org.nightlabs.jfire.store.dao.ProductTypeDAO; import org.nightlabs.jfire.store.id.ProductTypeID; import org.nightlabs.jfire.trade.admin.ui.resource.Messages; import org.nightlabs.jfire.trade.ui.accounting.AccountCellEditor; import org.nightlabs.jfire.trade.ui.accounting.AccountingUtil; import org.nightlabs.progress.NullProgressMonitor; import org.nightlabs.progress.ProgressMonitor; import org.nightlabs.util.Util; /** * @author Alexander Bieber <alex[AT]nightlabs[DOT]de> * */ public class MoneyFlowMappingTree extends AbstractTreeComposite { private static final int NODE_MODE_DELEGATE = 1; private static final int NODE_MODE_MAPPING = 2; private static class Node { private int mode; private MoneyFlowMapping mapping = null; private Object nodeObject = null; private List<Node> children = new LinkedList<Node>(); private Node parent; private Node(Node parent, int mode, Object nodeObject) { this.mode = mode; switch (mode) { case NODE_MODE_DELEGATE: if (!(nodeObject instanceof LocalAccountantDelegate)) throw new IllegalArgumentException("Node with type NODE_MODE_DELEGATE needs a LocalAccountantDelegate as nodeObject"); //$NON-NLS-1$ this.nodeObject = nodeObject; break; case NODE_MODE_MAPPING: if (!(nodeObject instanceof MoneyFlowMapping)) throw new IllegalArgumentException("Node with type NODE_MODE_MAPPING needs a LocalAccountantDelegate as nodeObject"); //$NON-NLS-1$ this.mapping = (MoneyFlowMapping)nodeObject; break; default: throw new IllegalArgumentException("Create a node only with one of the modes: [NODE_MODE_CURRENCY, NODE_MODE_DELEGATE, NODE_MODE_MAPPING]"); //$NON-NLS-1$ } this.parent = parent; if (parent != null) { parent.addChild(this); } } public static Node delegateNode(Node parent, LocalAccountantDelegate delegate) { return new Node(parent, NODE_MODE_DELEGATE, delegate); } public static Node mappingNode(Node parent, MoneyFlowMapping mapping) { return new Node(parent, NODE_MODE_MAPPING, mapping); } /** * @return Returns the mapping. */ public MoneyFlowMapping getMapping() { return mapping; } /** * @return Returns the mode. */ public int getMode() { return mode; } /** * @return Returns the nodeObject. */ public Object getNodeObject() { return nodeObject; } public void addChild(Node node) { children.add(node); } public boolean hasChildren() { return !children.isEmpty(); } public List<Node> getChildren() { return children; } public Node getParent() { return parent; } public void clearChildren() { children.clear(); } } private static class ContentProvider extends TreeContentProvider { private LocalAccountantDelegate currDelegate; private ProductTypeID currProductTypeID; private Map<MoneyFlowMapping, Node> nodesByMappings = new HashMap<MoneyFlowMapping, Node>(); /** * value Node delegateNode */ private List<Node> delegateNodes; public ContentProvider() { } protected void updateDelegateContent() { flushContent(); if (currDelegate == null) return; LocalAccountantDelegate delegateRun = currDelegate; while (delegateRun != null) { Node delegateNode = Node.delegateNode(null, delegateRun); if (delegateNodes == null) delegateNodes = new LinkedList<Node>(); delegateNodes.add(delegateNode); if (delegateRun instanceof MappingBasedAccountantDelegate) { for (Iterator<MoneyFlowMapping> iter = ((MappingBasedAccountantDelegate) delegateRun).getMoneyFlowMappings().iterator(); iter.hasNext();) { MoneyFlowMapping mapping = iter.next(); Node mappingNode = Node.mappingNode(delegateNode, mapping); nodesByMappings.put(mapping, mappingNode); } } // TODO IMPROVE: when fetch-depth works change this delegateRun = delegateRun.getExtendedAccountantDelegate(); if (delegateRun != null) delegateRun = Util.cloneSerializable(LocalAccountantDelegateDAO.sharedInstance().getDelegate( (LocalAccountantDelegateID)JDOHelper.getObjectId(delegateRun), DEFAULT_DELEGATE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor())); } } public void setDelegate(LocalAccountantDelegate delegate) { currDelegate = delegate; updateDelegateContent(); } private static Object[] NO_ELEMENTS = new Object[]{}; public Object[] getElements(Object inputElement) { if (delegateNodes == null) return NO_ELEMENTS; return delegateNodes.toArray(); } public void flushContent() { delegateNodes = null; nodesByMappings.clear(); } public Node getNodeByMapping(MoneyFlowMapping mapping) { return (Node)nodesByMappings.get(mapping); } /** * @see org.nightlabs.base.ui.tree.TreeContentProvider#getChildren(java.lang.Object) */ @Override public Object[] getChildren(Object parentElement) { if (parentElement instanceof Node) return ((Node)parentElement).getChildren().toArray(); return super.getChildren(parentElement); } /** * @see org.nightlabs.base.ui.tree.TreeContentProvider#getParent(java.lang.Object) */ @Override public Object getParent(Object element) { if (element instanceof Node) return ((Node)element).getParent(); return super.getParent(element); } /** * @see org.nightlabs.base.ui.tree.TreeContentProvider#hasChildren(java.lang.Object) */ @Override public boolean hasChildren(Object element) { if (element instanceof Node) return ((Node)element).hasChildren(); return super.hasChildren(element); } @Override public void dispose() { } } private class LabelProvider extends TableLabelProvider { public String getColumnText(Object element, int columnIndex) { if (!(element instanceof Node)) return ""; //$NON-NLS-1$ Node node = (Node)element; switch(node.getMode()) { case NODE_MODE_DELEGATE: if (columnIndex == 0) return ((LocalAccountantDelegate)node.getNodeObject()).getName().getText(); break; case NODE_MODE_MAPPING: // TODO: Implement LabelProvider mapping type MoneyFlowMapping mapping = node.getMapping(); if (columnIndex == 0) { // ProductType productType = ProductTypeDAO.sharedInstance().getProductType( // ProductType.primaryKeyToProductTypeID(mapping.getProductTypePK()), // DEFAULT_PTYPE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, // new NullProgressMonitor() // ); // return productType.getName().getText(); return mapping.getProductType().getName().getText(); } else if (columnIndex == 1) { return mapping.getPackageType(); } else if (columnIndex == currDimensionIDs.size() + 2) { // Account account = AccountDAO.sharedInstance().getAccount( // Account.primaryKeyToAnchorID(mapping.getAccountPK()), // AccountCellEditor.DEFAULT_FETCH_GROUPS, // NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, // new NullProgressMonitor() // ); // return account.getName().getText(NLLocale.getDefault().getLanguage()); return getAccountName(mapping.getRevenueAccount()); } else if (columnIndex == currDimensionIDs.size() + 3) return getAccountName(mapping.getExpenseAccount()); else if (columnIndex == currDimensionIDs.size() + 4) return getAccountName(mapping.getReverseRevenueAccount()); else if (columnIndex == currDimensionIDs.size() + 5) return getAccountName(mapping.getReverseExpenseAccount()); else { MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimension( (String)currDimensionIDs.get(columnIndex-2) ); return dimension.getValueText(mapping); } } return ""; //$NON-NLS-1$ } private String getAccountName(Account account) { return account == null ? "" : account.getName().getText(); //$NON-NLS-1$ } } private static class CellModifier implements ICellModifier { private MoneyFlowMappingTree tree; public CellModifier(MoneyFlowMappingTree tree) { this.tree = tree; } @Override public boolean canModify(Object element, String property) { if (element instanceof Node) { Node node = (Node)element; // Currency and Delegate Nodes are not modifiable if (node.getMode() == NODE_MODE_DELEGATE) return false; // get the registered dimension for the property if (COLUMN_PRODUCT_TYPE.equals(property)) return false; if (COLUMN_PACKAGE_TYPE.equals(property)) return false; if (COLUMN_REVENUE_ACCOUNT.equals(property)) return true; if (COLUMN_EXPENSE_ACCOUNT.equals(property)) return true; if (COLUMN_REVERSE_REVENUE_ACCOUNT.equals(property)) return true; if (COLUMN_REVERSE_EXPENSE_ACCOUNT.equals(property)) return true; MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimensionByPropertyName(property); if (dimension == null) throw new IllegalStateException("Could not find a registered MappingDimension with cellPropertyName "+property); //$NON-NLS-1$ // delegate the request return dimension.canModify(node.getMapping()); } else return false; } @Override public Object getValue(Object element, String property) { if (element instanceof Node) { Node node = (Node)element; // if (node.getMode() == NODE_MODE_DELEGATE) // // Should never be true as canModify returns false in this case // return null; if (COLUMN_REVENUE_ACCOUNT.equals(property)) return JDOHelper.getObjectId(node.getMapping().getRevenueAccount()); if (COLUMN_EXPENSE_ACCOUNT.equals(property)) return JDOHelper.getObjectId(node.getMapping().getExpenseAccount()); if (COLUMN_REVERSE_REVENUE_ACCOUNT.equals(property)) return JDOHelper.getObjectId(node.getMapping().getReverseRevenueAccount()); if (COLUMN_REVERSE_EXPENSE_ACCOUNT.equals(property)) return JDOHelper.getObjectId(node.getMapping().getReverseExpenseAccount()); // get the registered dimension for the property MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimensionByPropertyName(property); if (dimension == null) throw new IllegalStateException("Could not find a registered MappingDimension with cellPropertyName "+property); //$NON-NLS-1$ // delegate the request return dimension.getValue(node.getMapping()); } else return null; } @Override public void modify(Object element, String property, Object value) { // we assume canModify was correct and // now we can simply delegate to the MappingDimension boolean haveChanged = false; Object data = element; if (element instanceof TreeItem) data = ((TreeItem)element).getData(); if (data instanceof Node) { Node node = (Node)data; if (!(node.getMode() == NODE_MODE_MAPPING)) throw new IllegalStateException("Modify should only be called for Nodes with type NODE_MODE_MAPPING"); //$NON-NLS-1$ if (COLUMN_REVENUE_ACCOUNT.equals(property)) { // if (value instanceof Account) { node.getMapping().setRevenueAccount((Account)value); // } } else if (COLUMN_EXPENSE_ACCOUNT.equals(property)) { node.getMapping().setExpenseAccount((Account)value); } else if (COLUMN_REVERSE_REVENUE_ACCOUNT.equals(property)) { node.getMapping().setReverseRevenueAccount((Account)value); } else if (COLUMN_REVERSE_EXPENSE_ACCOUNT.equals(property)) { node.getMapping().setReverseExpenseAccount((Account)value); } else { // delegate to the MappingDimension MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimensionByPropertyName(property); if (dimension == null) throw new IllegalStateException("Could not find a registered MappingDimension with cellPropertyName "+property); //$NON-NLS-1$ dimension.modify(node.getMapping(), value); } if (haveChanged) tree.mappingModified(node.getMapping(), property); } } } public static final String COLUMN_PRODUCT_TYPE = "productType"; //$NON-NLS-1$ public static final String COLUMN_PACKAGE_TYPE = "packageType"; //$NON-NLS-1$ public static final String COLUMN_REVENUE_ACCOUNT = "revenueAccount"; //$NON-NLS-1$ public static final String COLUMN_EXPENSE_ACCOUNT = "expenseAccount"; //$NON-NLS-1$ public static final String COLUMN_REVERSE_REVENUE_ACCOUNT = "reverseRevenueAccount"; //$NON-NLS-1$ public static final String COLUMN_REVERSE_EXPENSE_ACCOUNT = "reverseExpenseAccount"; //$NON-NLS-1$ public static final String[] DEFAULT_PTYPE_FETCH_GROUPS = new String[] { FetchPlan.DEFAULT, LocalAccountantDelegate.FETCH_GROUP_NAME, ProductType.FETCH_GROUP_NAME, // ProductType.FETCH_GROUP_FIELD_METADATA_MAP, ProductType.FETCH_GROUP_PRODUCT_TYPE_LOCAL, ProductTypeLocal.FETCH_GROUP_FIELD_METADATA_MAP, ProductTypeLocal.FETCH_GROUP_LOCAL_ACCOUNTANT_DELEGATE, // added to speed up inheritance action ProductType.FETCH_GROUP_EXTENDED_PRODUCT_TYPE_ID }; public static final String[] DEFAULT_DELEGATE_FETCH_GROUPS = new String[] { FetchPlan.DEFAULT, LocalAccountantDelegate.FETCH_GROUP_EXTENDED_ACCOUNTANT_DELEGATE, LocalAccountantDelegate.FETCH_GROUP_NAME, ProductType.FETCH_GROUP_NAME, MappingBasedAccountantDelegate.FETCH_GROUP_MONEY_FLOW_MAPPINGS, MoneyFlowMapping.FETCH_GROUP_LOCAL_ACCOUNTANT_DELEGATE, MoneyFlowMapping.FETCH_GROUP_ALL_DIMENSIONS , Account.FETCH_GROUP_NAME }; private MappingBasedAccountantDelegate delegate; private Class currDelegateClass; private List<String> currDimensionIDs; private CellModifier cellModifier; /** * @param parent */ public MoneyFlowMappingTree(Composite parent, MappingBasedAccountantDelegate delegate) { super(parent, DEFAULT_STYLE_SINGLE | SWT.FULL_SELECTION, true, true, true); this.delegate = delegate; } /** * @see org.nightlabs.base.ui.tree.AbstractTreeComposite#setTreeProvider(org.eclipse.jface.viewers.TreeViewer) */ @Override public void setTreeProvider(TreeViewer treeViewer) { treeViewer.setContentProvider(new ContentProvider()); treeViewer.setLabelProvider(new LabelProvider()); cellModifier = new CellModifier(this); treeViewer.setCellModifier(cellModifier); treeViewer.addDragSupport(DND.DROP_MOVE, MoneyFlowMappingTransfer.MONEY_FLOW_MAPPING_TRANSFERS, new DragListener()); treeViewer.addDropSupport(DND.DROP_MOVE, MoneyFlowMappingTransfer.MONEY_FLOW_MAPPING_TRANSFERS, new DropAdapter(treeViewer)); } public MappingBasedAccountantDelegate getDelegate() { return delegate; } private void setDelegate(MappingBasedAccountantDelegate delegate) { this.delegate = delegate; getContentProvider().setDelegate(delegate); Display.getDefault().syncExec(new Runnable(){ public void run() { updateColumnsAndCellEditors(); } }); refresh(true); } public void setDelegateID(LocalAccountantDelegateID delegateID) { setDelegate(Util.cloneSerializable( (MappingBasedAccountantDelegate) LocalAccountantDelegateDAO.sharedInstance(). getDelegate(delegateID, DEFAULT_DELEGATE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor()))); } /** * @deprecated use {@link #setProductType(ProductType)} instead * * @param productTypeID the id of the {@link ProductType} to display the MoneyFlowMapping for * @param monitor the monitor to display the progress of the loading */ @Deprecated public void setProductTypeID(ProductTypeID productTypeID, ProgressMonitor monitor) { MappingBasedAccountantDelegate dDelegate = null; if (productTypeID == null) { getContentProvider().flushContent(); } else { ProductType productType = ProductTypeDAO.sharedInstance().getProductType( productTypeID, DEFAULT_PTYPE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, monitor); productType = Util.cloneSerializable(productType); if (productType != null && productType.getProductTypeLocal().getLocalAccountantDelegate() != null) dDelegate = Util.cloneSerializable((MappingBasedAccountantDelegate) LocalAccountantDelegateDAO.sharedInstance().getDelegate( (LocalAccountantDelegateID)JDOHelper.getObjectId(productType.getProductTypeLocal().getLocalAccountantDelegate()), DEFAULT_DELEGATE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor() )); } setDelegate(dDelegate); } /** * sets the {@link ProductType} to display the MoneyFlowMapping for * @param productType the productType to set */ public void setProductType(ProductType productType) { MappingBasedAccountantDelegate dDelegate = null; if (productType == null) { getContentProvider().flushContent(); } else { if (productType.getProductTypeLocal().getLocalAccountantDelegate() != null) { dDelegate = Util.cloneSerializable((MappingBasedAccountantDelegate) LocalAccountantDelegateDAO.sharedInstance().getDelegate( (LocalAccountantDelegateID)JDOHelper.getObjectId(productType.getProductTypeLocal().getLocalAccountantDelegate()), DEFAULT_DELEGATE_FETCH_GROUPS, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT, new NullProgressMonitor() )); } } setDelegate(dDelegate); } protected void updateColumnsAndCellEditors() { if (delegate == null) { currDelegateClass = null; return; } if (!delegate.getClass().equals(currDelegateClass)) { currDelegateClass = delegate.getClass(); TreeColumn[] columns = getTreeViewer().getTree().getColumns(); for (int i = 0; i < columns.length; i++) { columns[i].dispose(); } currDimensionIDs = delegate.getMoneyFlowDimensionIDs(); addLeadingColumns(); for (Iterator<String> iter = currDimensionIDs.iterator(); iter.hasNext();) { String moneyFlowDimensionID = iter.next(); MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimension(moneyFlowDimensionID); if (dimension == null) throw new IllegalStateException("Could not find MappingDimension with moneyFlowDimensionID "+moneyFlowDimensionID+". Maybe it was not registered as extension to "+MappingDimensionRegistry.EXTENSION_POINT_ID); //$NON-NLS-1$ //$NON-NLS-2$ TreeColumn column = new TreeColumn(getTree(), SWT.LEFT); column.setText(dimension.getName()); column.setResizable(true); // TODO: Set better width if (iter.hasNext()) column.setWidth(150); else column.setWidth(150); } addTrailingColumns(); getTreeViewer().setColumnProperties(getCurrentColumnProperties()); getTreeViewer().setCellEditors(getCurrentCellEditors()); } } protected void addLeadingColumns() { TreeColumn column = new TreeColumn(getTree(), SWT.LEFT); column.setResizable(true); column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.productTypeTreeColumn.text")); //$NON-NLS-1$ // TODO: Set better width column.setWidth(200); TreeColumn packageTypeCol = new TreeColumn(getTree(), SWT.LEFT); packageTypeCol.setResizable(true); packageTypeCol.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.packageTypeTreeColumn.text")); //$NON-NLS-1$ // TODO: Set better width packageTypeCol.setWidth(100); } protected void addTrailingColumns() { TreeColumn column; column = new TreeColumn(getTree(), SWT.LEFT); column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.revenueAccount.name")); //$NON-NLS-1$ column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.revenueAccount.tooltip")); //$NON-NLS-1$ column.setResizable(true); column.setWidth(150); column = new TreeColumn(getTree(), SWT.LEFT); column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.expenseAccount.name")); //$NON-NLS-1$ column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.expenseAccount.tooltip")); //$NON-NLS-1$ column.setResizable(true); column.setWidth(150); column = new TreeColumn(getTree(), SWT.LEFT); column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.reverseRevenueAccount.name")); //$NON-NLS-1$ column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.reverseRevenueAccount.tooltip")); //$NON-NLS-1$ column.setResizable(true); column.setWidth(150); column = new TreeColumn(getTree(), SWT.LEFT); column.setText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.reverseExpenseAccount.name")); //$NON-NLS-1$ column.setToolTipText(Messages.getString("org.nightlabs.jfire.trade.admin.ui.moneyflow.MoneyFlowMappingTree.column.reverseExpenseAccount.tooltip")); //$NON-NLS-1$ column.setResizable(true); column.setWidth(150); } protected String[] getCurrentColumnProperties() { int idLength = (currDimensionIDs == null) ? 0 : currDimensionIDs.size(); String[] result = new String[idLength + 6]; result[0] = COLUMN_PRODUCT_TYPE; result[1] = COLUMN_PACKAGE_TYPE; // result[1] = COLUMN_DELEGATE; result[result.length-4] = COLUMN_REVENUE_ACCOUNT; result[result.length-3] = COLUMN_EXPENSE_ACCOUNT; result[result.length-2] = COLUMN_REVERSE_REVENUE_ACCOUNT; result[result.length-1] = COLUMN_REVERSE_EXPENSE_ACCOUNT; int i = 2; if (currDimensionIDs != null) { for (Iterator<String> iter = currDimensionIDs.iterator(); iter.hasNext();) { String moneyFlowDimensionID = iter.next(); MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimension(moneyFlowDimensionID); result[i++] = dimension.getCellEditorPropertyName(); } } return result; } protected CellEditor[] getCurrentCellEditors() { int idLength = (currDimensionIDs == null) ? 0 : currDimensionIDs.size(); CellEditor[] result = new CellEditor[idLength + 6]; result[0] = null; result[1] = null; result[result.length-4] = new AccountCellEditor(AccountType.ACCOUNT_TYPE_ID_LOCAL_REVENUE, getTree()); result[result.length-3] = new AccountCellEditor(AccountType.ACCOUNT_TYPE_ID_LOCAL_EXPENSE, getTree()); result[result.length-2] = new AccountCellEditor(AccountType.ACCOUNT_TYPE_ID_LOCAL_REVENUE, getTree()); result[result.length-1] = new AccountCellEditor(AccountType.ACCOUNT_TYPE_ID_LOCAL_EXPENSE, getTree()); int i = 2; if (currDimensionIDs != null) { for (Iterator<String> iter = currDimensionIDs.iterator(); iter.hasNext();) { String moneyFlowDimensionID = iter.next(); MappingDimension dimension = MappingDimensionRegistry.sharedInstance().getDimension(moneyFlowDimensionID); result[i++] = dimension.getCellEditor(); } } return result; } private MoneyFlowMapping lastAddedMapping; private MoneyFlowMapping nextSelectMapping; /** * Called when a MoneyFlowMapping was modified or created. * * @param mapping The mapping that was modified or created. * @param property The column-property by which the mapping was modified or null if the mapping was newly created */ protected void mappingModified(MoneyFlowMapping mapping, String property) { try { AccountingUtil.getAccountingManager().storeMoneyFlowMapping(mapping, false, null, NLJDOHelper.MAX_FETCH_DEPTH_NO_LIMIT); nextSelectMapping = mapping; } catch (Exception e) { throw new RuntimeException(e); } refresh(false); } protected ContentProvider getContentProvider() { return (ContentProvider)getTreeViewer().getContentProvider(); } /** * @see org.nightlabs.base.ui.tree.AbstractTreeComposite#createTreeColumns(org.eclipse.swt.widgets.Tree) */ @Override public void createTreeColumns(Tree tree) { // nothing done here columns created dynamically } public MappingBasedAccountantDelegate getCurrentDelegate() { return delegate; } @Override public void refresh(final boolean refreshInput) { getContentProvider().updateDelegateContent(); Display.getDefault().asyncExec(new Runnable() { public void run() { if ((lastAddedMapping != null) || refreshInput) getTreeViewer().setInput(getTreeViewer().getContentProvider()); if (lastAddedMapping != null) lastAddedMapping = null; getTreeViewer().refresh(true); getTreeViewer().expandAll(); if (nextSelectMapping != null) { getTreeViewer().setSelection( new StructuredSelection( getContentProvider().getNodeByMapping(nextSelectMapping) ), true ); nextSelectMapping = null; } } }); } public void setLastAddedMapping( MoneyFlowMapping nextRefreshSelectMapping) { this.lastAddedMapping = nextRefreshSelectMapping; } public MoneyFlowMapping getLastAddedMapping() { return lastAddedMapping; } private Node getSelectedNode() { IStructuredSelection selection = null; try { selection = (IStructuredSelection)getTreeViewer().getSelection(); } catch(Throwable t) { throw new RuntimeException("Unable to get IStructuredSelection from TreeViewer: "+t.getMessage(), t); //$NON-NLS-1$ } if (selection.isEmpty()) return null; Object element = selection.getFirstElement(); if (!(element instanceof Node)) throw new IllegalStateException("Tree-element is not an instance of Node but "+element.getClass().getName()); //$NON-NLS-1$ return (Node)element; } public LocalAccountantDelegate getSelectedLocalAccountantDelegate() { Node node = getSelectedNode(); if (node == null) return null; if (node.getMode() == NODE_MODE_DELEGATE) return (LocalAccountantDelegate)node.getNodeObject(); else if (node.getMode() == NODE_MODE_MAPPING) return node.getMapping().getLocalAccountantDelegate(); else throw new IllegalStateException("Selected Node has unknown type: "+node.getMode()); //$NON-NLS-1$ } public MoneyFlowMapping getSelectedMoneyFlowMapping() { Node node = getSelectedNode(); if (node == null) return null; if (node.getMode() == NODE_MODE_MAPPING) return node.getMapping(); return null; } private class DragListener implements DragSourceListener { public void dragStart(DragSourceEvent event) { System.out.println("DragStart"); //$NON-NLS-1$ System.out.println(event.dataType); event.doit = true; } public void dragSetData(DragSourceEvent event) { IStructuredSelection selection = (IStructuredSelection) getTreeViewer().getSelection(); List<MoneyFlowMapping> mappings = new ArrayList<MoneyFlowMapping>(selection.size()); for (Iterator<Object> it = selection.iterator(); it.hasNext(); ) { Object o = it.next(); if (o instanceof Node) { if (((Node)o).getMode() == NODE_MODE_MAPPING) mappings.add(((Node)o).getMapping()); } } event.data = mappings; } public void dragFinished(DragSourceEvent event) { System.out.println("DragFinished"); //$NON-NLS-1$ event.doit = true; } }; private class DropAdapter extends ViewerDropAdapter { protected DropAdapter(Viewer viewer) { super(viewer); } @Override public boolean performDrop(Object data) { return false; } @Override public boolean validateDrop(Object target, int operation, TransferData transferType) { // System.out.println("target == "+((Node)target).getMode()); // System.out.println("Operation "+operation); if ((target instanceof Node && target != null)/* && ((operation & DND.DROP_MOVE) > 0)*/) { // System.out.println("Result "+ (((Node)target).getMode() == NODE_MODE_DELEGATE)); return ((Node)target).getMode() == NODE_MODE_DELEGATE; } return false; } }; }