This post originated from an RSS feed registered with Agile Buzz
by James Robertson.
Original Post: Making a Slideshow program WithStyle
Feed Title: Michael Lucas-Smith
Feed URL: http://www.michaellucassmith.com/site.atom
Feed Description: Smalltalk and my misinterpretations of life
In the spirit of Sam and Vassili and their exploration of Pollock, I thought it might be interesting to discuss how to make a simple yet powerful application using WithStyle. The particular example my colleagues wish me to talk about is the Slideshow program I made just recently.
What we want to do is give presentations to people, slide by slide, powerpoint style. The dialect we're going to be using for the main slide data is XHTML - great, most of the work is already done for us. There are zillions of HTML editors about so you can make your slides do practically anything you want.
We also need a slideshow dialect to describe what slides we have. To do this I just made a really simple one called Slideshow. First, we pick a namespace for it, http://www.softwarewithstyle.com/2004/03/slideshow
We could then go and make some XSD for it, but since I'm not going to be editing the slideshow just yet using WithStyle, there's no need. So we need a root tag, which will be <slideshow> and inside that we'll have lots of slides called <slide>. Each slide will have an attribute of href to point to the content of the slide.
In my case I made a class SlideshowExample and implemented on the class side the method slideshow to return:
So on and so forth. To make things easy for ourselves, we want to make each slide re-use as much styling information as possible. We want the following features: (a) a common Look and Feel, (b) a common click script to go to the next slide, (c) to still be XHTML.
It turns out that XSL is a good choice for this. We add a basic rule that puts out a HTML document which includes are default stylings in its head tag but also include a script:
<script xmlns="http://www.w3.org/2002/06/xhtml2" id="nextSlide" language="Smalltalk">
self wsCurrentView topComponent model nextSlide
</script>
Now on our body tag we have: <body ev:type="click" ev:handler="#nextSlide"> and we'll be using XML-Events to intercept any click inside the body area and make it run the script which will talk to our slideshow window to tell it to go to the next slide.
The rest of the XSLT is up to you: mine just copies all the data from inside my own body tag in to the new body tag. But in each slide we need only put a processing-instruction to tell it to use our XSLT. Eg:
Next step, we need to make a Slideshow window. We'll subclass it from the withstyle thin client window to pick up all the nice behaviour of download information, etc. So:
Notice we're not telling to navigate anywhere, we're giving it the parsed XML for our slideshow XML. On the instance side we add an instance variable of @slides and make slides: set the first slide with: self slide: self firstSlide
firstSlide is a simple method too, which does: ^self slides root firstSlide
We're now talking about behaviour on an XML DOM tree that currently doesn't exist. We'll come back to that after we've added a few more useful methods to our slideshow viewer.
Right, time to add the last bit of behaviour to our system. We want to add a new dialect that our system understand for dealing with slideshows. So first things first, lets make ourselves an abstract element class to base our behaviour off:
Now, the way the specialisation code works, by default, the name of the class is the name of the tag, so we don't need to add any more behaviour to the class to make the XML parser use these classes. We just need to add our specific behaviour.
To make href's be relative instead of absolute all the time, we have the instance variable #href on Slide, which will be set whenever there's an attribute called href in the XML for a slide - which there will be because we said there was. We implement a getter method for #href ^href and now we can call #resolvedHref on any Slide to get the absolute URL of the slide.
nextSlide and previousSlide are basic methods on Slide that do things like: ^self parent onlyElements after: self ifAbsent: nil. You can figure out previousSlide for yourself from that.
On Slideshow, we need only add #firstSlide, which is ^self onlyElements first and we're almost done. There's one last job we need to do; actually navigating to slides when they change. So we head back to our Slideshow window.
We already have the instance variable for slide, so we add getters and setters for that. Then for #slide: we want to navigate. So slide: becomes:
And we're done! That's all the hard slogging work completed. Upgrade your CSS and XSLT to get yourself the Look and Feel you want and you can now instigate a slideshow viewing from a HTTP address, FILE address, or internally with a resource address. In my case, I can view my slide by running:
A click inside the window takes me to the next slide. In the version that is in WithStyle, I've also added a right click popup menu which lets you go forward/backward between slides.