Issue #3516 - Get Color Maps for levels off the dispatch thread.
Change-Id: Icc89f4860eef0b0b404e1e5b66bb0178eedd73dc Former-commit-id:b35417acb6
[formerlyfffec40c30
] [formerlyc885873b25
] [formerly246bc4770f
[formerlyc885873b25
[formerly a67a429eb2d266e66a99b6c18916193cd0d20d9d]]] Former-commit-id:246bc4770f
Former-commit-id: 585c48a3a70deefbe881cc65a1154e6aacb31d16 [formerly775dd2520d
] Former-commit-id:9236b1f1fb
This commit is contained in:
parent
4d10d757b8
commit
0b3d2d714a
8 changed files with 598 additions and 152 deletions
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Sep 18, 2013 2421 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class ColorMapTreeFactory {
|
||||
|
||||
private static ColorMapTree baseTree;
|
||||
|
||||
private static Object baseTreeLock = new Object();
|
||||
|
||||
private static final Map<LocalizationLevel, ColorMapTree> treesByLevel = new HashMap<LocalizationLevel, ColorMapTree>();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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<LocalizationLevel, ColorMapTree> treesByLevel = new HashMap<LocalizationLevel, ColorMapTree>();
|
||||
|
||||
/**
|
||||
* Listeners needing treesByLevel information
|
||||
*/
|
||||
private List<ILevelMapsCallback> tlcListeners = new ArrayList<ILevelMapsCallback>();
|
||||
|
||||
/**
|
||||
* 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<IRefreshColorMapTreeListener> refreshListeners = Collections
|
||||
.synchronizedList(new ArrayList<IRefreshColorMapTreeListener>());
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Aug 28, 2014 3516 rferrel Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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);
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Sep 3, 2014 3516 rferrel Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @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();
|
||||
}
|
|
@ -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.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -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<ColorMapTree> subTrees = tree.getSubTrees();
|
||||
Collections.sort(subTrees, new Comparator<ColorMapTree>() {
|
||||
|
@ -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<ColorMapTree> getLevelTrees() {
|
||||
if (menu == cmapPopupMenu) {
|
||||
List<ColorMapTree> trees = new ArrayList<ColorMapTree>();
|
||||
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));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue