What controls the alignment of LegendItem in LegendAdornmentLayer?
The issue I have is that it aligns to the left when I loads the map; then if I zoom in, it aligns to the right and never comes back.
I always call the same function to create LegendAdornmentLayer. I did customize LegendAdornmentLayer but only the Title LegendItem.
Any ideas?
LegendItem alignment issues
Hi guangming,
We don’t have a API to set the alignment for LegendAdornmentLayer.
I know you customized the Title LegendItem, but I want to whether the issue only shows in Title, and by default setting this issue cannot be reproduced in my end.
so please show me more detail code about your new Title LegendItem class, a simple sample should be more helpful.
Regards,
Don
is that output of the legendAdornmentLayer an image or HTML component?
It does not have problem on my dev environment. On the production environment there are a lot of CSS applied which I did not know what they are.
pls see codes below: I changed only title part not other legendItems.
public class TitleWrappedLegendAdornmentLayer : LegendAdornmentLayer
{
private int rowHeight; // height for each item
private int legendItems; // # of items to show
public TitleWrappedLegendAdornmentLayer(int itemHeight, int items)
{
rowHeight = itemHeight;
legendItems = items;
}
protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
{
// find title text/style/font -> wrapped and adjust height?
WrapTitleWithHeight(canvas, this.Title);
// misc
this.Title.LeftPadding = 0;
this.Title.TextLeftPadding = 0;
this.Title.RightPadding = 0;
this.Title.TextRightPadding = 0;
this.Title.TextTopPadding = 0;
this.Title.TextBottomPadding = 0;
// decide layer height
this.Height = legendItems * rowHeight + this.Title.Height;
base.DrawCore(canvas, labelsInAllLayers);
}
this happens a lot when only one legendItem is there; sometime two legenditems stay in one row.
Hi guangming,
The legend in web edition is an image.
I think my test code have a little problem, could you please help me modify it for reproduce your issue?
using System;
using System.Collections.ObjectModel;
using ThinkGeo.MapSuite.Core;
using ThinkGeo.MapSuite.WebEdition;
namespace CSSamples.Samples
{
public class TitleWrappedLegendAdornmentLayer : LegendAdornmentLayer
{
private int rowHeight; // height for each item
private int legendItems; // # of items to show
public TitleWrappedLegendAdornmentLayer(int itemHeight, int items)
{
rowHeight = itemHeight;
legendItems = items;
}
protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
{
// find title text/style/font -> wrapped and adjust height?
//WrapTitleWithHeight(canvas, this.Title);
// misc
this.Title.LeftPadding = 0;
this.Title.TextLeftPadding = 0;
this.Title.RightPadding = 0;
this.Title.TextRightPadding = 0;
this.Title.TextTopPadding = 0;
this.Title.TextBottomPadding = 0;
// decide layer height
this.Height = legendItems * rowHeight + this.Title.Height;
base.DrawCore(canvas, labelsInAllLayers);
}
}
public partial class DisplayASimpleMap : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
TitleWrappedLegendAdornmentLayer legend = new TitleWrappedLegendAdornmentLayer(30, 3);
legend.Title = new LegendItem();
legend.Title.TextStyle = TextStyles.Capital1("Test Title");
LegendItem item1 = new LegendItem();
item1.TextStyle = TextStyles.City4("item1");
LegendItem item2 = new LegendItem();
item2.TextStyle = TextStyles.City4("item2");
legend.LegendItems.Add(item1);
legend.LegendItems.Add(item2);
Map1.AdornmentOverlay.Layers.Add(legend);
Map1.MapBackground.BackgroundBrush = new GeoSolidBrush(GeoColor.FromHtml("#E5E3DF"));
Map1.CurrentExtent = new RectangleShape(-2000000, 2000000, 2000000, -2000000);
Map1.MapUnit = GeographyUnit.Meter;
}
}
}
}
Regards,
Don
i put my complete customized class here. I guess I might have made some mistake there so pls review my code for wrapping (I did see the wrapping method has a bug - always put each word in one line).
Also, pls try just have one legentItem, and two legend items, + title. Then zoom in to see if the issue happens.
public class TitleWrappedLegendAdornmentLayer : LegendAdornmentLayer
{
private int rowHeight; // height for each item
private int legendItems; // # of items to show
public TitleWrappedLegendAdornmentLayer(int itemHeight, int items)
{
rowHeight = itemHeight;
legendItems = items;
}
protected override void DrawCore(GeoCanvas canvas, Collection<SimpleCandidate> labelsInAllLayers)
{
// find title text/style/font -> wrapped and adjust height?
WrapTitleWithHeight(canvas, this.Title);
// decide layer height
this.Height = legendItems * rowHeight + this.Title.Height;
base.DrawCore(canvas, labelsInAllLayers);
}
protected void WrapTitleWithHeight(GeoCanvas adornmentGeoCanvas, LegendItem titleItem)
{
string text = titleItem.TextStyle.TextColumnName.Replace("\r\n", " “).Replace(”\t", " “).Trim();
DrawingRectangleF drawingRectangleF = adornmentGeoCanvas.MeasureText(text, titleItem.TextStyle.Font);
//Compares the bounding box in screen coordinates with the size of the text.
if (this.Title.Width < drawingRectangleF.Width)
{
//If not, applies the word wrapping.
string[] Words = Wrap(adornmentGeoCanvas, text, titleItem.TextStyle.Font, (int)this.Title.Width); //drawingRectangleF.Width
string newLineText = “”;
for (int i = 0; i < Words.Length; i++)
{
newLineText = newLineText + Words[i] + Environment.NewLine;
}
titleItem.TextStyle.AllowLineCarriage = true;
titleItem.TextStyle.TextColumnName = newLineText;
drawingRectangleF = adornmentGeoCanvas.MeasureText(newLineText, titleItem.TextStyle.Font);
// adjust height
if (titleItem.Height < drawingRectangleF.Height)
{
titleItem.Height = drawingRectangleF.Height + 5;
}
}
return;
}
//Function to get the maximum length of the string without having a new line.
private int GetMaxStringLength(GeoCanvas canvas, float currentWidth)
{
//For now, the value is You can write your own logic to calculate that value based on
// the size of the text and the bounding box to hold it.
int result = (int)currentWidth; // 10;
return result;
}
//Function taken from velocityreviews.com/forums/t20370-word-wrap-line-break-code-and-algorithm-for-c.html
private string[] Wrap(GeoCanvas theCanvas, string text, GeoFont txtFont, int maxLength)
{
text = text.Replace(”\n", " “);
text = text.Replace(”\r", " “);
text = text.Replace(”.", “. “);
text = text.Replace(”>”, “> “);
text = text.Replace(”\t”, " “);
text = text.Replace(”,", “, “);
text = text.Replace(”;”, “; “);
text = text.Replace(”<br>”, " “);
text = text.Replace(” “, " “);
string[] Words = text.Split(’ ');
int currentLineLength = 0;
float wordLength = 0;
ArrayList Lines = new ArrayList(text.Length / maxLength);
string currentLine = “”;
bool InTag = false;
foreach (string currentWord in Words)
{
//ignore html
if (currentWord.Length > 0)
{
if (currentWord.Substring(0, 1) == “<”)
InTag = true;
if (InTag)
{
//handle filenames inside html tags
if (currentLine.EndsWith(”.”))
{
currentLine += currentWord;
}
else
currentLine += " " + currentWord;
if (currentWord.IndexOf(">") > -1)
InTag = false;
}
else
{
wordLength = theCanvas.MeasureText(currentWord, txtFont).Width;
// if (currentLineLength + currentWord.Length + 1 < maxLength)
if (currentLineLength + wordLength + 1 < maxLength)
{
currentLine += " " + currentWord;
// currentLineLength += (currentWord.Length + 1);
currentLineLength += ((int)wordLength + 1);
}
else
{
Lines.Add(currentLine);
currentLine = currentWord;
currentLineLength = (int)wordLength; // currentWord.Length;
}
}
}
}
if (currentLine != “”)
Lines.Add(currentLine);
string[] textLinesStr = new string[Lines.Count];
Lines.CopyTo(textLinesStr, 0);
return textLinesStr;
}// function
}// class
Hi Guangming,
Thanks for share your code, but I don’t think the issue you mentioned related with the logic you implemented for wrapping.
In fact your code works well in my end but it still cannot reproduced the exception you mentioned.
I tested both for two scenario:
1. Just one legend item
2. Two legend items and title
Could you please help me to know what I ignored for reproduced it?
Regards,
Don
12558.zip (3.26 KB)
I am confident it is an implementation bug of a newer version of mapsuitecore.dll. the newer version 7.0.316.0 will have the issue; the older one 7.0.0.0 does not.
I attached some key changes to your code to replicate my case and see the effect:
in the controller cs class:
[MapActionFilter]
public string MapSetUpChanged(Map map, GeoCollection<object> args)
{
UpdateLegend(map, 1, “There is only one legent Item”);
LayerOverlay sOverlay = (LayerOverlay)map.CustomOverlays[0];
sOverlay.Redraw();
return “redraw”;
}
private void UpdateLegend(Map map, int items, string title)
{
if (map.AdornmentOverlay.Layers.Count > 0)
map.AdornmentOverlay.Layers.RemoveAt(0); // at most one
TitleWrappedLegendAdornmentLayer legend = new TitleWrappedLegendAdornmentLayer(30, items);
legend.Title = new LegendItem();
legend.Title.TextStyle = new TextStyle(title, new GeoFont(“Courier”, 10),
new GeoSolidBrush(GeoColor.SimpleColors.Red));
//legend.Title.TextStyle.Font.Size = 26;
legend.Location = AdornmentLocation.UpperRight;
// legend.ContentResizeMode = LegendContentResizeMode.Fixed; // only new version mapsuitecore.dll supports
LegendItem item1 = new LegendItem();
item1.TextStyle = TextStyles.City4(“My name is”);
item1.ImageStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.SimpleColors.Transparent, GeoColor.SimpleColors.Red,
2, LineDashStyle.Solid);
legend.LegendItems.Add(item1);
//legend.Height = 1 * 30;
if (items > 1)
{
LegendItem item2 = new LegendItem();
item2.TextStyle = TextStyles.City4(“My name is item2”);
item2.ImageStyle = AreaStyles.CreateSimpleAreaStyle(GeoColor.SimpleColors.Transparent, GeoColor.SimpleColors.Red,
2, LineDashStyle.Solid);
legend.LegendItems.Add(item2);
//legend.Height = 2 * 30;
}
legend.Width = 220;
map.AdornmentOverlay.Layers.Add(legend);
}
in the client side, I added a button to call the js fun below and then trigger the server side function to change legend:
function switchLegend() {
Map1.ajaxCallAction(’@ViewContext.RouteData.Values[“Controller”].ToString()’,
‘MapSetUpChanged’,
{
s: 1
},
function (result) {
var resultString = result.get_responseData();
Map1.redrawLayer(‘AdornmentOverlay’);
Map1.redrawLayer(“StaticOverlay”);
});
};
Hi Guangming,
You meant you are using 7.0 version?
I am sorry I tested that with latest 8.0 daily build.
If that’s in 7.0, I think that should be a known issue and have been fixed in 8.0.
Could you please replace your dlls to test latest 8.0 for that? Because we have stopped build 7.0 package, if that proved is a bug in 7.0 we can only fix that in latest 8.0 dlls.
Regards,
Don