Tuesday 11 August 2009

Determining the size of a Silverlight multi-scale image deep zoom source

Had a bit of a problem today trying to set a multi-scale image with a deep zoom source to fit the height. Fitting the width is easy:

   1: //Reset origin
   2: multiSourceImage.ViewportOrigin = new Point(0, 0);
   3: multiSourceImage.ViewportWidth = 1;

That is right you are just setting the viewport width to 1 which makes sense!! But unfortunately there is no such thing as a viewport height. So another way is required:

   1: //locals
   2: double lastRow = -1;
   3: double lastBottom = 0.0;
   4: double height = 0.0;
   5: bool firstRow = true;
   6:  
   7: //Loop over images
   8: foreach (MultiScaleSubImage subImage in multiSourceImage.SubImages)
   9: {
  10:     //Have we reached a new row ? (NB this only works with images layed out in a grid)
  11:     if (subImage.ViewportOrigin.Y != lastRow)
  12:     {
  13:         //Have new row
  14:         //Take aspect ratio of image here
  15:         lastRow = subImage.ViewportOrigin.Y;
  16:  
  17:         //Work out bottom of image - to get to gap
  18:         double width = multiSourceImage.ActualWidth / (multiSourceImage.ViewportWidth * subImage.ViewportWidth);
  19:         double height2 = multiSourceImage.ActualWidth / (multiSourceImage.ViewportWidth * subImage.ViewportWidth * subImage.AspectRatio);
  20:  
  21:         Point pos = multiSourceImage.LogicalToElementPoint(new Point(
  22:             -subImage.ViewportOrigin.X / subImage.ViewportWidth,
  23:             -subImage.ViewportOrigin.Y / subImage.ViewportWidth)
  24:         );
  25:         Rect rect = new Rect(pos.X, pos.Y, width, height2);
  26:  
  27:         //Work out gap
  28:         double gapHeight = rect.Top - lastBottom;
  29:         lastBottom = rect.Bottom;
  30:  
  31:         //height += height2;
  32:         height += (multiSourceImage.ActualWidth / subImage.ViewportWidth) * 1 / (subImage.AspectRatio);
  33:         if (!firstRow)
  34:             height += gapHeight;
  35:         firstRow = false;
  36:     }
  37: }
  38:  
  39: //Set to actual height here
  40: multiSourceImage.ViewportWidth = height / multiSourceImage.ActualHeight;            
  41: multiSourceImage.ViewportOrigin = new Point(0, 0);

As noted in the notes, this only works if the images are in a nice gridded layout. I guess you can modify it to work with the left hand most image of each row.

It basically works by looping over each sub image. Seeing if that image is on a new line, if it is record its origin y co-ordinate.

For any subsequent rows, work out the gap between the bottom of the image in the row above, and add those dimensions to a running total.

You can work out the height of a sub image simply by



   1: subImageHeight = multiSourceImage.ActualWidth / (subImage.ViewPortWidth * subImage.AspectRatio)

Finally this running total for the height over the size of the multi source image element should give you the viewport width you require.

Setting the viewport origin to 0,0 will also make it line up in the element box nicely.

Monday 10 August 2009

Silverlight: Accessing child properties after they have been rendered

I came across an interesting issue today. Essentially its to do with the events related to a Silverlight User Control.

The problem I had was related to a child control which I wanted to set in its parent after the control had been rendered. For example setting a width on a child canvas control. The issue I had was when I wanted to set the parameter it had not yet been created, as loaded event is fired on the parent before the child.

The initialisation cycle of a Silverlight control (source Control Lifecycle), states the last event to be called is the ‘LayoutUpdated’ event. This seems to be fired when the child control has finished being rendered. Interesting!

   1: private void UserControl_LayoutUpdated(object sender, EventArgs e)
   2: {
   3:     //All controls are hopefully loaded set the template
   4:     ChildControl.ChildProperty.Width = <ChildValue>;
   5: }

Thursday 30 July 2009

Useful Test Site for creating new Global Unique Identifiers

After spending hours re-writing database scripts and using a website that creates a new global unique identifier only one at a time. I decided to see if the domain createnewguid.com was available.

Much to my surprise it is!! So an hour later a new website was deployed. Hope people find it useful. Its easy to use, there are a few options for creating an empty guid or using upper case values only. I have also allowed additional options to select 1, 10, 100 or 1000 new guids.

To visit the site click here.

Wednesday 15 July 2009

IE6 Ghost Text Bug

I have come across this a few times before, but today it really got me. IE6 can be extremely frustrating at times. Especially due to the fact that the box model is not implemented properly. But normally these things are relatively quite easy to pick out.

Anyway I received this mark-up which I had to integrate with an existing website and came across a weird repeating text problem occurring at the bottom of the screen.

ghostTextBug

As you can see in this example, the ‘been adjusted accordingly’ was repeated twice. After doing various searches the following suggestions were repeated as causes of the problem:

1. Comments and <DIV> tags

Yes this is a common problem with IE6. Hit this before! Its all related to comments in-between floating <DIV> in sequence. Its weird because its only the last bit of content that gets repeated.

   1: <!-- IE6 does not like comments -->
   2: <div class="floating_div">
   3:   <... some markup ...>  
   4: </div>
   5: <!-- IE6 does not like comments really -->



There is reports that if you have content that wraps beyond the border of the containing div, i.e. it fills up the whole width, IE6 has a 3px buffer on the right hand side which apparently triggers the re-rendering of the text.

Solutions to this include:

a) using <!—[IF !IE]>  tags around the comment.

b) remove them – genius!

c) in the preceding float add a style {display:inline;}

d) Use –ve margins on appropriate floating divs.

Alas none of these sold my problem. I removed all the comments from the markup and the problem still occurred.

2. {display:none} or hiding specific elements

Ha i thought I did have some of these but I removed all the display:none stylings on <div> tags and problem was still apparent. So I think this is a red-herring!

3. Whitespace between list tags such as <ul>, <li> or <dl>

Browsers generally are not supposed to bother about whitespace. But IE6 has other ideas. This will work if its these tags causing the problem, but alas my mark-up was clean of this problem.

Unfortunately none of the above applied. Eventually I found a missing </DIV> tag buried in some mark-up supplied. Interestingly the mark-up had been formatted!! After putting the end tag in the web page behaved. Moral of the story – do not trust other peoples mark-up!

Of course one solution would be for people to use a modern browser such as IE7 or 8 – although the later has  a whole host of problems!! eek. Food for thought though below are the ACID 3 test results for IE6/7/8 compared with Firefox, Opera and Safari – you get the idea – more problems to come! Also bear in mind 25% of internet users still use IE6 which is now 8 years old!

Acid Test 3

Acid Test 3 Results

Firefox (3.5.30729): 93%
Safari (4.0): 100%
Opera (9.64): 85%
Chrome (2.0.172): 100%
Internet Explorer (8.0.6): 20%
Internet Explorer (7): 12%
Internet Explorer (6.0.2): 12%

Tuesday 14 July 2009

URL Shorteners Article

A friend of mine threw this up on twitter and I thought i’d make a note of it here!

URL Shorteners: Which Shortening Service Should You Use?

Ok yes I am a nerd – but I found this very useful in explaining this functionality used on services such as twitter and how search engines are dealing with these links.

Thursday 9 July 2009

Silverlight 2 and Deep Zoom Composer comments no.1

This is the beginning of I suspect a series of notes on Silverlight 2/3 and related technologies, I have the joy to play around with. I wanted to start with a few example links to

A good place to start is to go to the Microsoft Silverlight website and the MSDN sites:

http://silverlight.net/Default.aspx

http://msdn.microsoft.com/en-us/library/cc838158(VS.95).aspx

A very useful Silverlight debugging tool:

http://silverlightspy.com/silverlightspy/download-silverlight-spy/

Some interesting articles relating to a modal windows:

http://silverlightmodal.codeplex.com/

And deep zoom image composers

http://blogs.msdn.com/expression/archive/2008/11/26/hello-deepzoomtools-dll-deep-zoom-image-tile-generation-made-easy.aspx

http://msdn.microsoft.com/en-us/magazine/dd943052.aspx

I’ll write more later and start including some examples on my website :)

Monday 29 June 2009

Switching Between HTTP and HTTPS Automatically

I needed some code to automatically redirect a user from http to https. My friend Kamil came to the rescue and forwarded me a link to this code component:

Matt Sollars - Web Page Security

Of course you could just have a response redirect on default.aspx but I wanted something a lot more elegant and this did exactly that.

Although the whole of my site had to be secure, it was pretty clear here how to restrict https to certain directories or files with relative ease using web.config.

The code extends the IHttpModule and therefore can be easily configured to work for all files and removes the necessity to embed code into all pages.

Tuesday 26 May 2009

Welsh on Windows Server 2003

Beware if you want to use cy-GB locale on Windows Server 2003 - you will need to update to Service Pack 2 - as this locale is not present in the original release or service pack 1.

If you cannot upgrade to service pack 2, I found a useful resource on the University of Wales - Bangor - language technology website.

I have repeated the relevant information here for future reference:

1. Create a cy-gb.ldml with the C# code by running the following code on a windows XP SP2 machine (NB this references the following Sample code for getting ELK cultures on other platforms by Michael Kaplan).

   1: using System;
   2: using System.Globalization;
   3:  
   4: namespace Testing 
   5: {
   6:     class Test 
   7:     {
   8:             [STAThread]
   9:             static void Main(string[] args) {
  10:                 CultureAndRegionInfoBuilder carib = new CultureAndRegionInfoBuilder("cy-GB", CultureAndRegionModifiers.Replacement);
  11:                 carib.LoadDataFromCultureInfo(new CultureInfo("cy-GB", false));
  12:                 carib.LoadDataFromRegionInfo(new RegionInfo("cy-GB"));
  13:                 carib.Save(@"c:\cy-GB.ldml");
  14:             }
  15:         }
  16:     }
  17: }

2. Copy the cy-gb.ldml file to your Windows 2003 (or Windows 2000) machine

3. Open the cy-gb.ldml file in Notepad or any text editor and search for the lines containing :


   1: msLocale:textInfoName type="cy-GB"
   2: msLocale:sortName type="cy-GB"

and change them to


   1: msLocale:textInfoName type="en-GB"
   2: msLocale:sortName type="en-GB"

Then register your new ‘custom locale’ by executing the following code on the Windows 2003 box:

   1: using System;
   2: using System.Globalization;
   3:  
   4: namespace Testing {
   5:       class Test {
   6:           [STAThread]
   7:           static void Main(string[] args) {
   8:               CultureAndRegionInfoBuilder carib = CultureAndRegionInfoBuilder.CreateFromLdml(@"c:\cy-GB.ldml");
   9:               carib.Register();
  10:           }
  11:       }
  12:   }

NB - to compile the code you can use the following:

   1: csc /r:sysglobl.dll welsh.cs

So should all be okay now!!

Tuesday 28 April 2009

Fixing Display Issue with IE6 and AJAX toolkit Modal Popup Extender

I had a bit of a nightmare trying to get the modal popup extender working when viewing a webpage containing this Ajax control in IE6. My thoughts regarding IE6 are best left out of this!! After some digging I found several articles that pointed to a variety of things - this is what worked for me.

As I was working with a page which relied on a series of masters I could not change the “doctype”.

This left me to hack the source of the Ajax toolkit. If you open this solution, and look at the JavaScript the answer lies there.

This works with v1.0.10123.0

1. Change the file Common.js which is found at AjaxControlToolkit\Common\Common.js
2. Search for a method called 'getClientBounds'
3. Replace switch with



   1: switch(Sys.Browser.agent) {
   2:     case Sys.Browser.InternetExplorer:
   3:         if (document.documentElement &amp;&amp; document.documentElement.clientWidth)
   4:             clientWidth = document.documentElement.clientWidth;
   5:         else if (document.body)
   6:             clientWidth = document.body.clientWidth;
   7:         if (document.documentElement &amp;&amp; document.documentElement.clientHeight)
   8:             clientHeight = document.documentElement.clientHeight;
   9:         else if (document.body)
  10:             clientHeight = document.body.clientHeight;
  11:         break;
  12:     case Sys.Browser.Safari:
  13:         clientWidth = window.innerWidth;
  14:         clientHeight = window.innerHeight;
  15:         break;

4. Important part is the next bit - as absolute positioning is not correctly implemented in IE6. Look for the initalize function and look for the background i.e.

replace this line:



   1: this._foregroundElement.style.position = 'fixed'; 

with



   1: if (this._isIE6)
   2:   this._foregroundElement.style.position = 'fixed';
   3: else
   4:   this._foregroundElement.style.position = 'absolute';

and this line:


   1: this._backgroundElement.style.position = 'fixed';

withp>



   1: if (this._isIE6)
   2: this._backgroundElement.style.position = 'fixed';
   3: else
   4: this._backgroundElement.style.position = 'absolute';

This should solve the problem.

Monday 16 March 2009

AJAX Drag Panel toolkit – drag panel issue with IE6

I found another issue with IE6 today relating to a drag panel ajax extender I was implementing in a page. First of all when I moved the drag panel to the right hand side of the screen the panel was changing size. This is likely to be related to the panel conforming to the width set on its parent container.

The drag panel code:

   1: <asp:Panel ID="pnlDetailsContainer" runat="server" style="display:none;" CssClass="containerBox">
   2:     <asp:Panel ID="pnlDetailsHeader" runat="server" CssClass="popupBoxHeader">
   3:         ....        
   4:     </asp:Panel>
   5:     <div class="pnlDetailsMarkup">
   6:         ...some markup...
   7:     </div>
   8: </asp:Panel>

The CSS:

   1: .containerBox
   2: {
   3:     border-style:solid;
   4:     border-width:2px;
   5:     border-color:Black;
   6:     background-color:#ffffff;
   7:     width:300px;
   8: }

To fix this resizing problem i put the whole panel into a surrounding div:


   1: <div class="detailsContainer">
   2: ...panel..
   3: </div>

Set the width and height parameters in CSS and it works fine in IE7 and Firefox 3. But not IE6. For some reason in IE6 it puts the div in and therefore moves other page elements out of place instead of just showing when required.

To fix this I set an IE6 specific style to a height and width 1px. This had the desired effect.

Tuesday 10 February 2009

HTML - Special Entity Codes - useful link

I found this link today which is very useful for finding those special entity codes for html.

HTML - Special Entity Codes

Friday 30 January 2009

Displaying really large text files over 3GB in size

I ran a data importer process last night and ended up with a log of 3.3GB nice :) Found this useful tool to be able to view it - poor old notepad hasn't a chance.

http://www.swiftgear.com/ltfviewer/features.html

Tuesday 27 January 2009

Tag Clouds for Blogger

I found this useful tag cloud for blogger.

Simple Tag Cloud Widget for Blogger

I've replicated the code below just in case the above link does not work. All you need to do is add a label widget and change its code to the following:

   1: <b:widget id='TagCloud' locked='false' title='Tags' type='Label'>
   2:     <b:includable id='main'>
   3:     <b:if cond='data:title'>
   4:       <h2><data:title/></h2>
   5:     </b:if>
   6:     <div class='widget-content' style='text-align: justify;'>
   7:          <script type="text/javascript">
   8:         /*
   9:         Simple Blogger Tag Cloud Widget
  10:         by Raymond May Jr.
  11:         http://www.compender.com
  12:         Released to the Public Domain
  13:         */
  14:         //Variables:
  15:         var max = 150; //max css size (in percent)
  16:         var min = 50; //min css size (...)
  17:         var showCount = 1;  // show counts? 1 for yes
  18:         var minCount = 1;  // what is the minimum count for a Tag to be shown? 1 for all.
  19:         
  20:         //Begin code:
  21:         var range = max - min;
  22:  
  23:         //Build label Array
  24:         var labels = new Array();
  25:          <b:loop values='data:labels' var='label'>
  26:            labels.push("<data:label.name/>");
  27:          </b:loop>
  28:  
  29:         //URLs
  30:         var urls = new Array();
  31:          <b:loop values='data:labels' var='label'>
  32:            urls.push("<data:label.url/>");
  33:          </b:loop>
  34:         
  35:         //Counts
  36:         var counts = new Array();
  37:          <b:loop values='data:labels' var='label'>
  38:            counts.push("<data:label.count/>");
  39:          </b:loop>
  40:         
  41:         //Number sort funtion (high to low)
  42:         function sortNumber(a, b)
  43:         {
  44:          return b - a;
  45:         }
  46:         
  47:         //Make an independant copy of counts for sorting
  48:         var sorted = counts.slice();
  49:         
  50:         //Find the largest tag count
  51:         var most = sorted.sort(sortNumber)[0];
  52:         
  53:         //Begin HTML output
  54:         for (x in labels)
  55:         {
  56:              if(x != "peek" && x != "forEach" && counts[x] >= minCount)
  57:              {
  58:                   //Calculate textSize
  59:                   var textSize = min + Math.floor((counts[x]/most) * range);
  60:                   //Show counts?
  61:                   if(showCount == 1)
  62:                   {
  63:                        var count = "(" + counts[x] + ")";
  64:                   }else{
  65:                        var count = "";
  66:                   }
  67:                   //Output
  68:                   document.write("<span style='font-size:" + textSize + "%'><a href='" + urls[x] + "'>" + labels[x] + count + "</a></span> " );
  69:              }
  70:             }
  71:             </script>
  72:         </div>
  73:     </b:includable>
  74: </b:widget>