[mapguide-commits] r4676 - in trunk/MgDev/Web/src: localized mapviewerjava mapviewernet mapviewerphp viewerfiles

svn_mapguide at osgeo.org svn_mapguide at osgeo.org
Sat Mar 20 08:54:52 EDT 2010


Author: jng
Date: 2010-03-20 08:54:51 -0400 (Sat, 20 Mar 2010)
New Revision: 4676

Added:
   trunk/MgDev/Web/src/mapviewerjava/getselectedfeatures.jsp
   trunk/MgDev/Web/src/mapviewernet/getselectedfeatures.aspx
   trunk/MgDev/Web/src/mapviewerphp/getselectedfeatures.php
Modified:
   trunk/MgDev/Web/src/localized/en
   trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp
   trunk/MgDev/Web/src/mapviewernet/mapframe.aspx
   trunk/MgDev/Web/src/mapviewerphp/mapframe.php
   trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ
   trunk/MgDev/Web/src/viewerfiles/propertyctrl.templ
Log:
#1053: Merge the sandbox work into trunk. This marks the completion of RFC71

Modified: trunk/MgDev/Web/src/localized/en
===================================================================
--- trunk/MgDev/Web/src/localized/en	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/localized/en	2010-03-20 12:54:51 UTC (rev 4676)
@@ -247,3 +247,11 @@
 
 # Localized Icon Files
 POWEREDBYICON           = PoweredBy_en.gif
+
+# Property Pane Toolbar
+ZOOMSELECTEDFEATUREDESC = Zoom to this feature
+NOFEATSELECTRESPONSE    = No response from feature selection request
+
+# Multiple Property Processing
+SERVERERROR             = Server Error
+ERRORSTACKTRACE         = Stack Trace

Copied: trunk/MgDev/Web/src/mapviewerjava/getselectedfeatures.jsp (from rev 4675, sandbox/rfc71/mapviewerjava/getselectedfeatures.jsp)
===================================================================
--- trunk/MgDev/Web/src/mapviewerjava/getselectedfeatures.jsp	                        (rev 0)
+++ trunk/MgDev/Web/src/mapviewerjava/getselectedfeatures.jsp	2010-03-20 12:54:51 UTC (rev 4676)
@@ -0,0 +1,441 @@
+<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
+<%@ page import="org.osgeo.mapguide.*" %>
+<%@ page import="java.util.*" %>
+<%@ page import="java.lang.*" %>
+<%@ page import="java.io.*" %>
+<%@ page import="java.text.*" %>
+<%@ page import="javax.xml.parsers.DocumentBuilder" %>
+<%@ page import="javax.xml.parsers.DocumentBuilderFactory" %>
+<%@ page import="org.w3c.dom.Document" %>
+<%@ page import="org.w3c.dom.Element" %>
+<%@ page import="org.w3c.dom.Node" %>
+<%@ page import="org.w3c.dom.NodeList" %>
+<%@ page import="javax.servlet.jsp.*" %>
+<%@ page import="javax.servlet.http.*" %>
+<%@ include file="common.jsp" %>
+<%@ page isThreadSafe="false" %>
+<%!
+
+    String mapName;
+    String sessionId;
+    String localeCode;
+    Locale locale;
+
+    class SelectionSet
+    {
+        private HashMap<String, Vector<Feature>> _layers;
+
+        public SelectionSet()
+        {
+            _layers = new HashMap<String, Vector<Feature>>();
+        }
+
+        public void addFeature(Feature feat)
+        {
+            if (!_layers.containsKey(feat.LayerName))
+                _layers.put(feat.LayerName, new Vector<Feature>());
+
+            _layers.get(feat.LayerName).add(feat);
+        }
+
+        public String[] getLayers()
+        {
+            String[] layers = new String[_layers.keySet().size()];
+            _layers.keySet().toArray(layers);
+            
+            return layers;
+        }
+
+        public Feature[] getFeatures(String layerName)
+        {
+            if (_layers.containsKey(layerName))
+            {
+                Vector<Feature> layerFeatures = _layers.get(layerName);
+                Feature[] feats = new Feature[layerFeatures.size()];
+                layerFeatures.toArray(feats);
+                return feats;
+            }
+
+            return null;
+        }
+    }
+
+    class ZoomPoint
+    {
+        public double X;
+        public double Y;
+    }
+
+    class FeatureProperty
+    {
+        public String Name;
+        public String Value;
+    }
+
+    class Feature
+    {
+        public String LayerName;
+        public ZoomPoint Zoom;
+
+        private HashMap<String, FeatureProperty> _properties;
+
+        public Feature(String layerName)
+        {
+            this.LayerName = layerName;
+            _properties = new HashMap<String, FeatureProperty>();
+        }
+
+        public void addProperty(FeatureProperty prop)
+        {
+            _properties.put(prop.Name, prop);
+        }
+
+        public FeatureProperty[] getProperties()
+        {
+            Collection<FeatureProperty> values = _properties.values();
+            FeatureProperty[] props = new FeatureProperty[values.size()];
+            values.toArray(props);
+            return props;
+        }
+    }
+    
+    static String getTextValue(Element el, String tagName)
+    {
+        String textVal = null;
+        NodeList nl = el.getElementsByTagName(tagName);
+        if (nl != null && nl.getLength() > 0)
+        {
+            Element e = (Element)nl.item(0);
+            textVal = e.getFirstChild().getNodeValue();
+        }
+        return textVal;
+    }
+    
+    static HashMap<String, String> GetLayerPropertyMappings(MgResourceService resSvc, MgLayerBase layer) throws Exception
+    {
+        HashMap<String, String> mappings = new HashMap<String, String>();
+        
+        MgByteReader content = resSvc.GetResourceContent(layer.GetLayerDefinition());
+        ByteArrayInputStream contentReader = new ByteArrayInputStream(content.ToString().getBytes("UTF-8"));
+        
+        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+        DocumentBuilder db = dbf.newDocumentBuilder();
+        Document doc = db.parse(contentReader);
+        
+        doc.getDocumentElement().normalize();
+        NodeList propNodes = doc.getElementsByTagName("PropertyMapping");
+        
+        for (int i = 0; i < propNodes.getLength(); i++)
+        {
+            Element propEl = (Element)propNodes.item(i);
+            String name = getTextValue(propEl, "Name");
+            String value = getTextValue(propEl, "Value");
+            
+            if (name != null && value != null)
+                mappings.put(name, value);
+        }
+        
+        return mappings;
+    }
+    
+    String GetPropertyValueFromFeatureReader(MgFeatureReader reader, MgAgfReaderWriter agfRw, int propType, String propName) throws Exception
+    {
+        String value = "";
+        switch(propType)
+        {
+            case MgPropertyType.Boolean:
+                value = String.format(locale, "%s", reader.GetBoolean(propName));
+                break;
+            case MgPropertyType.Byte:
+                value = String.format(locale, "%d", reader.GetByte(propName));
+                break; 
+            case MgPropertyType.DateTime:
+                value = GetDateTimeString(reader.GetDateTime(propName)); // yyyy-mm-dd is enforced regardless of locale
+                break;
+            case MgPropertyType.Single:
+                value = String.format(locale, "%f", reader.GetSingle(propName));
+                break;
+            case MgPropertyType.Double:
+                value = String.format(locale, "%f", reader.GetDouble(propName));
+                break;
+            case MgPropertyType.Int16:
+                value = String.format(locale, "%d", reader.GetInt16(propName));
+                break;
+            case MgPropertyType.Int32:
+                value = String.format(locale, "%d", reader.GetInt32(propName));
+                break;
+            case MgPropertyType.Int64:
+                value = String.format(locale, "%d", reader.GetInt64(propName));
+                break;
+            case MgPropertyType.String:
+                value = JsonEscape(reader.GetString(propName)); // string content is arbitrary
+                break;
+            default: //NOT PRESENTABLE IN PROPERTY GRID
+                value = "";
+                break;
+        }
+        return value;   
+    }
+
+    static String GetDateTimeString(MgDateTime value) throws MgException
+    {
+        return value.GetYear() + "-" + value.GetMonth() + "-" + value.GetDay();
+    }
+    
+    void GetParameters(HttpServletRequest request)
+    {
+        mapName = GetParameter(request, "MAPNAME");
+        sessionId = GetParameter(request, "SESSION");
+        localeCode = GetParameter(request, "LOCALE");
+    }
+    
+    String JsonEscape(String str)
+    {
+        return EscapeForHtml(str).replace("\\", "\\\\");
+    }
+    
+    String JsonifyError(Exception ex)
+    {
+        if (ex == null)
+            return "";
+        /*
+        {
+            "Error" : {
+                "Message" : <exception-message>,
+                "StackTrace" : <exception-stack-trace>
+            }
+        }
+        */
+        
+        StringBuffer sb = new StringBuffer();
+        //Use exception message or type name if no message found
+        String msg = ex.getMessage();
+        if (msg == null || msg.length() == 0)
+        {
+            msg = MgLocalizer.GetString("SERVERERROR", localeCode);
+        }
+        //Begin response
+        sb.append("{\"Error\":{");
+        //Exception message
+        sb.append("\"Message\":\"" + JsonEscape(msg) + "\",");
+        StringBuffer strace = new StringBuffer();
+        StackTraceElement[] st = ex.getStackTrace();
+        for (int i = 0; i < st.length; i++)
+        {
+            strace.append(st[i].getClassName() + "." + st[i].getMethodName() + "(" + st[i].getLineNumber() + ")\\n");
+        }
+        sb.append("\"StackTrace\":\"" + JsonEscape(strace.toString()) + "\"");
+        //End response
+        sb.append("}}");
+        return sb.toString();
+    }
+    
+    static String GetJson(SelectionSet set)
+    {
+        /*
+        A sample of the JSON output this method will produce:
+        
+        
+        {
+            "Layer1" : [ 
+                { 
+                    'values' { "name" : "name1" , "value" : "value1" }, 
+                    'zoom' : { x: num1, y: num2 } 
+                } , 
+                ..,
+                ..,
+                ..,
+            ],
+            "Layer2" : [ 
+                { 
+                    'values' { "name" : "name2" , "value" : "value2" }, 
+                    'zoom' : { x: num1, y: num2 } 
+                } , 
+                ..,
+                ..,
+                ..,
+            ]
+        }
+        */
+        
+        if (set == null)
+            return "";
+        
+        StringBuffer sb = new StringBuffer();
+        //Begin selection set
+        sb.append("{");
+        String[] layers = set.getLayers();
+        for (int i = 0; i < layers.length; i++)
+        {
+            //Begin layer
+            sb.append("\"" + layers[i] + "\" : [");
+            Feature[] features = set.getFeatures(layers[i]);
+            for (int j = 0; j < features.length; j++)
+            {
+                Feature feat = features[j];
+                //begin feature
+                //begin feature properties
+                sb.append("{\"values\" : [");
+                FeatureProperty[] properties = feat.getProperties();
+                for(int k = 0; k < properties.length; k++)
+                {
+                    FeatureProperty fp = properties[k];
+                    sb.append("{\"name\" : \"" + fp.Name + "\", \"value\" : \"" + fp.Value + "\" }");
+                    if (k != properties.length - 1)
+                        sb.append(",");
+                }
+                //end feature properties
+                //begin zoom
+                sb.append("], \"zoom\" : ");
+                if (feat.Zoom == null)
+                    sb.append("null");
+                else
+                    sb.append("{\"x\" : " + feat.Zoom.X + ", \"y\" : " + feat.Zoom.Y + "}");
+                //end zoom
+                //end feature
+                sb.append("}");
+                if (j != features.length - 1)
+                    sb.append(",");
+            }
+            //End Layer
+            sb.append("]");
+            if (i != layers.length - 1)
+                sb.append(",");
+        }
+        //End selection set
+        sb.append("}");
+        return sb.toString();
+    }
+%>
+<%
+    mapName = "";
+    sessionId = "";
+    localeCode = "";
+
+    GetParameters(request);
+    
+    if (null == localeCode || localeCode.length() == 0)
+        localeCode = GetDefaultLocale();
+        
+    locale = new Locale(localeCode);
+
+    try
+    {
+        MgUserInformation cred = new MgUserInformation(sessionId);
+        cred.SetClientIp(GetClientIp(request));
+        cred.SetClientAgent(GetClientAgent());
+
+        MgSiteConnection site = new MgSiteConnection();
+        site.Open(cred);
+
+        MgResourceService resSvc = (MgResourceService)site.CreateService(MgServiceType.ResourceService);
+        
+        MgMap map = new MgMap(site);
+        map.Open(mapName);
+
+        MgSelection selection = new MgSelection(map);
+        selection.Open(resSvc, mapName);
+
+        MgReadOnlyLayerCollection layers = selection.GetLayers();
+        if (layers != null && layers.GetCount() > 0)
+        {
+            int layerCount = layers.GetCount();
+            MgAgfReaderWriter agfRW = new MgAgfReaderWriter();
+            SelectionSet selectionSet = new SelectionSet();
+
+            for (int i = 0; i < layerCount; i++)
+            {
+                MgLayerBase layer = layers.GetItem(i);
+                String layerName = layer.GetName();
+
+                MgResourceIdentifier fsId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+                String className = layer.GetFeatureClassName();
+                String geomName = layer.GetFeatureGeometryName();
+
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                HashMap<String, String> mappings = GetLayerPropertyMappings(resSvc, layer);
+                Set<String> propNames = mappings.keySet();
+
+                for (String name : propNames)
+                {
+                    query.AddFeatureProperty(name);
+                }
+
+                query.AddFeatureProperty(geomName);
+                String filter = selection.GenerateFilter(layer, className);
+                query.SetFilter(filter);
+
+                MgFeatureReader reader = layer.SelectFeatures(query);
+
+                MgClassDefinition clsDef = reader.GetClassDefinition();
+                MgPropertyDefinitionCollection props = clsDef.GetProperties();
+
+                while (reader.ReadNext())
+                {
+                    Feature feat = new Feature(layerName);
+                    ZoomPoint zoom = null;
+
+                    for (int k = 0; k < props.GetCount(); k++)
+                    {
+                        MgPropertyDefinition propDef = props.GetItem(k);
+                        String propName = propDef.GetName();
+                        int propType = reader.GetPropertyType(propName);
+
+                        if (mappings.get(propName) != null || propType == MgPropertyType.Geometry)
+                        {
+                            String value = "";
+                            if (!reader.IsNull(propName))
+                            {
+                                if (propName.equals(geomName))
+                                {
+                                    MgByteReader agf = reader.GetGeometry(propName);
+                                    MgGeometry geom = agfRW.Read(agf);
+                                    MgCoordinate pt = geom.GetCentroid().GetCoordinate();
+
+                                    zoom = new ZoomPoint();
+                                    zoom.X = pt.GetX();
+                                    zoom.Y = pt.GetY();
+
+                                    feat.Zoom = zoom;
+                                }
+                                else
+                                {
+                                    value = GetPropertyValueFromFeatureReader(reader, agfRW, propType, propName);
+                                }
+
+                                if (mappings.get(propName) != null)
+                                {
+                                    FeatureProperty fp = new FeatureProperty();
+                                    fp.Name = mappings.get(propName);
+                                    fp.Value = value;
+
+                                    feat.addProperty(fp);
+                                }
+                            }
+                        }
+                    }
+                    selectionSet.addFeature(feat);
+                }
+                reader.Close();
+            }
+
+            //Now output the selection set
+            response.addHeader("Content-Type", "application/json");
+            response.addHeader("X-JSON", "true");
+
+            response.getWriter().write(GetJson(selectionSet));
+        }
+    }
+    catch (MgException ex)
+    {
+        response.addHeader("Content-Type", "application/json");
+        response.addHeader("X-JSON", "true");
+        response.getWriter().write(JsonifyError(ex));
+    }
+    catch (Exception ex)
+    {
+        response.addHeader("Content-Type", "application/json");
+        response.addHeader("X-JSON", "true");
+        response.getWriter().write(JsonifyError(ex));
+    }
+%>
\ No newline at end of file

Modified: trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp
===================================================================
--- trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/mapviewerjava/mapframe.jsp	2010-03-20 12:54:51 UTC (rev 4676)
@@ -176,6 +176,7 @@
                     vpath + "setselection.jsp",
                     showSlider != 0? "true": "false",
                     locale,
+                    vpath + "getselectedfeatures.jsp",
                     scaleCreationCode,
                     vpath + "ajaxviewerabout.jsp",
                     vpath + "legendctrl.jsp",

Copied: trunk/MgDev/Web/src/mapviewernet/getselectedfeatures.aspx (from rev 4675, sandbox/rfc71/mapviewernet/getselectedfeatures.aspx)
===================================================================
--- trunk/MgDev/Web/src/mapviewernet/getselectedfeatures.aspx	                        (rev 0)
+++ trunk/MgDev/Web/src/mapviewernet/getselectedfeatures.aspx	2010-03-20 12:54:51 UTC (rev 4676)
@@ -0,0 +1,387 @@
+<%@ Page Language="C#" %>
+<%@ Import Namespace="System" %>
+<%@ Import Namespace="System.IO" %>
+<%@ Import Namespace="System.Collections.Generic" %>
+<%@ Import Namespace="System.Web" %>
+<%@ Import Namespace="System.Xml" %>
+<%@ Import Namespace="System.Globalization" %>
+<%@ Import Namespace="OSGeo.MapGuide" %>
+<!-- #include File="common.aspx" -->
+
+<script runat="server">
+    
+    class SelectionSet
+    {
+        private Dictionary<string, List<Feature>> _layers;
+
+        public SelectionSet()
+        {
+            _layers = new Dictionary<String, List<Feature>>();
+        }
+
+        public void AddFeature(Feature feat)
+        {
+            if (!_layers.ContainsKey(feat.LayerName))
+                _layers[feat.LayerName] = new List<Feature>();
+
+            _layers[feat.LayerName].Add(feat);
+        }
+
+        public String[] GetLayers()
+        {
+            return new List<String>(_layers.Keys).ToArray();
+        }
+
+        public Feature[] GetFeatures(String layerName)
+        {
+            if (_layers.ContainsKey(layerName))
+                return _layers[layerName].ToArray();
+
+            return null;
+        }
+    }
+
+    class ZoomPoint
+    {
+        public double X;
+        public double Y;
+    }
+
+    class FeatureProperty
+    {
+        public String Name;
+        public String Value;
+    }
+
+    class Feature
+    {
+        public String LayerName;
+        public ZoomPoint Zoom;
+
+        private Dictionary<string, FeatureProperty> _properties;
+
+        public Feature(string layerName)
+        {
+            this.LayerName = layerName;
+            _properties = new Dictionary<string, FeatureProperty>();
+        }
+
+        public void AddProperty(FeatureProperty prop)
+        {
+            _properties[prop.Name] = prop;
+        }
+
+        public FeatureProperty[] GetProperties()
+        {
+            return new List<FeatureProperty>(_properties.Values).ToArray();
+        }
+    }
+    
+    String mapName;
+    String sessionId;
+    String locale;
+    CultureInfo culture;
+
+    static NameValueCollection GetLayerPropertyMappings(MgResourceService resSvc, MgLayerBase layer)
+    {
+        NameValueCollection mappings = new NameValueCollection();
+        MgByteReader content = resSvc.GetResourceContent(layer.GetLayerDefinition());
+        XmlDocument doc = new XmlDocument();
+        doc.LoadXml(content.ToString());
+        XmlNodeList propNodes = doc.SelectNodes("//LayerDefinition/VectorLayerDefinition/PropertyMapping");
+        foreach (XmlNode propNode in propNodes)
+        {
+            String name = propNode["Name"].InnerText;
+            String value = propNode["Value"].InnerText;
+
+            mappings[name] = value;
+        }
+        return mappings;
+    }
+    
+    String GetPropertyValueFromFeatureReader(MgFeatureReader reader, MgAgfReaderWriter agfRw, int propType, String propName)
+    {
+        String value = "";
+        switch(propType)
+        {
+            case MgPropertyType.Boolean:
+                value = String.Format(culture, "{0}", reader.GetBoolean(propName));
+                break;
+            case MgPropertyType.Byte:
+                value = String.Format(culture, "{0:d}", reader.GetByte(propName));
+                break; 
+            case MgPropertyType.DateTime:
+                value = GetDateTimeString(reader.GetDateTime(propName)); // yyyy-mm-dd is enforced regardless of locale
+                break;
+            case MgPropertyType.Single:
+                value = String.Format(culture, "{0:f}", reader.GetSingle(propName));
+                break;
+            case MgPropertyType.Double:
+                value = String.Format(culture, "{0:f}", reader.GetDouble(propName));
+                break;
+            case MgPropertyType.Int16:
+                value = String.Format(culture, "{0:d}", reader.GetInt16(propName));
+                break;
+            case MgPropertyType.Int32:
+                value = String.Format(culture, "{0:d}", reader.GetInt32(propName));
+                break;
+            case MgPropertyType.Int64:
+                value = String.Format(culture, "{0:d}", reader.GetInt64(propName));
+                break;
+            case MgPropertyType.String:
+                value = JsonEscape(reader.GetString(propName)); //String content is arbitrary
+                break;
+            default: //NOT PRESENTABLE IN PROPERTY GRID
+                value = "";
+                break;
+        }
+        return value;   
+    }
+
+    static String GetDateTimeString(MgDateTime value)
+    {
+        return String.Format("{0}-{1}-{2}", value.Year, value.Month, value.Day);
+    }
+    
+    void GetParameters(NameValueCollection param)
+    {
+        mapName = param["MAPNAME"];
+        sessionId = param["SESSION"];
+        locale = param["LOCALE"];
+    }
+
+    void GetRequestParameters()
+    {
+        if (Request.RequestType == "POST")
+            GetParameters(Request.Form);
+        else
+            GetParameters(Request.QueryString);
+    }
+    
+    String JsonEscape(String str)
+    {
+        return EscapeForHtml(str).Replace("\\", "\\\\");
+    }
+    
+    String JsonifyError(Exception ex)
+    {
+        return "{\"Error\":{\"Message\":\"" + JsonEscape(ex.Message) + "\",\"StackTrace\":\"" + JsonEscape(ex.StackTrace) + "\"}}";
+    }
+
+    static String GetJson(SelectionSet set)
+    {
+        /*
+        A sample of the JSON output this method will produce:
+        
+        
+        {
+            "Layer1" : [ 
+                { 
+                    'values' { "name" : "name1" , "value" : "value1" }, 
+                    'zoom' : { x: num1, y: num2 } 
+                } , 
+                ..,
+                ..,
+                ..,
+            ],
+            "Layer2" : [ 
+                { 
+                    'values' { "name" : "name2" , "value" : "value2" }, 
+                    'zoom' : { x: num1, y: num2 } 
+                } , 
+                ..,
+                ..,
+                ..,
+            ]
+        }
+        */
+        
+        if (set == null)
+            return "";
+        
+        StringBuilder sb = new StringBuilder();
+        //Begin selection set
+        sb.Append("{");
+        String[] layers = set.GetLayers();
+        for (int i = 0; i < layers.Length; i++)
+        {
+            //Begin layer
+            sb.Append("\"" + layers[i] + "\" : [");
+            Feature[] features = set.GetFeatures(layers[i]);
+            for (int j = 0; j < features.Length; j++)
+            {
+                Feature feat = features[j];
+                //begin feature
+                //begin feature properties
+                sb.Append("{\"values\" : [");
+                FeatureProperty[] properties = feat.GetProperties();
+                for(int k = 0; k < properties.Length; k++)
+                {
+                    FeatureProperty fp = properties[k];
+                    sb.Append("{\"name\" : \"" + fp.Name + "\", \"value\" : \"" + fp.Value + "\" }");
+                    if (k != properties.Length - 1)
+                        sb.Append(",");
+                }
+                //end feature properties
+                //begin zoom
+                sb.Append("], \"zoom\" : ");
+                if (feat.Zoom == null)
+                    sb.Append("null");
+                else
+                    sb.Append("{\"x\" : " + feat.Zoom.X + ", \"y\" : " + feat.Zoom.Y + "}");
+                //end zoom
+                //end feature
+                sb.Append("}");
+                if (j != features.Length - 1)
+                    sb.Append(",");
+            }
+            //End Layer
+            sb.Append("]");
+            if (i != layers.Length - 1)
+                sb.Append(",");
+        }
+        //End selection set
+        sb.Append("}");
+        return sb.ToString();
+    }
+    
+</script>
+<% 
+
+    mapName = "";
+    sessionId = "";
+    locale = "";
+
+    GetRequestParameters();
+    
+    if (String.IsNullOrEmpty(locale))
+        locale = GetDefaultLocale();
+        
+    culture = CultureInfo.GetCultureInfo(locale);
+    
+    //HACK: The default locale (en) resolves to a neutral culture, .net forbids the use of 
+    //neutral cultures for formatting purposes, so default to InvariantCulture if the resolved
+    //culture is not neutral.
+    if (culture.IsNeutralCulture)
+        culture = CultureInfo.InvariantCulture; //We need a non-neutral culture
+
+    try
+    {
+        MgUserInformation cred = new MgUserInformation(sessionId);
+        cred.SetClientIp(GetClientIp(Request));
+        cred.SetClientAgent(GetClientAgent());
+
+        MgSiteConnection site = new MgSiteConnection();
+        site.Open(cred);
+
+        MgResourceService resSvc = (MgResourceService)site.CreateService(MgServiceType.ResourceService);
+        
+        MgMap map = new MgMap(site);
+        map.Open(mapName);
+
+        MgSelection selection = new MgSelection(map);
+        selection.Open(resSvc, mapName);
+
+        MgReadOnlyLayerCollection layers = selection.GetLayers();
+        if (layers != null && layers.Count > 0)
+        {
+            int layerCount = layers.Count;
+            MgAgfReaderWriter agfRW = new MgAgfReaderWriter();
+            SelectionSet selectionSet = new SelectionSet();
+
+            for (int i = 0; i < layerCount; i++)
+            {
+                MgLayerBase layer = layers[i];
+                String layerName = layer.Name;
+
+                MgResourceIdentifier fsId = new MgResourceIdentifier(layer.GetFeatureSourceId());
+                String className = layer.GetFeatureClassName();
+                String geomName = layer.GetFeatureGeometryName();
+
+                MgFeatureQueryOptions query = new MgFeatureQueryOptions();
+                NameValueCollection mappings = GetLayerPropertyMappings(resSvc, layer);
+
+                foreach (String key in mappings.Keys)
+                {
+                    query.AddFeatureProperty(key);
+                }
+
+                query.AddFeatureProperty(geomName);
+                String filter = selection.GenerateFilter(layer, className);
+                query.SetFilter(filter);
+
+                MgFeatureReader reader = layer.SelectFeatures(query);
+
+                MgClassDefinition clsDef = reader.GetClassDefinition();
+                MgPropertyDefinitionCollection props = clsDef.GetProperties();
+
+                while (reader.ReadNext())
+                {
+                    Feature feat = new Feature(layerName);
+                    ZoomPoint zoom = null;
+
+                    for (int k = 0; k < props.Count; k++)
+                    {
+                        MgPropertyDefinition propDef = props[k];
+                        String propName = propDef.Name;
+                        int propType = reader.GetPropertyType(propName);
+
+                        if (mappings[propName] != null || propType == MgPropertyType.Geometry)
+                        {
+                            String value = "";
+                            if (!reader.IsNull(propName))
+                            {
+                                if (propName == geomName)
+                                {
+                                    MgByteReader agf = reader.GetGeometry(propName);
+                                    MgGeometry geom = agfRW.Read(agf);
+                                    MgCoordinate pt = geom.Centroid.Coordinate;
+
+                                    zoom = new ZoomPoint();
+                                    zoom.X = pt.X;
+                                    zoom.Y = pt.Y;
+
+                                    feat.Zoom = zoom;
+                                }
+                                else
+                                {
+                                    value = GetPropertyValueFromFeatureReader(reader, agfRW, propType, propName);
+                                }
+
+                                if (mappings[propName] != null)
+                                {
+                                    FeatureProperty fp = new FeatureProperty();
+                                    fp.Name = mappings[propName];
+                                    fp.Value = value;
+
+                                    feat.AddProperty(fp);
+                                }
+                            }
+                        }
+                    }
+                    selectionSet.AddFeature(feat);
+                }
+                reader.Close();
+            }
+
+            //Now output the selection set
+            Response.AddHeader("Content-Type", "application/json");
+            Response.AddHeader("X-JSON", "true");
+
+            Response.Write(GetJson(selectionSet));
+        }
+    }
+    catch (MgException ex)
+    {
+        Response.AddHeader("Content-Type", "application/json");
+        Response.AddHeader("X-JSON", "true");
+        Response.Write(JsonifyError(ex));
+    }
+    catch (Exception ex)
+    { 
+        Response.AddHeader("Content-Type", "application/json");
+        Response.AddHeader("X-JSON", "true");
+        Response.Write(JsonifyError(ex));
+    }
+    
+%>
\ No newline at end of file

Modified: trunk/MgDev/Web/src/mapviewernet/mapframe.aspx
===================================================================
--- trunk/MgDev/Web/src/mapviewernet/mapframe.aspx	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/mapviewernet/mapframe.aspx	2010-03-20 12:54:51 UTC (rev 4676)
@@ -178,6 +178,7 @@
                         vpath + "setselection.aspx",
                         showSlider != 0? "true": "false",
                         locale,
+                        vpath + "getselectedfeatures.aspx",
                         scaleCreationCode,
                         vpath + "ajaxviewerabout.aspx",
                         vpath + "legendctrl.aspx",

Copied: trunk/MgDev/Web/src/mapviewerphp/getselectedfeatures.php (from rev 4675, sandbox/rfc71/mapviewerphp/getselectedfeatures.php)
===================================================================
--- trunk/MgDev/Web/src/mapviewerphp/getselectedfeatures.php	                        (rev 0)
+++ trunk/MgDev/Web/src/mapviewerphp/getselectedfeatures.php	2010-03-20 12:54:51 UTC (rev 4676)
@@ -0,0 +1,485 @@
+<?php
+
+/*
+
+TODO:
+
+- Use the property mapping. This will have to be old-fashioned parsing the <PropertyMapping> elements 
+of the layer definition. I really wanted to use MgSelection::GetSelectedFeatures(layer, class, true) but realised
+that unless the geometry is mapped, you're not going to see it in the Feature Reader (ie. No zoom point). Right now 
+it is returning all properties.
+
+- I know of a few features in the Sheboygan Dataset that trip up the JSON response. Need to find out of addslashes() fixes this.
+
+- General cleanup of the code
+
+
+*/
+
+//require_once('FirePHPCore/fb.php');
+
+//
+// Used to model the JSON response.
+//
+class SelectionSet
+{
+    private $layers;
+    
+    public function __construct()
+    {
+        $this->layers = array();
+    }
+    
+    public function AddFeature($feat)
+    {
+        $layerName = $feat->layerName;
+        if(!array_key_exists($layerName, $this->layers))
+            $this->layers[$layerName] = array();
+            
+        array_push($this->layers[$layerName], $feat);
+    }
+    
+    public function GetLayers()
+    {
+        return array_keys($this->layers);
+    }
+    
+    public function GetFeatures($layerName)
+    {
+        if(array_key_exists($layerName, $this->layers))
+            return $this->layers[$layerName];
+        
+        return null;
+    }
+}
+
+class ZoomPoint
+{
+    public $x;
+    public $y;
+}
+
+//
+// Represents a selected feature property
+//
+class FeatureProperty
+{
+    public $name;
+    public $value;
+}
+
+//
+// Represents a selected feature
+//
+class Feature
+{
+    public $layerName;
+    public $zoom;
+    
+    private $properties;
+    
+    public function __construct($layerName)
+    {
+        $this->layerName = $layerName;
+        $this->properties = array();
+    }
+    
+    public function AddProperty($prop)
+    {
+        $this->properties[$prop->name] = $prop;
+    }
+    
+    public function GetProperties()
+    {
+        return $this->properties;
+    }
+}
+
+	include 'common.php';
+    include 'constants.php';
+
+    $mapName = "";
+    $sessionId = "";
+    $locale = "";
+
+    GetRequestParameters();
+    
+    if (null == $locale || strlen($locale) == 0)
+        $locale = GetDefaultLocale();
+        
+    setlocale(LC_ALL, $locale);
+   
+	try
+	{
+		InitializeWebTier();
+		
+		$cred = new MgUserInformation($sessionId);
+        $cred->SetClientIp(GetClientIp());
+        $cred->SetClientAgent(GetClientAgent());
+
+        //connect to the site and get an instance of the resource and feature service
+        //
+        $site = new MgSiteConnection();
+        $site->Open($cred);
+        $resourceSrvc = $site->CreateService(MgServiceType::ResourceService);
+
+        //load the map runtime state
+        //
+        $map = new MgMap($site);
+        $map->Open($mapName);
+		
+		// Create the selection set
+        $selection = new MgSelection($map);
+        $selection->Open($resourceSrvc, $mapName);
+		
+		$layers = $selection->GetLayers();
+        if($layers != null)
+        {
+            $nLayers = $layers->GetCount();
+            $agfRW = new MgAgfReaderWriter();
+            
+            $selectionSet = new SelectionSet();
+            
+            for ($i = 0; $i < $nLayers; $i++) {
+                $lyr = $layers->GetItem($i);
+                $layerName = $lyr->GetName();
+                
+                //FB::log("Layer Name: " . $lyr->GetName());
+                
+                $featResId = new MgResourceIdentifier($lyr->GetFeatureSourceId());
+                $class = $lyr->GetFeatureClassName();
+                
+                $queryOptions = new MgFeatureQueryOptions();
+                
+                $mappings = GetLayerPropertyMappings($resourceSrvc, $lyr);
+                //FB::log("Property Mappings for Layer: $layerName");
+                foreach($mappings as $name => $value) {
+                    $queryOptions->AddFeatureProperty($name);
+                    //FB::log("$name => $value");
+                }
+                $geomName = $lyr->GetFeatureGeometryName();
+                $queryOptions->AddFeatureProperty($geomName);
+                
+                $filter = $selection->GenerateFilter($lyr, $class);
+                $queryOptions->SetFilter($filter);
+                $fr = $lyr->SelectFeatures($queryOptions);
+                
+                $clsDef = $fr->GetClassDefinition();
+                $props = $clsDef->GetProperties();
+                
+                //FB::log("Geometry: $geomName");
+                
+                while($fr->ReadNext())
+                {
+                    $feat = new Feature($layerName);
+                    $zoom = null;
+                    
+                    for ($k = 0; $k < $props->GetCount(); $k++)
+                    {
+                        $prop = $props->GetItem($k);
+                        $propName = $prop->GetName();
+                        $propType = $fr->GetPropertyType($propName);
+                        
+                        //We only care about mapped properties or geometry properties
+                        if (array_key_exists($propName, $mappings) || $propType == MgPropertyType::Geometry)
+                        {
+                            $value = "";
+                            if (!$fr->IsNull($propName))
+                            {
+                                if(strcmp($propName,$geomName) == 0)
+                                {
+                                    //We want the centroid so we have a zoom-to point
+                                    $agf = $fr->GetGeometry($propName);
+                                    $geom = $agfRW->Read($agf);
+                                    $pt = $geom->GetCentroid()->GetCoordinate();
+                                    
+                                    $zoom = new ZoomPoint();
+                                    $zoom->x = $pt->GetX();
+                                    $zoom->y = $pt->GetY();
+                                    
+                                    $feat->zoom = $zoom;
+                                    //FB::log("zoom: (".$zoom->x.",".$zoom->y.")");
+                                }
+                                else
+                                {
+                                    $value = GetPropertyValueFromFeatureReader($fr, $agfRW, $propType, $propName);
+                                }
+                            }
+                        
+                            if (array_key_exists($propName, $mappings))
+                            {
+                                $fp = new FeatureProperty();
+                                $fp->name = $mappings[$propName];
+                                $fp->value = $value;
+                                
+                                $feat->AddProperty($fp);
+                            }
+                        }
+                    }
+                    
+                    $c = count($feat->GetProperties());
+                    //FB::log("Selected feature processed ($c)");
+                    
+                    $selectionSet->AddFeature($feat);
+                }
+                $fr->Close();
+            }
+            
+            //Now output the selection set
+            
+            header("Content-Type: application/json");
+            header("X-JSON: true");
+            echo GetJson($selectionSet);
+        }
+    }
+    catch(Exception $e)
+    {
+        header("Content-Type: application/json");
+        header("X-JSON: true");
+        echo JsonifyError($e->getMessage(), $e->getTraceAsString());
+    }
+	catch(MgException $e)
+    {
+        header("Content-Type: application/json");
+        header("X-JSON: true");
+        echo JsonifyError($e->GetDetails(), $e->GetStackTrace());
+    }
+
+function GetJson($selectionSet)
+{
+    if($selectionSet == null)
+        return "";
+        
+    //FB::log("Processing JSON response");
+    /*
+	A sample of the JSON output this method will produce:
+	
+	
+	{
+		"Layer1" : [ 
+			{ 
+				'values' { "name" : "name1" , "value" : "value1" }, 
+				'zoom' : { x: num1, y: num2 } 
+			} , 
+			..,
+			..,
+			..,
+		],
+		"Layer2" : [ 
+			{ 
+				'values' { "name" : "name2" , "value" : "value2" }, 
+				'zoom' : { x: num1, y: num2 } 
+			} , 
+			..,
+			..,
+			..,
+		]
+	}
+	*/
+    
+    $layers = $selectionSet->GetLayers();
+    $totalLayers = array(); //The data portion of the JSON response
+    
+    //FB::log("Layers in selection set: ".count($layers));
+    
+    for ($i = 0; $i < count($layers); $i++)
+    {   
+        $layerName = $layers[$i];
+		
+        $features = $selectionSet->GetFeatures($layerName);
+        
+        //FB::log("Features: ".$features);
+        
+        if($features != null)
+        {
+            //FB::log("Processing layer: $layerName");
+        
+            $totalFeaturesOnLayer = array();
+            
+            if (count($features) > 0)
+            {
+                for ($j = 0; $j < count($features); $j++)
+                {
+                    $feat = $features[$j];
+                    $featureProperties = array();
+                    
+                    $fps = $feat->GetProperties();
+                    foreach($fps as $fp)
+                    {
+                        $name = $fp->name;
+                        $value = $fp->value;
+                        //Add JSONified feature property
+                        array_push($featureProperties, "{\"name\" : \"$name\", \"value\" : \"$value\" }");
+                    }
+                    //Add JSONified feature
+                    if($feat->zoom != null)
+                        array_push($totalFeaturesOnLayer, "{\"values\" : [".join(",", $featureProperties)."], \"zoom\" : { \"x\": ".$feat->zoom->x.", \"y\": ".$feat->zoom->y." } }");
+                    else
+                        array_push($totalFeaturesOnLayer, "{\"values\" : [".join(",", $featureProperties)."], \"zoom\" : null }");
+                        
+                    //FB::log("Feature processed on layer: $layerName");
+                }
+            }
+            
+            array_push($totalLayers, "\"$layerName\" : [" . join(", ", $totalFeaturesOnLayer) . "]");
+            //FB::log("Selected features on layer added to final JSON response");
+        }
+    }
+    
+    //FB::log("Selection layer count: ".count($totalLayers));
+    
+    $result = "{" . join(",",$totalLayers) . "}";
+    //return json_encode($result);
+    return $result;
+}
+
+function GetPropertyValueFromFeatureReader($fr, $agfRW, $propType, $propName)
+{
+    $val = "";
+    $tStr = "";
+    switch($propType)
+    {
+        case MgPropertyType::Null:
+            $tStr = "Null";
+            $val = "";
+            break;
+        case MgPropertyType::Boolean:
+            $tStr = "Boolean";
+            $val = sprintf("%s", $fr->GetBoolean($propName));
+            break;
+        case MgPropertyType::Byte:
+            $tStr = "Byte";
+            $val = sprintf("%d", $fr->GetByte($propName));
+            break;
+        case MgPropertyType::DateTime:
+            $tStr = "DateTime";
+            $val = printDateTime($fr->GetDateTime($propName)); // yyyy-mm-dd is enforced regardless of locale
+            break;
+        case MgPropertyType::Single:
+            $tStr = "Single";
+            $val = sprintf("%f", $fr->GetSingle($propName));
+            break;
+        case MgPropertyType::Double:
+            $tStr = "Double";
+            $val = sprintf("%f", $fr->GetDouble($propName));
+            break;
+        case MgPropertyType::Int16:
+            $tStr = "Int16";
+            $val = sprintf("%d", $fr->GetInt16($propName));
+            break;
+        case MgPropertyType::Int32:
+            $tStr = "Int32";
+            $val = sprintf("%d", $fr->GetInt32($propName));
+            break;
+        case MgPropertyType::Int64:
+            $tStr = "Int64";
+            $val = sprintf("%d", $fr->GetInt64($propName));
+            break;
+        case MgPropertyType::String:
+            $tStr = "String";
+            $val = JsonEscape($fr->GetString($propName)); //String content is arbitrary
+            break;
+        case MgPropertyType::Blob: //NOT PRESENTABLE IN PROPERTY GRID
+            $tStr = "BLOB";
+            break;
+        case MgPropertyType::Clob: //NOT PRESENTABLE IN PROPERTY GRID
+            $tStr = "CLOB";
+            break;
+        case MgPropertyType::Feature: //NOT PRESENTABLE IN PROPERTY GRID
+            $tStr = "Feature";
+            break;
+        case MgPropertyType::Geometry: //NOT PRESENTABLE IN PROPERTY GRID
+            $tStr = "Geometry";
+            break;
+        case MgPropertyType::Raster: //NOT PRESENTABLE IN PROPERTY GRID
+            $tStr = "Raster";
+            break;
+    }
+    //FB::log("$propName ($tStr) = $val");
+    return $val;
+}
+
+/* retrieve the property mappings for a layer */
+function GetLayerPropertyMappings($resourceService, $layer) {
+    $mappings = array();
+    $byteReader = $resourceService->GetResourceContent($layer->GetLayerDefinition());
+    $xmldoc = DOMDocument::loadXML(ByteReaderToString($byteReader));
+    $mappingNodeList = $xmldoc->getElementsByTagName('PropertyMapping');
+    for ($i=0; $i<$mappingNodeList->length; $i++) {
+        $mapping = $mappingNodeList->item($i);
+        $nameElt = $mapping->getElementsByTagName('Name');
+        $name = $nameElt->item(0)->nodeValue;
+        $valueElt = $mapping->getElementsByTagName('Value');
+        $value = $valueElt->item(0)->nodeValue;
+        $mappings[$name] = $value;
+    }
+    return $mappings;
+}
+
+function ByteReaderToString($byteReader)
+{
+    return $byteReader->ToString();
+}
+
+function printDateTime($mgDateTime)
+{
+   $dayToday = $mgDateTime->GetDay();
+   $month = $mgDateTime->GetMonth();
+   $year = $mgDateTime->GetYear();
+   return $dayToday.".".$month.".".$year;
+}
+
+function GetParameters($params)
+{
+    global $mapName, $sessionId, $locale;
+
+    $mapName = $params['MAPNAME'];
+    $sessionId = $params['SESSION'];
+    $locale = $params['LOCALE'];
+}
+
+function JsonEscape($str)
+{
+    return str_replace("\\", "\\\\", EscapeForHtml($str));
+}
+
+function JsonifyError($msg, $st)
+{
+    /*
+    {
+        "Error" : {
+            "Message" : <exception-message>,
+            "StackTrace" : <exception-stack-trace>
+        }
+    }
+    */
+    $emsg = JsonEscape($msg);
+    $est = JsonEscape($st);
+    $json = "{\"Error\":{\"Message\":\"$emsg\",\"StackTrace\":\"$est\"}}";
+    return $json;
+}
+
+function UnescapeMagicQuotes($str)
+{
+    if(ini_get("magic_quotes_sybase") == "1")
+        return str_replace("''", "'", $str);
+    else if(get_magic_quotes_gpc() == "1")
+    {
+        //Unescape double quotes
+        $str = str_replace('\\"', '"', $str);
+
+        //remove additional backslash
+        return str_replace("\\", "", $str);
+    }
+    return $str;
+}
+
+function GetRequestParameters()
+{
+    if($_SERVER['REQUEST_METHOD'] == "POST")
+        GetParameters($_POST);
+    else
+        GetParameters($_GET);
+}
+
+?>
\ No newline at end of file

Modified: trunk/MgDev/Web/src/mapviewerphp/mapframe.php
===================================================================
--- trunk/MgDev/Web/src/mapviewerphp/mapframe.php	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/mapviewerphp/mapframe.php	2010-03-20 12:54:51 UTC (rev 4676)
@@ -145,6 +145,7 @@
                     $vpath . "setselection.php",
                     $showSlider? "true": "false",
                     $locale,
+                    $vpath . "getselectedfeatures.php",
                     $scaleCreationCode,
                     $vpath . "ajaxviewerabout.php",
                     $vpath . "legendctrl.php",

Modified: trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ
===================================================================
--- trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/viewerfiles/ajaxmappane.templ	2010-03-20 12:54:51 UTC (rev 4676)
@@ -334,6 +334,7 @@
 var openHlinkText = macOS ? "__#OPENHYPERLINKMAC#__" : "__#OPENHYPERLINK#__";
 var selectionColor = '0x0000FFFF'; // Blue
 var lastLegendScaleUpdate = curScale;
+var featureRequestUrl = '%s';
 %s
 
 
@@ -551,6 +552,9 @@
     cancelTgt = document.getElementById("KeyTarget");
 
     initTimer = setInterval(delayedInit, 200);
+    
+    var btn = document.getElementById("imgZoomFeature");
+    btn.title = "__#ZOOMSELECTEDFEATUREDESC#__";
 }
 
 function delayedInit()
@@ -2877,26 +2881,17 @@
     }
     if(which & 2)
     {
-        properties = new Array();
-        if(selection.count == 1)
+        if (IsPropertyCtrlVisible())
         {
-            try
+            if (selection.count > 0)
             {
-                var props = xmlIn.getElementsByTagName("Property");
-                if(props != null)
-                {
-                    for(var i=0; i < props.length; i++)
-                    {
-                        var name = props[i].getAttribute("name");
-                        var value = props[i].getAttribute("value");
-                        properties.push(new Property(name, value));
-                    }
-                }
+                RequestSelectedFeatureProperties();
             }
-            catch(e) {}
+            else
+            {
+                ResetPropertyPane();
+            }
         }
-        properties.sort(CompareProperties);
-        GetPropertyCtrl().SetProperties(selection.count, properties);
     }
     if(which & 4)
     {
@@ -3824,6 +3819,202 @@
     }
 }
 
+//--- Property Pane Toolbar ---//
+var selFeatureZoom = 200;
+var hovered = "";
+var active = "";
+var selFeatures = {};
+
+function RequestSelectedFeatureProperties()
+{
+    var mapname = GetMapName();
+    var session = GetSessionId();
+    var selRequest = CreateRequestHandler();
+    var reqParams = "MAPNAME="+mapname+"&SESSION="+session+"&LOCALE="+locale+"&SEQ="+Math.random();
+    selRequest.open("POST", featureRequestUrl, false);
+    selRequest.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+    selRequest.send(reqParams);
+    
+    var respText = selRequest.responseText;
+    if (respText && respText.length > 0)
+    {
+        var resp = eval('(' + respText + ')');
+        //If an error occurred server-side, it is written as the error property of the JSON response
+        if (resp.Error)
+            RequestFailed(resp.Error.Message + "\n\n__#ERRORSTACKTRACE#__:\n\n" + resp.Error.StackTrace);
+        else
+            ProcessSelectedFeatureSet(resp);
+    }
+    else
+        RequestFailed("__#NOFEATSELECTRESPONSE#__");
+}
+
+function ProcessSelectedFeatureSet(resp)
+{
+    selFeatures = {};
+    if (!resp)
+        return;
+        
+    var selLayers = document.getElementById("selLayers");
+    selLayers.length = 0;
+    GetPropertyCtrl().Clear();
+    
+    //Construct layer list
+    for(var layerName in resp)
+    {
+        var opt = new Option();
+        opt.text = layerName;
+        opt.value = layerName;
+        
+        if(msie)
+            selLayers.add(opt);
+        else
+            selLayers.add(opt, null);
+ 
+        //Associates the selected features on layer
+        selFeatures[layerName] = resp[layerName];
+    }
+    
+    if (selLayers.length > 0)
+    {
+        SetPropertyPaneToolbarVisibility(true);
+        //Set to first result on the layer list
+        selLayers.selectedIndex = 0;
+        OnSelectedFeatureLayerChanged();
+    }
+}
+
+function IsPropertyCtrlVisible()
+{
+    return GetPropertyCtrl().width > 0;
+}
+
+function ResetPropertyPane()
+{
+    var selLayers = document.getElementById("selLayers");
+    selLayers.length = 0;
+    var selFeature = document.getElementById("selFeature");
+    selFeature.length = 0;
+    SetPropertyPaneToolbarVisibility(false);
+    GetPropertyCtrl().SetProperties(0);
+}
+
+function OnSelectedFeatureLayerChanged()
+{
+    var sLayer = document.getElementById("selLayers");
+    var layerIdx = sLayer.selectedIndex;
+    var layerName = sLayer.options[layerIdx].value;
+    var count = selFeatures[layerName].length;
+    
+    //Clear feature dropdown and repopulate by numerical index (offset by 1)
+    var sFeature = document.getElementById("selFeature");
+    sFeature.length = 0;
+    
+    for (var i = 1; i <= count; i++)
+    {
+        //This is just for display purposes. The selected index
+        //gives use the matching feature
+        var opt = new Option();
+        opt.text = i;
+        opt.value = 1;
+        
+        if (msie)
+            sFeature.add(opt);
+        else
+            sFeature.add(opt, null);    
+    }
+    
+    if (count > 0)
+    {
+        sFeature.selectedIndex = 0;
+        OnSelectedFeatureChanged();
+    }
+}
+
+function OnSelectedFeatureChanged()
+{
+    var sLayer = document.getElementById("selLayers");
+    var layerIdx = sLayer.selectedIndex;
+    var sFeature = document.getElementById("selFeature");
+    var featureIdx = sFeature.selectedIndex;
+    
+    //Get matching selected feature from array
+    var layerName = sLayer.options[layerIdx].value;
+    var feat = selFeatures[layerName][featureIdx];
+    
+    //Show feature
+    GetPropertyCtrl().SetProperties(1, feat.values);
+}
+
+function GetFeatureZoomLevel()
+{
+    return selFeatureZoom;
+}
+
+function ZoomSelectedFeature()
+{
+    var sLayer = document.getElementById("selLayers");
+    var layerIdx = sLayer.selectedIndex;
+    var sFeature = document.getElementById("selFeature");
+    var featureIdx = sFeature.selectedIndex;
+    
+    //Get matching selected feature from array
+    var layerName = sLayer.options[layerIdx].value;
+    var feat = selFeatures[layerName][featureIdx];
+    
+    //Get the zoom component of the selected feature, and zoom to that view
+    if (feat.zoom)
+        ZoomToView(feat.zoom.x, feat.zoom.y, GetFeatureZoomLevel(), true);
+}
+
+function HoverButton(eltId, description)
+{
+    if (hovered != "")
+        document.getElementById(hovered).style.border = "solid #f0f0f0 1px";
+    
+    document.getElementById(eltId).style.border = "solid #99B5CA 1px";
+    hovered = eltId;
+    parent.SetStatusMsg(description);
+}
+
+function LeaveButton(eltId)
+{
+    if (eltId == active)
+        document.getElementById(eltId).style.border = "solid #99B5CA 1px";
+    else
+        document.getElementById(eltId).style.border = "solid #f0f0f0 1px";
+    hovered = "";
+    parent.SetStatusMsg('');
+}
+
+function SetPropertyPaneToolbarVisibility(visible)
+{
+    var tb = document.getElementById("PropertyPaneToolbar");
+    tb.style.display = visible ? "block" : "none";
+}
+
+function OnResizeToolbar(e)
+{
+    var tb = document.getElementById("PropertyPaneToolbar");
+    if (tb)
+    {
+        width = msie ? document.body.clientWidth : window.innerWidth - 2;
+        height = 32;
+        tb.style.width = width + "px";
+        tb.style.height = height + "px";
+    }
+    return true;
+}
+
+function OnPropertyPaneDropDownClick(e)
+{
+    if(msie)
+        e.cancelBubble = true;
+    else
+        e.stopPropagation();
+    return true;
+}
+
 </script>
 
 </head>
@@ -3854,6 +4045,23 @@
            </table>
          </div>
          <div class="propertyCtrl" id="PropertyCtrlDiv"  style="visibility: hidden;">
+           <div id="PropertyPaneToolbar" class="Toolbar" style="display:none">
+             <table width=100 height=30 border=0 cellpadding=0 cellspacing=0>
+               <tr height=30>
+                 <td align=center valign=center>
+                   <select id="selLayers" onchange="OnSelectedFeatureLayerChanged()" onmousedown="return OnPropertyPaneDropDownClick(event)"></select>
+                 </td>
+                 <td align=center valign=center>
+                   <select id="selFeature" onchange="OnSelectedFeatureChanged()" onmousedown="return OnPropertyPaneDropDownClick(event)"></select>
+                 </td>
+                 <td align=right>
+                   <span class="btn" id="btnZoomSelectedFeature" style="position: absolute; right: 2px;" onmouseover="HoverButton('btnZoomSelectedFeature', '')" onmouseout="LeaveButton('btnZoomSelectedFeature', '')" onclick="ZoomSelectedFeature()">
+                     <img class="btnImg" id="imgZoomFeature" title="" src="../stdicons/icon_zoomselect.gif" width=16 height=16>
+                   </span>
+                 </td>
+               </tr>
+             </table>
+           </div>
            <iframe id="PropertyCtrl" name="PropertyCtrl" src="%s?LOCALE=%s" frameborder="0" width="0">
            </iframe>
          </div>

Modified: trunk/MgDev/Web/src/viewerfiles/propertyctrl.templ
===================================================================
--- trunk/MgDev/Web/src/viewerfiles/propertyctrl.templ	2010-03-20 05:21:01 UTC (rev 4675)
+++ trunk/MgDev/Web/src/viewerfiles/propertyctrl.templ	2010-03-20 12:54:51 UTC (rev 4676)
@@ -60,9 +60,15 @@
     {
         var text;
         if(count == 0)
+        {
             text = "__#PROPERTIESNONE#__";
+            GetMapFrame().SetPropertyPaneToolbarVisibility(false);
+        }
         else
+        {
             text = GetMainFrame().FormatMessage("__#PROPERTIESITEMSEL#__", new Array(count, "unused"));
+            GetMapFrame().SetPropertyPaneToolbarVisibility(true);
+        }
         code = '<table id="Grid" cellspacing=0 cellpadding=0 border=0><tr><td class="Info" align="center">' + text + '</td></tr></table>';
     }
     else
@@ -71,15 +77,26 @@
         for(var i=0; i < properties.length; i++)
             code += '<tr class="GridCell"><td><span style="font-family: __#@font#__; font-size: __#@fontsize#__;">&nbsp;' + properties[i].name + '</span></td><td></td><td><span style="font-family: __#@font#__; font-size: __#@fontsize#__;">' + properties[i].value + '</span></td></tr>';
         code += '</table>';
+        GetMapFrame().SetPropertyPaneToolbarVisibility(true);
     }
 
+    SetContent(code);
+}
+
+// private functions -----------------------------------------------
+//
+function Clear()
+{
+    SetContent("");
+}
+
+function SetContent(html)
+{
     var content = document.getElementById("Content");
-    content.innerHTML = code; //SAFARI
+    content.innerHTML = html; //SAFARI
     OnResizeGrid();
 }
 
-// private functions -----------------------------------------------
-//
 function InitDocument()
 {
     document.onmousedown = OnMouseDown;



More information about the mapguide-commits mailing list