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

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.

Tuesday, 2 December 2008

Syntax highlighting

Following on from Scott Hanselman's post about the SyntaxHighlighter script, here's the secret sauce I needed to get it to work.

The separate hosting is the easy bit -- the trick was getting the code I needed to run the repainting into a window.onload, and to keep Blogger from mutilating the code by use of a CDATA section.

Et voilà!

<link href='.../SyntaxHighlighter.css' rel='stylesheet' type='text/css'/>
<script src='.../shCore.js' type='text/javascript'/>
<script src='.../shBrushPython.js' type='text/javascript'/>
<script src='.../shBrushRuby.js' type='text/javascript'/>
...
<script type='text/javascript'>//<![CDATA[
window.onload = function () {
    dp.SyntaxHighlighter.ClipboardSwf = ".../clipboard.swf";
    dp.SyntaxHighlighter.BloggerMode();
    dp.SyntaxHighlighter.HighlightAll("code",true,false,false,1,false);
}
//]]></script>

There is also a Scala brush for this -- but F# or Erlang will need to be hand-cranked first.

Later: hand cranking done & linked.

Saturday, 29 November 2008

Python Swings; Ruby still doesn't

Here's a proof-of-concept of running a Swing UI from Python on the CLR and the JVM, following up on earlier experiments (which I had forgotten about).

try:  
  # IronPython must load the J# redistributable libraries  
  # Using the FullName of the assemblies is probably overkill  
  import clr  
  clr.AddReference( 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' )  
  clr.AddReference( 'vjssupuilib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' )  
except ImportError:  
  pass  
     
import javax.swing  
import java.awt.event  
import java.lang  
  
class Exit(java.awt.event.WindowAdapter):  
  def windowClosing(self, evt):  
    evt.getWindow().setVisible(False)
    evt.getWindow().dispose()
  def windowClosed(self, evt):  
    java.lang.System.exit(0) 
    
# With the 'import's above, we can now refer to things that are part of the  
# standard Java platform via their full paths.  
frame = javax.swing.JFrame("Window") # Creating a Java JFrame.  
label = javax.swing.JLabel("Hello")  
     
# We can transparently call Java methods on Java objects, just as if they were defined in Python.  
frame.getContentPane().add(label)  # Invoking the Java method 'getContentPane'.  
frame.addWindowListener(Exit()) # Need to do this for IronPython/J# which is barely JDK 1.2 level  
frame.pack()  
frame.setVisible(True)

which works happily with java -jar jython-complete.jar HelloSwing.py using Jython 2.5β0 and with ipy.exe HelloSwing.py for IronPython2.0RC2 as well.

I was briefly conflicted earlier this week when I saw that IronRuby had reached α2, and wondered about a JRuby/IronRuby UI, but the nigh-equivalent

begin  
  require 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'  
  require 'vjssupuilib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'  
rescue LoadError  
  # This is the 'magical Java require line'.  
  require 'java'  
end    
        
class Exit < java.awt.event.WindowAdapter
  def windowClosing evt
    evt.getWindow.setVisible(false)
    evt.getWindow.dispose # make Closed
  end
  def windowClosed evt
    java.lang.System.exit 0 
  end
end

# With the 'require' above, we can now refer to things that are part of the  
# standard Java platform via their full paths.  
frame = javax.swing.JFrame.new("Window") # Creating a Java JFrame.  
label = javax.swing.JLabel.new("Hello")  
     
# We can transparently call Java methods on Java objects, just as if they were defined in Ruby.  
frame.getContentPane.add(label)  # Invoking the Java method 'getContentPane'.  
frame.addWindowListener(Exit.new()) # Need to do this for IronRuby/J# which is barely JDK 1.2 level  
frame.pack  
frame.setVisible(true)  

which works on JRuby 1.1.5, fails in IronRuby α2 when trying to load Swing classes, and I've not found a dodge that will get me at even class metadata for the Swing files. Ruby's casing rules may make it impossible for IronRuby to recognise the lower-case Java namespaces (I had fun with that earlier with Ruby.Net).

LATER: I could do something VM dependent that takes the class name and argument list for construction in {Iron|J}Ruby. What is more tricky is inheritance like

class Exit < java.awt.event.WindowAdapter

which is a major use-case. I wonder if there might be a metaprogramming technique I can use for this...

LATER YET: The problem is that there is no exposed mechanism to wrap a System.Type as a Ruby Class; I could manually subclass everything that is not final that I want in a C# assembly with a My.JavaNamespace and emulate the way that JRuby maps namespace Java::JavaAwtEvent to a value named java.awt.event, but the nearest to automation I can see is to Reflection.Emit a whole ton of stuff.

So, for the moment, consider it a dead end.

Sunday, 19 October 2008

Sign of the times -- Impedence mismatch of Scala and J#

Following up on the Scala/.Net experiments, I took the interfaces for hashes and cyphers from my Java port; and replaced them in the Java world with a set of Scala traits, like:

trait MDA
{
    def update(data:Array[byte], offset:int, length:int): unit

    def update(data:byte) : unit

    def digest() : Array[byte] 
}

and it builds happily (though NetBeans 6.5 nightly complains it can't find the interface definition from the library in the code view).

Over to Visual Studio, with a suitable script to build the equivalent .dll -- and the implementing classes in J# fail to build because the Array[byte] maps to ubyte[] while a J# byte[] is an sbyte[], and so the J# compilation fails to match the signature of the Scala.Net trait -- and there's no Java ubyte type I can force everything to. And as byte arrays -- or at least bytes -- are the fundamental building block for streams, it looks like all the Java code has to get the elbow.

Thursday, 25 September 2008

Why am I doing this sort of thing?

Michael Foord (aka Fuzzyman) has wondered, while linking me, about why one would want to talk to Scala from IronPython.

Partly, it is the intellectual challenge of that particular sub-problem. But the broader goal is to see how far it is possible, in this polyglot age, to build a language stack -- along the lines the Ola Bini mused about at the start of the year -- that one could drop onto the JVM or .Net using essentially the same code base, give or take a thin C# layer to provide compatible APIs in .Net to those needed in Java but not present in J#.

While the Fan language is developed to be exactly so code-compatible across the JVM and CLR, it appears to be resolutely monoglot, with the platform hidden behind an abstraction layer.

The ulterior motive is to take a codebase that I already have in Java/J#, the first stages of a reimplementation in a VM targeted language, of my old CTClib project -- and be able to complete the reimplementation/upgrade to RFC2440 spec, in a platform neutral way, and without having to write any more Java, even if the IronPython/J#+Swing interface will be rather less Pythonic than I could manage if I were just doing it in Jython.

And why Scala as well? For any new static layer code, especially where being explicit about the types involved, such as around the crypto, will make things clearer.

One correction, though, to the remarks : ATM, I'm using the scala-net compiler, which is part of the Scala bazaar, and seems (from its failure modes when the J# libraries are in the loop) to be a different generator to that in IKVM. Not being IKVM means I'm also spared having to drag in the GNU Classpath library, where the server stuff has priority, and desktop UI support is still primitive -- its AWT is less functional, in many important respects, than Java 1.0 was.

Wednesday, 24 September 2008

Scaling the tower of Babel II

Finally, a little digital extraction. Scala from IronPython, works as expected. In file operator.scala:

package com_ravnaandtines.operator

trait Process {
 def op(x:Int, y:Int) : Int
}

class Multiply extends Process {
  def op(x:Int, y:Int) : Int =
   x * y
}

class Perform69 {
 def sixByNine(x: Process) =
  x.op(6,9)
}

Set up as in the previous post, and build using %SCALA_HOME%\bin\scalac-net.bat operator.scala to get operator.msil -- no assembly is generated at this point. Edit the .msil file as required to point at the appropriate versions of the runtime (see previous post). Then ilasm .\Operator.msil /dll /output=operator.dll. Now fire up IronPython:

>>> import clr
>>> clr.AddReference("operator.dll")
>>> from com_ravnaandtines.operator import *
>>> dir()
['Multiply', 'Perform69', 'Process', '__builtins__', '__doc__', '__name__', 'clr']
>>> m = Multiply()
>>> p69 = Perform69()
>>> p69.sixByNine(m)
54
>>> class Adder(Process):
...   def op(self,a,b):
...     return a+b
...
>>> add = Adder()
>>> p69.sixByNine(add)
15
>>>

So long as we get our interfaces/traits from Scala, all is fine.

In order to do the same in the JVM world, I need to have done set CLASSPATH=%CLASSPATH%;C:\scala-2.7.1.final\lib\scala-library.jar; and then I can do exactly as above, but without the first two lines with clr. Those I can put in a try/except, for common coding.

Note -- it is neither necessary nor sufficient to put the Scala library jar in java.class.path or python.path properties.