/******************************************************************************* * Copyright (c) 2010 Oak Ridge National Laboratory. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html ******************************************************************************/ package org.csstudio.swt.xygraph.toolbar; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Arrays; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.csstudio.swt.xygraph.dataprovider.IDataProvider; import org.csstudio.swt.xygraph.dataprovider.ISample; import org.csstudio.swt.xygraph.figures.Axis; import org.csstudio.swt.xygraph.figures.Trace; import org.csstudio.swt.xygraph.figures.Trace.BaseLine; import org.csstudio.swt.xygraph.figures.Trace.ErrorBarType; import org.csstudio.swt.xygraph.figures.Trace.PointStyle; import org.csstudio.swt.xygraph.figures.Trace.TraceType; import org.csstudio.swt.xygraph.figures.XYGraph; import org.csstudio.swt.xygraph.util.SingleSourceHelper; import org.csstudio.swt.xygraph.util.XYGraphMediaFactory; import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFolder; import org.eclipse.core.resources.IProject; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.jface.preference.ColorSelector; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; import org.eclipse.swt.widgets.Text; /**This will help to create the necessary widgets * to configure an axis's properties. * @author Xihui Chen * */ public class TraceConfigPage { private XYGraph xyGraph; private Trace trace; private Text nameText; private Combo xAxisCombo; private Combo yAxisCombo; private ColorSelector traceColorSelector; private Combo traceTypeCombo; private Spinner lineWidthSpinner; private Combo pointStyleCombo; private Spinner pointSizeSpinner; private Combo baseLineCombo; private Spinner areaAlphaSpinner; private Button antiAliasing; private Button errorBarEnabledButton; private Combo xErrorBarTypeCombo; private Combo yErrorBarTypeCombo; private ColorSelector errorBarColorSelector; private Spinner errorBarCapWidthSpinner; private Button drawYErrorInAreaButton; private Button visible; private Composite composite; public TraceConfigPage(XYGraph xyGraph, Trace trace) { this.xyGraph = xyGraph; this.trace = trace; } public void createPage(final Composite composite){ this.composite = composite; composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); composite.setLayout(new GridLayout(2, false)); Composite traceCompo = new Composite(composite, SWT.NONE); traceCompo.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1)); traceCompo.setLayout(new GridLayout(3, false)); final Group errorBarGroup = new Group(composite, SWT.NONE); errorBarGroup.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 1, 1)); errorBarGroup.setLayout(new GridLayout(2, false)); errorBarGroup.setText("Error Bar"); GridData gd; GridData labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); visible = new Button(traceCompo, SWT.CHECK); visible.setText("Visible"); visible.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 3, 1)); final Label nameLabel = new Label(traceCompo, 0); nameLabel.setText("Name: "); nameLabel.setLayoutData(labelGd); nameText = new Text(traceCompo, SWT.BORDER | SWT.SINGLE); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); nameText.setLayoutData(gd); final Label xAxisLabel = new Label(traceCompo, 0); xAxisLabel.setText("X-Axis: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); xAxisLabel.setLayoutData(labelGd); xAxisCombo = new Combo(traceCompo, SWT.DROP_DOWN); for(Axis axis : xyGraph.getXAxisList()) xAxisCombo.add(axis.getTitle()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); xAxisCombo.setLayoutData(gd); final Label yAxisLabel = new Label(traceCompo, 0); yAxisLabel.setText("Y-Axis: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); yAxisLabel.setLayoutData(labelGd); yAxisCombo = new Combo(traceCompo, SWT.DROP_DOWN); for(Axis axis : xyGraph.getYAxisList()) yAxisCombo.add(axis.getTitle()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); yAxisCombo.setLayoutData(gd); final Label traceColorLabel = new Label(traceCompo, 0); traceColorLabel.setText("Trace Color: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1); traceColorLabel.setLayoutData(labelGd); traceColorSelector = new ColorSelector(traceCompo); gd = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1); traceColorSelector.getButton().setLayoutData(gd); final Label traceTypeLabel = new Label(traceCompo, 0); traceTypeLabel.setText("Trace Type: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); traceTypeLabel.setLayoutData(labelGd); traceTypeCombo = new Combo(traceCompo, SWT.DROP_DOWN); traceTypeCombo.setItems(TraceType.stringValues()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); traceTypeCombo.setLayoutData(gd); traceTypeCombo.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { baseLineCombo.setEnabled( traceTypeCombo.getSelectionIndex() == Arrays.asList(TraceType.values()).indexOf(TraceType.BAR) || traceTypeCombo.getSelectionIndex() == Arrays.asList(TraceType.values()).indexOf(TraceType.AREA)); } }); final Label lineWidthLabel = new Label(traceCompo, 0); lineWidthLabel.setText("Line Width (pixels): "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1); lineWidthLabel.setLayoutData(labelGd); lineWidthSpinner = new Spinner(traceCompo, SWT.BORDER); lineWidthSpinner.setMaximum(100); lineWidthSpinner.setMinimum(0); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); lineWidthSpinner.setLayoutData(gd); final Label pointStyleLabel = new Label(traceCompo, 0); pointStyleLabel.setText("Point Style: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); pointStyleLabel.setLayoutData(labelGd); pointStyleCombo = new Combo(traceCompo, SWT.DROP_DOWN); pointStyleCombo.setItems(PointStyle.stringValues()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); pointStyleCombo.setLayoutData(gd); final Label pointSizeLable = new Label(traceCompo, 0); pointSizeLable.setText("Point Size (pixels): "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1); pointSizeLable.setLayoutData(labelGd); pointSizeSpinner = new Spinner(traceCompo, SWT.BORDER); pointSizeSpinner.setMaximum(100); pointSizeSpinner.setMinimum(0); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); pointSizeSpinner.setLayoutData(gd); final Label baseLineLabel = new Label(traceCompo, 0); baseLineLabel.setText("Base Line: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); baseLineLabel.setLayoutData(labelGd); baseLineLabel.setToolTipText("The baseline for BAR or AREA trace type"); baseLineCombo = new Combo(traceCompo, SWT.DROP_DOWN); baseLineCombo.setItems(BaseLine.stringValues()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1); baseLineCombo.setLayoutData(gd); final Label alphaLable = new Label(traceCompo, 0); alphaLable.setText("Area Alpha: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); alphaLable.setLayoutData(labelGd); areaAlphaSpinner = new Spinner(traceCompo, SWT.BORDER); areaAlphaSpinner.setMaximum(255); areaAlphaSpinner.setMinimum(0); gd = new GridData(SWT.BEGINNING, SWT.CENTER, true, false, 2, 1); areaAlphaSpinner.setLayoutData(gd); areaAlphaSpinner.setToolTipText("0 for transparent, 255 for opaque"); antiAliasing = new Button(traceCompo, SWT.CHECK); antiAliasing.setText("Anti Aliasing Enabled"); antiAliasing.setLayoutData( new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 3, 1)); Button export = new Button(traceCompo, SWT.NONE); export.setText("Export data..."); export.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 2, 1)); export.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { final IFile exportTo = SingleSourceHelper.getProjectSaveFileLocation(trace.getName()); if (exportTo!=null) { try { exportToDat(exportTo, trace.getDataProvider()); } catch (Exception e1) { e1.printStackTrace(); } } } }); //error bar settings... errorBarEnabledButton = new Button(errorBarGroup, SWT.CHECK); errorBarEnabledButton.setText("Error Bar Enabled"); errorBarEnabledButton.setLayoutData( new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 2, 1)); errorBarEnabledButton.addSelectionListener(new SelectionAdapter(){ @Override public void widgetSelected(SelectionEvent e) { boolean enabled = errorBarEnabledButton.getSelection(); xErrorBarTypeCombo.setEnabled(enabled); yErrorBarTypeCombo.setEnabled(enabled); errorBarColorSelector.setEnabled(enabled); errorBarCapWidthSpinner.setEnabled(enabled); drawYErrorInAreaButton.setEnabled(enabled); } }); final Label xErrorBarTypeLabel = new Label(errorBarGroup, 0); xErrorBarTypeLabel.setText("X Error Bar Type: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); xErrorBarTypeLabel.setLayoutData(labelGd); xErrorBarTypeCombo = new Combo(errorBarGroup, SWT.DROP_DOWN); xErrorBarTypeCombo.setItems(ErrorBarType.stringValues()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); xErrorBarTypeCombo.setLayoutData(gd); final Label yErrorBarTypeLabel = new Label(errorBarGroup, 0); yErrorBarTypeLabel.setText("Y Error Bar Type: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); yErrorBarTypeLabel.setLayoutData(labelGd); yErrorBarTypeCombo = new Combo(errorBarGroup, SWT.DROP_DOWN); yErrorBarTypeCombo.setItems(ErrorBarType.stringValues()); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); yErrorBarTypeCombo.setLayoutData(gd); final Label errorBarColorLabel = new Label(errorBarGroup, 0); errorBarColorLabel.setText("Error Bar Color: "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); errorBarColorLabel.setLayoutData(labelGd); errorBarColorSelector = new ColorSelector(errorBarGroup); gd = new GridData(SWT.BEGINNING, SWT.CENTER, false, false, 1, 1); errorBarColorSelector.getButton().setLayoutData(gd); final Label errorBarCapWidthLabel = new Label(errorBarGroup, 0); errorBarCapWidthLabel.setText("Error Bar Cap Width \n(pixels): "); labelGd = new GridData(SWT.FILL, SWT.CENTER, false, false, 1, 1); errorBarCapWidthLabel.setLayoutData(labelGd); errorBarCapWidthSpinner = new Spinner(errorBarGroup, SWT.BORDER); errorBarCapWidthSpinner.setMaximum(100); errorBarCapWidthSpinner.setMinimum(0); gd = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1); errorBarCapWidthSpinner.setLayoutData(gd); drawYErrorInAreaButton = new Button(errorBarGroup, SWT.CHECK); drawYErrorInAreaButton.setText("Draw Y Error In Area"); drawYErrorInAreaButton.setLayoutData( new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false, 2, 1)); initialize(); } protected void exportToDat(IFile exportTo, IDataProvider dataProvider) throws Exception { final IFile dat = getUniqueFile(exportTo, null, "dat"); final StringBuilder contents = new StringBuilder(); final IDataProvider prov = trace.getDataProvider(); final NumberFormat format = new DecimalFormat("##0.#####E0"); for (int i = 0; i < prov.getSize(); i++) { final ISample isample = prov.getSample(i); contents.append(format.format(isample.getXValue())); contents.append("\t"); contents.append(format.format(isample.getYValue())); contents.append("\n"); } InputStream stream = new ByteArrayInputStream(contents.toString().getBytes()); dat.create(stream, true, new NullProgressMonitor()); dat.getParent().refreshLocal(IResource.DEPTH_INFINITE, new NullProgressMonitor()); // TODO FIXME opening the exported file does not work in the RAP context of // this plugin. // final IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage(); // IEditorDescriptor desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(dat.getName()); // if (desc == null) desc = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(dat.getName()+".txt"); // page.openEditor(new FileEditorInput(dat), desc.getId()); } /** * @return the composite */ public Composite getComposite() { return composite; } public void applyChanges(){ trace.setName(nameText.getText()); trace.setXAxis(xyGraph.getXAxisList().get(xAxisCombo.getSelectionIndex())); trace.setYAxis(xyGraph.getYAxisList().get(yAxisCombo.getSelectionIndex())); trace.setTraceColor(XYGraphMediaFactory.getInstance().getColor( traceColorSelector.getColorValue())); trace.setTraceType(TraceType.values()[traceTypeCombo.getSelectionIndex()]); trace.setLineWidth(lineWidthSpinner.getSelection()); trace.setPointStyle(PointStyle.values()[pointStyleCombo.getSelectionIndex()]); trace.setPointSize(pointSizeSpinner.getSelection()); trace.setBaseLine(BaseLine.values()[baseLineCombo.getSelectionIndex()]); trace.setAreaAlpha(areaAlphaSpinner.getSelection()); trace.setAntiAliasing(antiAliasing.getSelection()); trace.setErrorBarEnabled(errorBarEnabledButton.getSelection()); trace.setXErrorBarType(ErrorBarType.values()[xErrorBarTypeCombo.getSelectionIndex()]); trace.setYErrorBarType(ErrorBarType.values()[yErrorBarTypeCombo.getSelectionIndex()]); trace.setErrorBarColor(XYGraphMediaFactory.getInstance().getColor( errorBarColorSelector.getColorValue())); trace.setErrorBarCapWidth(errorBarCapWidthSpinner.getSelection()); trace.setDrawYErrorInArea(drawYErrorInAreaButton.getSelection()); boolean vis = visible.getSelection(); if (vis!=trace.isVisible()) trace.setVisible(vis); } private void initialize(){ nameText.setText(trace.getName()); xAxisCombo.select(xyGraph.getXAxisList().indexOf(trace.getXAxis())); yAxisCombo.select(xyGraph.getYAxisList().indexOf(trace.getYAxis())); traceColorSelector.setColorValue(trace.getTraceColor().getRGB()); traceTypeCombo.select(Arrays.asList(TraceType.values()) .indexOf(trace.getTraceType())); lineWidthSpinner.setSelection(trace.getLineWidth()); pointStyleCombo.select(Arrays.asList(PointStyle.values()) .indexOf(trace.getPointStyle())); pointSizeSpinner.setSelection(trace.getPointSize()); baseLineCombo.select(Arrays.asList(BaseLine.values()) .indexOf(trace.getBaseLine())); areaAlphaSpinner.setSelection(trace.getAreaAlpha()); antiAliasing.setSelection(trace.isAntiAliasing()); errorBarEnabledButton.setSelection(trace.isErrorBarEnabled()); xErrorBarTypeCombo.select(Arrays.asList(ErrorBarType.values()) .indexOf(trace.getXErrorBarType())); yErrorBarTypeCombo.select(Arrays.asList(ErrorBarType.values()) .indexOf(trace.getYErrorBarType())); errorBarColorSelector.setColorValue(trace.getErrorBarColor().getRGB()); errorBarCapWidthSpinner.setSelection(trace.getErrorBarCapWidth()); drawYErrorInAreaButton.setSelection(trace.isDrawYErrorInArea()); boolean enabled = errorBarEnabledButton.getSelection(); xErrorBarTypeCombo.setEnabled(enabled); yErrorBarTypeCombo.setEnabled(enabled); errorBarColorSelector.setEnabled(enabled); errorBarCapWidthSpinner.setEnabled(enabled); drawYErrorInAreaButton.setEnabled(enabled); visible.setSelection(trace.isVisible()); baseLineCombo.setEnabled( traceTypeCombo.getSelectionIndex() == Arrays.asList(TraceType.values()).indexOf(TraceType.BAR) || traceTypeCombo.getSelectionIndex() == Arrays.asList(TraceType.values()).indexOf(TraceType.AREA)); } /** * Gets a unique file. The file must have a parent of IFolder. * @param file * @return new file, not created. */ public static IFile getUniqueFile(IFile file, final String conjunctive, final String extension) { final String name = file.getName(); final Matcher matcher = Pattern.compile("(.+)(\\d+)\\."+extension, Pattern.CASE_INSENSITIVE).matcher(name); int start = 0; String frag=name; try { frag = name.substring(0,name.lastIndexOf(".")); } catch (Throwable ignored) { // Nowt } String indexStr=""; if (matcher.matches()) { frag = matcher.group(1); indexStr = matcher.group(2); start = Integer.parseInt(indexStr); } if (conjunctive!=null) { frag = frag+conjunctive; } // First try without a start position final IContainer parent = file.getParent(); final IFile newFile; if (parent instanceof IFolder) { newFile = ((IFolder)parent).getFile(frag+indexStr+"."+extension); } else if (parent instanceof IProject) { newFile = ((IProject)parent).getFile(frag+indexStr+"."+extension); } else { newFile = null; } if (newFile!=null&&!newFile.exists()) return newFile; return getUniqueFile(parent, frag, ++start, extension); } private static IFile getUniqueFile(IContainer parent, String frag, int start, final String extension) { final IFile file; if (parent instanceof IFolder) { file = ((IFolder)parent).getFile(frag+start+"."+extension); } else if (parent instanceof IProject) { file = ((IProject)parent).getFile(frag+start+"."+extension); } else { throw new RuntimeException("The parent is neither a project nor a folder."); } if (!file.exists()) return file; return getUniqueFile(parent, frag, ++start, extension); } }