change layer definition runtime

classic Classic list List threaded Threaded
20 messages Options
Reply | Threaded
Open this post in threaded view
|

change layer definition runtime

makoychan
Is there a way to change or update layer defintion on runtime? W/o using the .net api warpper?


I am currently using a fusion template, but i wanted to change the layer defintion the map is using to a different layerdefinition. Is it spossible to do the the fusion script?

i wanted to do it before maps load and refreshing the map

Thank you very much.
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Jackie Ng
You have to manipulate MgMap/MgLayer objects, so you have to use a server-side script. It doesn't have to be .net. It could be in Java or PHP. But it has to be one of the 3 languages which can work with the MapGuide Web API.

Your script needs to take in mapname/sessionid and do the following:

 - Opens the MgMap from the mapname
 - Finds the matching MgLayer in the map's layer collection by its layer name
 - Make a new MgLayer that points to your new layer definition
 - Replace the matching MgLayer with your new MgLayer
   - Insert the new MgLayer to the layer collection at the matching index of the old MgLayer
   - Remove the old MgLayer from the layer collection
 - Save the map state and trigger a map refresh back on the client-side

- Jackie
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Thanks Jackie, 

I think i got the gist, but will this also work with fusion? I am currently using the fusion templates. I was wondering if i could also do this with .net to rebuild the mapdefinition or layer definition.

Thanks for the response, im a bit stuck on this.


On Wed, Sep 7, 2016 at 12:03 AM, Jackie Ng
You have to manipulate MgMap/MgLayer objects, so you have to use a
server-side script. It doesn't have to be .net. It could be in Java or PHP.
But it has to be one of the 3 languages which can work with the MapGuide Web
API.

Your script needs to take in mapname/sessionid and do the following:

- Opens the MgMap from the mapname
- Finds the matching MgLayer in the map's layer collection by its layer
name
- Make a new MgLayer that points to your new layer definition
- Replace the matching MgLayer with your new MgLayer
  - Insert the new MgLayer to the layer collection at the matching index of
the old MgLayer
  - Remove the old MgLayer from the layer collection
- Save the map state and trigger a map refresh back on the client-side

- Jackie



--
View this message in context: http://osgeo-org.1560.x6.nabble.com/change-layer-definition-runtime-tp5284382p5284422.html
Sent from the MapGuide Users mailing list archive at Nabble.com.
_______________________________________________
mapguide-users mailing list
<a shape="rect" ymailto="mailto:mapguide-users@lists.osgeo.org" href="javascript:return">mapguide-users@...
http://lists.osgeo.org/mailman/listinfo/mapguide-users

_______________________________________________
mapguide-users mailing list
[hidden email]
http://lists.osgeo.org/mailman/listinfo/mapguide-users
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
In reply to this post by Jackie Ng
Hi,

I have created layer definition from each maps on Maestro and just 1 MapDefinition, What i am trying to do is the just updated the layerdefinition of the mapdefinition to the specific selected map. I wanted to do it runtime. I cam currtently using fusion, is this possible to do on JS or just .net? And how? i am quite stuck now.

Also another option for me to do is the create mapdefinition on runtime, but still no success on doing this.

Any help will do.

Thanks in advance
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
This post was updated on .
Hi,

I made an example of a class to manipulate the atribute Filter of a layer, you can use as an example to manipulate any atribute of a layer. It´s made in c#.

 public class UtilMap
    {
        private string strSessionMap;
        private string strMapDefinition;
        private MgSiteConnection siteConnection;
        private MgUserInformation userInfo;
        private MgFeatureService featureService;
        private MgResourceService resourceService;
        private MgMap map;
        private string mapName;
        private string strTempLayerSufix;

        /// <summary>
        /// Constructor of class to manipulate the RunTime Mapguide Map
        /// </summary>
        /// Map Session ID
        /// Map Library Definition
        public UtilMap(string pstrSessionMap, string pstrMapDefinition)
        {
            try
            {
                strSessionMap = pstrSessionMap;
                strMapDefinition = pstrMapDefinition;
                strTempLayerSufix = "-" + strSessionMap;

                siteConnection = new MgSiteConnection();
                userInfo = new MgUserInformation(strSessionMap);

                siteConnection.Open(userInfo);
                featureService = (MgFeatureService)siteConnection.CreateService(MgServiceType.FeatureService);
                resourceService = (MgResourceService)siteConnection.CreateService(MgServiceType.ResourceService);

                mapName = strMapDefinition;

                //if mapName is empty, I just want to work with session repository, no map operations
                if (mapName != "")
                {
                    map = new MgMap(siteConnection);
                    map.Open(resourceService, mapName);
                }

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }
       
        /// <summary>
        /// Set a filter to a Layer in session repository
        /// </summary>
        /// Layer Name
        /// Filter condition
        /// <returns>Operation success</returns>
        public bool SetLayerFilter(string strLayerName, string strFilter)
        {
            try
            {
                //
                // Set a filter to a temporary layer created based on an original one.
                //
                MgResourceIdentifier resId, resIdTemp;
                MgLayerBase layer, layerTemp;
                string tempResource;
                string strLayerNameForSession;
                string strXml;

                //Verify if Layer Name is the temporary layer. If It is, correct to original Layer Name.
                if (strLayerName.IndexOf(strTempLayerSufix) > 0)
                {
                    strLayerName = strLayerName.Replace(strTempLayerSufix, "");
                }

                //Use random name to avoid overwrites
                strLayerNameForSession = strLayerName + this.strTempLayerSufix;

                //Test if the original or temporary layers existis
                if (GetLayerByName(map, strLayerName) == null && GetLayerByName(map, strLayerNameForSession) == null)
                    return false;

                //Test if the filter is not null
                if (strFilter == null)
                    strFilter = "";

                //Get the temporary layer
                layer = GetLayerByName(map, strLayerNameForSession);

                //Get the original layer, if temporary later not exist
                if (layer == null)
                    layer = GetLayerByName(map, strLayerName);

                //If the temp resource was not created, read the original xml
                tempResource = "Session:" + strSessionMap + "//" + strLayerNameForSession + "." + MgResourceType.LayerDefinition;
                resIdTemp = new MgResourceIdentifier(tempResource);

                //Read the resource original layer
                resId = layer.GetLayerDefinition();
                strXml = (resourceService.GetResourceContent(resId)).ToString();

                //Manipulate xml, set the Tags Filter

                strXml = Util.SetTagTextContent(strXml, "/LayerDefinition/VectorLayerDefinition/Filter", strFilter, true, "/LayerDefinition/VectorLayerDefinition/FeatureNameType");

                //Write the resource
                System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
                MgByteSource ByteSource = new MgByteSource(encoding.GetBytes(strXml), strXml.Length);
                resourceService.SetResource(resIdTemp, ByteSource.GetReader(), null);

                //Get the temp layer
                layerTemp = GetLayerByName(map, strLayerNameForSession);
                if (layerTemp == null)
                {
                    layerTemp = new MgLayer(resIdTemp, resourceService);
                    layerTemp.SetGroup(layer.GetGroup());
                    layerTemp.SetName(strLayerNameForSession);
                    layerTemp.SetLegendLabel(strLayerName);
                    layerTemp.SetSelectable(true);
                    layerTemp.SetVisible(true);

                    MgLayerCollection layers = map.GetLayers();
                    //Insert at the same position of the original layer
                    layers.Insert(layers.IndexOf(strLayerName), layerTemp);
                }

                layerTemp.ForceRefresh();
                map.Save(resourceService);

                return true;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

        }
       
      }  

********************************************************

objUtilMap = new UtilMap(SessionMapLightining, MapNameLightining);
string strFiltroLayer = "time_lightining >= ToDate('2016-09-08 10:00:00') AND time_lightining < ToDate('2016-09-08 10:05:00')";
objUtilMap.SetLayerFilter("Lightining", strFiltroLayer);
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Thanks Liglio

I will definitely give this  shot. Ill let you know if it works. Thanks thanks  a bunch.
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
In reply to this post by Liglio
Hi Liglio,

Sorry to have disturbed you but, what namespace did you use for Util.SetTagTextContent and where is the method GetLayerByName?

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
This post was updated on .
Put in UtilMap class

        /// <summary>
        /// Get layer object by his name in the Runtime Map
        /// </summary>
        /// Mapguide MapObject
        /// Layer Name
        /// <returns></returns>
        private MgLayerBase GetLayerByName(MgMap map, string layerName)
        {
            try
            {
                MgLayerBase layer = null;
                for (int i = 0; i < map.GetLayers().GetCount(); i++)
                {
                    MgLayerBase nextLayer = map.GetLayers().GetItem(i);
                    if (nextLayer.GetName().ToUpper() == layerName.ToUpper())
                    {
                        layer = nextLayer;
                        break;
                    }
                }
                return layer;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

*********************************************************
using System;
using System.IO;
using System.Xml;
using System.Data;

static public class Util
    {
   static public string SetTagTextContent(string strXml, string strNode, string strContent, bool bolCreateIfInexist = true, string strNodeCreateAfter = null)
        {
            XmlDocument xmlDoc = new XmlDocument();
            XmlNode xmlNode = null;
            XmlNode xmlNewNode;
            XmlNode xmlAfterNode;
            string strRet;
            string strTag;

            xmlDoc.PreserveWhitespace = true;
            xmlDoc.LoadXml(strXml);
            try
            {
                xmlNode = xmlDoc.SelectSingleNode(strNode);
                if (xmlNode == null && bolCreateIfInexist)
                {
                    strTag = strNode.Substring(strNode.LastIndexOf("/") + 1);
                    xmlNewNode = xmlDoc.CreateNode(XmlNodeType.Element, strTag, null);
                    xmlNewNode.InnerText += " " + strContent;
                    xmlNode = xmlDoc.SelectSingleNode(strNode.Replace("/" + strTag, ""));
                    xmlAfterNode = xmlDoc.SelectSingleNode(strNodeCreateAfter);
                    xmlNode.InsertAfter(xmlNewNode, xmlAfterNode);
                }
                else
                {
                    xmlNode.InnerText = strContent;
                }
            }
            catch (System.Xml.XPath.XPathException)
            {
            }

            strRet = xmlDoc.InnerXml;

            return strRet;
        }
       
    }
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Hi Liglio,

Thanks for the quick update, i am getting this error when it reaches  map.open
 
if i keyed in: resourceService and resourceidentifier
"Resource data was not found: RuntimeData"

if i keyed in: resourceService and mapName or mapdefinition

Invalid resource path: Library://Langan Floor Plans

My scenario is i have fusion, the i am calling the function mapwidget.getSessionId(), as soon i get the session id, i have a ajax to call server side method and call

UtilMap up = new UtilMap(sessionid, "Library://Langan Floor Plans/Floor Plan Map.MapDefinition")

but if i call map.create(resourceIdentifier,"anyName") i works. i can even access all layers, but is there any difference between the open and create?
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Solved the error. I should be getting the mapname from the mapdwiget.

Now there is no error. But it looks like i need to refresh  fusion mapwidget for the layers to effect.

Only thing now i think is to refresh the mapwidget for the layers to take effect. But it seems that  layerTemp.ForceRefresh(); wont refresh the widget.
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
You have to refresh the map using javascript.

Put in UtilMap class:
        /// <summary>
        /// Refresh the Map in the Client using JavaScrit
        /// </summary>
        /// Page Object calling this method
        public void RefreshMapClient(Page objPage)
        {
            try
            {
                string strScript = "";

                strScript += "<script type='text/javascript'>" + "\r\n"; //strScript += "debugger;" + "\r\n"; strScript += "var mapWidget;" + "\r\n"; strScript += "var curWindow;" + "\r\n"; strScript += "if (navigator.userAgent.indexOf('Chrome') != -1)" + "\r\n"; strScript += " curWindow = window.top.FrameMapa.contentWindow;" + "\r\n"; strScript += "else" + "\r\n"; strScript += " curWindow = window.top.FrameMapa;" + "\r\n"; strScript += "\r\n"; strScript += "if (curWindow.Fusion)" + "\r\n"; strScript += " mapWidget = curWindow.Fusion.getWidgetById('Map');" + "\r\n"; strScript += " else if(parent.curWindow.Fusion)" + "\r\n"; strScript += " mapWidget = parent.curWindow.Fusion.getWidgetById('Map');" + "\r\n"; strScript += " else if (parent.parent.curWindow.Fusion) " + "\r\n"; strScript += " mapWidget = parent.parent.curWindow.Fusion.getWidgetById('Map');" + "\r\n"; strScript += "\r\n"; strScript += "if (mapWidget.isMapLoaded()) {" + "\r\n"; strScript += " mapWidget.redraw();" + "\r\n"; strScript += "}else {" + "\r\n"; strScript += "alert('O mapa está ocupado, aguarde.');}" + "\r\n"; strScript += "</script>" + "\r\n";

                // Detect if the page has ScriptManager
                if (System.Web.UI.ScriptManager.GetCurrent(objPage) == null)
                    objPage.ClientScript.RegisterStartupScript(objPage.GetType(), "RefreshMapClient", strScript, false);
                else
                    System.Web.UI.ScriptManager.RegisterStartupScript(objPage, objPage.GetType(), "RefreshMapClient", strScript, false);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }


Put in the your page server-side, after setting the filter layer:
objUtilMap.RefreshMapClient(this);

Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Thank Liglio,

It worked well! :)

last question, is there a way to also change featuresourceid , featureclassname? the properties are "read only"

Thanks
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
This post was updated on .
The layer definition is a xml where you can modify all atributes, including  featuresourceid , featureclassname, etc. Debug the code and examine the string xml layer read in the set filter method.
You read this xml, modify and write it back. This can be used to map definition, feature source definition, web layout definition.
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Thanks, found it and made it work.

Also, sorry for asking this here cause i know ive already posted this on a new thread.

Do you happen to know how to refresh the jxpanel? because it seems that when i replaces all the layers via the .net api's, the jxpanels doesnt work anymore with the changed map, the legends and the selections doesnt work anymore.

Thhanks
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
In reply to this post by makoychan
After refreshing, the select button at the toolbar doesnt work anymore, each time i select an objct on the map. It does nothing, any idea? need help been stuck here for almost a week..

Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
I don´t know what is happening in your application. What version of mapguide are you using? You are using Fusion framework ?
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Hi,

Back again, was able to make it work before with MapGuide 2.6.1 32bit  now upgraded to 3.1.0  64bit.. Same code  with changing layer at runtime.. funny thing now, nothing happens, but if select something on the map, it throws an error inside fusion-compressed.js, 'layerName' does not exists.

From the c# code layers.remove(layer) it did work it seems that the layer was really removed on the map.. but the mapwidget itself didnt refresh to the new layer, it still looks the same. did call the command. mapWidget.redraw, mapWidget.reloadMap(). but nothing happens.

Tried almost everything but its not working at all..

Is there something that i missed on the code?
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Anyone tried this with MGOS 3.1 and Fusion 3? apparantly after i updated
everything to this version, none of the code works.



--
Sent from: http://osgeo-org.1560.x6.nabble.com/MapGuide-Users-f4182607.html
_______________________________________________
mapguide-users mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/mapguide-users
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

Liglio
Reply | Threaded
Open this post in threaded view
|

Re: change layer definition runtime

makoychan
Hi,

Have you experience that after doing this update of layer using ajax and
redraw a couple of time. Mapguide server breaks? because i suddenly get
session expired or magguide server is not responding.. Im on the site the
whole time and doing switching of layers to stress test it. But suddenly it
turned pink and got that message reload map and got that error.


Thanks





--
Sent from: http://osgeo-org.1560.x6.nabble.com/MapGuide-Users-f4182607.html
_______________________________________________
mapguide-users mailing list
[hidden email]
https://lists.osgeo.org/mailman/listinfo/mapguide-users