The Artima Developer Community
Sponsored Link

Agile Buzz Forum
Making a Slideshow program WithStyle

0 replies on 1 page.

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 0 replies on 1 page
James Robertson

Posts: 29924
Nickname: jarober61
Registered: Jun, 2003

David Buck, Smalltalker at large
Making a Slideshow program WithStyle Posted: Mar 21, 2004 9:02 PM
Reply to this message Reply

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
Latest Agile Buzz Posts
Latest Agile Buzz Posts by James Robertson
Latest Posts From Michael Lucas-Smith

Advertisement

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:

^'<slideshow xmlns="http://www.softwarewithstyle.com/2004/03/slideshow">
	<slide href="slide1"/>
	<slide href="slide2"/>
</slideshow>'

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:

<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xml" href="slidesXSLT"?>
<html xmlns="http://www.w3.org/1999/xhtml">
....
</html>

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:

WithStyle.Client defineClass: #WsSlideshowWindow
	superclass: #{WithStyle.Client.WsThinClientWindow}
	indexedType: #none
	private: false
	instanceVariableNames: 'slides slide '
	classInstanceVariableNames: ''
	imports: ''
	category: 'WithStyle'

Now we can change its windowSpec to have anything in it that we want. We need a basic opening method on the class side:

browse: aURI
	| browser |
	browser := self new.
	browser slides: aURI asURI asResource.
	^browser

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.

nextSlide
	self slide: self slide nextSlide.

previousSlide
	self slide: self slide previousSlide

hasNextSlide
	^self slide nextSlide notNil

hasPreviousSlide
	^self slide previousSlide notNil

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:

WithStyle.Slideshow defineClass: #Element
	superclass: #{WithStyle.Specialisation.Element}
	indexedType: #none
	private: false
	instanceVariableNames: ''
	classInstanceVariableNames: ''
	imports: ''
	category: 'WithStyle'

And on its class side we implement the method #namespace to return ^'http://www.softwarewithstyle.com/2004/03/slideshow'

We can now add our two subclasses for Slideshow and Slide:

WithStyle.Slideshow defineClass: #Slide
	superclass: #{WithStyle.Slideshow.Element}
	indexedType: #none
	private: false
	instanceVariableNames: 'href '
	classInstanceVariableNames: ''
	imports: ''
	category: 'WithStyle'

WithStyle.Slideshow defineClass: #Slideshow
	superclass: #{WithStyle.Slideshow.Element}
	indexedType: #none
	private: false
	instanceVariableNames: ''
	classInstanceVariableNames: ''
	imports: ''
	category: 'WithStyle'

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:

slide: anObject
	(slide := anObject) ifNil: [^self slide: self firstSlide].
	self navigateTo: slide resolvedHref

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:

WithStyle.Client.WsSlideshowWindow browse: 'resource://WithStyle.SlideshowExample/slideshow'

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.

Read: Making a Slideshow program WithStyle

Topic: Make It Work, Make It Right Previous Topic   Next Topic Topic: Code Coverage

Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2019 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use