Sunday, June 10, 2007

SilverLight Surface Demo Adaptation

David Anson created a SilverLight based Surface demo to emulate Microsoft's new Surface product. The demo was very compelling and gave me an idea for an application I have been wanting to create. Check out his blog for more information about his demo and to download the code.

http://blogs.msdn.com/delay/archive/2007/06/01/silverlight-surface-demonstration-silverlight-implementation-of-surface-s-photo-table-ui.aspx

His application looks like this:

Silverlight

My Adaptation Idea

The idea I have is to create an application that lets people import photos from a third-party service or through an upload interface and then attach annotations or perhaps attach video clips or audio notes to the photos. The first purpose for this application will be to use it as another way showcase my great-grandmother's artwork.

I would like to figure out a way to make it so that people could create collage images and then save the image and print it as a poster, similar to what you can do with Picasa or other on-line photo editing tools like the ones that use Flickr images.

I also want to use the idea as part of a presentation I started to author aimed at educating middle or high school aged students about career opportunities in information technology. The URL for the first draft of that is http://www.ultravioletconsulting.com/Default.aspx?tabid=94

In order to make that demonstration optimally compelling, I'd like to integrate this application with the new Facebook API so that students could import images from friends' shared photo albums and then attach the comments and annotations using the application.

I could not get the Facebook DLL to comply with the compile under Orcas because it was asking for the 2.0.0.0 System DLL while Orcas and SilverLight are using .NET 3.5.

Does anyone have any ideas on how I could get it to work?

Progress So Far

The original code had a hard-coded set of images. I found that I could not read files on the drive due to Sandbox restrictions, so I made a small local web service and created a proxy to it.

The web service code is very simple, but the key is using the ScriptService attribute so that it is consumable using JSON from SilverLight.

using System
using System.Data;
using System.Linq;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.ComponentModel;
using System.Web.Script.Services;

using System.IO;

namespace GetFilesService
{
    /// <summary>
    /// Summary description for Service1
    /// </summary>
    [ScriptService]
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service1 : System.Web.Services.WebService
    {

        [WebMethod]
        public string[] GetFiles()
        {
            string dirName = @"C:\Documents and Settings\Josh\My Documents\My Sites\CarolaArt\ImagesAll\";
            DirectoryInfo di = new DirectoryInfo(dirName);
            FileInfo[] files = di.GetFiles();

            System.Collections.Generic.List<string> fileNames =
                new System.Collections.Generic.List<string>();

            foreach (var file in files)
            {
                string name = file.Name;

                if (name.ToLower().EndsWith(".jpg"))
                {
                    fileNames.Add(name);
                }
            }

            return fileNames.ToArray();
        }
    }
}

Next, I changed the load method to pull the file names from the web service call instead of a local array. This results in this huge stack of photos:

image

Then, I added that little "Tile Pictures" button by adding the SilverLight Controls project. After adding a few convenience properties to the Photo class, I added this buggy event handler to the code to make them tile:

    public void OnClick(object sender, EventArgs e)
    {
        double width = Width;
        double height = Height;

        int numPics = _photos.Count;

        // calculate block size in terms of number of images
        double area = width * height;

        double blockSize = area / numPics;

        // get square root of the given area
        double side = Math.Sqrt(blockSize);

        double startX, startY;
        startX = startY = 0.0d;
        foreach (var pic in _photos)
        {
            pic.Width = side;
            pic.Height = side;
            pic.X = startX;
            pic.Y = startY;
            pic.Angle = 0.0d;

            startX += side;
            if (startX >= width)
            {
                startY += side;
                startX = 0;
            }
        }
    }
}

I am a total SilverLight / WPF newbie, so I'm not really sure what I need to do here to correctly achieve this, but this is a basic start so far.

Here is what the semi-functional tile function does so far. It is not really setting the width and height of the photo properly. I need to do what with Scale somehow.

image

6/12/2007 Update

Here is a screen shot of a small update.

image

I added these properties to the Photo class to get the computed pixel width in accordance to the current scale transform:

public double ActualHeight
{
    get
    {
        return _root.Height;
    }
}

public double ActualWidth
{
    get
    {
        return _root.Width;
    }
}

public double ScaleHeight
{
    get
    {
        return ActualHeight * _scaleTransform.ScaleY;
    }
}

public double ScaleWidth
{
    get
    {
        return ActualWidth * _scaleTransform.ScaleX;
    }
}

No comments: