/* * Copyright (C) 2010 Brockmann Consult GmbH (info@brockmann-consult.de) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 3 of the License, or (at your option) * any later version. * This program 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 General Public License for * more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see http://www.gnu.org/licenses/ */ package org.esa.snap.timeseries.ui.manager; import org.esa.snap.core.datamodel.GeoCoding; import org.esa.snap.core.datamodel.GeoPos; import org.esa.snap.core.datamodel.PinDescriptor; import org.esa.snap.core.datamodel.PixelPos; import org.esa.snap.core.datamodel.Placemark; import org.esa.snap.core.datamodel.Product; import org.esa.snap.core.datamodel.ProductManager; import org.esa.snap.core.datamodel.ProductNode; import org.esa.snap.core.datamodel.ProductNodeEvent; import org.esa.snap.rcp.SnapApp; import org.esa.snap.timeseries.core.TimeSeriesMapper; import org.esa.snap.timeseries.core.insitu.InsituSource; import org.esa.snap.timeseries.core.timeseries.datamodel.AbstractTimeSeries; import org.esa.snap.timeseries.core.timeseries.datamodel.TimeSeriesChangeEvent; import org.esa.snap.timeseries.core.timeseries.datamodel.TimeSeriesListener; import org.openide.awt.ActionID; import org.openide.awt.ActionReference; import org.openide.awt.ActionReferences; import org.openide.util.HelpCtx; import org.openide.util.NbBundle; import org.openide.windows.TopComponent; import javax.swing.border.EmptyBorder; import java.awt.BorderLayout; import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.WeakHashMap; @TopComponent.Description( preferredID = "TimeSeriesManagerTopComponent", iconBase = "org/esa/snap/timeseries/ui/icons/timeseries-manager.png", persistenceType = TopComponent.PERSISTENCE_ALWAYS ) @TopComponent.Registration( mode = "navigator", openAtStartup = false, position = 1 ) @TopComponent.OpenActionRegistration( displayName = "#CTL_TimeSeriesManagerTopComponent_Name", preferredID = "TimeSeriesManagerTopComponent" ) @ActionID(category = "Window", id = "org.esa.snap.timeseries.ui.manager.TimeSeriesManagerTopComponent") @ActionReferences({ @ActionReference(path = "Menu/View/Tool Windows/Time Series", position = 1210, separatorBefore = 1200), @ActionReference(path = "Toolbars/Time Series", position = 10) }) @NbBundle.Messages({ "CTL_TimeSeriesManagerTopComponent_Name=Time Series Manager", "CTL_TimeSeriesManagerTopComponent_ComponentName=Time_Series_Manager" }) /** * Main class for the manager tool. * * @author Marco Peters * @author Thomas Storm * @author Sabine Embacher */ public class TimeSeriesManagerTopComponent extends TopComponent { private static final String HELP_ID = "timeSeriesManager"; private Product selectedProduct; private String prefixTitle; private final WeakHashMap<Product, TimeSeriesManagerForm> formMap; private TimeSeriesManagerForm activeForm; private final TimeSeriesManagerTSL timeSeriesManagerTSL; public TimeSeriesManagerTopComponent() { setName(Bundle.CTL_TimeSeriesManagerTopComponent_ComponentName()); formMap = new WeakHashMap<>(); timeSeriesManagerTSL = new TimeSeriesManagerTSL(); initUI(); } private void initUI() { setLayout(new BorderLayout()); setBorder(new EmptyBorder(4, 4, 4, 4)); prefixTitle = Bundle.CTL_TimeSeriesManagerTopComponent_Name(); setSelectedProduct(SnapApp.getDefault().getSelectedProduct()); realizeActiveForm(); updateTitle(); SnapApp.getDefault().getSelectionSupport(ProductNode.class).addHandler((oldValue, newValue) -> { if(newValue != null) { setSelectedProduct(newValue.getProduct()); } else { setSelectedProduct(null); } }); SnapApp.getDefault().getProductManager().addListener(new ProductManager.Listener() { @Override public void productAdded(ProductManager.Event event) { } @Override public void productRemoved(ProductManager.Event event) { productClosed(event.getProduct()); } }); } @Override public HelpCtx getHelpCtx() { return new HelpCtx(HELP_ID); } Product getSelectedProduct() { return selectedProduct; } private void productClosed(Product product) { formMap.remove(product); setSelectedProduct(null); } private void updateTitle() { final String suffix; final Product product = getSelectedProduct(); if (product != null) { suffix = " - " + product.getDisplayName(); } else { suffix = ""; } setDisplayName(prefixTitle + suffix); } private void setSelectedProduct(Product newProduct) { Product oldProduct = selectedProduct; if (newProduct != oldProduct) { if (oldProduct != null) { final AbstractTimeSeries timeSeries = TimeSeriesMapper.getInstance().getTimeSeries(oldProduct); if (timeSeries != null) { timeSeries.removeTimeSeriesListener(timeSeriesManagerTSL); } } selectedProduct = newProduct; realizeActiveForm(); updateTitle(); if (newProduct != null) { final AbstractTimeSeries timeSeries = TimeSeriesMapper.getInstance().getTimeSeries(newProduct); if (timeSeries != null) { timeSeries.addTimeSeriesListener(timeSeriesManagerTSL); } } } } private void realizeActiveForm() { if (getComponentCount() > 0) { remove(0); } activeForm = getOrCreateActiveForm(getSelectedProduct()); add(activeForm.getControl(), BorderLayout.CENTER); validate(); repaint(); } private TimeSeriesManagerForm getOrCreateActiveForm(Product product) { if (formMap.containsKey(product)) { activeForm = formMap.get(product); } else { activeForm = new TimeSeriesManagerForm(HELP_ID); formMap.put(product, activeForm); } activeForm.updateFormControl(product); return activeForm; } private void updateInsituPins() { final AbstractTimeSeries timeSeries = TimeSeriesMapper.getInstance().getTimeSeries(selectedProduct); timeSeries.clearInsituPlacemarks(); addPlacemarks(timeSeries); } private void addPlacemarks(AbstractTimeSeries timeSeries) { final InsituSource insituSource = timeSeries.getInsituSource(); final List<String> selectedInsituVariables = getSelectedInsituVariables(timeSeries, insituSource); final Set<GeoPos> geoPoses = new TreeSet<>(createGeoPosComparator()); for (String selectedInsituVariable : selectedInsituVariables) { geoPoses.addAll(insituSource.getInsituPositionsFor(selectedInsituVariable)); } final Product tsProduct = timeSeries.getTsProduct(); final GeoCoding geoCoding = tsProduct.getGeoCoding(); final PixelPos pixelPos = new PixelPos(); for (GeoPos geoPos : geoPoses) { geoCoding.getPixelPos(geoPos, pixelPos); if (!AbstractTimeSeries.isPixelValid(tsProduct, pixelPos)) { continue; } String name; if (insituSource.hasStationNames()) { name = insituSource.getNameFor(geoPos); } else { name = geoPos.getLatString() + "_" + geoPos.getLonString(); } final String pinName = "Insitu_" + name; final String pinLabel = name; final String pinDescription = name; final Placemark placemark = Placemark.createPointPlacemark( PinDescriptor.getInstance(), pinName, pinLabel, pinDescription, null, new GeoPos(geoPos), geoCoding); timeSeries.registerRelation(placemark, geoPos); } } private Comparator<GeoPos> createGeoPosComparator() { return (o1, o2) -> o1.toString().compareTo(o2.toString()); } private List<String> getSelectedInsituVariables(AbstractTimeSeries timeSeries, InsituSource insituSource) { final String[] parameterNames = insituSource.getParameterNames(); final List<String> selectedInsituVariables = new ArrayList<>(); for (String parameterName : parameterNames) { if (timeSeries.isInsituVariableSelected(parameterName)) { selectedInsituVariables.add(parameterName); } } return selectedInsituVariables; } private class TimeSeriesManagerTSL extends TimeSeriesListener { @Override public void timeSeriesChanged(TimeSeriesChangeEvent event) { final int type = event.getType(); if (type == TimeSeriesChangeEvent.START_TIME_PROPERTY_NAME || type == TimeSeriesChangeEvent.END_TIME_PROPERTY_NAME) { activeForm.updateFormControl(getSelectedProduct()); } else if (type == TimeSeriesChangeEvent.PROPERTY_INSITU_VARIABLE_SELECTION) { updateInsituPins(); } } @Override public void nodeChanged(ProductNodeEvent event) { activeForm.updateFormControl(getSelectedProduct()); } } }