/***************************************************************************** * Limpet - the Lightweight InforMation ProcEssing Toolkit * http://limpet.info * * (C) 2015-2016, Deep Blue C Technologies Ltd * * This library is free software; you can redistribute it and/or * modify it under the terms of the Eclipse Public License v1.0 * (http://www.eclipse.org/legal/epl-v10.html) * * 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. *****************************************************************************/ package info.limpet.ui.operations; import info.limpet.ICollection; import info.limpet.ICommand; import info.limpet.IContext; import info.limpet.IOperation; import info.limpet.IStore; import info.limpet.IStoreGroup; import info.limpet.IStoreItem; import info.limpet.ITemporalQuantityCollection; import info.limpet.data.commands.AbstractCommand; import info.limpet.data.impl.TemporalQuantityCollection; import info.limpet.data.operations.CollectionComplianceTests; import info.limpet.data.store.IGroupWrapper; import info.limpet.stackedcharts.model.AngleAxis; import info.limpet.stackedcharts.model.AxisType; import info.limpet.stackedcharts.model.Chart; import info.limpet.stackedcharts.model.ChartSet; import info.limpet.stackedcharts.model.Dataset; import info.limpet.stackedcharts.model.DependentAxis; import info.limpet.stackedcharts.model.IndependentAxis; import info.limpet.stackedcharts.model.NumberAxis; import info.limpet.stackedcharts.model.Orientation; import info.limpet.stackedcharts.model.StackedchartsFactory; import info.limpet.stackedcharts.ui.view.StackedChartsView; import info.limpet.stackedcharts.ui.view.StackedChartsView.ControllableDate; import info.limpet.ui.data_provider.data.CollectionWrapper; import info.limpet.ui.range_slider.RangeSliderView; import info.limpet.ui.stacked.LimpetStackedChartsAdapter; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.List; import org.eclipse.ui.IViewPart; import org.eclipse.ui.IViewReference; import org.eclipse.ui.IWorkbenchPage; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PartInitException; import org.eclipse.ui.PlatformUI; public class ShowInStackedChartsOverview implements IOperation<IStoreItem> { private final CollectionComplianceTests aTests = new CollectionComplianceTests(); private final String _title; public ShowInStackedChartsOverview(String title) { _title = title; } protected CollectionComplianceTests getTests() { return aTests; } public Collection<ICommand<IStoreItem>> actionsFor( List<IStoreItem> selection, IStore destination, IContext context) { Collection<ICommand<IStoreItem>> res = new ArrayList<ICommand<IStoreItem>>(); if (appliesTo(selection)) { ICommand<IStoreItem> newC = new ShowInStackedChartsOperation(_title, selection, context); res.add(newC); } return res; } protected boolean appliesTo(List<IStoreItem> selection) { boolean nonEmpty = aTests.nonEmpty(selection); boolean allData = aTests.allCollections(selection); boolean allQuantity = aTests.allQuantity(selection); boolean allTemporal = aTests.allTemporal(selection); return (nonEmpty && allData && allQuantity && allTemporal); } public static class ShowInStackedChartsOperation extends AbstractCommand<IStoreItem> { public ShowInStackedChartsOperation(String title, List<IStoreItem> selection, IContext context) { super(title, "Show selection in Stacked Charts", null, false, false, selection, context); } @Override protected String getOutputName() { return null; } @Override public void execute() { String secId = getInputs().toString(); String viewId = StackedChartsView.ID; // create a new instance of the specified view IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); IWorkbenchPage page = window.getActivePage(); try { page.showView(viewId, secId, IWorkbenchPage.VIEW_ACTIVATE); } catch (PartInitException e) { e.printStackTrace(); } // try to recover the view IViewReference viewRef = page.findViewReference(viewId, secId); if (viewRef != null) { final IViewPart theView = viewRef.getView(true); // double check it's what we're after if (theView instanceof StackedChartsView) { final StackedChartsView chartView = (StackedChartsView) theView; // create the charts set model ChartSet model = createModelFor(this.getInputs()); if (model != null) { // set follow selection to off // cv.follow(getInputs()); chartView.setModel(model); // also, see if we can listen to changes in it final IStoreGroup group = RangeSliderView.findTopParent(this.getInputs().get(0)); if (group != null) { final PropertyChangeListener listener = new PropertyChangeListener() { @Override public void propertyChange(PropertyChangeEvent evt) { // ok, update the time now Date newTime = (Date) evt.getNewValue(); chartView.updateTime(newTime); } }; group.addTimeChangeListener(listener); Runnable closer = new Runnable() { @Override public void run() { group.removeTimeChangeListener(listener); } }; chartView.addRunOnCloseCallback(closer); ControllableDate timeC = new ControllableDate() { @Override public void setDate(Date date) { group.setTime(date); } @Override public Date getDate() { return group.getTime(); } }; chartView.setDateSupport(timeC); } // // take a copy of the model // URI resourceURI = URI.createFileURI("/home/ian/tacticalOverview.stackedcharts"); // Resource resource = new ResourceSetImpl().createResource(resourceURI); // System.out.println("saving to:" + resourceURI.toFileString()); // resource.getContents().add(model); // try // { // resource.save(null); // } // catch (IOException e) // { // e.printStackTrace(); // } } } } } @Override protected void recalculate(IStoreItem subject) { // don't worry } } protected static TemporalQuantityCollection<?> getFirstCollectionFor( List<IStoreItem> selection) { TemporalQuantityCollection<?> res = null; if (selection != null) { IStoreItem first = selection.iterator().next(); if (first instanceof IGroupWrapper) { IGroupWrapper group = (IGroupWrapper) first; IStoreItem nextItem = group.getGroup().iterator().next(); while (nextItem instanceof IStoreGroup) { IStoreGroup storeGroup = (IStoreGroup) nextItem; nextItem = storeGroup.iterator().next(); } if (nextItem != null) { ICollection coll = (ICollection) nextItem; if (coll.isQuantity() && coll.isTemporal()) { res = (TemporalQuantityCollection<?>) coll; } } } else if (first instanceof CollectionWrapper) { CollectionWrapper cw = (CollectionWrapper) first; ICollection collection = cw.getCollection(); if (collection.isQuantity() && collection.isTemporal()) res = (TemporalQuantityCollection<?>) collection; } else if (first instanceof TemporalQuantityCollection<?>) { res = (TemporalQuantityCollection<?>) first; } } return res; } public static ChartSet createModelFor(List<IStoreItem> selection) { // ok, use the limpet adapter to get the data ChartSet res = null; // our data generator LimpetStackedChartsAdapter adapter = new LimpetStackedChartsAdapter(); if (adapter.canConvertToDataset(selection)) { List<Dataset> datasets = adapter.convertToDataset(selection); if (datasets != null) { StackedchartsFactory factory = StackedchartsFactory.eINSTANCE; Chart thisChart = null; for (Object thisO : datasets) { if (thisO instanceof Dataset) { Dataset dataset = (Dataset) thisO; // set the independent axis final String theseUnits = dataset.getUnits(); if (res == null) { // ok, we need a chart-set res = factory.createChartSet(); res.setOrientation(Orientation.VERTICAL); // get the first item, so we can determine the independent axis TemporalQuantityCollection<?> firstItem = getFirstCollectionFor(selection); if (firstItem instanceof ITemporalQuantityCollection) { IndependentAxis ia = factory.createIndependentAxis(); ia.setAxisType(factory.createDateAxis()); res.setSharedAxis(ia); } else { System.err .println("FAILED TO CREATE CHARTSET - WE DON'T HAVE TIME AS INDEPENDENT AXIS"); } } // ok, plot this dataset if (thisChart == null) { thisChart = factory.createChart(); res.getCharts().add(thisChart); } DependentAxis dependent = findAxisFor(res, theseUnits); if (dependent == null) { dependent = factory.createDependentAxis(); // double-check if this is angular data final NumberAxis numAxis; if ("\u00b0".equals(dataset.getUnits()) || "Degs".equals(dataset.getUnits())) { final AngleAxis angleAxis = factory.createAngleAxis(); angleAxis.setMinVal(0); angleAxis.setMaxVal(360); numAxis = angleAxis; } else { numAxis = factory.createNumberAxis(); } numAxis.setUnits(dataset.getUnits()); dependent.setAxisType(numAxis); dependent.setName(theseUnits); thisChart.getMinAxes().add(dependent); } dependent.getDatasets().add(dataset); } } } } return res; } private static DependentAxis findAxisFor(ChartSet charts, String units) { DependentAxis res = null; for (Chart chart : charts.getCharts()) { for (DependentAxis da : chart.getMinAxes()) { AxisType thisType = da.getAxisType(); if (thisType instanceof NumberAxis) { NumberAxis na = (NumberAxis) thisType; if (na.getUnits() != null && na.getUnits().equals(units)) { return da; } } } for (DependentAxis da : chart.getMaxAxes()) { AxisType thisType = da.getAxisType(); if (thisType instanceof NumberAxis) { NumberAxis na = (NumberAxis) thisType; if (na.getUnits() != null && na.getUnits().equals(units)) { return da; } } } } return res; } }