Saturday, March 15, 2008

Dan has posted an excellent article on implementing a Tree structure in C#.  He has beaten me to the punch, after talking about my "Tree of dependent tasks" idea over beers.  I should have something to add to the discussion in the coming weeks.

Saturday, March 15, 2008 3:45:31 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, March 14, 2008

http://www.ps3fanboy.com/2008/03/14/microsoft-predicts-blu-ray-irrelevance-in-12-18-months/

This is ludicrous talking head speak for the vast overwhelming majority of the movie-watching population.  If I can get better than 1.5mb/s DSL in the next 18 months I'll be shocked, let alone enough pipe to handle True HD video.  At this stage of the market, digital downloads and packaged optical media are NOT different versions of the same product, as these people seem to believe.  They are utterly different products.  38mb/s MPEG4 with 5 mb/s LPCM is not "the same" as the puny bitrates we get through video on demand at this time, and the average consumer can handle having a shelf full of optical discs much easier than they can prepare for terrabytes of digital storage medium.  How many average users have a backup strategy?  The first time you want to watch The Matrix but that hard drive died and you have to redownload you'll be mad.  When you realize the DRM might make re-downloading insanely painful or impossible (as Casey has shown) you'll be wishing you had a Blu-Ray player instead.

The market will figure this out, but not in 12 months, sorry Mr Pundit.

{Edit: I ironically realized after I posted that the words of someone linking to any website with "fanboy" in the name are probably deserving of a side of salt as well.  Oh well, it's the internet...}

Movies | Rant
Friday, March 14, 2008 3:37:05 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

What an astouning letdown: I was on track for a red letter day yesterday.  My parts came in, it was sunny, and I drank some beer and BBQ-ed some poultry.  Hickory smoked BBQ chicken is among my favorite foods and I haven't been able to have it for months because my wife has a pregnancy aversion to most forms of chicken and it's also been ridiculously cold.  I went to best buy and got Bioshock only to discover later that one of my parts is either DOA, I've plugged something in wrong, or the specifications are lying about compatibility.  What a letdown, I expected to be fighting issues like MySQL on 64bit Vista but instead I have no POST.  Luckily my brother recently bought very similar Intel hardware so I should be able swap parts around to find out which piece is dead.  As much as it's a badge of geek honor to build one's own screaming development PC, I think in the future I will not do so during times like now where I have plenty of other things to worry about.

Friday, March 14, 2008 10:53:05 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  |  Trackback

My sister had a little boy at 9pm last night, Daniel James Sapp.  I'm an uncle for the 3rd time in a short while.

Friday, March 14, 2008 10:44:02 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Thursday, March 13, 2008

I pulled the trigger on a new desktop setup which is out for delivery according to the internets.  Because of my recent research I went ahead and went the quad core route, and after reading Scott Hanselman's blog post about going x64 being a complete non issue I'll be giving Vista x64 a try.  I also got a 1080p monitor and a Blu-Ray drive; probably slightly overkill but why not.  It's difficult to explain to non-programmers, but an appropriate setup with the right desk space, music, multiple monitors, and a repsonsive machine can make developing software a joy.  It can be a joy without a Raptor drive and a 24" display but these things help. 

I got a decent enough video card to check out some of the recent games, Bioshock being at the top of the list.

Thursday, March 13, 2008 8:19:39 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Friday, March 07, 2008

Catastrophic failure!  Now that is an error message worthy of my college dating life!... anyhoo, I digress.  Many controls in winforms and WPF probably try to do things in the constructor or an "OnLoad" event of some kind that are not design-time-friendly, but the magic of the environment mostly keeps things like this from happening.  This magic dust has not yet been sprinkled upon the Silverlight 2.0 tools for VS2008, but I'm still very excited about the possibilities as this platform matures.  The error below occurs if I add some test images into the loaded event of the carousel and try to view the designer. 

Friday, March 07, 2008 8:23:31 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Here's my carousel sample, as a user control within my Silverlight image uploader. The Tesla Roadster is such a sexy car it's perfect for any automotive industry technology demonstration.

Friday, March 07, 2008 8:07:43 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback

Ok, here is my silverlight 2 port of the ever popular Image Carousel sample.  For me, at least, it's much easier to follow what's going on than the JavaScript version.  Here's the markup required in the page:

<UserControl x:Class="ImageUploader.ImageCarousel"

    xmlns="http://schemas.microsoft.com/client/2007"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Width="800" Height="600" Canvas.Top="0">   

<Canvas x:Name="_mainCanvas" Loaded="mainCanvasLoaded" MouseMove="whenMouseMoves"

        MouseLeftButtonDown="mainDown" MouseLeftButtonUp="mainUp" MouseLeave="mainCanvasMouseLeave" >

    <Canvas Name="imagesHolder" Canvas.Left="0" Canvas.Top="0">

        <Canvas Name="mainImageHolder" Canvas.Left="200" Canvas.Top="60" Canvas.ZIndex="169" Opacity="1.0">

            <Image Name="mainImage" Stretch="UniformToFill" Height="225" Width="300"/>

        </Canvas>

    </Canvas>

</Canvas>

</UserControl>

And here is the code-behind:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Media.Imaging;

namespace ImageUploader
{
public partial class ImageCarousel : UserControl
{
public ImageCarousel()
{
InitializeComponent();
_mainDown = false;
_urls = new Dictionary<Image, string>();
_angles = new List<double>();
_imagePaths = new List<string>();
//_imagePaths.Add("Upload/1.jpg");
//_imagePaths.Add("Upload/2.jpg");
//_imagePaths.Add("Upload/3.jpg");
_dispTimer = new System.Windows.Threading.DispatcherTimer();
_dispTimer.Interval = TimeSpan.FromMilliseconds(25);
_dispTimer.Tick += new EventHandler(dt_Tick);
_dispTimer.Stop();
}

private List<double> _angles;
private bool _mainDown = false;
private List<string> _imagePaths;
private List<ScaleTransform> _scaleTransforms = new List<ScaleTransform>();
private double _speed = -0.0425;
private Dictionary<Image, string> _urls;
private System.Windows.Threading.DispatcherTimer _dispTimer;

public void AddImage(string imageUrl)
{
_mainDown = false;
_dispTimer.Stop();
_angles.Clear();
_scaleTransforms.Clear();
_urls.Clear();

for (int i = 0; i < _imagePaths.Count; ++i)
{
Canvas holder = (Canvas)_mainCanvas.FindName("imgHolder" + i);
_mainCanvas.Children.Remove(holder);
}

_imagePaths.Add(imageUrl);
Image img = (Image)_mainCanvas.FindName("mainImage");
string srcPath = _imagePaths[_imagePaths.Count -1 ];
img.Source = new BitmapImage(new Uri(GetURLBase() + srcPath));
img.SetValue(Canvas.ZIndexProperty, 169);

BuildImages();
}

private void mainCanvasLoaded(object sender, RoutedEventArgs e)
{
if (_imagePaths.Count > 0)
{
Image img = (Image)_mainCanvas.FindName("mainImage");
img.Source = new BitmapImage(new Uri(GetURLBase() + _imagePaths[0]));
img.SetValue(Canvas.ZIndexProperty, 169);
//
BuildImages();
}
}

public List<string> ServerImagePaths { get; set; }

protected void BuildImages()
{
int leftPos = 0;
for (int i = 0; i < _imagePaths.Count; ++i)
{
Canvas imgHolder = new Canvas();
imgHolder.SetValue(Canvas.NameProperty, "imgHolder" + i);
imgHolder.SetValue(Canvas.LeftProperty, leftPos);
imgHolder.SetValue(Canvas.TopProperty, 0);
//Come back to reflections...
//Canvas imgHolderReflection = new Canvas();
//imgHolderReflection.SetValue(Canvas.NameProperty, "imgHolderRef" + i);
//imgHolderReflection.SetValue(Canvas.TopProperty, 160);
//imgHolderReflection.Opacity = 1;
//LinearGradientBrush lgb = new LinearGradientBrush();
//lgb.StartPoint = new Point(0, 0);
//lgb.EndPoint = new Point(0, 1);
//lgb.GradientStops.Add(new GradientStop());
//lgb.GradientStops.Add(new GradientStop());
//lgb.GradientStops[0].Offset = .37;
//lgb.GradientStops[0].Color = Color.FromArgb(0x00, 0x00, 0x00, 0x00);
//lgb.GradientStops[1].Offset = 1;
//lgb.GradientStops[1].Color = Color.FromArgb(0x88, 0x00, 0x00, 0x00);
//imgHolderReflection.OpacityMask = lgb;
//imgHolder.Children.Add(imgHolderReflection);
//
Rectangle rec = new Rectangle();
rec.SetValue(Rectangle.NameProperty, "rec" + i);
rec.SetValue(Canvas.TopProperty, -6);
rec.SetValue(Canvas.LeftProperty, -6);
rec.Height = 92.0;
rec.Width = 92.0;
rec.Fill = new SolidColorBrush(Colors.LightGray);
imgHolder.Children.Add(rec);
//
Image img = new Image();
img.Cursor = Cursors.Hand;
img.MouseEnter +=new MouseEventHandler(img_MouseEnter);
img.MouseLeave +=new MouseEventHandler(img_MouseLeave);
img.MouseLeftButtonDown +=new MouseButtonEventHandler(img_MouseLeftButtonDown);
img.MouseLeftButtonUp +=new MouseButtonEventHandler(img_MouseLeftButtonUp);
img.Stretch = Stretch.UniformToFill;
img.SetValue(Image.NameProperty, "img" + i);
BitmapImage imgSource = new BitmapImage(new Uri(GetURLBase() + _imagePaths[i]));
_urls.Add(img, GetURLBase() + _imagePaths[i]);
img.Source = imgSource;
img.Width = 300;
img.Height = 225;

img.Opacity = 1;
imgHolder.Children.Add(img);
ScaleTransform imgCanvasScaleTrans = new ScaleTransform();
_scaleTransforms.Add(imgCanvasScaleTrans);
imgCanvasScaleTrans.ScaleX = 1;
imgCanvasScaleTrans.ScaleY = 1;
imgCanvasScaleTrans.CenterX = 50;
imgCanvasScaleTrans.CenterY = 50;
imgHolder.RenderTransform = imgCanvasScaleTrans;
//
_mainCanvas.Children.Add(imgHolder);
//
_angles.Add( i*((Math.PI*2)/_imagePaths.Count) );
}
PositionItems();
_mainDown = true;// huh?
//Set dispatcher interval
_dispTimer.Start();
}

/// <summary>
/// Not used yet
/// </summary>
/// <param name="i"></param>
protected void AddOne(int i)
{
}

void dt_Tick(object sender, EventArgs e)
{
MoveItems();
}

protected void PositionItems()
{
int radiusX=400;
int radiusY=110;
int centerX=425;
int centerY = 260;

for(int i = 0; i < _imagePaths.Count;++i)
{
double myX = Math.Cos(_angles[i])*radiusX + centerX;
double myY = Math.Sin(_angles[i])*radiusY + centerY;
Canvas imgCanvas = (Canvas)_mainCanvas.FindName("imgHolder" + i);
imgCanvas.SetValue(Canvas.LeftProperty, myX);
imgCanvas.SetValue(Canvas.TopProperty, myY);
ScaleTransform stRef = _scaleTransforms[i];
double sc = (myY - stRef.ScaleY) / (centerY + radiusY-stRef.ScaleY);
stRef.ScaleX = sc;
stRef.ScaleY = sc;
_angles[i] += _speed;
imgCanvas.SetValue(Canvas.ZIndexProperty, (int)myY);
}
}

protected void MoveItems()
{
if (_mainDown)
{
PositionItems();
}
}

void img_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{

}

void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Image img = (Image)sender;

     Image mainImg = (Image)_mainCanvas.FindName("mainImage");
mainImg.Source = new BitmapImage(new Uri(_urls[img]));
mainImg.SetValue(Canvas.ZIndexProperty, 169);
}

void img_MouseLeave(object sender, MouseEventArgs e)
{
//Change color BACK or something cool
}

void img_MouseEnter(object sender, MouseEventArgs e)
{
//Change color or something cool
}

private void whenMouseMoves(object sender, MouseEventArgs e)
{
Point pt = e.GetPosition(null);
double _root_xmouse = pt.X;
     double _root_ymouse = pt.Y    ;
_speed = ((_root_xmouse - 500) / 500) * 0.0755;
}

private void mainDown(object sender, MouseButtonEventArgs e)
{
_mainDown = true;
}

private void mainUp(object sender, MouseButtonEventArgs e)
{
_mainDown = false;

}

private void mainCanvasMouseLeave(object sender, MouseEventArgs e)
{

}


protected string GetURLBase()
{
string str = System.Windows.Application.Current.Host.Source.OriginalString;
return str.Substring(0, str.LastIndexOf("/")).Replace("ClientBin", string.Empty);
}
}
}


 

Not formatted as well as my last posts, I know.  It seems that Google reader doesn't like it when I paste out of Word. Now, one thing that is not very apparent is how to add this UserControl to another UserControl, assuming that JUST having an image carousel is not what you're after.  You need to include the following on the top-level user control:

xmlns:CarSpot="clr-namespace:ImageUploader"

which then allows you to refer to the code:

<CarSpot:ImageCarousel x:Name="_carousel"></CarSpot:ImageCarousel>

This is an aspect of XAML I don't like. There's nothing (that I can see) in the structure/XSD of a XAML document that tells me that an attribute value starting with "clr-namespace:" is something special.  There's a lot of magic like this in XAML.  The Visual Studio "Silverlight Chainer" as the file calls the Beta 1 tools are definately buggy and incomplete.  I am lucky to be able to hit F5 10 times before I get errors trying to debug and having to kill Cassini and VS2008.  I've also found that it's very easy to crash the designer by having naughty things in your code-behind.  It appears that unlike more mature design-time experiences there is no "IsDesignTime" flag that would allow you to keep from having code execute while designing.  I can tell that this is Cider by the wonderfully descriptive stack traces I get, yet things like dragging the new Silverlight controls onto the surface or even moving them around (I'm sick of tweaking location with Canvas.Top/Canvas.Left) are not working yet.  This is a huge step forward, but I've got to think there'll be another beta after this one now.

And that's that.  I should have some more Silverlight 2 observations later, especially about the threading and HTTP aspects.

Friday, March 07, 2008 4:36:07 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [4]  |  Trackback

I have translated the Silverlight "Image Carousel" into Silverlight 2.0 and C# rather than the "JS writing XAML" model.  If I get the code cleaned up this afternoon I will post the carousel portion.

Friday, March 07, 2008 1:33:00 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback
 Wednesday, March 05, 2008
IE8

I am blogging from IE8.

Many useful things are broken, such as FreeTextBox which I am used to using to write this article.

Also broken, ironically enough, are the dynamic menus generated by asp.net from a sitemap data source. That alone will force me into "Emulate IE7" mode until Beta 2...

Wednesday, March 05, 2008 4:06:34 PM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [2]  |  Trackback
 Monday, March 03, 2008

I have never been more ready for spring than I am this year.

It was a whopping 40degrees here yesterday and I took advantage of it.  I spent hours chopping ice out of my driveway, I can't type so well today due to the blisters on my fingertips.  The huge piles of snow on either side of my driveway make surprisingly good reach-level beer holding areas, and I pulled out the bbq pit and made some brats.

I also wrote a Mapping tool this weekend.  When you're first getting started it's interesting to note the similarities in flat file, XML, object-to-object, and SQL to Object mapping: at least in terms of the initial abstractions that present themselves.  I specifically wanted to solve a flat-file to complex object problem and write a tool that previews the mapping in real time and realized I couldd do quite a bit more if I weren't lazy.  The main place I could see using this in my own efforts are class-to-class mapping.  For example: if you are consuming a web service the proxy generated will return to you class instances using whatever naming conventions and object structure the designers of said service wanted to give you.  Even if another team in your organization is the maintainer of this service, Directly using these proxy types within your code is probably a mistake; mapping ProxyObject.PrimaryKey to MyDomainObject.Id quickly becomes tedious.  A mapping tool that does the annoying work for you and saves the mapping as an easy XML file or better yet generates transformation code might be helpful. 

Monday, March 03, 2008 9:50:15 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [1]  |  Trackback
 Thursday, February 28, 2008

I downloaded the update package and installed from that, no luck.  I started searching for other people with the same problem and found that it is quite common.  I passed over some of the insane "fixes" in favor of trying some of the easier approaches.  Apparently, the Zune installer requires that the Windows Firewall service be running during installation.  What a bizarre dependency.  I'm all Zuned up now and liking it.  Now my wife wants one.

Thursday, February 28, 2008 9:50:53 AM (Central Standard Time, UTC-06:00)  #    Disclaimer  |  Comments [0]  |  Trackback