Tuesday, December 16, 2008

Some odd issues with using the Chart Control inside a wizard...

From: http://social.msdn.microsoft.com/Forums/en-US/MSWinWebChart/thread/1dc4b352-c9a5-49dc-8f35-9b176509faa1#page:2

I don't know if this is the same problem as everyone else has seen (sounds like maybe it's different).

I wrote a page with a chart in it.

I then changed the page to use an asp:Wizard - the chart being in the last step.

After this change, I got the executing error shown below when I reached the last page.

Moving the chart out of the wizard and back into the root of my control removed the error.

However, when I moved the chart back to the last step of the wizard again, the error was cleared....

Somewhat confused at present...


Error executing child request for ChartImg.axd.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.Web.HttpException: Error executing child request for ChartImg.axd.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:

[HttpException (0x80004005): Error executing child request for ChartImg.axd.]
System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride) +2675871
System.Web.HttpServerUtility.Execute(String path, TextWriter writer, Boolean preserveForm) +819
System.Web.HttpServerUtility.Execute(String path) +8
System.Web.UI.DataVisualization.Charting.ChartHttpHandler.EnsureInitialized(Boolean hardCheck) +152
System.Web.UI.DataVisualization.Charting.ChartHttpHandler.EnsureInstalled() +27
System.Web.UI.DataVisualization.Charting.Chart.GetImageStorageMode() +46
System.Web.UI.DataVisualization.Charting.Chart.Render(HtmlTextWriter writer) +201
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +99
System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +134
System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +19
System.Web.UI.Control.Render(HtmlTextWriter writer) +10
System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27

An odd bug in the chart control?

Still charting (even at 1am!)

And I've just found my first bug in the chart control...

Only a minor one.

If I plot a graph then this is how it looks on the web UI:



However, if I plot the chart and then call SaveImage before displaying it, then I get this:



For record, the saved chart looks fine:



In my case there's an easy workaround - but thought someone might find this interesting...

Edit - I've also just tried calling SaveImage twice in a row - I see the same effect - in the second chart the data is corrupted.

Workaround/fix from Alex Gorev on the Msoft forum - if I set the series XValueType then this prevents the problem :)


series.XValueType = ChartValueType.DateTime;

Monday, December 15, 2008

ASP.Net Cacheing - Excellent :)

I've spent the weekend writing some code which consumes a web service and uses it populate a table and a chart.

The problem is that talking to the webservice is quite slow (a good chunk of a second for the web hit) - but the good news is that the results don't change much from hour to hour - so the results are a really good candidate for cacheing.

I looked around and discovered this article from 4guysfromrolla - http://aspnet.4guysfromrolla.com/articles/100902-1.2.aspx - and saw how really lovely the ASP.Net cacheing is.

Here's the code I wrote....

private static CacheObject GetCachedObjectForEvent(string eventName, Cache cache)
{
CacheObject storedObject = null;

string cacheKey = string.Format("MY_EVENT_{0}", eventName);
try
{
storedObject = (CacheObject)cache.Get(cacheKey);
}
catch (InvalidCastException)
{
cache.Remove(cacheKey);
}

if (storedObject == null)
{
Dictionary eventDictionary = HttpCollector.Collect(eventName);
storedObject = new CacheObject(eventDictionary);
cache.Add(cacheKey, storedObject, null, DateTime.Now.AddMinutes(60.0), TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Normal, null);
}
return storedObject;
}

A couple of things to note here:
  1. The InvalidCastException won't happen in real deployments - but does happen during recompiles in the development environment.
  2. The cached object here is only stored for at most 60 minutes from insertion - an alternate strategy might have been to store it on a sliding scale.

Friday, December 12, 2008

Azure Invitiation code still not received :(

Come on - it's been well over a month now....

Really not impressed.

I've got two websites written and ready to upload to Azure.

I've played with the local SDK ad nauseum...

I really really really want to get my hands on the real deal.

But still no sign of the invitation code from Microsoft... and even when I do get the code I know it will only limit me to one website at a time...

Really not impressed.

Native client

Google's native client API sounds interesting to me - but not from the point of view of it being another AJAX/Flash/Silverlight/Java UI experience clone - instead it's more to do with the fact that that it could potentially let Google (and others) start leveraging other people's PCs for their needs - sort of like a big zombienet maybe?

Thursday, December 11, 2008

"Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."

If you see this error in the code behind function, while trying to do Asp.Net DataList formatting (as I saw in the 4GuysFromRolla articles on DataList's and ListView's - http://aspnet.4guysfromrolla.com/articles/091708-1.aspx then you might have made the same mistake that I did:
  • I missed out the # at the start of the <%# ... %> tag in the ASPX code.
Took a little while to debug that one!

"Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control."

Wednesday, December 10, 2008

Drawing for free

I'm finally reaching the "polish" stage of stage one of my "son of hollybar" project - so I thought I'd have a go at drawing a logo for my new website...

Only problem is that I've lost my copy of PaintShopPro (it's somewhere embedded within my XP image - and I'm not going back!) and Microsoft seem to have stopped shipping any paint programs - so I can't leverage my MSDN sub.

However, a quick search revealed... http://www.drawingcoach.com/free-drawing-software.html which has three good recommendations:
So I've had a go..... and:
  • G Sketchup was way too complicated - I seemed to get straight into architecture mode... into designing buildings. It's probably very good if you want to design for Google Earth...
  • But Gimp was gorgeous... I can't use it in exactly the same was as I could never use PaintShopPro nor Photoshop - so it's a winner!
  • (will try inkscape later...)

With all this talk about charts...

I've posted lots about charts recently.

After all the talk, I thought I really should add a few examples....

The data in these isn't a real example, but it's representative of the type of things I've been working on








Well I like them anyway :)

Listing all timezones in ASP.NET

I wanted to create a combobox (dropdown list) full of all the timezones...

Surfing around this guy had a partial list... but I wanted a full one.

I then looked at some old opennetcf code which parsed the timezone info from the registry... only to discover that Vista has moved the timezone code away from the registry....

I then discovered the right way... the latest .NET System.Core library has a TimeZoneInfo class (struct?) and some useful helper methods

To dump out a list is as simple as:

ReadOnlyCollection < TimeZoneInfo > collection = TimeZoneInfo.GetSystemTimeZones();
foreach (var t in collection)
{
Debug.WriteLine(string.Format("{1} - {0}", t.DisplayName, t.Id));
}

However... there is a possible problem running this on ASP.Net on a shared host - it probably will hit the registry on older PCs... so I've cached the results instead....


class TimeZoneHelper
{
public string DisplayName { get; set; }
public string Id { get; set; }
}

static List GetTimeZoneHelpers()
{
return new List()
{
new TimeZoneHelper() { DisplayName="(GMT) Casablanca", Id="Morocco Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London", Id="GMT Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT) Monrovia, Reykjavik", Id="Greenwich Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna", Id="W. Europe Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague", Id="Central Europe Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+01:00) Brussels, Copenhagen, Madrid, Paris", Id="Romance Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb", Id="Central European Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+01:00) West Central Africa", Id="W. Central Africa Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Amman", Id="Jordan Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Athens, Bucharest, Istanbul", Id="GTB Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Beirut", Id="Middle East Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Cairo", Id="Egypt Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Harare, Pretoria", Id="South Africa Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius", Id="FLE Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Jerusalem", Id="Israel Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Minsk", Id="E. Europe Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+02:00) Windhoek", Id="Namibia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:00) Baghdad", Id="Arabic Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:00) Kuwait, Riyadh", Id="Arab Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:00) Moscow, St. Petersburg, Volgograd", Id="Russian Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:00) Nairobi", Id="E. Africa Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:00) Tbilisi", Id="Georgian Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+03:30) Tehran", Id="Iran Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+04:00) Abu Dhabi, Muscat", Id="Arabian Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+04:00) Baku", Id="Azerbaijan Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+04:00) Yerevan", Id="Caucasus Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+04:30) Kabul", Id="Afghanistan Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:00) Ekaterinburg", Id="Ekaterinburg Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:00) Islamabad, Karachi", Id="Pakistan Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:00) Tashkent", Id="West Asia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi", Id="India Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:30) Sri Jayawardenepura", Id="Sri Lanka Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+05:45) Kathmandu", Id="Nepal Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+06:00) Almaty, Novosibirsk", Id="N. Central Asia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+06:00) Astana, Dhaka", Id="Central Asia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+06:30) Yangon (Rangoon)", Id="Myanmar Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+07:00) Bangkok, Hanoi, Jakarta", Id="SE Asia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+07:00) Krasnoyarsk", Id="North Asia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi", Id="China Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+08:00) Irkutsk, Ulaan Bataar", Id="North Asia East Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+08:00) Kuala Lumpur, Singapore", Id="Singapore Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+08:00) Perth", Id="W. Australia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+08:00) Taipei", Id="Taipei Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+09:00) Osaka, Sapporo, Tokyo", Id="Tokyo Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+09:00) Seoul", Id="Korea Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+09:00) Yakutsk", Id="Yakutsk Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+09:30) Adelaide", Id="Cen. Australia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+09:30) Darwin", Id="AUS Central Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+10:00) Brisbane", Id="E. Australia Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+10:00) Canberra, Melbourne, Sydney", Id="AUS Eastern Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+10:00) Guam, Port Moresby", Id="West Pacific Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+10:00) Hobart", Id="Tasmania Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+10:00) Vladivostok", Id="Vladivostok Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+11:00) Magadan, Solomon Is., New Caledonia", Id="Central Pacific Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+12:00) Auckland, Wellington", Id="New Zealand Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+12:00) Fiji, Kamchatka, Marshall Is.", Id="Fiji Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT+13:00) Nuku'alofa", Id="Tonga Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-01:00) Azores", Id="Azores Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-01:00) Cape Verde Is.", Id="Cape Verde Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-02:00) Mid-Atlantic", Id="Mid-Atlantic Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:00) Brasilia", Id="E. South America Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:00) Buenos Aires", Id="Argentina Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:00) Georgetown", Id="SA Eastern Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:00) Greenland", Id="Greenland Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:00) Montevideo", Id="Montevideo Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-03:30) Newfoundland", Id="Newfoundland Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-04:00) Atlantic Time (Canada)", Id="Atlantic Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-04:00) La Paz", Id="SA Western Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-04:00) Manaus", Id="Central Brazilian Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-04:00) Santiago", Id="Pacific SA Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-04:30) Caracas", Id="Venezuela Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-05:00) Bogota, Lima, Quito, Rio Branco", Id="SA Pacific Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-05:00) Eastern Time (US & Canada)", Id="Eastern Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-05:00) Indiana (East)", Id="US Eastern Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-06:00) Central America", Id="Central America Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-06:00) Central Time (US & Canada)", Id="Central Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-06:00) Guadalajara, Mexico City, Monterrey", Id="Central Standard Time (Mexico)", },
new TimeZoneHelper() { DisplayName="(GMT-06:00) Saskatchewan", Id="Canada Central Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-07:00) Arizona", Id="US Mountain Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-07:00) Chihuahua, La Paz, Mazatlan", Id="Mountain Standard Time (Mexico)", },
new TimeZoneHelper() { DisplayName="(GMT-07:00) Mountain Time (US & Canada)", Id="Mountain Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-08:00) Pacific Time (US & Canada)", Id="Pacific Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-08:00) Tijuana, Baja California", Id="Pacific Standard Time (Mexico)", },
new TimeZoneHelper() { DisplayName="(GMT-09:00) Alaska", Id="Alaskan Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-10:00) Hawaii", Id="Hawaiian Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-11:00) Midway Island, Samoa", Id="Samoa Standard Time", },
new TimeZoneHelper() { DisplayName="(GMT-12:00) International Date Line West", Id="Dateline Standard Time", }
};

If your encryption/decryption works in your test harness but it goes wrong in real life....

Had a bug in one of my (semi)secure data stores today.

Basically I was using the .Net cryptographic patter to encode and decode some strings that I didn't want to be in plain text in this website's database.

I had a unit test in place and the encryption/decryption was fine.

However, in 'real life' testing I saw my text get scrambled - the first few bytes of this text were often corrupted - and it didn't matter whether I used DESCryptoServiceProvider, RC2CryptoServiceProvider, etc

I spent some time looking at my byte to text converters to make sure that it wasn't them... and then I spotted the problem:

I wasn't always correctly initialising the Initialisation Vector (IV) for the encryption/decryption.

This worked fine in the test harnesses - as they always used the same IV and Key for every encrypt/decrypt (because they were in the same process) - but messed up in real use.

Moral of the story - if you are going to use the symmetric cryptographic services then always set both the Key and the IV.

Tuesday, December 09, 2008

Yet more color stuff for charts and beyond

I can't believe I'm spelling colour the American way?!

Anyways, here's a ColorProvider I built based around the Dundas/Microsoft Chart Control - it's just got a simple iteration and raw color access API - I'm sure you'll have no problems understanding it.

See my earlier post for more info about where the Colors come from.


using System;
using System.Collections.Generic;
using System.Text;
using System.Drawing;

namespace SlodgeRoutesTools
{
public class ColorProvider
{
readonly List myColors = null;
int myCurrent = -1;

public List Colors
{
get
{
return myColors;
}
}

public void Reset()
{
myCurrent = -1;
}

public Color GetNextColor()
{
myCurrent++;
myCurrent %= myColors.Count;
return myColors[myCurrent];
}

public ColorProvider(List colors)
{
myColors = colors;
}

public static ColorProvider GetColorProvider()
{
return GetColorProvider(ColorProviderPalette.Default);
}

public static ColorProvider GetColorProvider(ColorProviderPalette palette)
{
return new ColorProvider(GetColors(palette));
}

public enum ColorProviderPalette
{
Default,
Pastel,
Berry,
Fire,
SeaGreen,
EarthTones,
Excel,
GrayScale,
Chocolate,
Special,
Light


}

private static List GetColors(ColorProviderPalette palette)
{
switch (palette)
{
case ColorProviderPalette.Pastel:
return new List()
{
// pastel
Color.FromArgb(255, 135, 206, 235),
Color.FromArgb(255, 50, 205, 50),
Color.FromArgb(255, 186, 85, 211),
Color.FromArgb(255, 240, 128, 128),
Color.FromArgb(255, 70, 130, 180),
Color.FromArgb(255, 154, 205, 50),
Color.FromArgb(255, 64, 224, 208),
Color.FromArgb(255, 255, 105, 180),
Color.FromArgb(255, 240, 230, 140),
Color.FromArgb(255, 210, 180, 140),
Color.FromArgb(255, 143, 188, 139),
Color.FromArgb(255, 100, 149, 237),
Color.FromArgb(255, 221, 160, 221),
Color.FromArgb(255, 95, 158, 160),
Color.FromArgb(255, 255, 218, 185),
Color.FromArgb(255, 255, 160, 122)
};

case ColorProviderPalette.Special:
return new List()
{
// special - was originally Dundas
Color.FromArgb(255, 65, 140, 240),
Color.FromArgb(255, 252, 180, 65),
Color.FromArgb(255, 224, 64, 10),
Color.FromArgb(255, 5, 100, 146),
Color.FromArgb(255, 191, 191, 191),
Color.FromArgb(255, 26, 59, 105),
Color.FromArgb(255, 255, 227, 130),
Color.FromArgb(255, 18, 156, 221),
Color.FromArgb(255, 202, 107, 75),
Color.FromArgb(255, 0, 92, 219),
Color.FromArgb(255, 243, 210, 136),
Color.FromArgb(255, 80, 99, 129),
Color.FromArgb(255, 241, 185, 168),
Color.FromArgb(255, 224, 131, 10),
Color.FromArgb(255, 120, 147, 190)
};

case ColorProviderPalette.EarthTones:
return new List()
{
// earth tones
Color.FromArgb(255, 255, 128, 0),
Color.FromArgb(255, 184, 134, 11),
Color.FromArgb(255, 192, 64, 0),
Color.FromArgb(255, 107, 142, 35),
Color.FromArgb(255, 205, 133, 63),
Color.FromArgb(255, 192, 192, 0),
Color.FromArgb(255, 34, 139, 34),
Color.FromArgb(255, 210, 105, 30),
Color.FromArgb(255, 128, 128, 0),
Color.FromArgb(255, 32, 178, 170),
Color.FromArgb(255, 244, 164, 96),
Color.FromArgb(255, 0, 192, 0),
Color.FromArgb(255, 143, 188, 139),
Color.FromArgb(255, 178, 34, 34),
Color.FromArgb(255, 139, 69, 19),
Color.FromArgb(255, 192, 0, 0),
};
case ColorProviderPalette.Excel:
return new List()
{
// excel
Color.FromArgb(255, 153, 153, 255),
Color.FromArgb(255, 153, 51, 102),
Color.FromArgb(255, 255, 255, 204),
Color.FromArgb(255, 204, 255, 255),
Color.FromArgb(255, 102, 0, 102),
Color.FromArgb(255, 255, 128, 128),
Color.FromArgb(255, 0, 102, 204),
Color.FromArgb(255, 204, 204, 255),
Color.FromArgb(255, 0, 0, 128),
Color.FromArgb(255, 255, 0, 255),
Color.FromArgb(255, 255, 255, 0),
Color.FromArgb(255, 0, 255, 255),
Color.FromArgb(255, 128, 0, 128),
Color.FromArgb(255, 128, 0, 0),
Color.FromArgb(255, 0, 128, 128),
Color.FromArgb(255, 0, 0, 255)
};
case ColorProviderPalette.GrayScale:
return new List()
{
// grayscale
Color.FromArgb(255, 189, 189, 189),
Color.FromArgb(255, 178, 178, 178),
Color.FromArgb(255, 167, 167, 167),
Color.FromArgb(255, 156, 156, 156),
Color.FromArgb(255, 145, 145, 145),
Color.FromArgb(255, 134, 134, 134),
Color.FromArgb(255, 123, 123, 123),
Color.FromArgb(255, 112, 112, 112),
Color.FromArgb(255, 101, 101, 101),
Color.FromArgb(255, 90, 90, 90),
Color.FromArgb(255, 79, 79, 79),
Color.FromArgb(255, 68, 68, 68),
Color.FromArgb(255, 57, 57, 57),
Color.FromArgb(255, 46, 46, 46),
Color.FromArgb(255, 35, 35, 35)
};
case ColorProviderPalette.Light:
return new List()
{
// light
Color.FromArgb(255, 230, 230, 250),
Color.FromArgb(255, 255, 240, 245),
Color.FromArgb(255, 255, 218, 185),
Color.FromArgb(255, 255, 250, 205),
Color.FromArgb(255, 255, 228, 225),
Color.FromArgb(255, 240, 255, 240),
Color.FromArgb(255, 240, 248, 255),
Color.FromArgb(255, 245, 245, 245),
Color.FromArgb(255, 250, 235, 215),
Color.FromArgb(255, 224, 255, 255)
};
case ColorProviderPalette.SeaGreen:
return new List()
{
// seaGreen
Color.FromArgb(255, 46, 139, 87),
Color.FromArgb(255, 102, 205, 170),
Color.FromArgb(255, 70, 130, 180),
Color.FromArgb(255, 0, 139, 139),
Color.FromArgb(255, 95, 158, 160),
Color.FromArgb(255, 60, 179, 113),
Color.FromArgb(255, 72, 209, 204),
Color.FromArgb(255, 176, 196, 222),
Color.FromArgb(255, 143, 188, 139),
Color.FromArgb(255, 135, 206, 235)
};
case ColorProviderPalette.Berry:
return new List()
{
// berry
Color.FromArgb(255, 138, 43, 226),
Color.FromArgb(255, 186, 85, 211),
Color.FromArgb(255, 65, 105, 225),
Color.FromArgb(255, 199, 21, 133),
Color.FromArgb(255, 0, 0, 255),
Color.FromArgb(255, 138, 43, 226),
Color.FromArgb(255, 218, 112, 214),
Color.FromArgb(255, 123, 104, 238),
Color.FromArgb(255, 192, 0, 192),
Color.FromArgb(255, 0, 0, 205),
Color.FromArgb(255, 128, 0, 128)
};
case ColorProviderPalette.Fire:
return new List()
{
// fire
Color.FromArgb(255, 255, 215, 0),
Color.FromArgb(255, 255, 0, 0),
Color.FromArgb(255, 255, 20, 147),
Color.FromArgb(255, 220, 20, 60),
Color.FromArgb(255, 255, 140, 0),
Color.FromArgb(255, 255, 0, 255),
Color.FromArgb(255, 255, 255, 0),
Color.FromArgb(255, 255, 69, 0),
Color.FromArgb(255, 199, 21, 133),
Color.FromArgb(255, 221, 226, 33)
};

case ColorProviderPalette.Chocolate:
return new List()
{
// chocolate
Color.FromArgb(255, 160, 82, 45),
Color.FromArgb(255, 210, 105, 30),
Color.FromArgb(255, 139, 0, 0),
Color.FromArgb(255, 205, 133, 63),
Color.FromArgb(255, 165, 42, 42),
Color.FromArgb(255, 244, 164, 96),
Color.FromArgb(255, 139, 69, 19),
Color.FromArgb(255, 192, 64, 0),
Color.FromArgb(255, 178, 34, 34),
Color.FromArgb(255, 182, 92, 58)
};
case ColorProviderPalette.Default:
default:
return new List()
{
Color.FromArgb(255, 0, 128, 0),
Color.FromArgb(255, 0, 0, 255),
Color.FromArgb(255, 128, 0, 128),
Color.FromArgb(255, 0, 255, 0),
Color.FromArgb(255, 255, 0, 255),
Color.FromArgb(255, 0, 128, 128),
Color.FromArgb(255, 255, 255, 0),
Color.FromArgb(255, 128, 128, 128),
Color.FromArgb(255, 0, 255, 255),
Color.FromArgb(255, 0, 0, 128),
Color.FromArgb(255, 128, 0, 0),
Color.FromArgb(255, 255, 0, 0),
Color.FromArgb(255, 128, 128, 0),
Color.FromArgb(255, 192, 192, 192),
Color.FromArgb(255, 255, 99, 71),
Color.FromArgb(255, 255, 228, 181)
};
}
}
}
}

JScriptGenerator.cs with fixes for Gmap2.0

As I mentioned yesterday, I've put some fixes into JScriptGenerator.cs from http://dotnet.sys-con.com/node/171162

All changes are marked "// SL" - there aren't many. Here they are:



using System;
using System.Text;
namespace MapControl
{
///
/// Class that handles all Javascript Method
/// Generation
///
internal class JScriptGenerator
{
///
/// Default constructor
///
public JScriptGenerator()
{

}
///
/// Method to Generate the Function to Overlay a point
/// on the map
///
/// Variable representing an Array
/// Client ID of the control
/// JavaScript function as a string
public string GenerateOverLayPointFuncCall(string sArrayVariable, string sControlClientID)
{
StringBuilder sOverLayFunction = new StringBuilder();
sOverLayFunction.AppendFormat(" function OverlayLocation{0}(clong,cLat,popup,sFormattedHtml)\n",sControlClientID );
sOverLayFunction.Append("{\n");
sOverLayFunction.Append("var point = new GPoint(clong,cLat);");
sOverLayFunction.Append("var marker = new GMarker(point);\n");
sOverLayFunction.Append("if ( popup==1 ) { \n");
sOverLayFunction.Append("GEvent.addListener(marker, 'click', function() {marker.openInfoWindowHtml(sFormattedHtml);});");
sOverLayFunction.Append("\n } \n");
sOverLayFunction.AppendFormat("{0}.push(marker);\n",sArrayVariable);
sOverLayFunction.Append(" }");
return sOverLayFunction.ToString();

}
///
/// Method to Generate the Javascript funtion to Overlay a point that uses a custom
/// icon on the map
///
/// Variable representing an Array
/// Client ID of the control
/// JavaScript function as a string
public string GenerateCustomOverLayPointFuncCall(string sArrayVariable, string sControlClientID)
{
StringBuilder sOverLayFunction = new StringBuilder();
sOverLayFunction.AppendFormat(" function OverlayCustomMarkerLocation{0}(clong,cLat,iconimgUrl,iconshadowimgURL,iconwidth,iconheight,iconshwidth,iconshheight,iconAnchorX,iconAnchorY,infoWinX,infoWinY,popup,sFormattedHtml)\n",sControlClientID );
sOverLayFunction.Append("{\n");
sOverLayFunction.Append("var point = new GPoint(clong,cLat);\n");
sOverLayFunction.Append("var icon = new GIcon();\n");
sOverLayFunction.Append("icon.image =iconimgUrl ;\n");
sOverLayFunction.Append("icon.shadow =iconshadowimgURL ;\n");
sOverLayFunction.Append("icon.iconSize = new GSize(iconwidth, iconheight);\n");
sOverLayFunction.Append("icon.shadowSize = new GSize(iconshwidth, iconshheight);\n");
sOverLayFunction.Append("icon.iconAnchor = new GPoint(iconAnchorX, iconAnchorY);\n");
sOverLayFunction.Append("icon.infoWindowAnchor = new GPoint(infoWinX, infoWinY);\n");
sOverLayFunction.Append("var marker = new GMarker(point,icon);\n");
sOverLayFunction.Append("if ( popup==1 ) { \n");
sOverLayFunction.Append("GEvent.addListener(marker, 'click', function() {");
sOverLayFunction.Append("marker.openInfoWindowHtml(sFormattedHtml);});");
sOverLayFunction.Append(" } \n");
sOverLayFunction.AppendFormat("{0}.push(marker);\n",sArrayVariable);
sOverLayFunction.Append(" }");
return sOverLayFunction.ToString();

}

///
/// Method to generate the Javascript function to overlay a line
/// on the map
///
/// Variable representing the array
/// Client ID of the control
/// JavaScript function as a string
public string GenerateOverlayLineFuncCall(string sArrayVariable, string sControlClientID)
{
StringBuilder sOverLayFunction = new StringBuilder();
sOverLayFunction.AppendFormat(" function OverlayLine{0}(PointArray,weight,Color,opacity)\n",sControlClientID );
sOverLayFunction.Append("{\n");
sOverLayFunction.Append("var polyline = new GPolyline(PointArray,Color,weight,opacity);");
sOverLayFunction.AppendFormat("{0}.push(polyline);\n",sArrayVariable);
sOverLayFunction.Append(" }");
return sOverLayFunction.ToString();
}
///
/// Method to Overlay points on the map
/// Instead of overlaying each point or lay individually
/// it stores them in an array and overlays them together
///
/// JavaScript code as string
public string GenerateNewOverLayFunction()
{
// The credit for the method goes to Lokkju and is available
// on the google group for Google Maps
StringBuilder sOverLayFunction = new StringBuilder();
sOverLayFunction.Append("GMap.prototype.addOverlays=function(a)\n");
sOverLayFunction.Append("{ var b=this;\n ");
sOverLayFunction.Append(" for (i=0;iVariable representing the map
/// Client ID of the control
/// JavaScript function as a string
///
/// function ZoomIn(clong,cLat,ZoomLevel)
/// {
/// map.centerAndZoom(new GPoint(clong,cLat), ZoomLevel);
/// }
///
public string GenerateZoomInFunction(string sGMapVariable ,string sClientID)
{
StringBuilder sZoomInFunction = new StringBuilder();
//Generate a unique Name for the function
sZoomInFunction.AppendFormat("function ZoomIn{0}(clong,cLat,ZoomLevel)",sClientID);
sZoomInFunction.Append("\n{");
sZoomInFunction.AppendFormat("{0}.centerAndZoom(new GPoint(clong,cLat),ZoomLevel)",sGMapVariable );
sZoomInFunction.Append("\n; }");
return sZoomInFunction.ToString();
}
///
/// Utility Method to generate JavaScript code to Set the Map type
///
/// The Type of Map
/// Variable representing the Google Map object
/// Javascript code as string
public string GenerateMapType(GMapType mapType,string sGMapVariable)
{
string sMapType=string.Empty;
switch(mapType)
{
case GMapType.MAP :
// SL - changed
sMapType = "G_NORMAL_MAP";
break;
case GMapType.HYBRID:
// SL - changed
sMapType = "G_HYBRID_MAP";
break;
case GMapType.SATELLITE :
// SL - changed
sMapType = "G_SATELLITE_MAP";
break;
default:
// SL - changed
sMapType = "G_NORMAL_MAP";
break;
}
return string.Format("{0}.setMapType({1});\n",sGMapVariable,sMapType);
}
///
/// Method that generates JavaScript code to Initialize the map Variable
///
/// Variable representing the map
/// Client ID of the control
/// Set if the map can be dragged
/// set if there can be pop up windows on the map
/// set if the map Type can be changed
/// JavaScript code as string
public string GenerateGMapVariableInitialization(string sGMapVariable, string sClientID,bool bEnableDrag,bool bEnableInfoWindow, bool bEnableMapTypeControl)
{
StringBuilder sInitVarBuilder= new StringBuilder();
sInitVarBuilder.AppendFormat("{1} =new GMap(document.getElementById('{0}'));\n",sClientID,sGMapVariable);
if(!bEnableDrag)
sInitVarBuilder.AppendFormat("{0}.disableDragging() ;\n",sGMapVariable);
if(!bEnableInfoWindow)
sInitVarBuilder.AppendFormat("{0}.disableInfoWindow() ;\n",sGMapVariable);
if( bEnableMapTypeControl)
sInitVarBuilder.AppendFormat("{0}.addControl(new GMapTypeControl()) ;\n",sGMapVariable);
return sInitVarBuilder.ToString();
}
///
/// Method to Generat the JavaScript code to set the type of
/// Scroll Control on the Map
///
/// The Scroll Control to be added
/// Variable representing the Google Map
/// Javascript code as string
public string GenerateScrollControl(GMapScrollControl scrollType, string sGmapVariable)
{
string sScrollType=string.Empty;
switch (scrollType)
{
case GMapScrollControl.LARGE:
sScrollType= string.Format(" {0}.addControl(new GLargeMapControl());\n",sGmapVariable);
break;
case GMapScrollControl.SMALL :
sScrollType=string.Format(" {0}.addControl(new GSmallMapControl());\n",sGmapVariable);
break;
case GMapScrollControl.SMALLZOOMONLY:
sScrollType=string.Format(" {0}.addControl(new GSmallZoomControl());\n",sGmapVariable);
break;
case GMapScrollControl.NONE:
default:
sScrollType=string.Empty;
break;

}
return sScrollType;
}

}
}

Monday, December 08, 2008

Good pages for Microsoft Chart Control

I'm really quite enjoying getting the Microsoft Chart Control to produce lots of wonderful effects....

It's really very easy to program against, and very powerful

However, it's not the easiest thing to find out information about - mainly because it's so young.

The pages I've found most helpful so far are:

Haversine formula

I'm sure I've been through this calculation before somewhere....

And it kind of made me sad that today instead of trying to work out for myself how to get from lat and long to x and y... I just googled a solution.

Here were some of the better (quicker to understand) answers in C#
The first also contains some excellent unit tests - good on him :)

My own eventual code merged the two together....


/// Calculates the distance between two points of latitude and longitude.
/// Great Link - http://www.movable-type.co.uk/scripts/latlong.html
/// lat1 - First coordinate.
/// long1 - First coordinate.
/// lat2 - Second coordinate.
/// long2 - Second coordinate.
/// unitsOfLength - Sets the return value unit of length - m for metres, k for kilometres, anything else for (non-mautical)miles
/// the distance
public static Double Distance(double lat1, double lon1, double lat2, double lon2, char unitsOfLength)
{
var theta = lon1 - lon2;

var distance = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) +
Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) *
Math.Cos(deg2rad(theta));

distance = Math.Acos(distance);
distance = rad2deg(distance);
distance = distance * 60 * 1.1515;

if (unitsOfLength == 'k')
distance = distance * 1.609344/*_MilesToKilometers*/;

else if (unitsOfLength == 'm')
distance = distance * 1609.344/*_MilesToKilometers*/;

return (distance);
}

private static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}

private static double rad2deg(double rad) {
return (rad / Math.PI * 180.0);
}

More on chart colors...

The Palette object (used in Dundas and Microsoft Charts) has been thoroughly dissected and document here - these arrays might help me make my code output look less ugly in the future? (Might)


public static Color[] GetColorPalette(ChartColorPalette palette, bool isSemiTranparent)
{
Color[] paletteColors = null;
int colorAlpha;
if (isSemiTranparent)
colorAlpha = 200;
else
colorAlpha = 255;

switch (palette)
{
case ChartColorPalette.Berry:
paletteColors = new Color[11];
paletteColors[0] = Color.FromArgb(colorAlpha, 138, 43, 226);
paletteColors[1] = Color.FromArgb(colorAlpha, 186, 85, 211);
paletteColors[2] = Color.FromArgb(colorAlpha, 65, 105, 225);
paletteColors[3] = Color.FromArgb(colorAlpha, 199, 21, 133);
paletteColors[4] = Color.FromArgb(colorAlpha, 0, 0, 255);
paletteColors[5] = Color.FromArgb(colorAlpha, 138, 43, 226);
paletteColors[6] = Color.FromArgb(colorAlpha, 218, 112, 214);
paletteColors[7] = Color.FromArgb(colorAlpha, 123, 104, 238);
paletteColors[8] = Color.FromArgb(colorAlpha, 192, 0, 192);
paletteColors[9] = Color.FromArgb(colorAlpha, 0, 0, 205);
paletteColors[10] = Color.FromArgb(colorAlpha, 128, 0, 128);
break;
case ChartColorPalette.Chocolate:
paletteColors = new Color[10];
paletteColors[0] = Color.FromArgb(colorAlpha, 160, 82, 45);
paletteColors[1] = Color.FromArgb(colorAlpha, 210, 105, 30);
paletteColors[2] = Color.FromArgb(colorAlpha, 139, 0, 0);
paletteColors[3] = Color.FromArgb(colorAlpha, 205, 133, 63);
paletteColors[4] = Color.FromArgb(colorAlpha, 165, 42, 42);
paletteColors[5] = Color.FromArgb(colorAlpha, 244, 164, 96);
paletteColors[6] = Color.FromArgb(colorAlpha, 139, 69, 19);
paletteColors[7] = Color.FromArgb(colorAlpha, 192, 64, 0);
paletteColors[8] = Color.FromArgb(colorAlpha, 178, 34, 34);
paletteColors[9] = Color.FromArgb(colorAlpha, 182, 92, 58);
break;
case ChartColorPalette.Default:
paletteColors = new Color[16];
paletteColors[0] = Color.FromArgb(colorAlpha, 0, 128, 0);
paletteColors[1] = Color.FromArgb(colorAlpha, 0, 0, 255);
paletteColors[2] = Color.FromArgb(colorAlpha, 128, 0, 128);
paletteColors[3] = Color.FromArgb(colorAlpha, 0, 255, 0);
paletteColors[4] = Color.FromArgb(colorAlpha, 255, 0, 255);
paletteColors[5] = Color.FromArgb(colorAlpha, 0, 128, 128);
paletteColors[6] = Color.FromArgb(colorAlpha, 255, 255, 0);
paletteColors[7] = Color.FromArgb(colorAlpha, 128, 128, 128);
paletteColors[8] = Color.FromArgb(colorAlpha, 0, 255, 255);
paletteColors[9] = Color.FromArgb(colorAlpha, 0, 0, 128);
paletteColors[10] = Color.FromArgb(colorAlpha, 128, 0, 0);
paletteColors[11] = Color.FromArgb(colorAlpha, 255, 0, 0);
paletteColors[12] = Color.FromArgb(colorAlpha, 128, 128, 0);
paletteColors[13] = Color.FromArgb(colorAlpha, 192, 192, 192);
paletteColors[14] = Color.FromArgb(colorAlpha, 255, 99, 71);
paletteColors[15] = Color.FromArgb(colorAlpha, 255, 228, 181);
break;
case ChartColorPalette.Dundas:
paletteColors = new Color[15];
paletteColors[0] = Color.FromArgb(colorAlpha, 65, 140, 240);
paletteColors[1] = Color.FromArgb(colorAlpha, 252, 180, 65);
paletteColors[2] = Color.FromArgb(colorAlpha, 224, 64, 10);
paletteColors[3] = Color.FromArgb(colorAlpha, 5, 100, 146);
paletteColors[4] = Color.FromArgb(colorAlpha, 191, 191, 191);
paletteColors[5] = Color.FromArgb(colorAlpha, 26, 59, 105);
paletteColors[6] = Color.FromArgb(colorAlpha, 255, 227, 130);
paletteColors[7] = Color.FromArgb(colorAlpha, 18, 156, 221);
paletteColors[8] = Color.FromArgb(colorAlpha, 202, 107, 75);
paletteColors[9] = Color.FromArgb(colorAlpha, 0, 92, 219);
paletteColors[10] = Color.FromArgb(colorAlpha, 243, 210, 136);
paletteColors[11] = Color.FromArgb(colorAlpha, 80, 99, 129);
paletteColors[12] = Color.FromArgb(colorAlpha, 241, 185, 168);
paletteColors[13] = Color.FromArgb(colorAlpha, 224, 131, 10);
paletteColors[14] = Color.FromArgb(colorAlpha, 120, 147, 190);
break;
case ChartColorPalette.EarthTones:
paletteColors = new Color[16];
paletteColors[0] = Color.FromArgb(colorAlpha, 255, 128, 0);
paletteColors[1] = Color.FromArgb(colorAlpha, 184, 134, 11);
paletteColors[2] = Color.FromArgb(colorAlpha, 192, 64, 0);
paletteColors[3] = Color.FromArgb(colorAlpha, 107, 142, 35);
paletteColors[4] = Color.FromArgb(colorAlpha, 205, 133, 63);
paletteColors[5] = Color.FromArgb(colorAlpha, 192, 192, 0);
paletteColors[6] = Color.FromArgb(colorAlpha, 34, 139, 34);
paletteColors[7] = Color.FromArgb(colorAlpha, 210, 105, 30);
paletteColors[8] = Color.FromArgb(colorAlpha, 128, 128, 0);
paletteColors[9] = Color.FromArgb(colorAlpha, 32, 178, 170);
paletteColors[10] = Color.FromArgb(colorAlpha, 244, 164, 96);
paletteColors[11] = Color.FromArgb(colorAlpha, 0, 192, 0);
paletteColors[12] = Color.FromArgb(colorAlpha, 143, 188, 139);
paletteColors[13] = Color.FromArgb(colorAlpha, 178, 34, 34);
paletteColors[14] = Color.FromArgb(colorAlpha, 139, 69, 19);
paletteColors[15] = Color.FromArgb(colorAlpha, 192, 0, 0);
break;
case ChartColorPalette.Excel:
paletteColors = new Color[16];
paletteColors[0] = Color.FromArgb(colorAlpha, 153, 153, 255);
paletteColors[1] = Color.FromArgb(colorAlpha, 153, 51, 102);
paletteColors[2] = Color.FromArgb(colorAlpha, 255, 255, 204);
paletteColors[3] = Color.FromArgb(colorAlpha, 204, 255, 255);
paletteColors[4] = Color.FromArgb(colorAlpha, 102, 0, 102);
paletteColors[5] = Color.FromArgb(colorAlpha, 255, 128, 128);
paletteColors[6] = Color.FromArgb(colorAlpha, 0, 102, 204);
paletteColors[7] = Color.FromArgb(colorAlpha, 204, 204, 255);
paletteColors[8] = Color.FromArgb(colorAlpha, 0, 0, 128);
paletteColors[9] = Color.FromArgb(colorAlpha, 255, 0, 255);
paletteColors[10] = Color.FromArgb(colorAlpha, 255, 255, 0);
paletteColors[11] = Color.FromArgb(colorAlpha, 0, 255, 255);
paletteColors[12] = Color.FromArgb(colorAlpha, 128, 0, 128);
paletteColors[13] = Color.FromArgb(colorAlpha, 128, 0, 0);
paletteColors[14] = Color.FromArgb(colorAlpha, 0, 128, 128);
paletteColors[15] = Color.FromArgb(colorAlpha, 0, 0, 255);
break;
case ChartColorPalette.Fire:
paletteColors = new Color[10];
paletteColors[0] = Color.FromArgb(colorAlpha, 255, 215, 0);
paletteColors[1] = Color.FromArgb(colorAlpha, 255, 0, 0);
paletteColors[2] = Color.FromArgb(colorAlpha, 255, 20, 147);
paletteColors[3] = Color.FromArgb(colorAlpha, 220, 20, 60);
paletteColors[4] = Color.FromArgb(colorAlpha, 255, 140, 0);
paletteColors[5] = Color.FromArgb(colorAlpha, 255, 0, 255);
paletteColors[6] = Color.FromArgb(colorAlpha, 255, 255, 0);
paletteColors[7] = Color.FromArgb(colorAlpha, 255, 69, 0);
paletteColors[8] = Color.FromArgb(colorAlpha, 199, 21, 133);
paletteColors[9] = Color.FromArgb(colorAlpha, 221, 226, 33);
break;
case ChartColorPalette.GrayScale:
paletteColors = new Color[16];
paletteColors[1] = Color.FromArgb(colorAlpha, 189, 189, 189);
paletteColors[2] = Color.FromArgb(colorAlpha, 178, 178, 178);
paletteColors[3] = Color.FromArgb(colorAlpha, 167, 167, 167);
paletteColors[4] = Color.FromArgb(colorAlpha, 156, 156, 156);
paletteColors[5] = Color.FromArgb(colorAlpha, 145, 145, 145);
paletteColors[6] = Color.FromArgb(colorAlpha, 134, 134, 134);
paletteColors[7] = Color.FromArgb(colorAlpha, 123, 123, 123);
paletteColors[8] = Color.FromArgb(colorAlpha, 112, 112, 112);
paletteColors[9] = Color.FromArgb(colorAlpha, 101, 101, 101);
paletteColors[10] = Color.FromArgb(colorAlpha, 90, 90, 90);
paletteColors[11] = Color.FromArgb(colorAlpha, 79, 79, 79);
paletteColors[12] = Color.FromArgb(colorAlpha, 68, 68, 68);
paletteColors[13] = Color.FromArgb(colorAlpha, 57, 57, 57);
paletteColors[14] = Color.FromArgb(colorAlpha, 46, 46, 46);
paletteColors[15] = Color.FromArgb(colorAlpha, 35, 35, 35);
break;
case ChartColorPalette.Light:
paletteColors = new Color[10];
paletteColors[0] = Color.FromArgb(colorAlpha, 230, 230, 250);
paletteColors[1] = Color.FromArgb(colorAlpha, 255, 240, 245);
paletteColors[2] = Color.FromArgb(colorAlpha, 255, 218, 185);
paletteColors[3] = Color.FromArgb(colorAlpha, 255, 250, 205);
paletteColors[4] = Color.FromArgb(colorAlpha, 255, 228, 225);
paletteColors[5] = Color.FromArgb(colorAlpha, 240, 255, 240);
paletteColors[6] = Color.FromArgb(colorAlpha, 240, 248, 255);
paletteColors[7] = Color.FromArgb(colorAlpha, 245, 245, 245);
paletteColors[8] = Color.FromArgb(colorAlpha, 250, 235, 215);
paletteColors[9] = Color.FromArgb(colorAlpha, 224, 255, 255);
break;
case ChartColorPalette.Pastel:
paletteColors = new Color[16];
paletteColors[0] = Color.FromArgb(colorAlpha, 135, 206, 235);
paletteColors[1] = Color.FromArgb(colorAlpha, 50, 205, 50);
paletteColors[2] = Color.FromArgb(colorAlpha, 186, 85, 211);
paletteColors[3] = Color.FromArgb(colorAlpha, 240, 128, 128);
paletteColors[4] = Color.FromArgb(colorAlpha, 70, 130, 180);
paletteColors[5] = Color.FromArgb(colorAlpha, 154, 205, 50);
paletteColors[6] = Color.FromArgb(colorAlpha, 64, 224, 208);
paletteColors[7] = Color.FromArgb(colorAlpha, 255, 105, 180);
paletteColors[8] = Color.FromArgb(colorAlpha, 240, 230, 140);
paletteColors[9] = Color.FromArgb(colorAlpha, 210, 180, 140);
paletteColors[10] = Color.FromArgb(colorAlpha, 143, 188, 139);
paletteColors[11] = Color.FromArgb(colorAlpha, 100, 149, 237);
paletteColors[12] = Color.FromArgb(colorAlpha, 221, 160, 221);
paletteColors[13] = Color.FromArgb(colorAlpha, 95, 158, 160);
paletteColors[14] = Color.FromArgb(colorAlpha, 255, 218, 185);
paletteColors[15] = Color.FromArgb(colorAlpha, 255, 160, 122);
break;
case ChartColorPalette.SeaGreen:
paletteColors = new Color[10];
paletteColors[0] = Color.FromArgb(colorAlpha, 46, 139, 87);
paletteColors[1] = Color.FromArgb(colorAlpha, 102, 205, 170);
paletteColors[2] = Color.FromArgb(colorAlpha, 70, 130, 180);
paletteColors[3] = Color.FromArgb(colorAlpha, 0, 139, 139);
paletteColors[4] = Color.FromArgb(colorAlpha, 95, 158, 160);
paletteColors[5] = Color.FromArgb(colorAlpha, 60, 179, 113);
paletteColors[6] = Color.FromArgb(colorAlpha, 72, 209, 204);
paletteColors[7] = Color.FromArgb(colorAlpha, 176, 196, 222);
paletteColors[8] = Color.FromArgb(colorAlpha, 143, 188, 139);
paletteColors[9] = Color.FromArgb(colorAlpha, 135, 206, 235);
break;
}

return paletteColors;
}

Integrating GoogleMaps into ASP.NET

I started looking at GoogleMaps solutions...

And decided on this one -http://dotnet.sys-con.com/node/171162 - simply because I liked the article format and because I thought the code format (custom control) looked easiest to integrate and maintain.

Sadly though the code is a bit out of date (it dates back to an old v1 beta API!) so there are some fixes to do:
- I fixed the addOverlays and reOrderOverlays bugs - see the comments on that article
- I fixed the MAP_TYPE type bugs

If there are other fixes then refer here for some inspiration - http://code.google.com/apis/maps/documentation/upgrade.html#MapTypeNames

There are other implementations around - e.g. http://www.shabdar.org/google-maps-user-control-for-ASP-Net-part1.html - if maintenance proves too hard then I may switch to there!

An easy way to add a stylesheet to a header from an ASP.NET control

This was suggested in a comment at the bottom of this codeproject article - really quite a neat solution :)

private bool AddStyleSheetToPageHeader(string uniqueId, string href)
{
if (Page.Header.FindControl(uniqueId) == null)
{
Literal l = new Literal();
l.Text = string.Format(@"<link rel="'stylesheet'" href="'{0}'" type="'text/css'">", href);
l.ID = uniqueId;
Page.Header.Controls.Add(l);
return true;
}

return false;
}


It means this can be written as Page_Load:
protected void Page_Load(object sender, EventArgs e)
{
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
scriptManager.Scripts.Add(new ScriptReference(@"http://yui.yahooapis.com/2.6.0/build/utilities/utilities.js"));
scriptManager.Scripts.Add(new ScriptReference(@"http://yui.yahooapis.com/2.6.0/build/slider/slider-min.js"));
scriptManager.Scripts.Add(new ScriptReference(@"http://yui.yahooapis.com/2.6.0/build/colorpicker/colorpicker-min.js"));

if (AddStyleSheetToPageHeader("DesktopModules_SlodgeRoutes_SubControls_FilterSetupControl_ColorPicker", "http://yui.yahooapis.com/2.6.0/build/colorpicker/assets/skins/sam/colorpicker.css"))
{
// any one time init stuff
}
}
}

(Example shown is Yahoo UI Color picker)

Sunday, December 07, 2008

Instead of using colors...

In my last post I had a go at creating a color array for related segments in a pie chart....

But actually.... using the same color but a different hatch style works much better:

private static List HatchArray = new List()
{
ChartHatchStyle.None,
ChartHatchStyle.Percent10,
ChartHatchStyle.Percent20,
ChartHatchStyle.Percent30,
ChartHatchStyle.Percent40,
ChartHatchStyle.Percent50,
ChartHatchStyle.SmallCheckerBoard,
ChartHatchStyle.Trellis,
ChartHatchStyle.ZigZag,
ChartHatchStyle.Wave,
ChartHatchStyle.LargeConfetti,
ChartHatchStyle.DottedDiamond,
ChartHatchStyle.Cross,
ChartHatchStyle.OutlinedDiamond
};


coupled with:

int runListColorIndex = 0;
int bikeListColorIndex = 0;
int swimListColorIndex = 0;
foreach (DataPoint p in series.Points)
{
ChartHatchStyle hatchStyle = ChartHatchStyle.None;
Color colorToUse = Color.ForestGreen;
switch (p.AxisLabel[0])
{
case 'R':
colorToUse = myCurrentFilterOptions.RunColor;
hatchStyle = HatchArray[runListColorIndex];
runListColorIndex++;
runListColorIndex %= HatchArray.Count;
break;

case 'B':
colorToUse = myCurrentFilterOptions.BikeColor;
hatchStyle = HatchArray[bikeListColorIndex];
bikeListColorIndex++;
bikeListColorIndex %= HatchArray.Count;
break;

case 'S':
colorToUse = myCurrentFilterOptions.SwimColor;
hatchStyle = HatchArray[swimListColorIndex];
swimListColorIndex++;
swimListColorIndex %= HatchArray.Count;
break;
}
p.Color = colorToUse;
p.BackHatchStyle = hatchStyle;
}

Creating a color list

While setting up an ASP.Net Pie Chart Control, I wanted to create some sets of colors for subcategories within the chart.

To do this, I tried code like:

private List PieChartColorList(Color baseColor)
{
List list = new List();
list.Add(baseColor);
for (int i = 0; i < 5; i++)
{
list.Add(System.Windows.Forms.ControlPaint.Dark(baseColor, 0.25F - i * 0.05F));
list.Add(System.Windows.Forms.ControlPaint.Light(baseColor, 0.25F- i * 0.05F));
}
return list;
}

using the ControlPaint tip from (http://www.csharp411.com/lighten-and-darken-colors-in-net/) - but it didn't work very well....

Someone's asked for my hack of JsonWriter from Facebook.NET

Got an email today asking for the source to HackJsonWriter - the code I ripped out of Facebook.NET on Codeplex - as described here.

If you want to include this code in your projects then you probably need to add a comment attributing it back to Facebook.NET -not sure what the open source license is on that project (but it should be OK as you'll be using Facebook.NET anyway)

Also, importantly.... unless you are updating an old project, my advice is do not use Facebook.NET - the FacebookToolkit from Microsoft (also on Codeplex) looks a much better way to go!

Here's the very longwinded code:

using System;

using System.Collections.Generic;

using System.Web;

using System.Text;

using System.Globalization;

using System.Collections;

using System.ComponentModel;

using System.IO;

internal sealed class IndentedTextWriter : TextWriter

{

// Fields

private int _indentLevel;

private bool _minimize;

private bool _tabsPending;

private string _tabString;

private TextWriter _writer;

// Methods

public IndentedTextWriter(TextWriter writer, bool minimize) : base(CultureInfo.InvariantCulture)

{

this._writer = writer;

this._minimize = minimize;

if (this._minimize)

{

this.NewLine = "\r";

}

this._tabString = " ";

this._indentLevel = 0;

this._tabsPending = false;

}

public override void Close()

{

this._writer.Close();

}

public override void Flush()

{

this._writer.Flush();

}

private void OutputTabs()

{

if (this._tabsPending)

{

if (!this._minimize)

{

for (int i = 0; i < this._indentLevel; i++)

{

this._writer.Write(this._tabString);

}

}

this._tabsPending = false;

}

}

public override void Write(bool value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(char value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(string s)

{

this.OutputTabs();

this._writer.Write(s);

}

public override void Write(char[] buffer)

{

this.OutputTabs();

this._writer.Write(buffer);

}

public override void Write(double value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(int value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(long value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(object value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(float value)

{

this.OutputTabs();

this._writer.Write(value);

}

public override void Write(string format, params object[] arg)

{

this.OutputTabs();

this._writer.Write(format, arg);

}

public override void Write(string format, object arg0)

{

this.OutputTabs();

this._writer.Write(format, arg0);

}

public override void Write(char[] buffer, int index, int count)

{

this.OutputTabs();

this._writer.Write(buffer, index, count);

}

public override void Write(string format, object arg0, object arg1)

{

this.OutputTabs();

this._writer.Write(format, arg0, arg1);

}

public override void WriteLine()

{

this.OutputTabs();

this._writer.WriteLine();

this._tabsPending = true;

}

public override void WriteLine(bool value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(char value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(double value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(int value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(char[] buffer)

{

this.OutputTabs();

this._writer.WriteLine(buffer);

this._tabsPending = true;

}

public override void WriteLine(long value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(object value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(float value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(string s)

{

this.OutputTabs();

this._writer.WriteLine(s);

this._tabsPending = true;

}

public override void WriteLine(uint value)

{

this.OutputTabs();

this._writer.WriteLine(value);

this._tabsPending = true;

}

public override void WriteLine(string format, params object[] arg)

{

this.OutputTabs();

this._writer.WriteLine(format, arg);

this._tabsPending = true;

}

public override void WriteLine(string format, object arg0)

{

this.OutputTabs();

this._writer.WriteLine(format, arg0);

this._tabsPending = true;

}

public override void WriteLine(string format, object arg0, object arg1)

{

this.OutputTabs();

this._writer.WriteLine(format, arg0, arg1);

this._tabsPending = true;

}

public override void WriteLine(char[] buffer, int index, int count)

{

this.OutputTabs();

this._writer.WriteLine(buffer, index, count);

this._tabsPending = true;

}

public void WriteLineNoTabs(string s)

{

this._writer.WriteLine(s);

}

public void WriteNewLine()

{

if (!this._minimize)

{

this.WriteLine();

}

}

public void WriteSignificantNewLine()

{

this.WriteLine();

}

public void WriteTrimmed(string text)

{

if (!this._minimize)

{

this.Write(text);

}

else

{

this.Write(text.Trim());

}

}

// Properties

public override Encoding Encoding

{

get

{

return this._writer.Encoding;

}

}

public int Indent

{

get

{

return this._indentLevel;

}

set

{

if (value <>

{

value = 0;

}

this._indentLevel = value;

}

}

public override string NewLine

{

get

{

return this._writer.NewLine;

}

set

{

this._writer.NewLine = value;

}

}

}

///

/// Summary description for HackJsonWriter

///

public class HackJsonWriter

{

// Fields

private Stack _scopes;

private IndentedTextWriter _writer;

// Methods

public HackJsonWriter(TextWriter writer)

: this(writer, true)

{

}

public HackJsonWriter(TextWriter writer, bool minimizeWhitespace)

{

this._writer = new IndentedTextWriter(writer, minimizeWhitespace);

this._scopes = new Stack();

}

public void EndScope()

{

if (this._scopes.Count == 0)

{

throw new InvalidOperationException("No active scope to end.");

}

this._writer.WriteLine();

this._writer.Indent--;

if (this._scopes.Pop().Type == ScopeType.Array)

{

this._writer.Write("]");

}

else

{

this._writer.Write("}");

}

}

internal static string QuoteJScriptString(string s)

{

if (string.IsNullOrEmpty(s))

{

return string.Empty;

}

StringBuilder builder = null;

int startIndex = 0;

int count = 0;

for (int i = 0; i <>

{

char ch = s[i];

if ((((ch == '\r') || (ch == '\t')) || ((ch == '"') || (ch == '\''))) || (((ch == '\\') || (ch == '\r')) || ((ch < ' ') || (ch > '\x007f'))))

{

if (builder == null)

{

builder = new StringBuilder(s.Length + 6);

}

if (count > 0)

{

builder.Append(s, startIndex, count);

}

startIndex = i + 1;

count = 0;

}

switch (ch)

{

case '\'':

{

builder.Append(@"\'");

continue;

}

case '\\':

{

builder.Append(@"\\");

continue;

}

case '\t':

{

builder.Append(@"\t");

continue;

}

case '\n':

{

builder.Append(@"\n");

continue;

}

case '\r':

{

builder.Append(@"\r");

continue;

}

case '"':

{

builder.Append("\\\"");

continue;

}

}

if ((ch < ' ') || (ch > '\x007f'))

{

builder.AppendFormat(CultureInfo.InvariantCulture, @"\u{0:x4}", new object[] { (int)ch });

}

else

{

count++;

}

}

string str = s;

if (builder == null)

{

return str;

}

if (count > 0)

{

builder.Append(s, startIndex, count);

}

return builder.ToString();

}

public void StartArrayScope()

{

this.StartScope(ScopeType.Array);

}

public void StartObjectScope()

{

this.StartScope(ScopeType.Object);

}

private void StartScope(ScopeType type)

{

if (this._scopes.Count != 0)

{

Scope scope = this._scopes.Peek();

if ((scope.Type == ScopeType.Array) && (scope.ObjectCount != 0))

{

this._writer.WriteTrimmed(", ");

}

scope.ObjectCount++;

}

Scope item = new Scope(type);

this._scopes.Push(item);

if (type == ScopeType.Array)

{

this._writer.Write("[");

}

else

{

this._writer.Write("{");

}

this._writer.Indent++;

this._writer.WriteLine();

}

private void WriteCore(string text, bool quotes)

{

if (this._scopes.Count != 0)

{

Scope scope = this._scopes.Peek();

if (scope.Type == ScopeType.Array)

{

if (scope.ObjectCount != 0)

{

this._writer.WriteTrimmed(", ");

}

scope.ObjectCount++;

}

}

if (quotes)

{

this._writer.Write('"');

}

this._writer.Write(text);

if (quotes)

{

this._writer.Write('"');

}

}

public void WriteName(string name)

{

if (string.IsNullOrEmpty(name))

{

throw new ArgumentNullException("name");

}

if (this._scopes.Count == 0)

{

throw new InvalidOperationException("No active scope to write into.");

}

if (this._scopes.Peek().Type != ScopeType.Object)

{

throw new InvalidOperationException("Names can only be written into Object scopes.");

}

Scope scope = this._scopes.Peek();

if (scope.Type == ScopeType.Object)

{

if (scope.ObjectCount != 0)

{

this._writer.WriteTrimmed(", ");

}

scope.ObjectCount++;

}

this._writer.Write("\"");

this._writer.Write(name);

this._writer.WriteTrimmed("\": ");

}

public void WriteValue(bool value)

{

this.WriteCore(value ? "true" : "false", false);

}

public void WriteValue(ICollection items)

{

if ((items == null) || (items.Count == 0))

{

this.WriteCore("[]", false);

}

else

{

this.StartArrayScope();

foreach (object obj2 in items)

{

this.WriteValue(obj2);

}

this.EndScope();

}

}

public void WriteValue(IDictionary record)

{

if ((record == null) || (record.Count == 0))

{

this.WriteCore("{}", false);

}

else

{

this.StartObjectScope();

foreach (DictionaryEntry entry in record)

{

string key = entry.Key as string;

if (string.IsNullOrEmpty(key))

{

throw new ArgumentException("Key of unsupported type contained in Hashtable.");

}

this.WriteName(key);

this.WriteValue(entry.Value);

}

this.EndScope();

}

}

internal static readonly DateTime MinDate;

internal static readonly long MinDateTimeTicks;

// Methods

static HackJsonWriter()

{

DateTime time = new DateTime(0x7b2, 1, 1, 0, 0, 0);

MinDateTimeTicks = time.Ticks;

MinDate = new DateTime(100, 1, 1, 0, 0, 0);

}

public void WriteValue(DateTime dateTime)

{

if (dateTime <>

{

throw new ArgumentOutOfRangeException("dateTime");

}

this.WriteCore(@"\@" + (((dateTime.Ticks - HackJsonWriter.MinDateTimeTicks) / 0x2710L)).ToString(CultureInfo.InvariantCulture) + "@", true);

}

public void WriteValue(double value)

{

this.WriteCore(value.ToString(CultureInfo.InvariantCulture), false);

}

public void WriteValue(int value)

{

this.WriteCore(value.ToString(CultureInfo.InvariantCulture), false);

}

public void WriteValue(object o)

{

if (o == null)

{

this.WriteCore("null", false);

}

else if (o is bool)

{

this.WriteValue((bool)o);

}

else if (o is int)

{

this.WriteValue((int)o);

}

else if (o is float)

{

this.WriteValue((float)o);

}

else if (o is double)

{

this.WriteValue((double)o);

}

else if (o is DateTime)

{

this.WriteValue((DateTime)o);

}

else if (o is string)

{

this.WriteValue((string)o);

}

else if (o is IDictionary)

{

this.WriteValue((IDictionary)o);

}

else if (o is ICollection)

{

this.WriteValue((ICollection)o);

}

else

{

this.StartObjectScope();

foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(o))

{

this.WriteName(descriptor.Name);

this.WriteValue(descriptor.GetValue(o));

}

this.EndScope();

}

}

public void WriteValue(float value)

{

this.WriteCore(value.ToString(CultureInfo.InvariantCulture), false);

}

public void WriteValue(string s)

{

if (s == null)

{

this.WriteCore("null", false);

}

else

{

this.WriteCore(QuoteJScriptString(s), true);

}

}

// Nested Types

private sealed class Scope

{

// Fields

private int _objectCount;

private HackJsonWriter.ScopeType _type;

// Methods

public Scope(HackJsonWriter.ScopeType type)

{

this._type = type;

}

// Properties

public int ObjectCount

{

get

{

return this._objectCount;

}

set

{

this._objectCount = value;

}

}

public HackJsonWriter.ScopeType Type

{

get

{

return this._type;

}

}

}

private enum ScopeType

{

Array,

Object

}

}