/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.components.excel.gui.view; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Observable; import java.util.Observer; import org.apache.commons.io.FileUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IToolBarManager; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.wizard.WizardDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.SWTException; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; import org.eclipse.ui.part.ViewPart; import de.rcenvironment.components.excel.common.ChannelValue; import de.rcenvironment.components.excel.common.ExcelComponentConstants; import de.rcenvironment.components.excel.common.ExcelUtils; import de.rcenvironment.components.excel.common.SimpleExcelService; import de.rcenvironment.core.component.execution.api.ComponentExecutionInformation; import de.rcenvironment.core.gui.resources.api.ImageManager; import de.rcenvironment.core.gui.resources.api.StandardImages; import de.rcenvironment.core.gui.utils.common.ClipboardHelper; import de.rcenvironment.core.gui.workflow.view.ComponentRuntimeView; import de.rcenvironment.core.toolkitbridge.transitional.ConcurrencyUtils; import de.rcenvironment.core.utils.common.excel.legacy.ExcelFileExporter; import de.rcenvironment.core.utils.common.rpc.RemoteOperationException; import de.rcenvironment.toolkit.modules.concurrency.api.TaskDescription; /** * View of Excel component during run of workflow. * * @author Markus Kunde */ public class ExcelView extends ViewPart implements ComponentRuntimeView, Observer { /** * File Type of Excel-files. */ private static final String FILETYPENAME = "Excel"; /** * Logger. */ private static final Log LOGGER = LogFactory.getLog(ExcelView.class); /** * Data model of channel values. */ private final ModelProvider model; /** * Component information of this component view. */ private ComponentExecutionInformation compExeInfo = null; /** * Parent composite. */ private Composite parentComposite = null; /** * The form for the widgets. */ private ScrolledForm form = null; /** * TableViewer for input channel values. */ private TableViewer inputTableViewer = null; /** * TableViewer for output channel values. */ private TableViewer outputTableViewer = null; /** * TableSorter. */ private TableSorter tableSorter = null; /** * Filter in table for input channel type. */ private ChannelFilter inputChannelFilter = null; /** * Filter in table for output channel type. */ private ChannelFilter outputChannelFilter = null; /** * SelectionProvider for multiple selection providers. */ private SelectionProviderIntermediate spi = null; /** * Copy to clipboard action. */ private Action copyClipboardAction = null; /** * Export to Excel action. */ private Action exportToExcel = null; /** * Constructor. * */ public ExcelView() { super(); model = new ModelProvider(); model.addObserver(this); inputChannelFilter = new ChannelFilter(); inputChannelFilter.setChannelFilter(true); outputChannelFilter = new ChannelFilter(); outputChannelFilter.setChannelFilter(false); spi = new SelectionProviderIntermediate(); } @Override public void createPartControl(final Composite parent) { parentComposite = parent; final FormToolkit tk = new FormToolkit(parentComposite.getDisplay()); form = tk.createScrolledForm(parentComposite); form.setText(Messages.viewName); if (compExeInfo != null) { form.setText(Messages.viewName + compExeInfo.getInstanceName()); } parentComposite = form.getBody(); GridLayout gridLayout = new GridLayout(); gridLayout.numColumns = 2; gridLayout.makeColumnsEqualWidth = true; gridLayout.horizontalSpacing = ExcelViewConstants.NORMALCOLUMNWIDTH / 2; parentComposite.setLayout(gridLayout); createTableViewer(parentComposite); tableSorter = new TableSorter(); inputTableViewer.setInput(model.getChannelValues()); inputTableViewer.setSorter(tableSorter); inputTableViewer.addFilter(inputChannelFilter); outputTableViewer.setInput(model.getChannelValues()); outputTableViewer.setSorter(tableSorter); outputTableViewer.addFilter(outputChannelFilter); getSite().setSelectionProvider(spi); createActions(); createToolbar(); // Not nice, but workbook-object will not released. ExcelUtils.destroyGarbage(); } /** * Create table viewer. * * @param parent parent composite */ private void createTableViewer(final Composite parent) { inputTableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); createColumns(parent, inputTableViewer); inputTableViewer.setContentProvider(new ChannelValueContentProvider()); inputTableViewer.setLabelProvider(new ChannelValueLabelProvider()); inputTableViewer.getTable().setToolTipText(Messages.inputChannelNameType); inputTableViewer.addDoubleClickListener(new DoubleClickListener(parentComposite)); outputTableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION); createColumns(parent, outputTableViewer); outputTableViewer.setContentProvider(new ChannelValueContentProvider()); outputTableViewer.setLabelProvider(new ChannelValueLabelProvider()); outputTableViewer.getTable().setToolTipText(Messages.outputChannelNameType); outputTableViewer.addDoubleClickListener(new DoubleClickListener(parentComposite)); GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, true); inputTableViewer.getTable().setLayoutData(gridData); gridData = new GridData(GridData.FILL, GridData.FILL, true, true); outputTableViewer.getTable().setLayoutData(gridData); } /** * Create columns in table. */ private void createColumns(final Composite parent, final TableViewer tv) { final Menu headerMenu = new Menu(parent); String[] titles = { Messages.valueColumnName, Messages.channelColumnName, Messages.valueColumnIteration }; int[] bounds = { ExcelViewConstants.NORMALCOLUMNWIDTH, ExcelViewConstants.NORMALCOLUMNWIDTH, ExcelViewConstants.NORMALCOLUMNWIDTH / 2 }; for (int i = 0; i < titles.length; i++) { final int index = i; final TableViewerColumn viewerColumn = new TableViewerColumn(tv, SWT.NONE); final TableColumn column = viewerColumn.getColumn(); column.setAlignment(SWT.RIGHT); column.setText(titles[i]); column.setWidth(bounds[i]); column.setResizable(true); column.setMoveable(true); createMenuItem(headerMenu, column); column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tableSorter.setColumn(index); int dir = tv.getTable().getSortDirection(); if (tv.getTable().getSortColumn() == column) { // dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; if (dir == SWT.UP) { dir = SWT.DOWN; } else { dir = SWT.UP; } } else { dir = SWT.DOWN; } tv.getTable().setSortDirection(dir); tv.getTable().setSortColumn(column); tv.refresh(); } }); } final Table table = tv.getTable(); table.setHeaderVisible(true); table.setLinesVisible(true); table.addListener(SWT.MenuDetect, new Listener() { @Override public void handleEvent(Event event) { table.setMenu(headerMenu); } }); } /** * Create menu-items for table. * * @param parent parent menu * @param column column of table */ private void createMenuItem(Menu parent, final TableColumn column) { final MenuItem itemName = new MenuItem(parent, SWT.CHECK); itemName.setText(column.getText()); itemName.setSelection(column.getResizable()); itemName.addListener(SWT.Selection, new Listener() { @Override public void handleEvent(Event event) { if (itemName.getSelection()) { column.setWidth(ExcelViewConstants.NORMALCOLUMNWIDTH); column.setResizable(true); } else { column.setWidth(0); column.setResizable(false); } } }); } @Override public void setFocus() { if (compExeInfo != null) { form.setText(Messages.viewName + compExeInfo.getInstanceName()); } form.reflow(true); form.getParent().setFocus(); } @Override public void update(Observable o, Object arg) { // Push into model parentComposite.getDisplay().asyncExec(new Runnable() { @Override public void run() { inputTableViewer.refresh(); outputTableViewer.refresh(); } }); } /** * Create toolbar. */ private void createToolbar() { IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); mgr.add(copyClipboardAction); mgr.add(exportToExcel); } /** * Create actions. */ private void createActions() { copyClipboardAction = new Action(Messages.copyToClipboard) { @Override public void run() { copyToClipboard(); LOGGER.debug("Copy to clipboard..."); } }; copyClipboardAction.setImageDescriptor(ImageManager.getInstance().getImageDescriptor(StandardImages.COPY_16)); exportToExcel = new Action(Messages.exportExcel) { @Override public void run() { final NewFileWizard wizz; boolean isNewXLFile = model.getChannelValues().get(0).getFile().getName().endsWith(ExcelFileExporter.FILEEXTENSION_XL2010); if (isNewXLFile) { wizz = new NewFileWizard(FILETYPENAME, ExcelFileExporter.FILEEXTENSION_XL2010, new String("empty").getBytes(), null); } else { wizz = new NewFileWizard(FILETYPENAME, ExcelFileExporter.FILEEXTENSION_XL2003, new String("empty").getBytes(), null); } wizz.init(PlatformUI.getWorkbench(), new StructuredSelection()); final WizardDialog dialog = new WizardDialog(parentComposite.getShell(), wizz); dialog.create(); int a = dialog.open(); if (a == Dialog.OK) { exportToExcel(new File(wizz.getFile().getLocation().toPortableString())); } try { dialog.close(); } catch (SWTException e) { LOGGER.debug("Widget is disposed."); // Some error in threading, but it works. // Fix later. } LOGGER.debug("Export to Excel..."); } }; exportToExcel.setImageDescriptor(ImageManager.getInstance().getImageDescriptor(StandardImages.EXCEL_SMALL)); } /** * Export values to Excel. */ private void exportToExcel(final File saveTo) { final SimpleExcelService excel = new SimpleExcelService(); ConcurrencyUtils.getAsyncTaskService().execute(new Runnable() { @Override @TaskDescription("Export values to Excel") public void run() { try { // Fill Excel with all input values List<ChannelValue> allValues = model.getChannelValues(); FileUtils.copyFile(allValues.get(0).getFile(), saveTo); // Execute same macros as during component execution String preMacroName = allValues.get(0).getPreMacro(); if (preMacroName != null && !preMacroName.isEmpty()) { excel.runMacro(saveTo, preMacroName); } for (ChannelValue cval : allValues) { if (!cval.isInputValue()) { continue; } excel.setValues(saveTo, cval.getExcelAddress(), cval.getValues()); } // Execute same macros as during component execution String runMacroName = allValues.get(0).getRunMacro(); if (runMacroName != null && !runMacroName.isEmpty()) { excel.runMacro(saveTo, runMacroName); } // Execute same macros as during component execution String postMacroName = allValues.get(0).getPostMacro(); if (postMacroName != null && !postMacroName.isEmpty()) { excel.runMacro(saveTo, postMacroName); } // Show message box - action done parentComposite.getDisplay().asyncExec(new Runnable() { @Override public void run() { Image image = ImageManager.getInstance().getSharedImage(StandardImages.EXCEL_SMALL); MessageDialog md = new MessageDialog(parentComposite.getShell(), Messages.exportExcel, image, Messages.actionDone, MessageDialog.INFORMATION, new String[] { Messages.actionButton }, 0); md.open(); } }); } catch (RuntimeException re) { LOGGER.error("Could not interact with Excel.", re); // Show message box - action error parentComposite.getDisplay().asyncExec(new Runnable() { @Override public void run() { Image image = ImageManager.getInstance().getSharedImage(StandardImages.EXCEL_SMALL); MessageDialog md = new MessageDialog(parentComposite.getShell(), Messages.exportExcel, image, Messages.actionError, MessageDialog.ERROR, new String[] { Messages.actionButton }, 0); md.open(); } }); } catch (IOException e) { LOGGER.error("Cannot copy origin file to exporting directory.", e); } } }); } /** * Copy selected rows to clipboard. */ private void copyToClipboard() { ISelection selection = null; List<ChannelValue> channelValueList = new ArrayList<ChannelValue>(); // Input selection spi.setSelectionProviderDelegate(inputTableViewer); selection = this.getSite().getSelectionProvider().getSelection(); if (selection != null && selection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) selection; @SuppressWarnings("unchecked") Iterator<ChannelValue> iterator = sel.iterator(); while (iterator.hasNext()) { ChannelValue channelValue = iterator.next(); channelValueList.add(channelValue); } } // Output selection spi.setSelectionProviderDelegate(outputTableViewer); selection = this.getSite().getSelectionProvider().getSelection(); if (selection != null && selection instanceof IStructuredSelection) { IStructuredSelection sel = (IStructuredSelection) selection; @SuppressWarnings("unchecked") Iterator<ChannelValue> iterator = sel.iterator(); while (iterator.hasNext()) { ChannelValue channelValue = iterator.next(); channelValueList.add(channelValue); } } StringBuilder sb = new StringBuilder(); for (ChannelValue cval : channelValueList) { sb.append(channelValueToString(cval)); sb.append(ExcelComponentConstants.TABLELINESEPARATOR); } sb.delete(sb.lastIndexOf(ExcelComponentConstants.TABLELINESEPARATOR), sb.length()); ClipboardHelper.setContent(sb.toString()); // Deselect all rows. inputTableViewer.getTable().deselectAll(); outputTableViewer.getTable().deselectAll(); } /** * Returns String representation of channel value. * * @param channelValue to convert * @return string representation of channel value */ private String channelValueToString(final ChannelValue channelValue) { return ExcelUtils.smallTableToString(channelValue.getValues(), ExcelComponentConstants.TABLEVALUESEPARATOR, ExcelComponentConstants.TABLELINESEPARATOR); } @Override public void initializeData(ComponentExecutionInformation compInstanceDescr) { compExeInfo = compInstanceDescr; try { model.subscribeToLocalToolRunPlatForm(compExeInfo.getExecutionIdentifier(), compExeInfo.getNodeId()); } catch (RemoteOperationException e) { LogFactory.getLog(getClass()).error("Subscribing to remote notifiactions failed " + e); } } @Override public void dispose() { super.dispose(); // Not nice, but workbook-object will not released. ExcelUtils.destroyGarbage(); } @Override public void initializeView() { if (form != null) { form.setText(Messages.viewName + compExeInfo.getInstanceName()); } } }