Opened 14 years ago

Closed 7 years ago

#167 closed defect (duplicate)

Legend does not refresh correctly, when using the summary parameter

Reported by: ksgeograf Owned by: cmy
Priority: medium Milestone: 2.6
Component: Server Version: 2.1.0
Severity: major Keywords: legend summary refresh
Cc: External ID: 939559

Description

To reproduce, create a new datasource + layer + map + weblayout. On the map, set the layer "Display in legend" to false.

Then, using the .Net API, modify the current map, and call "SetDisplayInLegend?(true)" on the layer. Then on the client, call GetMapFrame?().Refresh().

The layer never shows in the legend. Zoom (eg. change scale) does not make the layer appear. This happens with both DWF viewer and AJAX viewer. The layer contents appear, and as of 1.2, the tooltips appear, and the "Selectability" works correct.

When modifying the legendctrl.templ, line 16, removing the "&SUMMARY=" string, the AJAX viewer now correctly refreshes the legend, obeying the "SetDisplayInLegend?". However the legend label is not displayed. Setting the legend label using the API, makes the label appear.

I cannot modify the call from the DWF, to test the DWF behavior.

I believe that the server has a defect, when it constructs the legend update summary. There is also a defect, when creating the runtime map, as layers that are not displayed in the legend does not get their label transfered.

Change History (16)

comment:1 Changed 14 years ago by ksgeograf

Ok, I found and fixed the problem.

The summary parameter is used in the viewer to minimize the amount of data that is returned.

In file legend.js, the fields for the summary are defined as:

function LayerSummary(name, objectId, layerRes)
{
    this.name = name;
    this.objectId = objectId;
    this.layerRes = layerRes;
    this.isGroup = false;
    this.type = 1;
}

This needs to be expanded to:

function LayerSummary(name, objectId, layerRes, displayInLegend, expanded, legend, visible)
{
    this.name = name;
    this.objectId = objectId;
    this.layerRes = layerRes;
    this.isGroup = false;
    this.type = 1;
    this.displayInLegend = displayInLegend;
    this.expanded = expanded;
    this.legend = legend;
    this.visible = visible;
}

There may be other fields needed.

In legendui.templ the following function resides:

function HasTreeChanged(current, lightTree)
{
    if(current.length != lightTree.length)
        return true;

    for(var i = 0; i < current.length; i++)
    {
        var node1 = current[i], node2 = lightTree[i];
        if(node1.type != node2.type || node1.objectId != node2.objectId)
            return true;
        if(node1.type == 1)
        {
            if(node1.layerRes != node2.layerRes)
                return true;
        }
        else if(node1.type == 0)
        {
            if(node1.children != null)
            {
                if(node2.children == null)
                    return true;
                if(HasTreeChanged(node1.children, node2.children))
                    return true;
            }
        }
    }
    return false;
}

This function needs to check for the new properties as well:

function HasTreeChanged(current, lightTree)
{
    if(current.length != lightTree.length)
        return true;

    for(var i = 0; i < current.length; i++)
    {
        var node1 = current[i], node2 = lightTree[i];
        if(node1.type != node2.type || node1.objectId != node2.objectId)
            return true;
        if(node1.type == 1)
        {
            if(node1.layerRes != node2.layerRes)
                return true;
	    if(node1.legend != node2.legend)
		return true; 
	    if(node1.expanded != node2.expanded)
		return true;
	    if(node1.displayInLegend != node2.displayInLegend)
		return true;
	    if(node1.visible != node2.visible)
		return true;
        }
        else if(node1.type == 0)
        {
            if(node1.children != null)
            {
                if(node2.children == null)
                    return true;
                if(HasTreeChanged(node1.children, node2.children))
                    return true;
            }
        }
    }
    return false;
}

Lastly, the different API's for the viewer must be updated to fill in the data. For the .Net version, the file to modify is legend.aspx, line 362 looks like:

output = output + String.Format("{0}[{1}] = new LayerSummary(\"{2}\", \"{3}\", \"{4}\"\n",
    container,
    i,
    rtLayer.GetName(),
    rtLayer.GetObjectId(),
    rtLayer.GetLayerDefinition().ToString(),
    );

It should be changed to:

output = output + String.Format("{0}[{1}] = new LayerSummary(\"{2}\", \"{3}\", \"{4}\", {5}, {6}, \"{7}\", {8});\n",
    container,
    i,
    rtLayer.GetName(),
    rtLayer.GetObjectId(),
    rtLayer.GetLayerDefinition().ToString(),
    rtLayer.GetDisplayInLegend() ? "true" : "false",
    rtLayer.GetExpandInLegend()? "true": "false",
    rtLayer.GetLegendLabel(),
    rtLayer.GetVisible()? "true": "false"
    );

This will fix the problem with the legend not updating correctly, using the AJAX viewer, the DWF viewer is still broken. I'm guessing it uses the same code internally.

A short term fix, would be to insert/remove layers from the runtime map, as this seems to be detected. Also swapping layers might work.

The above fix needs to be applied for groups as well, and also for the different other viewers.

comment:2 Changed 14 years ago by ksgeograf

The above fix does not solve the problem with the missing legend labels. That one can be fixed by modifying Map.cpp in MapGuideCommon?. In particular line 266 should be changed from:

if(layer->IsShowInLegend())
{
    rtLayer->SetExpandInLegend(layer->IsExpandInLegend());
    rtLayer->SetLegendLabel(layer->GetLegendLabel());
}

To:

rtLayer->SetExpandInLegend(layer->IsExpandInLegend());
rtLayer->SetLegendLabel(layer->GetLegendLabel());

The same goes for the Group part at line 196.

Since this will not be fixed in the Enterprise edition anytime soon, a temporary fix is:

Load the map definition.
Ensure that ALL layers and groups are visible.
Add a bogus layer, with a random resourceid, keep it invisible.
Save map in temporary location, preferably session repository.
Create runtime map from temporary MapDefinition.
Update runtime map, and hide any legends that should not be shown.

Everytime the legend has to update, change the resourceId of the bogus layer, save it and call map.Refresh();

comment:3 Changed 14 years ago by rexszeto

External ID: 939559

comment:4 Changed 14 years ago by tomfukushima

Milestone: 1.21.3

comment:5 Changed 13 years ago by tomfukushima

Milestone: 2.0

comment:6 Changed 12 years ago by ksgeograf

Patch for the server code is present in #833.

I can make patches for the templ/js/aspx files. I have no way of testing changes to the php and java files, but I can make patches for those as well if so desired.

comment:7 Changed 12 years ago by tomfukushima

Yes, if you could make all the required patches that would help. But please put a note that the PHP and Java were not tested.

comment:8 Changed 12 years ago by jbirch

Have any of these fixes been applied?

comment:9 Changed 12 years ago by tomfukushima

Owner: set to chrisclaydon

comment:10 Changed 11 years ago by cmy

Owner: changed from chrisclaydon to cmy

shank you! I have the same problem.

comment:11 Changed 11 years ago by cmy

Version: 1.2.02.0.2

comment:12 Changed 11 years ago by jbirch

Please re-test against 2.1 and let us know if this is still an issue (or close if has been fixed). Will close this ticket if no response by next ticket cleanup cycle.

comment:13 Changed 11 years ago by ksgeograf

Version: 2.0.22.1.0

comment:14 Changed 8 years ago by jng

Milestone: 2.5

comment:15 Changed 8 years ago by jng

Milestone: 2.52.6

comment:16 Changed 7 years ago by jng

Resolution: duplicate
Status: newclosed

Duplicate of #833

Note: See TracTickets for help on using tickets.