My hobbyist coding updates and releases as the mysterious "Mr. Tines"

Showing posts with label Silverlight. Show all posts
Showing posts with label Silverlight. Show all posts

Sunday, 22 March 2009

Belatedly, more IronPython + Silverlight

Domestic happenings and the demands of the day-job have kept me away from the codeface for playtime for a while; but at last, following up from last year, a SilverLight2/IronPython2 orrery-clock. Back-ported from F#, I confess, hence the possibly less than Pythonic idioms at times.

Tuesday, 16 December 2008

More Silverlight Clock

I could, I suppose, have implemented this project in JavaScript -- that language has all the tools to get the current URL query string and set a permalink to a custom URL, one that wouldn't need clicking, but could be right-clicked; and save the self-inflicted DLR download hit.

If I wanted to, I could put the permalink URL out to an element in the DOM with Silverlight, too, which negates one perceived advantage. And using Silverlight gives me something extra -- multithreading.

Yes, there are JavaScript clocks, like this annoying mouse-following one, but they have to fake such things because they are running full-time in the UI thread. By using a BackgroundWorker to prompt a redraw at intervals (and, later, perform updates on the positions of celestial bodies), with Silverlight, I can offload everything but the painting from the UI thread.

Sunday, 14 December 2008

Persisting user settings in Silverlight

Many years ago, the first GUI application I wrote (in X with Motif) was a little orrery-cum-clock thing, with the clock face doubling as a view of the sky, showing the classical planets. Some time in the intermediate past, I thought about doing this as a Java applet, but it never got anywhere, because out on the web, it would have to be settable to the user's geographic location, and I never figured a good way to persist that data between page visits.

Having done the basic tinkering with IronPython and Silverlight to get the two working together, I thought about resurrecting the project. And the first thing to solve is the settings persistence.

But now, I have an easy API to get at the current URL and such via System.Windows.Browser.HtmlPage.Document -- so I can read the values from its query string; and set the values in a hyperlink for bookmarking purposes, thus (app.py):

from System.Windows import Application
from System.Windows.Controls import Canvas
import System
import System.Windows.Browser

xaml = Application.Current.LoadRootVisual(Canvas(), "astroclock.xaml")
xaml.hyperlink.NavigateUri = System.Windows.Browser.HtmlPage.Document.DocumentUri
thisPage = System.Windows.Browser.HtmlPage.Document.DocumentUri.GetComponents(
  System.UriComponents.SchemeAndServer | System.UriComponents.Path,
  System.UriFormat.SafeUnescaped)
query = System.Windows.Browser.HtmlPage.Document.QueryString
  
try:
  xaml.slider1.Value = float(query['lat'])
except:
  pass
try:
  xaml.slider2.Value = float(query['long'])
except:
  pass
 
def latValueChanged(s, e):
  v = xaml.slider1.Value
  if v > 0:
 xaml.label1.Text = "Latitude %.2fN" % (v)
  elif v < 0:
 xaml.label1.Text = "Latitude %.2fS" % (-v)
  else: 
 xaml.label1.Text = "Latitude 0"
 xaml.hyperlink.NavigateUri = System.Uri("%s?lat=%f&long=%f" % (thisPage, v, xaml.slider2.Value))

xaml.slider1.ValueChanged += latValueChanged
latValueChanged(None, None)

def longValueChanged(s, e):
  v = xaml.slider2.Value
  if v > 0:
 xaml.label2.Text = "Longitude %.2fE" % (v)
  elif v < 0:
 xaml.label2.Text = "Longitude %.2fW" % (-v)
  else:
 xaml.label2.Text = "Longitude 0"
 xaml.hyperlink.NavigateUri = System.Uri("%s?lat=%f&long=%f" % (thisPage, xaml.slider1.Value, v))
 
xaml.slider2.ValueChanged += longValueChanged
longValueChanged(None, None)

driving some UI described by (astroclock.xaml)

<Canvas 
  x:Class="System.Windows.Controls.Canvas"
  xmlns="http://schemas.microsoft.com/client/2007"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Name="parentCanvas">
    <Grid>
        <Canvas Name="canvas1" Margin="0,0,0,129" Background="Black" Width="480" Height="240"/>
        <Slider Height="22" Margin="128,0,0,93" Name="slider1" VerticalAlignment="Bottom" Maximum="90" Minimum="-90" Value="52" LargeChange="10" SmallChange="1" Width="360"/>
        <TextBlock Height="28" Margin="0,0,0,87" Name="label1" VerticalAlignment="Bottom" HorizontalAlignment="Left" Width="120">Latitude</TextBlock>
        <TextBlock Height="28" HorizontalAlignment="Left" Margin="0,0,0,62" Name="label2" VerticalAlignment="Bottom" Width="120">Longitude</TextBlock>
        <Slider Height="22" Margin="128,0,0,65" Name="slider2" VerticalAlignment="Bottom" Maximum="180" Minimum="-180" LargeChange="10" SmallChange="1" Width="360"/>
        <HyperlinkButton Height="28" HorizontalAlignment="Left" Margin="0,0,0,17" Name="hyperlink" VerticalAlignment="Bottom" Width="87" NavigateUri="astroclock.html" Content="Permalink" />
    </Grid>
</Canvas>

Evolving implementation here.