Package com.bbn.openmap.layer.vpf

Source Code of com.bbn.openmap.layer.vpf.VPFConfig$FeatureInfo

// **********************************************************************
//
// <copyright>
//
//  BBN Technologies
//  10 Moulton Street
//  Cambridge, MA 02138
//  (617) 873-8000
//
//  Copyright (C) BBNT Solutions LLC. All rights reserved.
//
// </copyright>
// **********************************************************************
//
// $Source: /cvs/distapps/openmap/src/openmap/com/bbn/openmap/layer/vpf/VPFConfig.java,v $
// $RCSfile: VPFConfig.java,v $
// $Revision: 1.7.2.5 $
// $Date: 2008/01/25 17:44:27 $
// $Author: dietrick $
//
// **********************************************************************

package com.bbn.openmap.layer.vpf;

import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Properties;

import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.JTree;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeSelectionModel;

import com.bbn.openmap.Layer;
import com.bbn.openmap.LayerHandler;
import com.bbn.openmap.io.FormatException;
import com.bbn.openmap.omGraphics.DrawingAttributes;
import com.bbn.openmap.util.Debug;
import com.bbn.openmap.util.PaletteHelper;
import com.bbn.openmap.util.PropUtils;

/**
* A component that can look at the VPF configuration files at the top level of
* the VPF directory structure, and provide an interface for defining an OpenMap
* VPFLayer for chosen features.
* <p>
*
* If the VPFConfig is provided a LayerHandler, it will have a button that will
* create a layer with selected features. If it doesn't have a LayerHandler, it
* will provide a button to print out the properties for a VPFLayer for the
* selected features. This class can be run in stand-alone mode to create
* properties.
*/
public class VPFConfig extends JPanel implements ActionListener {

    // private static boolean DEBUG = false;

    // Optionally play with line styles. Possible values are
    // "Angled", "Horizontal", and "None" (the default).
    private boolean playWithLineStyle = false;
    private String lineStyle = "Angled";
    protected boolean showAll = false;
    protected boolean standAlone = false;

    public final static String AddFeatureCmd = "AddFeatureCommand";
    public final static String ClearFeaturesCmd = "ClearFeaturesCommand";
    public final static String CreateLayerCmd = "CreateLayerCommand";
    public final static String EMPTY_FEATURE_LIST = null;

    DefaultMutableTreeNode currentFeature = null;

    protected DrawingAttributes drawingAttributes = new DrawingAttributes();
    protected boolean searchByFeature = true;
    protected String paths = "";

    protected HashSet layerCoverageTypes = new HashSet();
    protected HashSet layerFeatureTypes = new HashSet();

    public final static String AREA = "area";
    public final static String TEXT = "text";
    public final static String EDGE = "edge";
    public final static String POINT = "point";
    public final static String CPOINT = "cpoint";
    public final static String EPOINT = "epoint";
    public final static String COMPLEX = "complex";
    public final static String UNKNOWN = "unknown";

    protected Hashtable layerFeatures;
    protected Properties layerProperties;
    protected LayerHandler layerHandler;
    protected LibraryBean libraryBean;
    protected String layerName;
    protected VPFLayer layer;

    JButton addFeatureButton;
    JButton clearFeaturesButton;
    JButton createLayerButton;
    JTextArea currentFeatureList;
    JTextField nameField;

    LinkedList featureList = new LinkedList();

    public VPFConfig(String[] dataPaths, String layerName) {
        this(dataPaths, null, layerName);
    }

    public VPFConfig(String[] dataPaths, LayerHandler layerHandler,
            String layerName) {
        this(dataPaths, layerHandler, layerName, false);
    }

    protected VPFConfig(String[] dataPaths, LayerHandler layerHandler,
            String layerName, boolean standAlone) {

        this.layerHandler = layerHandler;
        this.standAlone = standAlone;
        this.layerName = layerName;

        if (dataPaths != null && dataPaths.length > 0) {

            // Take the time to replace any \ with /, it matters if
            // the properties get printed out for later.
            // Permanently set them from \ to / for when they get
            // passed to BinaryFile.
            dataPaths[0] = dataPaths[0].replace('\\', '/');
            StringBuffer buf = new StringBuffer(dataPaths[0]);

            for (int i = 1; i < dataPaths.length; i++) {
                buf.append(";");
                // Permanently set them from \ to / for when they get
                // passed to BinaryFile.
                dataPaths[i] = dataPaths[i].replace('\\', '/');
                buf.append(dataPaths[i]);
            }
            paths = buf.toString();
        }

        // Create the nodes.
        DefaultMutableTreeNode top = new DefaultMutableTreeNode("VPF Data Libraries");
        try {
            createNodes(top, dataPaths);
        } catch (FormatException fe) {
            Debug.output("Caught FormatException reading data: "
                    + fe.getMessage());
            if (standAlone) {
                System.exit(0);
            }
        }

        init(top);
    }

    public VPFConfig(LibraryBean lb, LayerHandler layerHandler, String layerName) {
        this.layerHandler = layerHandler;
        this.layerName = layerName;

        // Create the nodes.
        DefaultMutableTreeNode top = new DefaultMutableTreeNode("VPF Data Libraries");
        try {
            createNodes(top, lb.getLibrarySelectionTable());
        } catch (FormatException fe) {
            Debug.output("Caught FormatException reading data: "
                    + fe.getMessage());
        }

        init(top);
    }

    public VPFConfig(VPFLayer layer) {
        if (layer != null && layer.lst != null) {
            this.layer = layer;
            this.layerName = layer.getName();
            // Create the nodes.
            DefaultMutableTreeNode top = new DefaultMutableTreeNode("VPF Data Libraries");
            try {
                createNodes(top, layer.lst);
            } catch (FormatException fe) {
                Debug.output("Caught FormatException reading data: "
                        + fe.getMessage());
            }
            init(top);
        }
    }

    public void init(DefaultMutableTreeNode top) {

        layerFeatures = new Hashtable();

        // Create a tree that allows one selection at a time.
        final JTree tree = new JTree(top);
        tree.getSelectionModel()
                .setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
        tree.setVisibleRowCount(10);

        // Listen for when the selection changes.
        tree.addTreeSelectionListener(new TreeSelectionListener() {
            public void valueChanged(TreeSelectionEvent e) {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();

                if (node == null)
                    return;

                Object nodeInfo = node.getUserObject();
                if (node.isLeaf() && nodeInfo instanceof FeatureInfo) {
                    currentFeature = node;
                    // enable addToLayer button here.
                    addFeatureButton.setEnabled(true);
                } else {
                    // disable addToLayer button here.
                    addFeatureButton.setEnabled(false);
                }
            }
        });

        if (playWithLineStyle) {
            tree.putClientProperty("JTree.lineStyle", lineStyle);
        }

        // Create the scroll pane and add the tree to it.
        GridBagLayout outergridbag = new GridBagLayout();
        GridBagConstraints outerc = new GridBagConstraints();

        JScrollPane treeView = new JScrollPane(tree);

        setLayout(outergridbag);

        outerc.fill = GridBagConstraints.BOTH;
        outerc.anchor = GridBagConstraints.WEST;
        outerc.insets = new Insets(10, 10, 10, 10);
        outerc.gridx = GridBagConstraints.REMAINDER;
        outerc.weighty = .75;
        outerc.weightx = 1.0;
        outergridbag.setConstraints(treeView, outerc);
        add(treeView);

        // Create the configuration pane
        JPanel configPanel = new JPanel();
        GridBagLayout gridbag = new GridBagLayout();
        GridBagConstraints c = new GridBagConstraints();
        configPanel.setLayout(gridbag);

        c.gridheight = GridBagConstraints.REMAINDER;
        Component da = drawingAttributes.getGUI();
        gridbag.setConstraints(da, c);
        configPanel.add(da);

        c.gridx = 1;
        c.gridheight = 1;
        c.gridy = 0;
        c.fill = GridBagConstraints.HORIZONTAL;
        c.insets = new Insets(0, 5, 0, 5);
        addFeatureButton = new JButton("Add Feature");
        addFeatureButton.addActionListener(this);
        addFeatureButton.setActionCommand(AddFeatureCmd);
        gridbag.setConstraints(addFeatureButton, c);
        configPanel.add(addFeatureButton);
        addFeatureButton.setEnabled(false);

        clearFeaturesButton = new JButton("Clear Features");
        clearFeaturesButton.addActionListener(this);
        clearFeaturesButton.setActionCommand(ClearFeaturesCmd);
        c.gridy = GridBagConstraints.RELATIVE;
        gridbag.setConstraints(clearFeaturesButton, c);
        configPanel.add(clearFeaturesButton);
        clearFeaturesButton.setEnabled(false);

        if (layer != null) {
            createLayerButton = new JButton("Set Features on Layer");
        } else if (layerHandler != null) {
            createLayerButton = new JButton("Create Layer");
        } else {
            createLayerButton = new JButton("Print Properties");
        }
        createLayerButton.addActionListener(this);
        createLayerButton.setActionCommand(CreateLayerCmd);
        gridbag.setConstraints(createLayerButton, c);
        configPanel.add(createLayerButton);
        createLayerButton.setEnabled(false);

        JPanel currentFeatureListPanel = PaletteHelper.createVerticalPanel(" Current Features: ");
        currentFeatureList = new JTextArea(EMPTY_FEATURE_LIST);
        currentFeatureList.setEditable(false);
        JScrollPane featureListScrollPane = new JScrollPane(currentFeatureList);
        featureListScrollPane.setPreferredSize(new Dimension(150, 10));
        currentFeatureListPanel.add(featureListScrollPane);

        c.gridx = 2;
        c.gridy = 0;
        c.weightx = 1.0;
        c.anchor = GridBagConstraints.NORTHWEST;
        c.gridheight = GridBagConstraints.REMAINDER;
        c.fill = GridBagConstraints.BOTH;
        gridbag.setConstraints(currentFeatureListPanel, c);
        configPanel.add(currentFeatureListPanel);

        GridBagLayout gridbag2 = new GridBagLayout();
        GridBagConstraints c2 = new GridBagConstraints();
        JPanel namePanel = new JPanel();
        namePanel.setLayout(gridbag2);

        c2.weightx = 0;
        c2.weighty = 0;
        c2.anchor = GridBagConstraints.WEST;
        JLabel nameLabel = new JLabel("Layer Name: ");
        gridbag2.setConstraints(nameLabel, c2);
        namePanel.add(nameLabel);

        c2.fill = GridBagConstraints.HORIZONTAL;
        c2.weightx = 1.0;
        c2.weighty = 1.0;
        nameField = new JTextField(layerName);
        gridbag2.setConstraints(nameField, c2);
        namePanel.add(nameField);

        outerc.anchor = GridBagConstraints.WEST;
        outerc.weighty = 0;
        outergridbag.setConstraints(namePanel, outerc);
        add(namePanel);

        outerc.fill = GridBagConstraints.HORIZONTAL;
        outerc.weighty = .25;
        outerc.anchor = GridBagConstraints.CENTER;
        outergridbag.setConstraints(configPanel, outerc);
        add(configPanel);

        DrawingAttributes oldDrawingAttributes = (DrawingAttributes) drawingAttributes.clone();

        if (layer != null) {
            // initialize currentFeatures list with anything the layer might
            // have
            // already.
            LayerGraphicWarehouseSupport warehouse = layer.getWarehouse();
            List initialFeatureList = warehouse.getFeatures();

            Iterator listIter = initialFeatureList.iterator();
            while (listIter.hasNext()) {
                // For each feature, find the corresponding tree node
                // and perform the AddFeatureCmd command
                loadCurrentFeatures(top.children(),
                        (String) listIter.next(),
                        warehouse);
            }
        }

        oldDrawingAttributes.setTo(drawingAttributes);
    }

    protected void loadCurrentFeatures(Enumeration treeEnum, String featureName, LayerGraphicWarehouseSupport warehouse) {
        while (treeEnum.hasMoreElements()) {
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) treeEnum.nextElement();
            Object obj = node.getUserObject();
            // Debug.output(node.getUserObject().getClass().getName()
            // + ", " + node.getUserObject());
            if (obj instanceof FeatureInfo) {
                FeatureInfo fi = (FeatureInfo) obj;
                if (fi.featureName.equals(featureName)) {
                    currentFeature = node;

                    if (warehouse instanceof VPFFeatureGraphicWarehouse) {
                        FeatureDrawingAttributes fda = ((VPFFeatureGraphicWarehouse) warehouse).getAttributesForFeature(featureName);
                        if (fda != null) {
                            fda.setTo(drawingAttributes);
                        }
                    }

                    actionPerformed(new ActionEvent(this, 0, AddFeatureCmd));
                }
            } else {
                loadCurrentFeatures(node.children(), featureName, warehouse);
            }
        }
    }

    public void actionPerformed(ActionEvent ae) {
        String command = ae.getActionCommand();

        if (command == AddFeatureCmd) {

            if (currentFeature != null) {
                FeatureInfo feature = (FeatureInfo) currentFeature.getUserObject();
                // Save the current DrawingAttributes
                // settings for the feature.
                feature.drawingAttributes = (DrawingAttributes) drawingAttributes.clone();
                featureList.add(currentFeature);

                String cfl = currentFeatureList.getText();
                if (featureList.size() == 1) {
                    cfl = feature.toString();
                } else {
                    cfl += "\n" + feature.toString();
                }

                currentFeatureList.setText(cfl);

                currentFeature = null;
                createLayerButton.setEnabled(true);
                addFeatureButton.setEnabled(false);
                clearFeaturesButton.setEnabled(true);
            } else {
                Debug.error("No feature selected");
            }
        } else if (command == ClearFeaturesCmd) {
            featureList.clear();
            layerFeatures.clear();

            createLayerButton.setEnabled(false);
            addFeatureButton.setEnabled(false);
            clearFeaturesButton.setEnabled(false);
            currentFeatureList.setText(EMPTY_FEATURE_LIST);
        } else if (command == CreateLayerCmd) {
            if (featureList.size() == 0) {
                Debug.error("No features selected for new VPFLayer");
                createLayerButton.setEnabled(false);
                clearFeaturesButton.setEnabled(false);
                return;
            }

            String name = nameField.getText();
            if (name == null) {
                name = "VPFLayer";
            }

            String propertyPrefix;
            if (layer != null) {
                propertyPrefix = PropUtils.getScopedPropertyPrefix(layer);
            } else {
                propertyPrefix = PropUtils.getScopedPropertyPrefix(name.replace(' ',
                        '_')
                        .toLowerCase());
            }

            if (layer != null) {
                layerProperties = layer.getProperties(null);
            } else {
                layerProperties = new Properties();
            }

            layerCoverageTypes.clear();
            layerFeatureTypes.clear();
            layerFeatures.clear();

            if (standAlone) {
                layerProperties.put(propertyPrefix + "class",
                        "com.bbn.openmap.layer.vpf.VPFLayer");
            }

            layerProperties.put(propertyPrefix + Layer.PrettyNameProperty, name);
            layerProperties.put(propertyPrefix + VPFLayer.pathProperty, paths);
            layerProperties.put(propertyPrefix
                    + VPFLayer.searchByFeatureProperty,
                    new Boolean(searchByFeature).toString());

            // Now, build up coverageTypeProperty and
            // featureTypesProperty
            // from the linked list of featureNodes...
            Iterator it = featureList.iterator();
            while (it.hasNext()) {
                addPropertiesForFeature((DefaultMutableTreeNode) it.next(),
                        propertyPrefix,
                        layerProperties);
            }

            // coverageTypeProperty and featureTypesProperty should
            // be built from above iteration, should push them into
            // properties...
            // List the coverages
            layerProperties.put(propertyPrefix + VPFLayer.coverageTypeProperty,
                    stringTogether(layerCoverageTypes.iterator()));
            // List area/edge/point/text, whatever has been set up
            // with the chosen features.
            layerProperties.put(propertyPrefix + VPFLayer.featureTypesProperty,
                    stringTogether(layerFeatureTypes.iterator()));

            // OK, now go through the layerFeature lists for
            // area/edge/text/point and add the property listing the
            // features associated with each type.
            Enumeration keys = layerFeatures.keys();
            while (keys.hasMoreElements()) {
                String key = (String) keys.nextElement();
                HashSet featureSet = (HashSet) layerFeatures.get(key);
                layerProperties.put(propertyPrefix + key,
                        stringTogether(featureSet.iterator()));
            }

            if (layer != null) {
                layer.setConfigSettings(layer.getPropertyPrefix(),
                        layerProperties);
            } else if (layerHandler != null) {
                VPFLayer layer = new VPFLayer();
                layer.setProperties(propertyPrefix, layerProperties);
                layerHandler.addLayer(layer);
            } else {
                printProperties(layerProperties);
            }

      // These commands clear out the GUI after action has been taken, I don't think we want that to happen anymore.

            // featureList.clear();
            //
            // currentFeatureList.setText(EMPTY_FEATURE_LIST);
            // createLayerButton.setEnabled(false);
            // addFeatureButton.setEnabled(false);
            // clearFeaturesButton.setEnabled(false);
        }
    }

    private void addPropertiesForFeature(DefaultMutableTreeNode featureNode,
                                         String propertyPrefix,
                                         Properties layerProperties) {
        FeatureInfo feature = (FeatureInfo) featureNode.getUserObject();
        CoverageInfo coverage = (CoverageInfo) ((DefaultMutableTreeNode) featureNode.getParent()).getUserObject();

        // Adding to coverage list
        layerCoverageTypes.add(coverage.coverageName);
        // Adding area, edge, text, point to list if it doesn't exist.
        layerFeatureTypes.add(feature.featureTypeString);

        // adding feature name to appropriate edge/area/text/point
        // list
        HashSet featureSet = ((HashSet) layerFeatures.get(feature.featureTypeString));

        if (featureSet == null) {
            // If it's the first category type for the feature
            featureSet = new HashSet();
            layerFeatures.put(feature.featureTypeString, featureSet);
        }
        // Add feature to feature type list for edge/area/text/point
        featureSet.add(feature.featureName);
        feature.drawingAttributes.setPropertyPrefix(propertyPrefix
                + feature.featureName);
        feature.drawingAttributes.getProperties(layerProperties);
    }

    private void printProperties(Properties props) {
        Enumeration keys = props.propertyNames();
        System.out.println("######## START Properties ########");
        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            System.out.println(key + "=" + props.getProperty(key));
        }
        System.out.println("######## END Properties ########");
    }

    private String stringTogether(Iterator it) {
        StringBuffer buf = null;

        while (it.hasNext()) {
            String val = (String) it.next();

            if (buf == null) {
                buf = new StringBuffer(val);
            } else {
                buf.append(" " + val);
            }
        }

        if (buf == null) {
            return "";
        } else {
            return buf.toString();
        }
    }

    private class FeatureInfo {
        public String featureName;
        public String featureDescription;
        public String featureTypeString;
        public int featureType;
        public CoverageTable.FeatureClassRec record;
        public DrawingAttributes drawingAttributes;

        public FeatureInfo(CoverageTable ct, CoverageTable.FeatureClassRec fcr) {
            record = fcr;

            featureTypeString = UNKNOWN;
            if (fcr.type == CoverageTable.TEXT_FEATURETYPE) {
                featureTypeString = TEXT;
            } else if (fcr.type == CoverageTable.EDGE_FEATURETYPE) {
                featureTypeString = EDGE;
            } else if (fcr.type == CoverageTable.AREA_FEATURETYPE) {
                featureTypeString = AREA;
            } else if (fcr.type == CoverageTable.UPOINT_FEATURETYPE) {
                FeatureClassInfo fci = ct.getFeatureClassInfo(fcr.feature_class);
                if (fci == null) {
                    featureTypeString = POINT;
                } else if (fci.getFeatureType() == CoverageTable.EPOINT_FEATURETYPE) {
                    featureTypeString = EPOINT;
                } else if (fci.getFeatureType() == CoverageTable.CPOINT_FEATURETYPE) {
                    featureTypeString = CPOINT;
                } else {
                    featureTypeString = POINT;
                }
            } else if (fcr.type == CoverageTable.COMPLEX_FEATURETYPE) {
                featureTypeString = COMPLEX;
            }

            featureType = fcr.type;
            featureName = fcr.feature_class;
            featureDescription = fcr.description;
        }

        public String toString() {
            return featureDescription + " (" + featureTypeString + ")";
        }
    }

    private class CoverageInfo {
        public String coverageName;
        public String coverageDescription;

        public CoverageInfo(CoverageAttributeTable cat, String covName) {
            coverageName = covName;
            coverageDescription = cat.getCoverageDescription(covName);
        }

        public String toString() {
            return coverageDescription;
        }
    }

    private boolean addFeatureNodes(DefaultMutableTreeNode coverageNode,
                                    CoverageTable ct) {
        int numFeatures = 0;
        Hashtable info = ct.getFeatureTypeInfo();
        for (Enumeration enumeration = info.elements(); enumeration.hasMoreElements();) {
            CoverageTable.FeatureClassRec fcr = (CoverageTable.FeatureClassRec) enumeration.nextElement();

            if (fcr.type == CoverageTable.SKIP_FEATURETYPE) {
                continue;
            }

            coverageNode.add(new DefaultMutableTreeNode(new FeatureInfo(ct, fcr)));
            numFeatures++;
        }
        return numFeatures > 0;
    }

    private void addCoverageNodes(DefaultMutableTreeNode libraryNode,
                                  CoverageAttributeTable cat) {
        String[] coverages = cat.getCoverageNames();
        for (int covi = 0; covi < coverages.length; covi++) {
            String coverage = coverages[covi];
            CoverageInfo covInfo = new CoverageInfo(cat, coverage);
            DefaultMutableTreeNode covNode = new DefaultMutableTreeNode(covInfo);
            if (showAll
                    || addFeatureNodes(covNode, cat.getCoverageTable(coverage))
                    || !cat.isTiledData()) {
                libraryNode.add(covNode);
            }
        }
    }

    private void createNodes(DefaultMutableTreeNode top,
                             LibrarySelectionTable lst) throws FormatException {

        DefaultMutableTreeNode category = null;

        String[] libraries = lst.getLibraryNames();
        for (int libi = 0; libi < libraries.length; libi++) {
            String library = libraries[libi];
            category = new DefaultMutableTreeNode(library);
            CoverageAttributeTable cat = lst.getCAT(library);
            top.add(category);
            addCoverageNodes(category, cat);
        }
    }

    private void createNodes(DefaultMutableTreeNode top, String[] dataPaths)
            throws FormatException {

        for (int i = 0; i < dataPaths.length; i++) {
            String rootpath = dataPaths[i];
            LibrarySelectionTable lst = new LibrarySelectionTable(rootpath);
            createNodes(top, lst);
        }
    }

    public static void createLayer(String[] vpfPaths,
                                   LayerHandler layerHandler, String layerName) {
        launchFrame(new VPFConfig(vpfPaths, layerHandler, layerName), false);
    }

    public static void createLayer(LibraryBean libraryBean,
                                   LayerHandler layerHandler, String layerName) {
        launchFrame(new VPFConfig(libraryBean, layerHandler, layerName), false);
    }

    protected static void launchFrame(JComponent content, boolean exitOnClose) {
        JFrame frame = new JFrame("Create VPF Data Layer");

        frame.getContentPane().add(content);
        if (exitOnClose) {
            frame.addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
        }

        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        if (args.length == 0) {
            System.out.println("Usage:  java com.bbn.openmap.layer.vpf.VPFConfig <path to VPF directory> <path to VPF directory> ...");
            System.exit(0);
        }

        VPFConfig vpfc = new VPFConfig(args, null, "VPF Layer", true);
        launchFrame(vpfc, true);
    }
}
TOP

Related Classes of com.bbn.openmap.layer.vpf.VPFConfig$FeatureInfo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.