Tuesday, June 16, 2009

Using WPF in PowerShell with PowerBoots

I got the bug to play with WPF a couple of weeks ago. I'm relatively familiar with Windows Forms, and thought I'd like to finally look at WPF. I downloaded VC# 2008 Express and messed around a little bit for a few days. I had the goal of writing a WPF program that would host powershell and act like a simple Matlab. Well, I ran across PowerBoots, written by Joel Bennet (http://huddledmasses.org/powerboots/). PowerBoots brings WPF to PowerShell with some extremely simple syntax. After playing with it for a day, I wrote this relatively simple preview-images function that provides an experience similar to the image "Preview" in XP. For a tutorial see http://huddledmasses.org/powerboots-tutorial-walkthrough/


I found a very nice online source code formatter to format the below code: http://www.manoli.net/csharpformat/

The result looks like this:




And Here is the code:


function global:preview-images
{
#by default load all images supported by the WPF image control (System.Windows.Controls.Image)
param($images = (ls *.bmp,*.gif,*.ico,*.jpg,*.png,*.wdp,*.tiff,*.tif ))

$count = $images.length
$global:images = $images
$global:i = 0
$global:imindex = 1 #index of the image control in the dockpanel children array

boots -left 100 -top 100 -width 1024 -title "Preview - $pwd" {

stackpanel{
wrappanel {
#0
button "<--" -FontSize 24 -width 50 -On_Click {
$global:i = 0
$this.parent.parent.children[1].children[$global:imindex].source = $images[$global:i].fullname
$block[0].Inlines.Clear();
$block[0].Inlines.Add($images[$global:i].name)
}
#1
button "<" -FontSize 24 -width 50 -On_Click {
if ($global:i -gt 0) {
$global:i--
}
else {
$global:i = $images.length-1
}
$this.parent.parent.children[1].children[$global:imindex].source = $images[$global:i].fullname
$block[0].Inlines.Clear();
$block[0].Inlines.Add($images[$global:i].name)
}
#2
button ">" -FontSize 24 -width 50 -On_Click {
if ($global:i -lt ($images.length-1)) {
$global:i++
}
else {
$global:i = 0
}
$this.parent.parent.children[1].children[$global:imindex].source = $images[$global:i].fullname
$block[0].Inlines.Clear();
$block[0].Inlines.Add($images[$global:i].name)
}
#3
button "-->" -FontSize 24 -width 50 -On_Click {
$global:i = $count - 1
$this.parent.parent.children[1].children[$global:imindex].source = $images[$global:i].fullname
$block[0].Inlines.Clear();
$block[0].Inlines.Add($images[$global:i].name)
}
#4
button "END" -FontSize 24 -width 75 -On_Click {
#$global:i = $count
$this.parent.parent.parent.close()
#$block[0].Inlines.Clear();
#$block[0].Inlines.Add( $images[$global:i].name)
}
#5
button "Image List" -FontSize 20 -On_Click {
$images | foreach{write-host $_.name}
}
#6
textblock " " -FontSize 30 -FontWeight bold -Foreground "#0000FF"
#7
textblock $images[$global:i].name -OutVariable script:block -FontSize 30 -FontWeight bold -Foreground "#0000FF"
}
dockpanel -lastchildfill $true {

$images | %{$_.name} | listbox -SelectedIndex 0 -maxheight 900 -On_MouseDoubleClick{
$global:i = $this.selectedIndex
$this.parent.children[$global:imindex].source = $images[$global:i].fullname
$block[0].Inlines.Clear();
$block[0].Inlines.Add($images[$global:i].name)
} | ForEach-Object { $_.SetValue(
[System.Windows.Controls.DockPanel]::DockProperty,
[System.Windows.Controls.Dock]::left)
$_
}
image -source $images[$i].fullname
}

}

} -Background (linearGradientBrush $(GradientStop -Offset 0 -Color "#ffffff";GradientStop -Offset 1 -Color "#222222"))
}