Merge "Issue #2421 optimize color map loading. Change-Id: I871ddf0f3eabee0e27d858e2cfa897563875c304" into development
Former-commit-id:eeee5c7948
[formerlyeeee5c7948
[formerly 7139b6fe32b6de8c87c96e3b55d6ad83f11b149a]] Former-commit-id:c01eb85e53
Former-commit-id:72a6650958
This commit is contained in:
commit
f34b07d207
4 changed files with 555 additions and 204 deletions
|
@ -47,14 +47,16 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
*
|
||||
* <pre>
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Feb 13, 2007 chammack Initial Creation.
|
||||
* Aug 20, 2007 njensen Added listColorMaps().
|
||||
* Aug 20, 2008 dglazesk JiBX to JaXB
|
||||
* Aug 20, 2008 dglazesk Updated for new ColorMap interface
|
||||
* Jun 10, 2013 2075 njensen Added listColorMapFiles(subdirectory)
|
||||
* Aug 06, 2013 2210 njensen Moved colormaps to common_static
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Feb 13, 2007 chammack Initial Creation.
|
||||
* Aug 20, 2007 njensen Added listColorMaps().
|
||||
* Aug 20, 2008 dglazesk JiBX to JaXB
|
||||
* Aug 20, 2008 dglazesk Updated for new ColorMap interface
|
||||
* Jun 10, 2013 2075 njensen Added listColorMapFiles(subdirectory)
|
||||
* Aug 06, 2013 2210 njensen Moved colormaps to common_static
|
||||
* Sep 18, 2013 2421 bsteffen Moved some listing capabilities into
|
||||
* ColorMapTree.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -64,9 +66,9 @@ import com.raytheon.uf.viz.core.exception.VizException;
|
|||
|
||||
public class ColorMapLoader {
|
||||
|
||||
private static final String EXTENSION = ".cmap";
|
||||
public static final String EXTENSION = ".cmap";
|
||||
|
||||
private static final String DIR_NAME = "colormaps";
|
||||
public static final String DIR_NAME = "colormaps";
|
||||
|
||||
private static final String sharedMutex = "";
|
||||
|
||||
|
@ -227,15 +229,6 @@ public class ColorMapLoader {
|
|||
+ subDirectory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists all the colormaps found in the system
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static LocalizationFile[] listColorMapFiles() {
|
||||
return internalListColorMapFiles(DIR_NAME);
|
||||
}
|
||||
|
||||
public static String shortenName(LocalizationFile file) {
|
||||
String name = file.getName()
|
||||
.replace(DIR_NAME + IPathManager.SEPARATOR, "")
|
||||
|
@ -258,7 +251,7 @@ public class ColorMapLoader {
|
|||
*/
|
||||
public static String[] listColorMaps(
|
||||
LocalizationContext.LocalizationLevel aType) {
|
||||
LocalizationFile[] files = listColorMapFiles();
|
||||
LocalizationFile[] files = internalListColorMapFiles(DIR_NAME);
|
||||
String[] cmaps = new String[files.length];
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
cmaps[i] = shortenName(files[i]);
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
/**
|
||||
* 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.lang.ref.Reference;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
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;
|
||||
import com.raytheon.uf.common.localization.LocalizationContext.LocalizationType;
|
||||
import com.raytheon.uf.common.localization.LocalizationFile;
|
||||
import com.raytheon.uf.common.localization.LocalizationNotificationObserver;
|
||||
|
||||
/**
|
||||
* ColorMapTree represents the directory structure of colormaps directory. The
|
||||
* levels of a Tree can represent a {@link LocalizationLevel}, a
|
||||
* {@link LocalizationContext} or a localization directory.
|
||||
*
|
||||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
*
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Sep 18, 2013 2421 bsteffen Initial creation
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
* @author bsteffen
|
||||
* @version 1.0
|
||||
*/
|
||||
public class ColorMapTree {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final IPathManager pathManager;
|
||||
|
||||
private final LocalizationLevel level;
|
||||
|
||||
private final LocalizationContext context;
|
||||
|
||||
private final Object filesLock = new Object();
|
||||
|
||||
private LocalizationFile[] files;
|
||||
|
||||
private final Object subTreesLock = new Object();
|
||||
|
||||
private List<ColorMapTree> subTrees;
|
||||
|
||||
/**
|
||||
* Create a tree for the given path and context. The tree will represent the
|
||||
* colormap files that exist at the path within the context.
|
||||
*/
|
||||
public ColorMapTree(IPathManager pathManager, LocalizationContext context,
|
||||
String path) {
|
||||
this.path = path;
|
||||
this.pathManager = pathManager;
|
||||
this.level = null;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a tree for the given path and level. The tree will have the same
|
||||
* name as the level and will have a subtree for each context that exists at
|
||||
* that level. Each context tree will represent the colormap files that
|
||||
* exist at the path.
|
||||
*/
|
||||
public ColorMapTree(IPathManager pathManager, LocalizationLevel level,
|
||||
String path) {
|
||||
this.path = path;
|
||||
this.pathManager = pathManager;
|
||||
this.level = level;
|
||||
this.context = null;
|
||||
LocalizationNotificationObserver.getInstance()
|
||||
.addGlobalFileChangeObserver(new FileChangeListener(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* For a tree based only on a {@link LocalizationLevel} this returns the
|
||||
* name of the level, for a tree at the root directory of a context this
|
||||
* will be the name of the {@link LocalizationContext} and for a tree
|
||||
* representing a subdirectory this will be the directory name.
|
||||
*/
|
||||
public String getName() {
|
||||
if (context == null) {
|
||||
return level.name();
|
||||
} else {
|
||||
int start = path.lastIndexOf(IPathManager.SEPARATOR);
|
||||
if (start <= 0) {
|
||||
return context.getContextName();
|
||||
}
|
||||
return path.substring(start + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For a tree based on a {@link LocalizationLevel} this returns a tree for
|
||||
* each context at the level. Otherwise it returns a tree for each
|
||||
* subdirectory of this tree.
|
||||
*/
|
||||
public List<ColorMapTree> getSubTrees() {
|
||||
synchronized (subTreesLock) {
|
||||
if (subTrees == null) {
|
||||
subTrees = new ArrayList<ColorMapTree>();
|
||||
if (context == null) {
|
||||
for (String context : pathManager.getContextList(level)) {
|
||||
LocalizationContext ctx = pathManager.getContext(
|
||||
LocalizationType.COMMON_STATIC, level);
|
||||
ctx.setContextName(context);
|
||||
subTrees.add(new ColorMapTree(pathManager, ctx, path));
|
||||
}
|
||||
} else {
|
||||
for (LocalizationFile file : requestFiles()) {
|
||||
if (file.isDirectory() && !path.equals(file.getName())) {
|
||||
subTrees.add(new ColorMapTree(pathManager, context,
|
||||
file.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return new ArrayList<ColorMapTree>(subTrees);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return all color map files within this level of the tree.
|
||||
*/
|
||||
public List<LocalizationFile> getColorMapFiles() {
|
||||
if (context == null) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<LocalizationFile> result = new ArrayList<LocalizationFile>();
|
||||
for (LocalizationFile file : requestFiles()) {
|
||||
if (!file.isDirectory()) {
|
||||
result.add(file);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return true if this tree does not contain any color map files or any
|
||||
* subtrees which contain color map files(recursively).
|
||||
*/
|
||||
public boolean isEmpty() {
|
||||
if (getColorMapFiles().isEmpty()) {
|
||||
for (ColorMapTree tree : getSubTrees()) {
|
||||
if (!tree.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public void optimizeIsEmpty() {
|
||||
/* isEmpty caches data in the subtrees so nothing else is needed. */
|
||||
isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will receive a message for every localization file in all
|
||||
* contexts. It must filter by path and by level and/or context.
|
||||
*/
|
||||
protected void handleUpdate(FileUpdatedMessage message) {
|
||||
if (message.getFileName().startsWith(path)) {
|
||||
LocalizationContext context = message.getContext();
|
||||
if (context.getLocalizationLevel().equals(level)) {
|
||||
synchronized (subTreesLock) {
|
||||
if (subTrees != null) {
|
||||
for (ColorMapTree subTree : subTrees) {
|
||||
if (subTree.getName().equals(
|
||||
context.getContextName())) {
|
||||
subTree.handleUpdate(message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
subTrees.add(new ColorMapTree(pathManager, context,
|
||||
path));
|
||||
}
|
||||
}
|
||||
} else if (context.equals(context)) {
|
||||
synchronized (filesLock) {
|
||||
files = null;
|
||||
}
|
||||
synchronized (subTreesLock) {
|
||||
subTrees = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private LocalizationFile[] requestFiles() {
|
||||
synchronized (filesLock) {
|
||||
if (files == null) {
|
||||
files = pathManager
|
||||
.listFiles(context, path,
|
||||
new String[] { ColorMapLoader.EXTENSION },
|
||||
false, false);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link WeakReference} based listener which automatically removes itself
|
||||
* when a notification arrives and the {@link ColorMapTree} has been garbage
|
||||
* collected.
|
||||
*/
|
||||
private static class FileChangeListener implements
|
||||
ILocalizationFileObserver {
|
||||
|
||||
private final Reference<ColorMapTree> treeRef;
|
||||
|
||||
private FileChangeListener(ColorMapTree tree) {
|
||||
treeRef = new WeakReference<ColorMapTree>(tree);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fileUpdated(FileUpdatedMessage message) {
|
||||
ColorMapTree tree = treeRef.get();
|
||||
if (tree == null) {
|
||||
LocalizationNotificationObserver.getInstance()
|
||||
.removeGlobalFileChangeObserver(this);
|
||||
} else {
|
||||
tree.handleUpdate(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,17 +19,20 @@
|
|||
**/
|
||||
package com.raytheon.viz.ui.dialogs;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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.MenuEvent;
|
||||
import org.eclipse.swt.events.MenuListener;
|
||||
import org.eclipse.swt.events.SelectionAdapter;
|
||||
import org.eclipse.swt.events.SelectionEvent;
|
||||
import org.eclipse.swt.graphics.Point;
|
||||
|
@ -41,8 +44,17 @@ 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.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;
|
||||
|
||||
|
@ -52,9 +64,10 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
|||
* <pre>
|
||||
*
|
||||
* SOFTWARE HISTORY
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------ ---------- ----------- --------------------------
|
||||
* Jul 26, 2010 mschenke Initial creation
|
||||
* Date Ticket# Engineer Description
|
||||
* ------------- -------- ----------- --------------------------
|
||||
* Jul 26, 2010 mschenke Initial creation
|
||||
* Sep 18, 2013 2421 bsteffen Use ColorMapTree for asyncronous loading.
|
||||
*
|
||||
* </pre>
|
||||
*
|
||||
|
@ -64,88 +77,15 @@ import com.raytheon.uf.viz.core.rsc.capabilities.ColorMapCapability;
|
|||
|
||||
public class ColormapComp {
|
||||
|
||||
private static final transient IUFStatusHandler statusHandler = UFStatus
|
||||
.getHandler(ColormapComp.class);
|
||||
|
||||
public static interface IColormapCompChangeListener {
|
||||
public void colormapChanged(String colorMap);
|
||||
}
|
||||
|
||||
private class ColorMapMenuItem {
|
||||
|
||||
/** null if not leaf node */
|
||||
private LocalizationFile cmapFile;
|
||||
|
||||
private Menu subMenu;
|
||||
|
||||
private MenuItem actualItem;
|
||||
|
||||
private Menu parent;
|
||||
|
||||
private String text;
|
||||
|
||||
/**
|
||||
* @param parent
|
||||
* @param style
|
||||
*/
|
||||
public ColorMapMenuItem(Menu parent, Menu subMenu,
|
||||
LocalizationFile cmapFile, String text) {
|
||||
this.parent = parent;
|
||||
this.subMenu = subMenu;
|
||||
this.cmapFile = cmapFile;
|
||||
this.text = text;
|
||||
|
||||
List<ColorMapMenuItem> children = childMap.get(parent);
|
||||
if (children == null) {
|
||||
children = new ArrayList<ColorMapMenuItem>();
|
||||
childMap.put(parent, children);
|
||||
}
|
||||
children.add(this);
|
||||
}
|
||||
|
||||
public void initializeComponents() {
|
||||
actualItem = new MenuItem(parent, subMenu == null ? SWT.NONE
|
||||
: SWT.CASCADE);
|
||||
actualItem.setText(text);
|
||||
if (subMenu != null) {
|
||||
actualItem.setMenu(subMenu);
|
||||
}
|
||||
|
||||
actualItem.addSelectionListener(new SelectionAdapter() {
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
if (cmapFile != null) {
|
||||
if (cmapButton != null) {
|
||||
cmapButton.setText(cmapFile.getName()
|
||||
.replace("colormaps" + File.separator, "")
|
||||
.replace(".cmap", ""));
|
||||
}
|
||||
|
||||
try {
|
||||
String shortName = ColorMapLoader
|
||||
.shortenName(cmapFile);
|
||||
params.setColorMap(ColorMapLoader
|
||||
.loadColorMap(shortName));
|
||||
cap.notifyResources();
|
||||
|
||||
for (IColormapCompChangeListener listener : listeners) {
|
||||
listener.colormapChanged(shortName);
|
||||
}
|
||||
} catch (VizException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public Menu getSubMenu() {
|
||||
return subMenu;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Set<IColormapCompChangeListener> listeners = new HashSet<IColormapCompChangeListener>();
|
||||
|
||||
private Map<Menu, List<ColorMapMenuItem>> childMap = new HashMap<Menu, List<ColorMapMenuItem>>();
|
||||
|
||||
private Button cmapButton;
|
||||
|
||||
private Shell shell;
|
||||
|
@ -211,54 +151,8 @@ public class ColormapComp {
|
|||
}
|
||||
|
||||
cmapPopupMenu.setVisible(false);
|
||||
|
||||
LocalizationFile[] files = ColorMapLoader.listColorMapFiles();
|
||||
for (LocalizationFile file : files) {
|
||||
|
||||
List<String> actualItems = new ArrayList<String>();
|
||||
|
||||
String[] split = ColorMapLoader.shortenName(file).split("[/\\\\]"); // Win32
|
||||
|
||||
Menu lastParent = cmapPopupMenu;
|
||||
|
||||
// Just to be sure, get rid of empty items
|
||||
for (String text : split) {
|
||||
if (text.trim().equals("") == false) {
|
||||
actualItems.add(text);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < actualItems.size(); ++i) {
|
||||
if (i == actualItems.size() - 1) {
|
||||
// leaf node
|
||||
new ColorMapMenuItem(lastParent, null, file,
|
||||
actualItems.get(i));
|
||||
} else {
|
||||
String text = actualItems.get(i);
|
||||
boolean found = false;
|
||||
// traverse lastParent's children to see if we already exist
|
||||
List<ColorMapMenuItem> children = childMap.get(lastParent);
|
||||
if (children == null) {
|
||||
children = new ArrayList<ColorMapMenuItem>();
|
||||
childMap.put(lastParent, children);
|
||||
}
|
||||
for (ColorMapMenuItem item : children) {
|
||||
if (item.subMenu != null && item.text.equals(text)) {
|
||||
found = true;
|
||||
lastParent = item.subMenu;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
Menu cmapParent = lastParent;
|
||||
lastParent = new Menu(shell, SWT.DROP_DOWN);
|
||||
new ColorMapMenuItem(cmapParent, lastParent, null, text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sortMenus(cmapPopupMenu);
|
||||
cmapPopupMenu.addMenuListener(new MenuPopulator(cmapPopupMenu,
|
||||
ColorMapTreeFactory.getBaseTree()));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -284,60 +178,6 @@ public class ColormapComp {
|
|||
refreshItems();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parent
|
||||
*/
|
||||
private void sortMenus(Menu parent) {
|
||||
List<ColorMapMenuItem> children = childMap.get(parent);
|
||||
if (children == null || children.size() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
Collections.sort(children, new Comparator<ColorMapMenuItem>() {
|
||||
@Override
|
||||
public int compare(ColorMapMenuItem o1, ColorMapMenuItem o2) {
|
||||
// catch user menu item
|
||||
if (o1.text.toUpperCase().equals("USER")) {
|
||||
// user is always last
|
||||
return 1;
|
||||
} else if (o2.text.toUpperCase().equals("USER")) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// catch site menu item
|
||||
if (o1.text.toUpperCase().equals("SITE")) {
|
||||
// site is after all but user ( user gets caught first )
|
||||
return 1;
|
||||
} else if (o2.text.toUpperCase().equals("SITE")) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// all other menu items
|
||||
if (o1.subMenu != null && o2.subMenu == null) {
|
||||
// Show those with submenus first
|
||||
return -1;
|
||||
} else if (o1.subMenu == null && o2.subMenu != null) {
|
||||
// Show those with submenus first
|
||||
return 1;
|
||||
} else {
|
||||
// else look at text
|
||||
return o1.text.toLowerCase().compareTo(
|
||||
o2.text.toLowerCase());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for (ColorMapMenuItem child : children) {
|
||||
child.initializeComponents();
|
||||
}
|
||||
|
||||
for (ColorMapMenuItem child : children) {
|
||||
if (child.subMenu != null) {
|
||||
sortMenus(child.subMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Menu getMenu() {
|
||||
return cmapPopupMenu;
|
||||
}
|
||||
|
@ -348,4 +188,160 @@ public class ColormapComp {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void changeColormap(String name) {
|
||||
if (cmapButton != null) {
|
||||
cmapButton.setText(name);
|
||||
}
|
||||
|
||||
try {
|
||||
params.setColorMap(ColorMapLoader.loadColorMap(name));
|
||||
cap.notifyResources();
|
||||
for (IColormapCompChangeListener listener : listeners) {
|
||||
listener.colormapChanged(name);
|
||||
}
|
||||
} catch (VizException e) {
|
||||
statusHandler.handle(Priority.ERROR, "Unable to change colormap.",
|
||||
e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class to recursively populate a menu based off the contents of a
|
||||
* {@link ColorMapTree}. The menu is not populated until it is shown. This
|
||||
* 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 final Menu menu;
|
||||
|
||||
private final ColorMapTree tree;
|
||||
|
||||
public MenuPopulator(Menu menu, ColorMapTree tree) {
|
||||
super("Loading Color Maps");
|
||||
this.menu = menu;
|
||||
this.tree = tree;
|
||||
schedule();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void menuHidden(MenuEvent e) {
|
||||
/* 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
|
||||
*/
|
||||
@Override
|
||||
public void menuShown(MenuEvent e) {
|
||||
int index = 0;
|
||||
List<ColorMapTree> subTrees = tree.getSubTrees();
|
||||
Collections.sort(subTrees, new Comparator<ColorMapTree>() {
|
||||
|
||||
@Override
|
||||
public int compare(ColorMapTree tree1, ColorMapTree tree2) {
|
||||
return tree1.getName().compareToIgnoreCase(tree2.getName());
|
||||
}
|
||||
|
||||
});
|
||||
for (ColorMapTree subTree : subTrees) {
|
||||
if (!subTree.isEmpty()) {
|
||||
addSubTree(subTree, index++);
|
||||
}
|
||||
}
|
||||
List<LocalizationFile> files = tree.getColorMapFiles();
|
||||
Collections.sort(files, new Comparator<LocalizationFile>() {
|
||||
|
||||
@Override
|
||||
public int compare(LocalizationFile file1,
|
||||
LocalizationFile file2) {
|
||||
return file1.getName().compareToIgnoreCase(file2.getName());
|
||||
}
|
||||
|
||||
});
|
||||
for (LocalizationFile file : files) {
|
||||
addFile(file, index++);
|
||||
}
|
||||
|
||||
for (ColorMapTree subTree : getLevelTrees()) {
|
||||
if (!subTree.isEmpty()) {
|
||||
addSubTree(subTree, index++);
|
||||
}
|
||||
}
|
||||
menu.removeMenuListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The root menu should show not only the base tree, but also an
|
||||
* additional menu item for each localization level(SITE, USER ...),
|
||||
* this method gets those trees when they are needed so menu items can
|
||||
* be added.
|
||||
*/
|
||||
private List<ColorMapTree> getLevelTrees() {
|
||||
if (menu == cmapPopupMenu) {
|
||||
List<ColorMapTree> trees = new ArrayList<ColorMapTree>();
|
||||
IPathManager pm = PathManagerFactory.getPathManager();
|
||||
LocalizationLevel[] levels = pm.getAvailableLevels();
|
||||
for (LocalizationLevel level : levels) {
|
||||
if (level != LocalizationLevel.BASE) {
|
||||
ColorMapTree tree = ColorMapTreeFactory
|
||||
.getTreeForLevel(level);
|
||||
trees.add(tree);
|
||||
|
||||
}
|
||||
}
|
||||
return trees;
|
||||
} else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private void addSubTree(ColorMapTree tree, int index) {
|
||||
MenuItem item = new MenuItem(menu, SWT.CASCADE, index);
|
||||
item.setText(tree.getName());
|
||||
Menu subMenu = new Menu(shell, SWT.DROP_DOWN);
|
||||
item.setMenu(subMenu);
|
||||
subMenu.addMenuListener(new MenuPopulator(subMenu, tree));
|
||||
}
|
||||
|
||||
private void addFile(LocalizationFile file, int index) {
|
||||
MenuItem item = new MenuItem(menu, SWT.None, index);
|
||||
final String name = ColorMapLoader.shortenName(file);
|
||||
int start = name.lastIndexOf(PathManager.SEPARATOR);
|
||||
if (start >= 0) {
|
||||
item.setText(name.substring(start + 1));
|
||||
} else {
|
||||
item.setText(name);
|
||||
}
|
||||
item.addSelectionListener(new SelectionAdapter() {
|
||||
|
||||
@Override
|
||||
public void widgetSelected(SelectionEvent e) {
|
||||
changeColormap(name);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue