From 6f9dca57e87d5b5eb52be0dc443703880fbc5193 Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Fri, 29 Aug 2014 11:47:06 -0500 Subject: [PATCH 1/6] Issue #3543 Fix gl datamapping of data with NaN conversions. Former-commit-id: 22f93b6905c8783a22e5461a9efa723a7519db55 [formerly bc12be9bb6e8c7f63550602f51bca3448c21d4c6] Former-commit-id: 190893e80777549935bbc9425868b0fd6178cb33 --- .../core/gl/ext/imaging/GLDataMappingFactory.java | 14 ++++++++++---- .../viz/grid/rsc/general/AbstractGridResource.java | 8 +++++++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/ext/imaging/GLDataMappingFactory.java b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/ext/imaging/GLDataMappingFactory.java index f867700f2b..67f898d5c7 100644 --- a/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/ext/imaging/GLDataMappingFactory.java +++ b/cave/com.raytheon.viz.core.gl/src/com/raytheon/viz/core/gl/ext/imaging/GLDataMappingFactory.java @@ -45,6 +45,7 @@ import com.raytheon.viz.core.gl.images.GLCMTextureData; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Oct 24, 2013 2492 mschenke Initial creation + * Aug 29, 2014 3543 bsteffen Fixes for NaN unit conversions * * * @@ -239,7 +240,12 @@ public class GLDataMappingFactory { dataMapping[0] = dataMin; dataMapping[dataMapping.length - 1] = dataMax; - numMappings = 2; + if (!Double.isNaN(dataMin)) { + numMappings += 1; + } + if (!Double.isNaN(dataMax)) { + numMappings += 1; + } if (colorMapToData.isLinear() == false) { // Populate the dataMapping/colorMapping arrays double increment = (colorMapMax - colorMapMin) @@ -261,7 +267,7 @@ public class GLDataMappingFactory { // occur in floats in GLSL so no need for the extra // precision float nextDelta = (float) ((nextValue - currEndValue) / (i - currEndIndex)); - if (nextDelta == currDelta) { + if (nextDelta == currDelta || Float.isNaN(nextDelta)) { // Remove linear entries dataMapping[currEndIndex] = colorMapping[currEndIndex] = Double.NaN; currEndValue = nextValue; @@ -297,12 +303,12 @@ public class GLDataMappingFactory { this.colorMapping = new GLBufferCMTextureData( new GLBufferColorMapData(new ColorMapData( FloatBuffer.wrap(condensedColorMapping), - new int[] { numMappings }), + new int[] { numMappingValues }), new GLFloatDataFormat())); this.dataMapping = new GLBufferCMTextureData( new GLBufferColorMapData(new ColorMapData( FloatBuffer.wrap(condensedDataMapping), - new int[] { numMappings }), + new int[] { numMappingValues }), new GLFloatDataFormat())); } } diff --git a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java index 9e4a976abc..9f90cfcb9b 100644 --- a/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java +++ b/cave/com.raytheon.viz.grid/src/com/raytheon/viz/grid/rsc/general/AbstractGridResource.java @@ -496,8 +496,9 @@ public abstract class AbstractGridResource case IMAGE: ColorMapCapability colorMapCap = getCapability(ColorMapCapability.class); ImagingCapability imagingCap = getCapability(ImagingCapability.class); + ColorMapParameters params = null; if (renderableMap.isEmpty()) { - ColorMapParameters params = createColorMapParameters(data); + params = createColorMapParameters(data); if (params.getColorMap() == null) { if (params.getColorMapName() == null) { params.setColorMapName("Grid/gridded data"); @@ -506,6 +507,11 @@ public abstract class AbstractGridResource .getColorMapName())); } colorMapCap.setColorMapParameters(params); + } else { + params = colorMapCap.getColorMapParameters(); + } + if (params.getDataMapping() != null) { + data.convert(params.getColorMapUnit()); } TileImageCreator creator = new DataSourceTileImageCreator( data.getScalarData(), data.getDataUnit(), From c23122797d424faef7356eeeb6c8623b0c3b6083 Mon Sep 17 00:00:00 2001 From: Ron Anderson Date: Tue, 9 Sep 2014 11:04:25 -0500 Subject: [PATCH 2/6] Issue #3592 Fixed several localization issue in GFE Change-Id: I2e65649d490372b5c1738f07c79b5ed15885f8c7 Former-commit-id: 52e5636261f96ece57357b5bb53f873e93823cc0 [formerly a5ef55df33009948fec139e7729dd53ae4251667] Former-commit-id: b91141ef7b66fc3cfd1756fa766ef3a5e5dc069b --- .../raytheon/viz/gfe/core/DataManager.java | 2 + .../viz/gfe/core/ISampleSetManager.java | 18 +- .../viz/gfe/core/SampleSetMgrInitJob.java | 3 +- .../viz/gfe/core/internal/ParmManager.java | 11 +- .../core/internal/ReferenceSetManager.java | 34 +-- .../gfe/core/internal/SampleSetManager.java | 198 +++++++++--------- .../core/internal/SelectTimeRangeManager.java | 110 +++++++--- .../textformatter/CombinationsFileUtil.java | 41 ++-- .../plugin/gfe/reference/ReferenceMgr.java | 14 +- .../uf/common/localization/IPathManager.java | 122 ++++++++--- .../uf/common/localization/PathManager.java | 70 ++++++- 11 files changed, 405 insertions(+), 218 deletions(-) diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java index 82f79583a5..a2e37e09f6 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/DataManager.java @@ -100,6 +100,7 @@ import com.raytheon.viz.gfe.textformatter.TextProductManager; * 09/05/2013 2307 dgilling Use better PythonScript constructor. * 09/16/2013 2033 dgilling Remove unused IToolController. * 12/09/2013 2367 dgilling Instantiate ProcedureJobPool here. + * 09/09/2014 3592 randerso Added call to SampleSetManager.dispose() * * * @@ -290,6 +291,7 @@ public class DataManager { * {@link DataManagerFactory#dispose(Object)} */ void dispose() { + sampleSetManager.dispose(); selectTimeRangeManager.dispose(); refManager.dispose(); parmManager.dispose(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISampleSetManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISampleSetManager.java index e64c4d02fb..f3b313afc2 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISampleSetManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/ISampleSetManager.java @@ -25,7 +25,6 @@ import java.util.List; import java.util.Map; import com.raytheon.uf.common.dataplugin.gfe.sample.SampleId; -import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.gfe.GFEException; import com.raytheon.viz.gfe.core.msgs.ISampleSetChangedListener; import com.raytheon.viz.gfe.edittool.GridID; @@ -39,7 +38,8 @@ import com.vividsolutions.jts.geom.Coordinate; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jun 30, 2008 chammack Initial creation - * Apr 9, 2009 1288 rjpeter Added add/remove method for sample set listener + * Apr 09, 2009 1288 rjpeter Added add/remove method for sample set listener + * Sep 09, 2014 3592 randerso Added dispose method, removed networkNotification method * * * @author chammack @@ -52,6 +52,11 @@ public interface ISampleSetManager { public static final float DEFAULT_THRESHOLD = 0.0f; + /** + * Dispose the SampleSetManager + */ + public void dispose(); + /** * Returns the set of sample points for the named sample set. If the sample * set is not known, an empty list will be returned. @@ -196,15 +201,6 @@ public interface ISampleSetManager { */ public boolean deleteSampleSet(final SampleId sampleId); - /** - * Input network sample notification from NetworkMgr indicating that the - * sample set inventory has changed or the contents of a sample set has - * changed. - */ - public void networkNotification(final SampleId[] anInventory, - final SampleId[] additions, final SampleId[] deletions, - final SampleId[] changes) throws VizException; - /** * @return the loadedSet */ diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/SampleSetMgrInitJob.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/SampleSetMgrInitJob.java index 97871128fd..8b9357d62e 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/SampleSetMgrInitJob.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/SampleSetMgrInitJob.java @@ -36,6 +36,7 @@ import com.raytheon.viz.gfe.core.internal.SampleSetManager; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * Jan 25, 2011 njensen Initial creation + * Sep 09, 2014 #3592 randerso Removed unused DataManager parameter to SampleSetManager constructor * * * @@ -60,7 +61,7 @@ public class SampleSetMgrInitJob extends Job { */ @Override protected IStatus run(IProgressMonitor monitor) { - dataMgr.sampleSetManager = new SampleSetManager(dataMgr); + dataMgr.sampleSetManager = new SampleSetManager(); dataMgr.getInitStatus().setSampleSetMgrDone(true); return Status.OK_STATUS; diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java index 2e8a40b35f..f7b5e7528d 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ParmManager.java @@ -143,6 +143,7 @@ import com.raytheon.viz.gfe.types.MutableInteger; * 04/02/2014 #2969 randerso Fix error when Toop parm is unloaded. * 05/01/2014 #3105 dgilling Ensure mutable db gets into availableServerDatabases * if it has to be created during ParmManager construction. + * 09/08/2104 #3592 randerso Changed to use new pm listStaticFiles() * * * @author chammack @@ -3099,11 +3100,10 @@ public class ParmManager implements IParmManager, IMessageClient { private List initVirtualCalcParmDefinitions() { // retrieve the inventory from the ifpServer IPathManager pathMgr = PathManagerFactory.getPathManager(); - LocalizationFile[] modules = pathMgr - .listFiles( - pathMgr.getLocalSearchHierarchy(LocalizationType.COMMON_STATIC), - FileUtil.join("gfe", "vcmodule"), - new String[] { "py" }, false, true); + LocalizationFile[] modules = pathMgr.listStaticFiles( + LocalizationType.COMMON_STATIC, + FileUtil.join("gfe", "vcmodule"), new String[] { "py" }, false, + true); List definitions = new ArrayList(modules.length); for (LocalizationFile mod : modules) { @@ -3112,6 +3112,7 @@ public class ParmManager implements IParmManager, IMessageClient { File textData = mod.getFile(true); // create the VCModule + statusHandler.debug("Loading VCModule: " + mod); VCModule m = new VCModule(dataManager, this, textData); if (!m.isValid()) { statusHandler.handle(Priority.PROBLEM, diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ReferenceSetManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ReferenceSetManager.java index c5a04b9350..68ce6163cb 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ReferenceSetManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/ReferenceSetManager.java @@ -109,6 +109,7 @@ import com.vividsolutions.jts.geom.Envelope; * 06/21/2013 14983 ryu Added method for synchronous evaluation of query. * 08/06/2013 1561 njensen Use pm.listFiles() instead of pm.listStaticFiles() * 09/30/2013 2361 njensen Use JAXBManager for XML + * 09/08/2104 #3592 randerso Changed to use new pm listStaticFiles() * * * @@ -231,9 +232,8 @@ public class ReferenceSetManager implements IReferenceSetManager, // load the complete list of edit areas List refIDs = new ArrayList(); IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext[] ctx = pm - .getLocalSearchHierarchy(LocalizationType.COMMON_STATIC); - LocalizationFile[] contents = pm.listFiles(ctx, EDIT_AREAS_DIR, + LocalizationFile[] contents = pm.listStaticFiles( + LocalizationType.COMMON_STATIC, EDIT_AREAS_DIR, new String[] { ".xml" }, false, true); if (contents != null) { for (LocalizationFile lf : contents) { @@ -245,7 +245,8 @@ public class ReferenceSetManager implements IReferenceSetManager, } // load the edit area group lists - LocalizationFile[] groupFiles = pm.listFiles(ctx, EDIT_AREA_GROUPS_DIR, + LocalizationFile[] groupFiles = pm.listStaticFiles( + LocalizationType.COMMON_STATIC, EDIT_AREA_GROUPS_DIR, new String[] { ".txt" }, false, true); if (groupFiles != null) { for (LocalizationFile lf : groupFiles) { @@ -779,8 +780,8 @@ public class ReferenceSetManager implements IReferenceSetManager, if (lf != null) { try { - refData = ReferenceData.getJAXBManager() - .unmarshalFromXmlFile(lf.getFile().getPath()); + refData = ReferenceData.getJAXBManager().unmarshalFromXmlFile( + lf.getFile().getPath()); } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, "Error reading xml file " @@ -921,7 +922,7 @@ public class ReferenceSetManager implements IReferenceSetManager, LocalizationFile lf = pm.getLocalizationFile(ctx, FileUtil.join(EDIT_AREAS_DIR, refID.getName() + ".xml")); - if (lf != null + if ((lf != null) && (!withVerification || AccessMgr.verifyDelete(lf.getName(), LocalizationType.COMMON_STATIC, false))) { try { @@ -1124,7 +1125,7 @@ public class ReferenceSetManager implements IReferenceSetManager, if (pointyTaper) { for (i = ll.x; i <= ur.x; i++) { for (j = ll.y; j <= ur.y; j++) { - grid.set(i, j, grid.get(i, j) * taperFactor / maxDist); + grid.set(i, j, (grid.get(i, j) * taperFactor) / maxDist); } } } @@ -1192,7 +1193,7 @@ public class ReferenceSetManager implements IReferenceSetManager, int y = j; while ((x >= 0) && (y >= 0) && (x < dim.x) && (y < dim.y) && bitGrid.getAsBoolean(x, y)) { - vdist = vdist + Math.sqrt(v.x * v.x + v.y * v.y); + vdist = vdist + Math.sqrt((v.x * v.x) + (v.y * v.y)); x = x + v.x; y = y + v.y; } @@ -1200,11 +1201,12 @@ public class ReferenceSetManager implements IReferenceSetManager, y = j; while ((x >= 0) && (y >= 0) && (x < dim.x) && (y < dim.y) && bitGrid.getAsBoolean(x, y)) { - avdist = avdist + Math.sqrt(av.x * av.x + av.y * av.y); + avdist = avdist + + Math.sqrt((av.x * av.x) + (av.y * av.y)); x = x + av.x; y = y + av.y; } - if (vdist + avdist == 0) { + if ((vdist + avdist) == 0) { grid.set(i, j, 0.0f); } else { grid.set(i, j, (float) (vdist / (vdist + avdist))); @@ -1352,7 +1354,7 @@ public class ReferenceSetManager implements IReferenceSetManager, /** * @param ref - * @param mode2 + * @param mode */ private void setRefSet(ReferenceData ref, RefSetMode mode) { mode = determineMode(mode); @@ -1383,7 +1385,7 @@ public class ReferenceSetManager implements IReferenceSetManager, } /** - * @param mode2 + * @param mode * @return */ private RefSetMode determineMode(RefSetMode mode) { @@ -1666,7 +1668,7 @@ public class ReferenceSetManager implements IReferenceSetManager, LocalizationFile lf = PathManagerFactory.getPathManager() .getStaticLocalizationFile(filePath); - if (lf != null && lf.exists()) { + if ((lf != null) && lf.exists()) { changes.add(refId); } else { deletions.add(refId); @@ -1718,7 +1720,7 @@ public class ReferenceSetManager implements IReferenceSetManager, .getFileName()); // if it exists, load it - if (lf != null && lf.exists()) { + if ((lf != null) && lf.exists()) { loadGroup(lf); } checkGroupConsistency(); @@ -1824,7 +1826,7 @@ public class ReferenceSetManager implements IReferenceSetManager, Date spedTime = dataManager.getSpatialDisplayManager() .getSpatialEditorTime(); - if (spedTime != null && msg.getTimeRange().contains(spedTime)) { + if ((spedTime != null) && msg.getTimeRange().contains(spedTime)) { evaluateActiveRefSet(listener); } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SampleSetManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SampleSetManager.java index c5df3e1ff1..bda485c29f 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SampleSetManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SampleSetManager.java @@ -22,6 +22,7 @@ package com.raytheon.viz.gfe.core.internal; import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; @@ -33,6 +34,8 @@ import org.geotools.referencing.GeodeticCalculator; import com.raytheon.uf.common.dataplugin.gfe.sample.SampleData; import com.raytheon.uf.common.dataplugin.gfe.sample.SampleId; +import com.raytheon.uf.common.localization.FileUpdatedMessage; +import com.raytheon.uf.common.localization.ILocalizationFileObserver; import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; @@ -47,10 +50,8 @@ import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; import com.raytheon.uf.common.util.FileUtil; -import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.viz.gfe.Activator; import com.raytheon.viz.gfe.GFEException; -import com.raytheon.viz.gfe.core.DataManager; import com.raytheon.viz.gfe.core.ISampleSetManager; import com.raytheon.viz.gfe.core.msgs.ISampleSetChangedListener; import com.raytheon.viz.gfe.edittool.GridID; @@ -68,13 +69,15 @@ import com.vividsolutions.jts.geom.Coordinate; * Apr 9, 2009 1288 rjpeter Added ISampleSetChangedListener handling. * Aug 6, 2013 1561 njensen Use pm.listFiles() instead of pm.listStaticFiles() * Sep 30, 2013 2361 njensen Use JAXBManager for XML + * Sep 08, 2104 #3592 randerso Changed to use new pm listStaticFiles() * * * @author rbell * @version 1.0 */ -public class SampleSetManager implements ISampleSetManager { +public class SampleSetManager implements ISampleSetManager, + ILocalizationFileObserver { private static final transient IUFStatusHandler statusHandler = UFStatus .getHandler(SampleSetManager.class); @@ -91,19 +94,20 @@ public class SampleSetManager implements ISampleSetManager { private Map> markerLocations; - private final DataManager dataManager; - private final Set sampleSetChangedListeners; private boolean showLatLon; + private IPathManager pathManager; + + private LocalizationFile sampleSetDir; + /** * Default constructor. * * Gets the initial sample inventory. */ - public SampleSetManager(DataManager dataManager) { - this.dataManager = dataManager; + public SampleSetManager() { this.loadedSet = new SampleId(); this.inventory = new HashSet(); @@ -114,17 +118,23 @@ public class SampleSetManager implements ISampleSetManager { this.sampleSetChangedListeners = new HashSet(); - IPathManager pm = PathManagerFactory.getPathManager(); + this.pathManager = PathManagerFactory.getPathManager(); - LocalizationFile[] files = pm.listFiles( - pm.getLocalSearchHierarchy(LocalizationType.COMMON_STATIC), - SAMPLE_SETS_DIR, new String[] { ".xml" }, true, true); + this.sampleSetDir = pathManager.getLocalizationFile(pathManager + .getContext(LocalizationType.COMMON_STATIC, + LocalizationLevel.BASE), SAMPLE_SETS_DIR); + + // initialize the inventory + LocalizationFile[] files = pathManager.listStaticFiles( + LocalizationType.COMMON_STATIC, SAMPLE_SETS_DIR, + new String[] { ".xml" }, true, true); for (LocalizationFile file : files) { String fn = LocalizationUtil.extractName(file.getName()).replace( ".xml", ""); this.inventory.add(new SampleId(fn)); } + this.sampleSetDir.addFileUpdatedObserver(this); // load default sample points String[] sampleSets = Activator.getDefault().getPreferenceStore() @@ -133,24 +143,22 @@ public class SampleSetManager implements ISampleSetManager { for (String id : sampleSets) { SampleId sid = new SampleId(id); if (this.inventory.contains(sid)) { - try { - loadSampleSet(sid, SampleSetLoadMode.ADD); - } catch (GFEException e) { - statusHandler.handle(Priority.PROBLEM, - e.getLocalizedMessage(), e); - - } + loadSampleSet(sid, SampleSetLoadMode.ADD); } } } - // get initial marker points - try { - getMarkerPoints(); - } catch (VizException e) { - statusHandler.handle(Priority.PROBLEM, - "Unable to get initial sampleset marker points", e); - } + getMarkerPoints(); + } + + /* + * (non-Javadoc) + * + * @see com.raytheon.viz.gfe.core.ISampleSetManager#dispose() + */ + @Override + public void dispose() { + this.sampleSetDir.removeFileUpdatedObserver(this); } /* @@ -160,8 +168,8 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#sampleSetLocations(java.lang * .String) */ - public List sampleSetLocations(final String setName) - throws GFEException { + @Override + public List sampleSetLocations(final String setName) { // verify set in inventory boolean found = false; for (SampleId thisId : this.inventory) { @@ -172,9 +180,10 @@ public class SampleSetManager implements ISampleSetManager { } if (!found) { - throw new GFEException( - "Attempt to get locations for unknown sample set [" + statusHandler + .error("Attempt to get locations for unknown sample set [" + setName + "]"); + return Collections.emptyList(); } String fileName = FileUtil.join(SAMPLE_SETS_DIR, setName + ".xml"); @@ -187,9 +196,9 @@ public class SampleSetManager implements ISampleSetManager { f = file.getFile(true); } catch (LocalizationException e) { if (f == null) { - throw new GFEException( - "An error occurred retrieving SampleSet: " + fileName, - e); + statusHandler.error("An error occurred retrieving SampleSet: " + + fileName, e); + return Collections.emptyList(); } } @@ -198,7 +207,8 @@ public class SampleSetManager implements ISampleSetManager { sampleData = SampleData.getJAXBManager().unmarshalFromXmlFile( f.getAbsolutePath()); } catch (Exception e) { - throw new GFEException("Unable to load sampledata: " + f, e); + statusHandler.error("Unable to load sampledata: " + f, e); + return Collections.emptyList(); } return sampleData.getPoints(); @@ -212,8 +222,9 @@ public class SampleSetManager implements ISampleSetManager { * .edex.plugin.gfe.sample.SampleId, * com.raytheon.viz.gfe.core.internal.SampleSetManager.SampleSetLoadMode) */ + @Override public void loadSampleSet(final SampleId sampleId, - SampleSetLoadMode loadMode) throws GFEException { + SampleSetLoadMode loadMode) { File f = PathManagerFactory.getPathManager().getStaticFile( FileUtil.join(SAMPLE_SETS_DIR, sampleId.getName() + ".xml")); @@ -221,8 +232,9 @@ public class SampleSetManager implements ISampleSetManager { try { sampleData = SampleData.getJAXBManager().unmarshalFromXmlFile( f.getPath()); + sampleData.setSampleId(sampleId); } catch (Exception e) { - throw new GFEException("Unable to load sampledata: " + f); + statusHandler.error("Unable to load sampledata: " + f); } // set the loadedSet flag appropriately @@ -247,6 +259,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#clearSamples() */ + @Override public void clearSamples() { mergeSamples(new ArrayList(), SampleSetLoadMode.REPLACE); this.loadedSet = new SampleId(); // no loaded set @@ -260,6 +273,7 @@ public class SampleSetManager implements ISampleSetManager { * @seecom.raytheon.viz.gfe.core.ISampleSetManager#addAnchoredSample(com. * vividsolutions.jts.geom.Coordinate) */ + @Override public void addAnchoredSample(final Coordinate sampleLocation) { mergeSamples(Arrays.asList(sampleLocation), SampleSetLoadMode.ADD); this.loadedSet = new SampleId(); // no longer a loaded set @@ -274,6 +288,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#removeAnchoredSample(com. * vividsolutions.jts.geom.Coordinate) */ + @Override public void removeAnchoredSample(final Coordinate sampleLocation) { removeAnchoredSample(sampleLocation, ISampleSetManager.DEFAULT_THRESHOLD); @@ -286,6 +301,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#removeAnchoredSample(com. * vividsolutions.jts.geom.Coordinate, float) */ + @Override public void removeAnchoredSample(final Coordinate sampleLocation, float threshold) { mergeSamples(Arrays.asList(sampleLocation), SampleSetLoadMode.REMOVE, @@ -301,6 +317,7 @@ public class SampleSetManager implements ISampleSetManager { * @seecom.raytheon.viz.gfe.core.ISampleSetManager#addAnchoredMarker(com. * vividsolutions.jts.geom.Coordinate) */ + @Override public void addAnchoredMarker(final Coordinate location, final GridID gid) { String set = activeMarkerSet(gid); List locations = markerLocations.get(set); @@ -319,6 +336,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#removeAnchoredMarker(com. * vividsolutions.jts.geom.Coordinate) */ + @Override public void removeAnchoredMarker(final Coordinate location, final GridID gid) { removeAnchoredMarker(location, gid, ISampleSetManager.DEFAULT_THRESHOLD); } @@ -330,6 +348,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#removeAnchoredMarker(com. * vividsolutions.jts.geom.Coordinate, float) */ + @Override public void removeAnchoredMarker(final Coordinate location, final GridID gid, float threshold) { boolean found = false; @@ -361,6 +380,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#anchoredMarkerAtLocation( * com.vividsolutions.jts.geom.Coordinate, float) */ + @Override public boolean anchoredMarkerAtLocation(final Coordinate location, final GridID gid, float threshold) { String set = activeMarkerSet(gid); @@ -388,6 +408,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#saveSampleSet(com.vividsolutions * .jts.geom.Coordinate[], com.raytheon.edex.plugin.gfe.sample.SampleId) */ + @Override public boolean saveSampleSet(final List sampleLocations, final SampleId sampleId) { @@ -413,13 +434,6 @@ public class SampleSetManager implements ISampleSetManager { e); } - this.inventory.add(sampleId); - - // // send a notification to interested users - // networkNotification(notification.inventory(), - // notification.additions(), - // notification.deletions(), notification.changes()); - return true; } @@ -430,6 +444,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#saveActiveSampleSet(com.raytheon * .edex.plugin.gfe.sample.SampleId) */ + @Override public boolean saveActiveSampleSet(final SampleId sampleId) { this.loadedSet = sampleId; return saveSampleSet(this.locations, sampleId); @@ -442,6 +457,7 @@ public class SampleSetManager implements ISampleSetManager { * com.raytheon.viz.gfe.core.ISampleSetManager#deleteSampleSet(com.raytheon * .edex.plugin.gfe.sample.SampleId) */ + @Override public boolean deleteSampleSet(final SampleId sampleId) { LocalizationFile file = PathManagerFactory.getPathManager() .getStaticLocalizationFile( @@ -458,7 +474,6 @@ public class SampleSetManager implements ISampleSetManager { try { file.delete(); - this.inventory.remove(sampleId); } catch (LocalizationOpFailedException e) { statusHandler.handle(Priority.PROBLEM, "Error deleting from localization server", e); @@ -471,69 +486,55 @@ public class SampleSetManager implements ISampleSetManager { * (non-Javadoc) * * @see - * com.raytheon.viz.gfe.core.ISampleSetManager#networkNotification(com.raytheon - * .edex.plugin.gfe.sample.SampleId[], - * com.raytheon.edex.plugin.gfe.sample.SampleId[], - * com.raytheon.edex.plugin.gfe.sample.SampleId[], - * com.raytheon.edex.plugin.gfe.sample.SampleId[]) + * com.raytheon.uf.common.localization.ILocalizationFileObserver#fileUpdated + * (com.raytheon.uf.common.localization.FileUpdatedMessage) */ - public void networkNotification(final SampleId[] anInventory, - final SampleId[] additions, final SampleId[] deletions, - final SampleId[] changes) throws VizException { + @Override + public void fileUpdated(FileUpdatedMessage message) { - // logDebug << "NetworkNotification newInv=" << anInventory - // << " add=" << additions << " del=" << deletions << " chg=" - // << changes << std::endl; - // logDebug << "OldInventory=" << anInventory << std::endl; - // logDebug << "Active loaded set=" << _loadedSet << std::endl; + String name = LocalizationUtil.extractName(message.getFileName()) + .replace(".xml", ""); + SampleId id = new SampleId(name); - // store the new inventory - this.inventory = new HashSet(Arrays.asList(anInventory)); + switch (message.getChangeType()) { + case ADDED: + case UPDATED: + this.inventory.add(id); - // loaded sample set changed?, check by name field for a match - for (SampleId changesId : changes) { - if (changesId.getName().equals(this.loadedSet.getName())) { - // logDebug << "LoadedSampleSet changed " << _loadedSet << - // std::endl; - loadSampleSet(changesId, SampleSetLoadMode.REPLACE); + // loaded sample set "added", may simply be a rename + if (id.getName().equals(this.loadedSet.getName())) { + loadSampleSet(id, SampleSetLoadMode.REPLACE); } - if (changesId.getName().equals(SampleSetManager.MARKER_NAME)) { - // logDebug << "MarkerSet changed " << changesId << std::endl; + if (id.getName().equals(SampleSetManager.MARKER_NAME)) { getMarkerPoints(); } - } + break; - // loaded sample set deleted? - for (SampleId deletionsId : deletions) { - if (deletionsId.getName().equals(this.loadedSet.getName())) { - // logDebug << "LoadedSampleSet deleted " << _loadedSet - // << ' ' << deletionsId << std::endl; - this.loadedSet = new SampleId(); + case DELETED: + LocalizationFile[] files = pathManager.listStaticFiles( + LocalizationType.COMMON_STATIC, message.getFileName(), + new String[] { ".xml" }, false, true); + + if (id.getName().equals(this.loadedSet.getName())) { + if (files.length > 0) { + loadSampleSet(id, SampleSetLoadMode.REPLACE); + } else { + this.inventory.remove(id); + this.loadedSet = new SampleId(); + } } - if (deletionsId.getName().equals(SampleSetManager.MARKER_NAME)) { - // logDebug << "MarkerSet deleted " << deletionsId << std::endl; + + if (id.getName().equals(SampleSetManager.MARKER_NAME)) { getMarkerPoints(); } + break; + + default: + statusHandler.error("Unexpected FileChangeType received: " + + message.getChangeType().name()); + break; } - // loaded sample set "added", may simply be a rename - for (SampleId additionsId : additions) { - if (additionsId.getName().equals(this.loadedSet.getName())) { - // logDebug << "LoadedSampleSet added " << _loadedSet - // << " " << additionsId << std::endl; - loadSampleSet(additionsId, SampleSetLoadMode.REPLACE); - } - if (additionsId.getName().equals(SampleSetManager.MARKER_NAME)) { - // logDebug << "MarkerSet added " << additionsId << std::endl; - getMarkerPoints(); - } - } - - // inventory changed? - if ((additions.length > 0) || (deletions.length > 0) - || (changes.length > 0)) { - } - // logDebug << "Active set is now: " << _loadedSet << std::endl; fireSampleSetChangedListeners(); } @@ -603,7 +604,7 @@ public class SampleSetManager implements ISampleSetManager { * * Gets the set of points, sends out notification of changes. */ - private void getMarkerPoints() throws VizException { + private void getMarkerPoints() { // ensure it is in the inventory this.markerLocations.clear(); @@ -621,6 +622,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getLoadedSet() */ + @Override public SampleId getLoadedSet() { return this.loadedSet; } @@ -630,6 +632,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getInventory() */ + @Override public SampleId[] getInventory() { return this.inventory.toArray(new SampleId[this.inventory.size()]); } @@ -639,6 +642,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getInventoryAsList() */ + @Override public ArrayList getInventoryAsList() { ArrayList ids = new ArrayList(); for (SampleId id : this.inventory) { @@ -652,6 +656,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getInventoryAsStrings() */ + @Override public String[] getInventoryAsStrings() { String[] retVal = new String[this.inventory.size()]; int i = 0; @@ -663,6 +668,7 @@ public class SampleSetManager implements ISampleSetManager { return retVal; } + @Override public String activeMarkerSet(GridID gid) { // get office type from GridID String ot = gid.getParm().getOfficeType(); @@ -678,6 +684,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getLocations() */ + @Override public List getLocations() { return new ArrayList(this.locations); } @@ -687,6 +694,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#getMarkerLocations() */ + @Override public Map> getMarkerLocations() { return this.markerLocations; } @@ -696,6 +704,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#isShowLatLon() */ + @Override public boolean isShowLatLon() { return showLatLon; } @@ -705,6 +714,7 @@ public class SampleSetManager implements ISampleSetManager { * * @see com.raytheon.viz.gfe.core.ISampleSetManager#setShowLatLon(boolean) */ + @Override public void setShowLatLon(boolean showLatLon) { this.showLatLon = showLatLon; fireSampleSetChangedListeners(); diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java index 624cded8de..e065eaa428 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/core/internal/SelectTimeRangeManager.java @@ -22,15 +22,15 @@ package com.raytheon.viz.gfe.core.internal; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; +import java.util.TreeMap; import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange; import com.raytheon.uf.common.dataplugin.gfe.time.SelectTimeRange.Mode; @@ -62,6 +62,7 @@ import com.raytheon.viz.gfe.core.msgs.SelectTimeRangesChangedMsg; * Dec 3, 2009 #3135 randerso Initial creation * Aug 1, 2012 #965 dgilling Change location of SelectTimeRange. * Aug 6, 2013 #1561 njensen Use pm.listFiles() instead of pm.listStaticFiles() + * Sep 8, 2104 #3592 randerso Changed to use new pm listStaticFiles() * * * @@ -78,23 +79,17 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, private static final String FILE_EXT = ".SELECTTR"; - private static final IPathManager pathManager = PathManagerFactory - .getPathManager(); - private static final TimeZone ZULU = TimeZone.getTimeZone("GMT"); - protected DataManager dataManager; + private IPathManager pathManager; private TimeZone timeZone; - private String[] inventory; - private Map rangeMap; private LocalizationFile selectTRDir; public SelectTimeRangeManager(DataManager dataManager) { - this.dataManager = dataManager; // Find the referenced time zone timeZone = TimeZone.getTimeZone("GMT"); try { @@ -105,13 +100,13 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, "Unable to retrieve GFE time zone, using GMT", e); } - IPathManager pathMgr = PathManagerFactory.getPathManager(); - selectTRDir = pathMgr.getLocalizationFile(pathMgr.getContext( + this.pathManager = PathManagerFactory.getPathManager(); + selectTRDir = pathManager.getLocalizationFile(pathManager.getContext( LocalizationType.COMMON_STATIC, LocalizationLevel.BASE), FILE_PATH); selectTRDir.addFileUpdatedObserver(this); - fileUpdated(null); + loadInventory(); } @Override @@ -123,15 +118,17 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, @Override public String[] inventory() { + String[] inventory = this.rangeMap.keySet().toArray( + new String[this.rangeMap.size()]); return inventory; } private SelectTimeRange loadTimeRange(LocalizationFile lf) { - File file = lf.getFile(); + String rangeName = rangeNameFromFileName(lf.getName()); BufferedReader in = null; try { - in = new BufferedReader(new FileReader(file)); + in = new BufferedReader(new InputStreamReader(lf.openInputStream())); String[] s = in.readLine().split("\\s+"); int start = Integer.parseInt(s[0]); int end = Integer.parseInt(s[1]); @@ -140,21 +137,22 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, mode = Mode.values()[Integer.parseInt(s[2])]; } - SelectTimeRange range = new SelectTimeRange(FileUtil.unmangle(file - .getName().replace(FILE_EXT, "")), start, end, mode, lf - .getContext().getLocalizationLevel(), + SelectTimeRange range = new SelectTimeRange(rangeName, start, end, + mode, lf.getContext().getLocalizationLevel(), (mode.equals(Mode.ZULU) ? ZULU : timeZone)); return range; } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, - "Error reading SELECTTR file " + file.getAbsolutePath(), e); + "Error reading SELECTTR file " + + lf.getFile().getAbsolutePath(), e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { statusHandler.handle(Priority.PROBLEM, - "Error closing file " + file.getAbsolutePath(), e); + "Error closing file " + + lf.getFile().getAbsolutePath(), e); } } } @@ -173,22 +171,26 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, LocalizationLevel.USER), FileUtil.join(FILE_PATH, FileUtil.mangle(name) + FILE_EXT)); - File file = lf.getFile(); BufferedWriter out = null; try { - out = new BufferedWriter(new FileWriter(file)); + out = new BufferedWriter(new OutputStreamWriter( + lf.openOutputStream())); out.write(String.format("%d %d %d", start, end, mode.ordinal())); out.close(); + out = null; lf.save(); } catch (Exception e) { statusHandler.handle(Priority.PROBLEM, - "Error writing SELECTTR file " + file.getAbsolutePath(), e); + "Error writing SELECTTR file " + + lf.getFile().getAbsolutePath(), e); } finally { try { - out.close(); + if (out != null) { + out.close(); + } } catch (IOException e) { statusHandler.handle(Priority.PROBLEM, "Error closing file " - + file.getAbsolutePath(), e); + + lf.getFile().getAbsolutePath(), e); } } } @@ -210,9 +212,48 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, @Override public void fileUpdated(FileUpdatedMessage message) { - LocalizationFile[] files = pathManager.listFiles(pathManager - .getLocalSearchHierarchy(LocalizationType.COMMON_STATIC), - FILE_PATH, new String[] { FILE_EXT }, false, true); + SelectTimeRange range; + + switch (message.getChangeType()) { + case ADDED: + case UPDATED: + LocalizationFile lf = pathManager.getLocalizationFile( + message.getContext(), message.getFileName()); + range = loadTimeRange(lf); + if (range != null) { + this.rangeMap.put(range.getName(), range); + } + break; + + case DELETED: + LocalizationFile[] files = pathManager.listStaticFiles( + LocalizationType.COMMON_STATIC, message.getFileName(), + new String[] { FILE_EXT }, false, true); + + if (files.length > 0) { + range = loadTimeRange(files[0]); // should only be one + if (range != null) { + this.rangeMap.put(range.getName(), range); + } + } else { + String rangeName = rangeNameFromFileName(message.getFileName()); + this.rangeMap.remove(rangeName); + } + break; + + default: + statusHandler.error("Unexpected FileChangeType received: " + + message.getChangeType().name()); + break; + } + + new SelectTimeRangesChangedMsg().send(); + } + + private void loadInventory() { + LocalizationFile[] files = pathManager.listStaticFiles( + LocalizationType.COMMON_STATIC, FILE_PATH, + new String[] { FILE_EXT }, false, true); List ranges = new ArrayList( files.length); @@ -224,19 +265,22 @@ public class SelectTimeRangeManager implements ISelectTimeRangeManager, } Collections.sort(ranges); - String[] inv = new String[ranges.size()]; - Map map = new HashMap(); - int i = 0; + Map map = new TreeMap(); for (SelectTimeRange range : ranges) { - inv[i++] = range.getName(); map.put(range.getName(), range); } synchronized (this) { - this.inventory = inv; this.rangeMap = map; } new SelectTimeRangesChangedMsg().send(); } + + private String rangeNameFromFileName(String fileName) { + File file = new File(fileName); + String rangeName = FileUtil.unmangle(file.getName().replace(FILE_EXT, + "")); + return rangeName; + } } diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/CombinationsFileUtil.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/CombinationsFileUtil.java index ca3a85a581..470b444da4 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/CombinationsFileUtil.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/textformatter/CombinationsFileUtil.java @@ -72,6 +72,8 @@ import com.raytheon.viz.gfe.textformatter.CombinationsFileUtil.ComboData.Entry; * Sep 30, 2013 2361 njensen Use JAXBManager for XML * Feb 05, 2014 #2591 randerso Forced retrieval of combinations file * Implemented retry on error + * Sep 08, 2104 #3592 randerso Changed to use only list site level files as all + * combo files are saved to the site level * * * @@ -138,8 +140,8 @@ public class CombinationsFileUtil { public static LocalizationFile[] getSavedCombos() { IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationFile[] combos = pm.listFiles( - pm.getLocalSearchHierarchy(LocalizationType.CAVE_STATIC), + LocalizationFile[] combos = pm.listFiles(pm.getContext( + LocalizationType.CAVE_STATIC, LocalizationLevel.SITE), SAVED_COMBO_DIR, new String[] { ".xml" }, false, true); return combos; @@ -222,8 +224,9 @@ public class CombinationsFileUtil { IPathManager pm = PathManagerFactory.getPathManager(); // retrieve combinations file if it's changed - LocalizationFile lf = pm.getStaticLocalizationFile(FileUtil.join( - COMBO_DIR_PATH, comboName + ".py")); + LocalizationFile lf = pm.getStaticLocalizationFile( + LocalizationType.CAVE_STATIC, + FileUtil.join(COMBO_DIR_PATH, comboName + ".py")); File pyFile = null; if (lf != null) { try { @@ -234,7 +237,7 @@ public class CombinationsFileUtil { } } - if (pyFile == null || !pyFile.exists()) { + if ((pyFile == null) || !pyFile.exists()) { return Collections.emptyList(); } @@ -250,24 +253,24 @@ public class CombinationsFileUtil { map.put("comboName", comboName); PythonScript python = null; for (int retryCount = 0; retryCount < MAX_TRIES; retryCount++) { - try { + try { python = new PythonScript(scriptPath, PyUtil.buildJepIncludePath( - GfePyIncludeUtil.getCombinationsIncludePath(), - GfePyIncludeUtil.getCommonPythonIncludePath()), - CombinationsFileUtil.class.getClassLoader()); + GfePyIncludeUtil.getCombinationsIncludePath(), + GfePyIncludeUtil.getCommonPythonIncludePath()), + CombinationsFileUtil.class.getClassLoader()); - Object com = python.execute("getCombinations", map); - combos = (List>) com; + Object com = python.execute("getCombinations", map); + combos = (List>) com; // if successfully retrieved break out of the loop break; - } catch (JepException e) { + } catch (JepException e) { // remove the .pyo file new File(pyFile.getAbsolutePath() + "o").delete(); // if not last try, log and try again - if (retryCount < MAX_TRIES - 1) { + if (retryCount < (MAX_TRIES - 1)) { // log but don't pop up statusHandler.handle(Priority.EVENTB, "Error loading combinations file: " + comboName @@ -275,15 +278,15 @@ public class CombinationsFileUtil { } // else throw exception else { - throw new GfeException("Error loading combinations file: " - + comboName, e); + throw new GfeException("Error loading combinations file: " + + comboName, e); + } + } finally { + if (python != null) { + python.dispose(); } - } finally { - if (python != null) { - python.dispose(); } } - } return combos; } diff --git a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java index d7df5c8ca7..c4bcac4377 100644 --- a/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java +++ b/edexOsgi/com.raytheon.edex.plugin.gfe/src/com/raytheon/edex/plugin/gfe/reference/ReferenceMgr.java @@ -49,6 +49,7 @@ import com.raytheon.uf.common.util.FileUtil; * Jul 24, 2012 dgilling Initial creation * Aug 07, 2013 1561 njensen Use pm.listFiles() instead of pm.listStaticFiles() * Sep 30, 2013 2361 njensen Use JAXBManager for XML + * Sep 08, 2104 3592 randerso Changed to use new pm listStaticFiles() * * * @@ -81,9 +82,9 @@ public class ReferenceMgr { public ServerResponse> getInventory() { List refIDs = new ArrayList(); IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationFile[] contents = pm.listFiles( - pm.getLocalSearchHierarchy(LocalizationType.COMMON_STATIC), - EDIT_AREAS_DIR, new String[] { ".xml" }, false, true); + LocalizationFile[] contents = pm.listStaticFiles( + LocalizationType.COMMON_STATIC, EDIT_AREAS_DIR, + new String[] { ".xml" }, false, true); if (contents != null) { for (LocalizationFile lf : contents) { String s = LocalizationUtil.extractName(lf.getName()); @@ -116,7 +117,8 @@ public class ReferenceMgr { // process each ReferenceID requested for (ReferenceID id : ids) { String path = FileUtil.join(EDIT_AREAS_DIR, id.getName() + ".xml"); - LocalizationFile lf = pathMgr.getStaticLocalizationFile(path); + LocalizationFile lf = pathMgr.getStaticLocalizationFile( + LocalizationType.COMMON_STATIC, path); // does it exist? if (lf == null) { @@ -129,8 +131,8 @@ public class ReferenceMgr { // open and read the file ReferenceData refData = null; try { - refData = ReferenceData.getJAXBManager() - .unmarshalFromXmlFile(lf.getFile().getPath()); + refData = ReferenceData.getJAXBManager().unmarshalFromXmlFile( + lf.getFile().getPath()); } catch (Exception e) { sr.addMessage("Unable to read reference data [" + id + "]"); data = Collections.emptyList(); diff --git a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/IPathManager.java b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/IPathManager.java index 1c0516e85f..eb8c8db060 100644 --- a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/IPathManager.java +++ b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/IPathManager.java @@ -41,6 +41,10 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; * Date Ticket# Engineer Description * ------------ ---------- ----------- -------------------------- * 02/12/2008 chammack Initial Creation. + * Sep 08, 2014 3592 randerso Added single type listStaticFiles, + * getStaticLocalizationFile, and getStaticFile APIs + * Improved JavaDoc for all listStaticFiles, + * getStaticLocalizationFile, and getStaticFile APIs. * * * @@ -49,13 +53,16 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; */ public interface IPathManager { + /** + * Directory separator used by Localization + */ public static final String SEPARATOR = "/"; /** * - * Checks the localization hierarchy for a static file - * - * First searches user, then site and finally base to find the file. + * Finds the specified file in any applicable LocalizationType. Note: If the + * same file exists in multiple localization levels, only the lowest level + * version of the file will be returned. * * Returns null if file is not found. * @@ -63,13 +70,30 @@ public interface IPathManager { * the name of the file to search for * @return a pointer to the location on the filesystem */ - public abstract File getStaticFile(String name); + public File getStaticFile(String name); /** * - * Checks the localization hierarchy for a static file + * Finds the specified file in the specified LocalizationType. Note: If the + * same file exists in multiple localization levels, only the lowest level + * version of the file will be returned. * - * First searches user, then site and finally base to find the file. + * Returns null if file is not found. + * + * @param type + * LocalizationType of file to be found + * + * @param name + * the name of the file to search for + * @return a pointer to the location on the filesystem + */ + public File getStaticFile(LocalizationType type, String name); + + /** + * + * Finds the specified file in any applicable LocalizationType. Note: If the + * same file exists in multiple localization levels, only the lowest level + * version of the file will be returned. * * Returns null if file is not found. * @@ -77,7 +101,25 @@ public interface IPathManager { * the name of the file to search for * @return the file and the context it was found in */ - public abstract LocalizationFile getStaticLocalizationFile(String name); + public LocalizationFile getStaticLocalizationFile(String name); + + /** + * + * Finds the specified file in the specified LocalizationType. Note: If the + * same file exists in multiple localization levels, only the lowest level + * version of the file will be returned. + * + * Returns null if file is not found. + * + * @param type + * LocalizationType of file to be found + * + * @param name + * the name of the file to search for + * @return the file and the context it was found in + */ + public LocalizationFile getStaticLocalizationFile(LocalizationType type, + String name); /** * @@ -89,7 +131,7 @@ public interface IPathManager { * the filename to search * @return an absolute pointer on the filesystem to the file */ - public abstract File getFile(LocalizationContext context, String name); + public File getFile(LocalizationContext context, String name); /** * @@ -101,8 +143,8 @@ public interface IPathManager { * the filename to search * @return an absolute pointer on the filesystem to the file */ - public abstract LocalizationFile getLocalizationFile( - LocalizationContext context, String name); + public LocalizationFile getLocalizationFile(LocalizationContext context, + String name); /** * Returns a map containing a LocalizationFile for each LocalizationLevel @@ -114,11 +156,13 @@ public interface IPathManager { * the localization file name * @return map of LocalizationLevel to LocalizationFile */ - public abstract Map getTieredLocalizationFile( + public Map getTieredLocalizationFile( LocalizationType type, String name); /** - * Lists files in the directory + * Lists all files in the localization hierarchy for the specified directory + * Note: If the same file exists in multiple localization levels, all + * versions of the file will be returned in the array. * * @param context * the localization context to use @@ -134,12 +178,14 @@ public interface IPathManager { * directories * @return the files on the filesystem in the directory */ - public abstract LocalizationFile[] listFiles(LocalizationContext context, + public LocalizationFile[] listFiles(LocalizationContext context, String name, String[] extensions, boolean recursive, boolean filesOnly); /** - * Lists files in the directory + * Lists all files in the localization hierarchy for the specified directory + * Note: If the same file exists in multiple localization levels, all + * versions of the file will be returned in the array. * * @param contexts * the localization contexts to search @@ -156,9 +202,9 @@ public interface IPathManager { * @return the files on the filesystem in the directory or null in case of * error */ - public abstract LocalizationFile[] listFiles( - LocalizationContext[] contexts, String name, String[] extensions, - boolean recursive, boolean filesOnly); + public LocalizationFile[] listFiles(LocalizationContext[] contexts, + String name, String[] extensions, boolean recursive, + boolean filesOnly); /** * Lists all files in all localization contexts in a particular directory. @@ -177,8 +223,32 @@ public interface IPathManager { * directories * @return a list of files */ - public abstract LocalizationFile[] listStaticFiles(String name, - String[] extensions, boolean recursive, boolean filesOnly); + public LocalizationFile[] listStaticFiles(String name, String[] extensions, + boolean recursive, boolean filesOnly); + + /** + * Lists all files in the specified LocalizationType in a particular + * directory. Note: If the same file exists in multiple localization levels, + * only the lowest level version of the file will be returned in the array. + * + * @param type + * the localization type to use + * + * @param name + * the directory to look in + * @param extensions + * a list of file extensions to look for, or null if no filter + * @param recursive + * true for recursive directory listing, false for a single level + * listing + * @param filesOnly + * true if only files are listed, false to list both files and + * directories + * @return a list of files + */ + public LocalizationFile[] listStaticFiles(LocalizationType type, + String name, String[] extensions, boolean recursive, + boolean filesOnly); /** * Returns a localization context for the given type and level for the @@ -188,7 +258,7 @@ public interface IPathManager { * @param level * @return the localization context */ - public abstract LocalizationContext getContext(LocalizationType type, + public LocalizationContext getContext(LocalizationType type, LocalizationLevel level); /** @@ -198,8 +268,8 @@ public interface IPathManager { * @param siteId * @return the site localization context */ - public abstract LocalizationContext getContextForSite( - LocalizationType type, String siteId); + public LocalizationContext getContextForSite(LocalizationType type, + String siteId); /** * Return the localization contexts that should be searched given a @@ -209,16 +279,16 @@ public interface IPathManager { * the type * @return the localization contexts */ - public abstract LocalizationContext[] getLocalSearchHierarchy( + public LocalizationContext[] getLocalSearchHierarchy( LocalizationContext.LocalizationType type); /** * Get the available context strings for the given level * * @param level - * @return + * @return the available contexts */ - public abstract String[] getContextList(LocalizationLevel level); + public String[] getContextList(LocalizationLevel level); /** * Returns the available levels to be used, sorted from lowest search level @@ -226,5 +296,5 @@ public interface IPathManager { * * @return Available sorted levels */ - public abstract LocalizationLevel[] getAvailableLevels(); + public LocalizationLevel[] getAvailableLevels(); } \ No newline at end of file diff --git a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/PathManager.java b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/PathManager.java index 57c09fefa1..2399e47bf0 100644 --- a/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/PathManager.java +++ b/edexOsgi/com.raytheon.uf.common.localization/src/com/raytheon/uf/common/localization/PathManager.java @@ -55,6 +55,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; * ------------ ---------- ----------- -------------------------- * 02/12/2008 chammack Initial Creation. * Oct 23, 2012 1322 djohnson Allow test code in the same package to clear fileCache. + * Sep 08, 2014 3592 randerso Added single type listStaticFiles, + * getStaticLocalizationFile, and getStaticFile APIs * * * @@ -63,8 +65,8 @@ import com.raytheon.uf.common.status.UFStatus.Priority; */ public class PathManager implements IPathManager { - private static final IUFStatusHandler statusHandler = UFStatus - .getHandler(PathManager.class, "Localization"); + private static final IUFStatusHandler statusHandler = UFStatus.getHandler( + PathManager.class, "Localization"); // @VisibleForTesting static final Map fileCache = new ConcurrentHashMap(); @@ -93,6 +95,33 @@ public class PathManager implements IPathManager { return file; } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.localization.IPathManager#getStaticFile(com.raytheon + * .uf.common.localization.LocalizationContext.LocalizationType, + * java.lang.String) + */ + @Override + public File getStaticFile(LocalizationType type, String name) { + LocalizationFile locFile = getStaticLocalizationFile(type, name); + File file = null; + if (locFile != null) { + file = locFile.getFile(); + } + + return file; + } + + @Override + public LocalizationFile getStaticLocalizationFile(LocalizationType type, + String name) { + Validate.notNull(name, "Path name must not be null"); + return this.getStaticLocalizationFile(new LocalizationType[] { type }, + name); + } + /* * (non-Javadoc) * @@ -103,11 +132,16 @@ public class PathManager implements IPathManager { @Override public LocalizationFile getStaticLocalizationFile(String name) { Validate.notNull(name, "Path name must not be null"); + LocalizationType[] types = this.adapter.getStaticContexts(); + return this.getStaticLocalizationFile(types, name); + } + private LocalizationFile getStaticLocalizationFile( + LocalizationType[] types, String name) { + Validate.notNull(name, "Path name must not be null"); name = name.replace(File.separator, IPathManager.SEPARATOR); // Iterate through the types - LocalizationType[] types = this.adapter.getStaticContexts(); List contexts = new ArrayList(); for (LocalizationType type : types) { // Iterate through the hierarchy @@ -122,7 +156,7 @@ public class PathManager implements IPathManager { name); for (LocalizationFile file : files) { - if (file != null && file.exists()) { + if ((file != null) && file.exists()) { // First file found in hierarchy is used return file; } @@ -156,7 +190,7 @@ public class PathManager implements IPathManager { LocalizationFile[] files = getLocalizationFile(contexts, name); for (LocalizationFile lf : files) { - if (lf != null && lf.exists()) { + if ((lf != null) && lf.exists()) { map.put(lf.getContext().getLocalizationLevel(), lf); } } @@ -259,7 +293,7 @@ public class PathManager implements IPathManager { LocalizationFileKey key = new LocalizationFileKey(response.fileName, response.context); LocalizationFile lf = fileCache.get(key); - if (lf != null && lf.isNull() == false) { + if ((lf != null) && (lf.isNull() == false)) { // Ensure latest data for file, will only be null if no File can be // returned for path/context. lf.update(response); @@ -361,6 +395,21 @@ public class PathManager implements IPathManager { return false; } + /* + * (non-Javadoc) + * + * @see + * com.raytheon.uf.common.localization.IPathManager#listFiles(java.lang. + * String , java.lang.String[]) + */ + @Override + public LocalizationFile[] listStaticFiles(LocalizationType type, + String name, String[] filter, boolean recursive, boolean filesOnly) { + + return this.listStaticFiles(new LocalizationType[] { type }, name, + filter, recursive, filesOnly); + } + /* * (non-Javadoc) * @@ -375,6 +424,13 @@ public class PathManager implements IPathManager { // Iterate through the types LocalizationType[] types = this.adapter.getStaticContexts(); + return this.listStaticFiles(types, name, filter, recursive, filesOnly); + } + + private LocalizationFile[] listStaticFiles(LocalizationType[] types, + String name, String[] filter, boolean recursive, boolean filesOnly) { + Validate.notNull(name, "Path name must not be null"); + List contexts = new ArrayList(); for (LocalizationType type : types) { // Iterate through the hierarchy @@ -512,7 +568,7 @@ public class PathManager implements IPathManager { ListResponseEntry lre = entry.getValue(); SerializableKey key = entry.getKey(); LocalizationFile file = new LocalizationFile(); - if (lre.getContext() != null && lre.getFileName() != null) { + if ((lre.getContext() != null) && (lre.getFileName() != null)) { file = new LocalizationFile(pm.adapter, lre.getContext(), pm.adapter.getPath(lre.getContext(), lre.getFileName()), lre.getDate(), From dca7627c1e13c158ce183c8e4750d1564460253c Mon Sep 17 00:00:00 2001 From: Ben Steffensmeier Date: Wed, 10 Sep 2014 14:42:41 -0500 Subject: [PATCH 3/6] Issue #3604 Fix NPE in Imaging Dialog. Former-commit-id: 15f35e6dcce31ca1aa3128173121f2f45eb1931d [formerly e2043fd8034dde47963a32108b1475ee7db1ea18] Former-commit-id: ed7b8169894c27306f3d872d29c58ecbe8cf15bb --- .../radar/rsc/mosaic/RadarMosaicResource.java | 35 +++++++++++++++---- .../viz/ui/dialogs/ImagingDialog.java | 17 +++++---- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java index fe90908e1f..7b113fbda6 100644 --- a/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java +++ b/cave/com.raytheon.viz.radar/src/com/raytheon/viz/radar/rsc/mosaic/RadarMosaicResource.java @@ -59,6 +59,7 @@ import com.raytheon.uf.viz.core.rsc.IRefreshListener; import com.raytheon.uf.viz.core.rsc.IResourceDataChanged; import com.raytheon.uf.viz.core.rsc.LoadProperties; import com.raytheon.uf.viz.core.rsc.ResourceList; +import com.raytheon.uf.viz.core.rsc.capabilities.AbstractCapability; import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability; import com.raytheon.uf.viz.core.rsc.capabilities.ColorableCapability; import com.raytheon.viz.core.rsc.BestResResource; @@ -82,6 +83,9 @@ import com.vividsolutions.jts.geom.Coordinate; * Jun 12, 2009 1937 askripsk Initial creation * May 21, 2009 6309 garmendariz Modified path for Geotools 2.6.4 * May 01, 2014 3100 bsteffen perform time matching on data update. + * Sep 10, 2014 3604 bsteffen Ensure capability changes propogate to + * all resources/listeners. + * * * * @@ -123,7 +127,7 @@ public class RadarMosaicResource extends }; protected RadarMosaicResource(RadarMosaicResourceData rrd, - LoadProperties loadProps) throws VizException { + LoadProperties loadProps) { super(rrd, loadProps); timeUpdateJob.setSystem(true); rrd.addChangeListener(this); @@ -230,12 +234,7 @@ public class RadarMosaicResource extends return maxSeverity; } - /* - * (non-Javadoc) - * - * @seecom.raytheon.viz.core.rsc.IVizResource#paint(com.raytheon.viz.core. - * IGraphicsTarget, com.raytheon.viz.core.PixelExtent, double, float) - */ + @Override protected void paintInternal(IGraphicsTarget target, PaintProperties paintProps) throws VizException { DataTime[] frameTimes = paintProps.getFramesInfo().getTimeMap() @@ -624,6 +623,17 @@ public class RadarMosaicResource extends } dataTimes.remove(time); break; + case CAPABILITY: + AbstractCapability cap = (AbstractCapability) object; + /* + * Since mosaic shares capabilities, need to make sure resourceData + * is always set to the mosaic resource data so that all resources + * are notified. + */ + if (cap.getResourceData() != resourceData) { + cap.setResourceData(resourceData); + resourceData.fireChangeListeners(type, object); + } } synchronized (this) { force = true; @@ -631,6 +641,16 @@ public class RadarMosaicResource extends issueRefresh(); } + @Override + protected void resourceDataChanged(ChangeType type, Object updateObject) { + if (ChangeType.CAPABILITY == type) { + for (ResourcePair rp : getResourceList()) { + rp.getResourceData().fireChangeListeners(type, updateObject); + + } + } + } + @Override public String getName() { if (groupName == null) { @@ -651,6 +671,7 @@ public class RadarMosaicResource extends return groupName; } + @Override public String[] getUpperText(DataTime time) { if (!getResourceData().getMergeUpperText()) { return null; diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java index 9268d210d4..4c53727a84 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ImagingDialog.java @@ -91,6 +91,7 @@ import com.raytheon.viz.ui.editor.IMultiPaneEditor; * ColorMapCapability is not present. * Apr 08, 2014 2905 bsteffen Add option to interpolate colors. * Apr 16, 2014 3037 lvenable Add dispose check in runAsync call. + * Sep 10, 2014 3604 bsteffen Check for colormap before setting interpolation state. * * * @@ -771,26 +772,28 @@ public class ImagingDialog extends CaveSWTDialog implements if (topResource.hasCapability(ColorMapCapability.class)) { final ColorMapCapability cmcap = topResource .getCapability(ColorMapCapability.class); + ColorMapParameters cmparms = cmcap.getColorMapParameters(); String currentCMap = "Not Selected"; - if (cmcap.getColorMapParameters() != null - && cmcap.getColorMapParameters().getColorMap() != null) { - currentCMap = cmcap.getColorMapParameters().getColorMap() - .getName(); + if (cmparms != null && cmparms.getColorMap() != null) { + currentCMap = cmparms.getColorMap().getName(); if (currentCMap == null) { currentCMap = ""; } } topColormapComp.setCap(cmcap); - topColormapComp.setParams(cmcap.getColorMapParameters()); + topColormapComp.setParams(cmparms); if (currentCMap.isEmpty()) { currentCMap = UNSAVED_CMAP_DISPLAY_NAME; } topColormapComp.getCMapButton().setText(currentCMap); topColorMapButton.setText("Edit " + topResourceName); + interpolateColorsCheckbox.setEnabled(true); - interpolateColorsCheckbox.setSelection(cmcap - .getColorMapParameters().isInterpolate()); + if (cmparms != null) { + interpolateColorsCheckbox.setSelection(cmparms + .isInterpolate()); + } } else { topColorMapButton.setText(topResourceName + " is not color mapped."); From 775dd2520d5e0533829fa4728a4b6277ded4bf2b Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Wed, 3 Sep 2014 09:17:34 -0500 Subject: [PATCH 4/6] Issue #3516 - Get Color Maps for levels off the dispatch thread. Change-Id: Icc89f4860eef0b0b404e1e5b66bb0178eedd73dc Former-commit-id: c885873b25c51606eed351c0de3066b12df35683 [formerly a67a429eb2d266e66a99b6c18916193cd0d20d9d] Former-commit-id: 246bc4770f4ce023e8728f92dc96b86c26bb2acc --- .../core/drawables/ColorMapTreeFactory.java | 95 ----- .../gfe/actions/ChangeColorTableAction.java | 3 + cave/com.raytheon.viz.ui/META-INF/MANIFEST.MF | 1 + .../viz/ui/colormap}/ColorMapTree.java | 35 +- .../viz/ui/colormap/ColorMapTreeFactory.java | 327 ++++++++++++++++++ .../viz/ui/colormap/ILevelMapsCallback.java | 52 +++ .../IRefreshColorMapTreeListener.java | 46 +++ .../raytheon/viz/ui/dialogs/ColormapComp.java | 191 +++++++--- 8 files changed, 598 insertions(+), 152 deletions(-) delete mode 100644 cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTreeFactory.java rename cave/{com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables => com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap}/ColorMapTree.java (88%) create mode 100644 cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTreeFactory.java create mode 100644 cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ILevelMapsCallback.java create mode 100644 cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/IRefreshColorMapTreeListener.java diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTreeFactory.java b/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTreeFactory.java deleted file mode 100644 index bfca3db606..0000000000 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTreeFactory.java +++ /dev/null @@ -1,95 +0,0 @@ -/** - * This software was developed and / or modified by Raytheon Company, - * pursuant to Contract DG133W-05-CQ-1067 with the US Government. - * - * U.S. EXPORT CONTROLLED TECHNICAL DATA - * This software product contains export-restricted data whose - * export/transfer/disclosure is restricted by U.S. law. Dissemination - * to non-U.S. persons whether in the United States or abroad requires - * an export license or other authorization. - * - * Contractor Name: Raytheon Company - * Contractor Address: 6825 Pine Street, Suite 340 - * Mail Stop B8 - * Omaha, NE 68106 - * 402.291.0100 - * - * See the AWIPS II Master Rights File ("Master Rights File.pdf") for - * further licensing information. - **/ -package com.raytheon.uf.viz.core.drawables; - -import java.util.HashMap; -import java.util.Map; - -import com.raytheon.uf.common.localization.IPathManager; -import com.raytheon.uf.common.localization.LocalizationContext; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; -import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; -import com.raytheon.uf.common.localization.PathManagerFactory; - -/** - * Factory which can provide cached versions of {@link ColorMapTree} objects. - * - *
- * 
- * SOFTWARE HISTORY
- * 
- * Date          Ticket#  Engineer    Description
- * ------------- -------- ----------- --------------------------
- * Sep 18, 2013  2421     bsteffen    Initial creation
- * 
- * 
- * - * @author bsteffen - * @version 1.0 - */ - -public class ColorMapTreeFactory { - - private static ColorMapTree baseTree; - - private static Object baseTreeLock = new Object(); - - private static final Map treesByLevel = new HashMap(); - - private static Object treesByLevelLock = new Object(); - - /** - * Get a tree for the BASE localization context. This tree will be different - * from the tree returned by getTreeForLevel(LocalizationLevel.BASE) because - * it will not be for the BASE level but instead is for the BASE context. - * - */ - public static ColorMapTree getBaseTree() { - synchronized (baseTreeLock) { - if(baseTree == null){ - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationContext baseContext = pm.getContext( - LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); - baseTree = new ColorMapTree(pm, baseContext, - ColorMapLoader.DIR_NAME); - } - return baseTree; - } - - } - - /** - * Return a {@link ColorMapTree}Tree for the provided level. The tree will - * have the same name as the level and will have a subtree for each context - * that exists at that level. - */ - public static ColorMapTree getTreeForLevel(LocalizationLevel level) { - synchronized (treesByLevelLock) { - ColorMapTree tree = treesByLevel.get(level); - if (tree == null) { - IPathManager pm = PathManagerFactory.getPathManager(); - tree = new ColorMapTree(pm, level, ColorMapLoader.DIR_NAME); - treesByLevel.put(level, tree); - } - return tree; - } - } - -} \ No newline at end of file diff --git a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ChangeColorTableAction.java b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ChangeColorTableAction.java index 7d9c2bcc24..136c96fa18 100644 --- a/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ChangeColorTableAction.java +++ b/cave/com.raytheon.viz.gfe/src/com/raytheon/viz/gfe/actions/ChangeColorTableAction.java @@ -24,6 +24,7 @@ import org.eclipse.jface.action.IMenuCreator; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Menu; +import org.eclipse.swt.widgets.MenuItem; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; import com.raytheon.uf.common.dataplugin.gfe.db.objects.GFERecord.GridType; @@ -43,6 +44,7 @@ import com.raytheon.viz.ui.dialogs.ColormapComp; * ------------ ---------- ----------- -------------------------- * Apr 8, 2009 njensen Initial creation * Aug 11, 2010 wldougher + * Aug 28, 2014 3516 rferrel Add separator after color map component. * * * @@ -120,6 +122,7 @@ public class ChangeColorTableAction extends AbstractRightClickAction implements // Build a ColormapComp to get the menu from ColormapComp comp = new ColormapComp(parent, parms, cap); menu = comp.getMenu(); + new MenuItem(menu, SWT.SEPARATOR); } ActionContributionItem aci = new ActionContributionItem( diff --git a/cave/com.raytheon.viz.ui/META-INF/MANIFEST.MF b/cave/com.raytheon.viz.ui/META-INF/MANIFEST.MF index 3a8d021d9a..6a387dc6fd 100644 --- a/cave/com.raytheon.viz.ui/META-INF/MANIFEST.MF +++ b/cave/com.raytheon.viz.ui/META-INF/MANIFEST.MF @@ -24,6 +24,7 @@ Export-Package: com.raytheon.viz.ui, com.raytheon.viz.ui.actions, com.raytheon.viz.ui.cmenu, com.raytheon.viz.ui.color, + com.raytheon.viz.ui.colormap, com.raytheon.viz.ui.dialogs, com.raytheon.viz.ui.dialogs.colordialog, com.raytheon.viz.ui.editor, diff --git a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTree.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java similarity index 88% rename from cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTree.java rename to cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java index bfb2895859..f703343a51 100644 --- a/cave/com.raytheon.uf.viz.core/src/com/raytheon/uf/viz/core/drawables/ColorMapTree.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java @@ -17,7 +17,7 @@ * See the AWIPS II Master Rights File ("Master Rights File.pdf") for * further licensing information. **/ -package com.raytheon.uf.viz.core.drawables; +package com.raytheon.viz.ui.colormap; import java.lang.ref.Reference; import java.lang.ref.WeakReference; @@ -33,6 +33,7 @@ import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.LocalizationNotificationObserver; +import com.raytheon.uf.viz.core.drawables.ColorMapLoader; /** * ColorMapTree represents the directory structure of colormaps directory. The @@ -46,6 +47,8 @@ import com.raytheon.uf.common.localization.LocalizationNotificationObserver; * Date Ticket# Engineer Description * ------------- -------- ----------- -------------------------- * Sep 18, 2013 2421 bsteffen Initial creation + * Sep 11, 2014 3516 rferrel file updates now inform the factory. + * getName() no longer returns a null. * * * @@ -110,7 +113,11 @@ public class ColorMapTree { } else { int start = path.lastIndexOf(IPathManager.SEPARATOR); if (start <= 0) { - return context.getContextName(); + String name = context.getContextName(); + if (name == null) { + name = context.getLocalizationLevel().name(); + } + return name; } return path.substring(start + 1); } @@ -181,15 +188,22 @@ public class ColorMapTree { } /** - * Optimize the internal structure so future {@link #isEmpty()} calls are - * fast. isEmpty() is a slow operations on trees with many empty subtrees, - * so this can be called in the background to enable faster calls to isEmpty - * when it is needed. In cases where isEmpty does not need extra data or is - * already optimized this call should complete very quickly. + * Recursively optimize the internal structure so future {@link #isEmpty()} + * calls are fast. isEmpty() is a slow operations on trees with many empty + * subtrees, so this can be called in the background to enable faster calls + * to isEmpty when it is needed. In cases where isEmpty does not need extra + * data or is already optimized this call should complete very quickly. + * Intended for use on non-UI thread. */ public void optimizeIsEmpty() { - /* isEmpty caches data in the subtrees so nothing else is needed. */ isEmpty(); + + /* + * isEmpty() may not check all sub trees. Force check of all sub trees. + */ + for (ColorMapTree subTree : getSubTrees()) { + subTree.optimizeIsEmpty(); + } } /** @@ -258,10 +272,9 @@ public class ColorMapTree { .removeGlobalFileChangeObserver(this); } else { tree.handleUpdate(message); + tree.optimizeIsEmpty(); + ColorMapTreeFactory.getInstance().refresh(); } - } - } - } diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTreeFactory.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTreeFactory.java new file mode 100644 index 0000000000..6e69f88034 --- /dev/null +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTreeFactory.java @@ -0,0 +1,327 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.ui.colormap; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; +import org.eclipse.core.runtime.jobs.Job; + +import com.raytheon.uf.common.localization.IPathManager; +import com.raytheon.uf.common.localization.LocalizationContext; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType; +import com.raytheon.uf.common.localization.PathManagerFactory; +import com.raytheon.uf.viz.core.VizApp; +import com.raytheon.uf.viz.core.drawables.ColorMapLoader; + +/** + * Factory which can provide cached versions of {@link ColorMapTree} objects. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date          Ticket#  Engineer    Description
+ * ------------- -------- ----------- --------------------------
+ * Sep 18, 2013  2421     bsteffen    Initial creation
+ * Aug 28, 2014  3516     rferrel     Getting treesByLevel no longer
+ *                                     on the UI thread.
+ *                                    Converted to singleton.
+ *                                    Added localized file observer.
+ * 
+ * 
+ * + * @author bsteffen + * @version 1.0 + */ + +public class ColorMapTreeFactory { + + /** + * The only allowed instance of this class. + */ + private final static ColorMapTreeFactory instance = new ColorMapTreeFactory(); + + /** + * + * @return instance + */ + public static ColorMapTreeFactory getInstance() { + return instance; + } + + /** + * BASE localization tree must be handled differently from the other + * localization levels. Its items are placed directly on the top menu while + * the other levels are in their own pop up menu. + */ + private ColorMapTree baseTree; + + /** + * Lock when working on baseTree. + */ + private Object baseTreeLock = new Object(); + + /** + * Trees for non-BASE localization levels. + */ + private final Map treesByLevel = new HashMap(); + + /** + * Listeners needing treesByLevel information + */ + private List tlcListeners = new ArrayList(); + + /** + * Non-BASE localization levels. + */ + private final LocalizationLevel[] treesLevelLocalization; + + /** + * Thread safe list of listeners to notify when localized colormaps + * directories have a file change. Since the list is modified more often + * then it is traversed CopyOnWriterArrayList is not recommended. + * + */ + private final List refreshListeners = Collections + .synchronizedList(new ArrayList()); + + /** + * Singleton constructor. + */ + private ColorMapTreeFactory() { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationLevel[] allLevels = pm.getAvailableLevels(); + // Remove BASE + treesLevelLocalization = Arrays.copyOfRange(allLevels, 1, + allLevels.length); + + // Start creating trees off the UI-thread + Job job = new Job("Find ColorMapTree base") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + ColorMapTree base = getBaseTree(); + base.optimizeIsEmpty(); + return Status.OK_STATUS; + } + + }; + job.setSystem(true); + job.schedule(); + initTreeByLevel(); + } + + /** + * Get a tree for the BASE localization context. This tree is treated + * differently from the other localization context trees. The tree items are + * placed directly on the top menu while the other level trees are put in + * their own pop up menu. + */ + public ColorMapTree getBaseTree() { + synchronized (baseTreeLock) { + if (baseTree == null) { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationContext baseContext = pm.getContext( + LocalizationType.COMMON_STATIC, LocalizationLevel.BASE); + + /* + * Useful for testing delay in getting base tree. + */ + // try { + // baseTreeLock.wait(8000L); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } + + baseTree = new ColorMapTree(pm, baseContext, + ColorMapLoader.DIR_NAME); + } + return baseTree; + } + } + + /** + * This immediately performs the call back for each non-BASE localization + * level sending a null tree when a level's tree has not yet been created. + * This allows the call back to generate a place holder for the level. When + * needed the call back routine will be called as any missing trees are + * generated. + * + * @param listener + */ + public void updateLevelMapsCallack(ILevelMapsCallback listener) { + synchronized (treesByLevel) { + + /* + * Immediately perform the action for all levels. When treeByLevel + * entry is null the tree for the level has not yet been created; + * invoke the listener with a null tree. This allows a listener + * creating menu items to generate a place holder entry such as + * "USER ???". + */ + for (LocalizationLevel level : getTreesLevelLocalization()) { + ColorMapTree tree = treesByLevel.get(level); + listener.treeCreated(level, tree); + } + + /* + * Still missing trees. Must call the callback again as each missing + * tree is created. + */ + if (isMissingLevelTrees()) { + tlcListeners.add(listener); + } + } + } + + /** + * + * @return true if still generating trees + */ + private boolean isMissingLevelTrees() { + return tlcListeners != null; + } + + /** + * Return a {@link ColorMapTree}Tree for the provided level. The tree will + * have the same name as the level and will have a subtree for each context + * that exists at that level. + */ + public ColorMapTree getTreeForLevel(LocalizationLevel level) { + synchronized (treesByLevel) { + ColorMapTree tree = treesByLevel.get(level); + if (tree == null) { + IPathManager pm = PathManagerFactory.getPathManager(); + tree = new ColorMapTree(pm, level, ColorMapLoader.DIR_NAME); + treesByLevel.put(level, tree); + } + return tree; + } + } + + /** + * + * @return treesLevelLocalization + */ + public LocalizationLevel[] getTreesLevelLocalization() { + return treesLevelLocalization; + } + + /** + * This creates the trees for treesByLevel off of the UI thread. It informs + * all listeners when a tree is created. + */ + private void initTreeByLevel() { + synchronized (treesByLevel) { + treesByLevel.clear(); + + Job job = new Job("Finding Colormaps") { + + @Override + protected IStatus run(IProgressMonitor monitor) { + IPathManager pm = PathManagerFactory.getPathManager(); + LocalizationLevel[] levels = getTreesLevelLocalization(); + for (final LocalizationLevel level : levels) { + ColorMapTree tree = new ColorMapTree(pm, level, + ColorMapLoader.DIR_NAME); + tree.optimizeIsEmpty(); + + synchronized (treesByLevel) { + /* + * Use for debugging. Simulates a long delay in + * getting tree level's color map. Allows testing to + * see if menu items for the tree levels are + * properly handled. + */ + // try { + // treesByLevel.wait(3000L); + // } catch (InterruptedException e) { + // e.printStackTrace(); + // } + + treesByLevel.put(level, tree); + for (ILevelMapsCallback listener : tlcListeners) { + listener.treeCreated(level, tree); + } + } + } + + synchronized (treesByLevel) { + /* + * Free up tlcListeners space and indicate all level + * trees are now generated. + */ + tlcListeners.clear(); + tlcListeners = null; + } + return Status.OK_STATUS; + } + }; + job.schedule(); + } + } + + /** + * Method used to inform listeners of any changes to any ColorMapTree. + * + * @param level + */ + public void refresh() { + + VizApp.runAsync(new Runnable() { + + @Override + public void run() { + IRefreshColorMapTreeListener[] rListeners = refreshListeners + .toArray(new IRefreshColorMapTreeListener[0]); + for (IRefreshColorMapTreeListener listener : rListeners) { + listener.refreshColorMapTree(); + } + } + }); + } + + /** + * Thread safe removal of listener. + * + * @param listener + */ + public void removeRefreshItemsListener(IRefreshColorMapTreeListener listener) { + refreshListeners.remove(listener); + } + + /** + * Thread safe adding listener. + * + * @param listener + */ + public void addRefreshItemsListener(IRefreshColorMapTreeListener listener) { + refreshListeners.add(listener); + } +} diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ILevelMapsCallback.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ILevelMapsCallback.java new file mode 100644 index 0000000000..ea85e7f1f2 --- /dev/null +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ILevelMapsCallback.java @@ -0,0 +1,52 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.ui.colormap; + +import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; + +/** + * Use by {@link ColorMapTreeFactory} to perform an action for each non-Base + * localization level. May be invoked from a non-UI thread. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Aug 28, 2014 3516       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public interface ILevelMapsCallback { + /** + * Method invoked for each non-BASE localization level. When tree is null it + * is being generated and this method will be called again once the tree is + * created. + * + * @param level + * @param tree + */ + public void treeCreated(LocalizationLevel level, ColorMapTree tree); +} diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/IRefreshColorMapTreeListener.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/IRefreshColorMapTreeListener.java new file mode 100644 index 0000000000..d0d5bc1224 --- /dev/null +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/IRefreshColorMapTreeListener.java @@ -0,0 +1,46 @@ +/** + * This software was developed and / or modified by Raytheon Company, + * pursuant to Contract DG133W-05-CQ-1067 with the US Government. + * + * U.S. EXPORT CONTROLLED TECHNICAL DATA + * This software product contains export-restricted data whose + * export/transfer/disclosure is restricted by U.S. law. Dissemination + * to non-U.S. persons whether in the United States or abroad requires + * an export license or other authorization. + * + * Contractor Name: Raytheon Company + * Contractor Address: 6825 Pine Street, Suite 340 + * Mail Stop B8 + * Omaha, NE 68106 + * 402.291.0100 + * + * See the AWIPS II Master Rights File ("Master Rights File.pdf") for + * further licensing information. + **/ +package com.raytheon.viz.ui.colormap; + +/** + * Used by ColorMapTreeFactory to notify listeners when there changes to a + * colormaps localization files. + * + *
+ * 
+ * SOFTWARE HISTORY
+ * 
+ * Date         Ticket#    Engineer    Description
+ * ------------ ---------- ----------- --------------------------
+ * Sep 3, 2014  3516       rferrel     Initial creation
+ * 
+ * 
+ * + * @author rferrel + * @version 1.0 + */ + +public interface IRefreshColorMapTreeListener { + /** + * Method called on the UI thread to inform listener of changes in non-BASE + * levels files in the colormaps directory. + */ + public void refreshColorMapTree(); +} diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ColormapComp.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ColormapComp.java index 134c4514fc..6e71c5878d 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ColormapComp.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/dialogs/ColormapComp.java @@ -26,11 +26,9 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.eclipse.core.runtime.IProgressMonitor; -import org.eclipse.core.runtime.IStatus; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.jobs.Job; import org.eclipse.swt.SWT; +import org.eclipse.swt.events.DisposeEvent; +import org.eclipse.swt.events.DisposeListener; import org.eclipse.swt.events.MenuEvent; import org.eclipse.swt.events.MenuListener; import org.eclipse.swt.events.SelectionAdapter; @@ -44,19 +42,20 @@ import org.eclipse.swt.widgets.MenuItem; import org.eclipse.swt.widgets.Shell; import com.raytheon.uf.common.colormap.prefs.ColorMapParameters; -import com.raytheon.uf.common.localization.IPathManager; import com.raytheon.uf.common.localization.LocalizationContext.LocalizationLevel; import com.raytheon.uf.common.localization.LocalizationFile; import com.raytheon.uf.common.localization.PathManager; -import com.raytheon.uf.common.localization.PathManagerFactory; import com.raytheon.uf.common.status.IUFStatusHandler; import com.raytheon.uf.common.status.UFStatus; import com.raytheon.uf.common.status.UFStatus.Priority; +import com.raytheon.uf.viz.core.VizApp; import com.raytheon.uf.viz.core.drawables.ColorMapLoader; -import com.raytheon.uf.viz.core.drawables.ColorMapTree; -import com.raytheon.uf.viz.core.drawables.ColorMapTreeFactory; import com.raytheon.uf.viz.core.exception.VizException; import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability; +import com.raytheon.viz.ui.colormap.ColorMapTree; +import com.raytheon.viz.ui.colormap.ColorMapTreeFactory; +import com.raytheon.viz.ui.colormap.ILevelMapsCallback; +import com.raytheon.viz.ui.colormap.IRefreshColorMapTreeListener; /** * Cascading control for colormaps @@ -68,6 +67,8 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability; * ------------- -------- ----------- -------------------------- * Jul 26, 2010 mschenke Initial creation * Sep 18, 2013 2421 bsteffen Use ColorMapTree for asyncronous loading. + * Aug 28, 2014 3616 rferrel Display ColorMapTree status while creating off + * the UI thread; and added refresh item. * * * @@ -136,7 +137,7 @@ public class ColormapComp { this.cap = cap; } - public void refreshItems() { + public void initItems() { if (cmapPopupMenu != null) { cmapPopupMenu.dispose(); } @@ -151,8 +152,12 @@ public class ColormapComp { } cmapPopupMenu.setVisible(false); - cmapPopupMenu.addMenuListener(new MenuPopulator(cmapPopupMenu, - ColorMapTreeFactory.getBaseTree())); + cmapPopupMenu.addMenuListener(new MenuPopulator(cmapPopupMenu, null)); + } + + public void initializeComponents(Shell shell) { + this.shell = shell; + initializeComponents(); } /** @@ -165,6 +170,31 @@ public class ColormapComp { gd.widthHint = 250; cmapButton.setLayoutData(gd); + /** + * Add listeners and when needed set up removal. + */ + final IRefreshColorMapTreeListener riListener = new IRefreshColorMapTreeListener() { + + @Override + public void refreshColorMapTree() { + if (!cmapButton.isDisposed()) { + initItems(); + } + } + }; + + shell.addDisposeListener(new DisposeListener() { + + @Override + public void widgetDisposed(DisposeEvent e) { + ColorMapTreeFactory.getInstance() + .removeRefreshItemsListener(riListener); + } + }); + + ColorMapTreeFactory.getInstance().addRefreshItemsListener( + riListener); + cmapButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { @@ -175,7 +205,7 @@ public class ColormapComp { } }); } - refreshItems(); + initItems(); } public Menu getMenu() { @@ -212,17 +242,15 @@ public class ColormapComp { * is also an eclipse Job that will automatically try to prefetch some * information from the tree for faster population. */ - private class MenuPopulator extends Job implements MenuListener { + private class MenuPopulator implements MenuListener { private final Menu menu; - private final ColorMapTree tree; + private ColorMapTree tree; public MenuPopulator(Menu menu, ColorMapTree tree) { - super("Loading Color Maps"); this.menu = menu; this.tree = tree; - schedule(); } @Override @@ -230,29 +258,24 @@ public class ColormapComp { /* Do Nothing */ } - /** - * Get all the subTrees that will be displayed and call - * optimizeIsEmpty(). isEmpty() is usually the slowest operation in - * menuShown because it can go recursive. optimizeIsEmpty ensures that - * future calls(from menuShown) are as fast as possible. - */ - @Override - protected IStatus run(IProgressMonitor monitor) { - for (ColorMapTree subTree : tree.getSubTrees()) { - subTree.optimizeIsEmpty(); - } - for (ColorMapTree subTree : getLevelTrees()) { - subTree.optimizeIsEmpty(); - } - return Status.OK_STATUS; - } - - /** + /* * Fill the menu with items from the tree. Always create menus at the - * top even if there are other items + * top even if there are empty trees. */ @Override public void menuShown(MenuEvent e) { + + /* + * When null assume base tree is needed. This allows any dialog + * display to come up without the delay of creating the base tree. + */ + if (tree == null) { + shell.setCursor(shell.getDisplay().getSystemCursor( + SWT.CURSOR_WAIT)); + tree = ColorMapTreeFactory.getInstance().getBaseTree(); + shell.setCursor(null); + } + int index = 0; List subTrees = tree.getSubTrees(); Collections.sort(subTrees, new Comparator() { @@ -282,14 +305,93 @@ public class ColormapComp { addFile(file, index++); } - for (ColorMapTree subTree : getLevelTrees()) { - if (!subTree.isEmpty()) { - addSubTree(subTree, index++); + if (menu == cmapPopupMenu) { + new MenuItem(menu, SWT.SEPARATOR, index++); + final int startLevelIndex = index; + + /* + * Place holders for levels in order to display properly in the + * color bar popup menu. + */ + for (LocalizationLevel level : ColorMapTreeFactory + .getInstance().getTreesLevelLocalization()) { + MenuItem mi = new MenuItem(menu, SWT.NONE, index++); + mi.setText(level.name()); + } + + ColorMapTreeFactory.getInstance().updateLevelMapsCallack( + new ILevelMapsCallback() { + @Override + public void treeCreated( + final LocalizationLevel level, + final ColorMapTree tree) { + /* + * VizApp.runAsync does not update the menu item + * correctly when parent is a menu instead of a + * button. + */ + VizApp.runSync(new Runnable() { + + @Override + public void run() { + updateMenu(startLevelIndex, level, tree); + } + }); + } + }); + } else { + for (ColorMapTree subTree : getLevelTrees()) { + if (!subTree.isEmpty()) { + addSubTree(subTree, index++); + } } } menu.removeMenuListener(this); } + /** + * Update/Add menu item for a level entry with the associated tree. + * Assume running on the UI thread. + * + * @param startLevelIndex + * @param level + * @param tree + * - When null generate unknown place holder + */ + private void updateMenu(int startLevelIndex, LocalizationLevel level, + ColorMapTree tree) { + if (menu.isDisposed()) { + return; + } + int index = startLevelIndex; + MenuItem mi = null; + String name = level.name(); + while (index < menu.getItemCount()) { + mi = menu.getItem(index); + if (mi.getText().startsWith(name)) { + break; + } + ++index; + } + if (index == menu.getItemCount()) { + mi = new MenuItem(menu, SWT.NONE); + } + + if (tree == null) { + mi.setText(name + " ???"); + } else if (tree.isEmpty()) { + mi.setText(name + " ---"); + Menu miMenu = mi.getMenu(); + if (miMenu != null) { + miMenu.dispose(); + mi.setMenu(null); + } + } else { + mi.dispose(); + addSubTree(tree, index); + } + } + /** * The root menu should show not only the base tree, but also an * additional menu item for each localization level(SITE, USER ...), @@ -299,15 +401,11 @@ public class ColormapComp { private List getLevelTrees() { if (menu == cmapPopupMenu) { List trees = new ArrayList(); - IPathManager pm = PathManagerFactory.getPathManager(); - LocalizationLevel[] levels = pm.getAvailableLevels(); + ColorMapTreeFactory cmtf = ColorMapTreeFactory.getInstance(); + LocalizationLevel[] levels = cmtf.getTreesLevelLocalization(); for (LocalizationLevel level : levels) { - if (level != LocalizationLevel.BASE) { - ColorMapTree tree = ColorMapTreeFactory - .getTreeForLevel(level); - trees.add(tree); - - } + ColorMapTree tree = cmtf.getTreeForLevel(level); + trees.add(tree); } return trees; } else { @@ -319,6 +417,7 @@ public class ColormapComp { MenuItem item = new MenuItem(menu, SWT.CASCADE, index); item.setText(tree.getName()); Menu subMenu = new Menu(shell, SWT.DROP_DOWN); + subMenu.setData(tree.getName()); item.setMenu(subMenu); subMenu.addMenuListener(new MenuPopulator(subMenu, tree)); } From 7b052e61ca4ffab43fcf4281134ec417f6477aa3 Mon Sep 17 00:00:00 2001 From: Roger Ferrel Date: Fri, 12 Sep 2014 14:45:25 -0500 Subject: [PATCH 5/6] Issue #3516 ColorMapTree change listener now only gets colormaps changes. Change-Id: Id19d0c0e958ec64a19abc064817780d067add023 Former-commit-id: fa91c4ac44dc9113522f03703532037f68c4a189 [formerly bb265611d13e6cb9812aca3966d9fe2a20990a36] Former-commit-id: 28347129a1e2dd9147c3aa3574ac923dd616f7c8 --- .../src/com/raytheon/viz/ui/colormap/ColorMapTree.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java index f703343a51..240b4f2682 100644 --- a/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java +++ b/cave/com.raytheon.viz.ui/src/com/raytheon/viz/ui/colormap/ColorMapTree.java @@ -49,6 +49,7 @@ import com.raytheon.uf.viz.core.drawables.ColorMapLoader; * Sep 18, 2013 2421 bsteffen Initial creation * Sep 11, 2014 3516 rferrel file updates now inform the factory. * getName() no longer returns a null. + * FileChangeListener now only gets colormaps changes. * * * @@ -97,8 +98,11 @@ public class ColorMapTree { this.pathManager = pathManager; this.level = level; this.context = null; - LocalizationNotificationObserver.getInstance() - .addGlobalFileChangeObserver(new FileChangeListener(this)); + + LocalizationFile dir = pathManager.getLocalizationFile( + pathManager.getContext(LocalizationType.COMMON_STATIC, level), + path); + dir.addFileUpdatedObserver(new FileChangeListener(this)); } /** @@ -227,7 +231,7 @@ public class ColorMapTree { path)); } } - } else if (context.equals(context)) { + } else if (context.equals(this.context)) { synchronized (filesLock) { files = null; } From 5e84bc687eda4a710a8b2fa7b2fe4a236c9601a4 Mon Sep 17 00:00:00 2001 From: Slav Korolev Date: Mon, 15 Sep 2014 17:46:10 -0400 Subject: [PATCH 6/6] Issue #2757 - Removed unnecessary dialogs. Former-commit-id: d682a69b8d3125fc9d441d68279d99d5c758ea67 [formerly 1a906e4f7a5e7cc9e4cd8b4a717f0f2bb02cbb61] Former-commit-id: 65d1cca6fd80ec031e96a40d6f95cbd7ff8f0ad9 --- .../fog/ui/dialogs/FogMonitoringAreaConfigDlg.java | 12 ++---------- .../ui/dialogs/SSMonitoringAreaConfigDlg.java | 12 ++---------- .../snow/ui/dialogs/SnowMonitoringAreaConfigDlg.java | 12 ++---------- 3 files changed, 6 insertions(+), 30 deletions(-) diff --git a/cave/com.raytheon.uf.viz.monitor.fog/src/com/raytheon/uf/viz/monitor/fog/ui/dialogs/FogMonitoringAreaConfigDlg.java b/cave/com.raytheon.uf.viz.monitor.fog/src/com/raytheon/uf/viz/monitor/fog/ui/dialogs/FogMonitoringAreaConfigDlg.java index e3dedafe2c..22bac98d62 100644 --- a/cave/com.raytheon.uf.viz.monitor.fog/src/com/raytheon/uf/viz/monitor/fog/ui/dialogs/FogMonitoringAreaConfigDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.fog/src/com/raytheon/uf/viz/monitor/fog/ui/dialogs/FogMonitoringAreaConfigDlg.java @@ -42,6 +42,7 @@ import com.raytheon.uf.viz.monitor.ui.dialogs.MonitoringAreaConfigDlg; * Nov 27, 2012 1351 skorolev Changes for non-blocking dialog. * Jan 29, 2014 2757 skorolev Changed OK button handler. * Apr 23, 2014 3054 skorolev Fixed issue with removing a new station from list. + * Sep 15, 2014 2757 skorolev Removed extra dialog. * * * @@ -97,16 +98,7 @@ public class FogMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg { configManager.getAddedStations().clear(); } } - } else { - String message3 = "No changes made.\nDo you want to exit?"; - int yesno = showMessage(shell, - SWT.ICON_QUESTION | SWT.YES | SWT.NO, "Exit", message3); - if (yesno == SWT.NO) { - return; - } - setReturnValue(true); - close(); - } + } } /* diff --git a/cave/com.raytheon.uf.viz.monitor.safeseas/src/com/raytheon/uf/viz/monitor/safeseas/ui/dialogs/SSMonitoringAreaConfigDlg.java b/cave/com.raytheon.uf.viz.monitor.safeseas/src/com/raytheon/uf/viz/monitor/safeseas/ui/dialogs/SSMonitoringAreaConfigDlg.java index 7f21dbd69a..3e7e45277b 100644 --- a/cave/com.raytheon.uf.viz.monitor.safeseas/src/com/raytheon/uf/viz/monitor/safeseas/ui/dialogs/SSMonitoringAreaConfigDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.safeseas/src/com/raytheon/uf/viz/monitor/safeseas/ui/dialogs/SSMonitoringAreaConfigDlg.java @@ -42,6 +42,7 @@ import com.raytheon.uf.viz.monitor.ui.dialogs.MonitoringAreaConfigDlg; * Nov 27, 2012 1351 skorolev Changes for non-blocking dialog. * Jan 29, 2014 2757 skorolev Changed OK button handler. * Apr 23, 2014 3054 skorolev Fixed issue with removing a new station from list. + * Sep 15, 2014 2757 skorolev Removed extra dialog. * * * @@ -103,16 +104,7 @@ public class SSMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg { configManager.getAddedStations().clear(); } } - } else { - String message3 = "No changes made.\nDo you want to exit?"; - int yesno = showMessage(shell, - SWT.ICON_QUESTION | SWT.YES | SWT.NO, "Exit", message3); - if (yesno == SWT.NO) { - return; - } - setReturnValue(true); - close(); - } + } } /* diff --git a/cave/com.raytheon.uf.viz.monitor.snow/src/com/raytheon/uf/viz/monitor/snow/ui/dialogs/SnowMonitoringAreaConfigDlg.java b/cave/com.raytheon.uf.viz.monitor.snow/src/com/raytheon/uf/viz/monitor/snow/ui/dialogs/SnowMonitoringAreaConfigDlg.java index 066f6bfc82..a615e67f1b 100644 --- a/cave/com.raytheon.uf.viz.monitor.snow/src/com/raytheon/uf/viz/monitor/snow/ui/dialogs/SnowMonitoringAreaConfigDlg.java +++ b/cave/com.raytheon.uf.viz.monitor.snow/src/com/raytheon/uf/viz/monitor/snow/ui/dialogs/SnowMonitoringAreaConfigDlg.java @@ -42,6 +42,7 @@ import com.raytheon.uf.viz.monitor.ui.dialogs.MonitoringAreaConfigDlg; * Nov 27, 2012 1351 skorolev Changes for non-blocking dialog. * Jan 29, 2014 2757 skorolev Changed OK button handler. * Apr 23, 2014 3054 skorolev Fixed issue with removing a new station from list. + * Sep 15, 2014 2757 skorolev Removed extra dialog. * * * @@ -96,16 +97,7 @@ public class SnowMonitoringAreaConfigDlg extends MonitoringAreaConfigDlg { configManager.getAddedZones().clear(); configManager.getAddedStations().clear(); } - } else { - String message3 = "No changes made.\nDo you want to exit?"; - int yesno = showMessage(shell, - SWT.ICON_QUESTION | SWT.YES | SWT.NO, "Exit", message3); - if (yesno == SWT.NO) { - return; - } - setReturnValue(true); - close(); - } + } } /*