Skip to content

Instantly share code, notes, and snippets.

@ymnk
Created September 16, 2008 09:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ymnk/11008 to your computer and use it in GitHub Desktop.
Save ymnk/11008 to your computer and use it in GitHub Desktop.
import javax.swing.{ImageIcon, JWindow, JLabel}
import java.net.URL
import scala.xml.XML
import scala.collection.mutable.Queue
import scala.actors.Actor
import scala.actors.Actor.loop
import scala.concurrent.ops.spawn
object ViewImagesInFeed extends Application {
/**
* messages to be delivered to actors.
*/
sealed abstract class MESSAGE
case object GETIMAGE extends MESSAGE
case object FEEDIMAGE extends MESSAGE
case class UPDATEIMAGE(url:String) extends MESSAGE
/**
* This actor will retrieve the URLs of recent images on Flickr
* via friendfeed.com, and then send each of them to ViewUpdater actor with
* the UPDATEIMAGE message.
*/
private object FeedReceiver extends Actor {
val images = new Queue[String]()
/**
* Thanks to the XML support on Scala, it is really easy to extract URLs
* for thumbnails. The URLs will be kept in "images".
*/
def getImages() = {
val url = "http://friendfeed.com/api/feed/public?format=xml&service=flickr&num=100"
val xml = XML.load(new URL(url).openStream)
(xml \ "entry" \ "media" \ "thumbnail" \ "url").foldLeft(images){
(i, u) => i += u.text; i
}
}
/**
* The interval to delay to send messaes to actors.
*/
val interval=1000
def act {
getImages()
this ! FEEDIMAGE
loop {
react {
case FEEDIMAGE => images.isEmpty match {
case true => ping(interval, GETIMAGE)
case false => {
ViewUpdater ! UPDATEIMAGE(images.dequeue)
ping(interval*10, FEEDIMAGE)
}
}
case GETIMAGE => getImages.isEmpty match {
case true => ping(interval, GETIMAGE)
case false => ping(interval, FEEDIMAGE)
}
}
}
}
/**
* Send a message to myself after some interval in the forked thread.
*/
def ping(sleep:Int, m:MESSAGE) {
spawn { Thread.sleep(sleep); this ! m }
}
}
/**
* This actor will update the view according to the given message; UPDATEIMAGE.
* The update operation will be delegated to "w" object via its "<<" method.
*/
private object ViewUpdater extends Actor {
def act {
loop {
react {
case UPDATEIMAGE(url) => w << url
}
}
}
}
/**
* The main window to show thumbnails.
* Please note that we don't have to invent the class name for "w"!
* In java, we can not invoke "<<" method in "ViewUpdater" object without
* doing that.
*/
private val w = new JWindow {
import java.awt.Toolkit
import java.awt.event._
val icon = new ImageIcon
addMouseListener(new MouseAdapter(){
override def mouseClicked(e:MouseEvent){ System.exit(0) }
})
getContentPane.add(new JLabel(icon))
setSize(75, 75)
setVisible(true)
// switch image with the given URL
def << (url:String) {
// release resource in the image if required.
icon.getImage match {
case i => if(i!=null){ i.flush }
}
val image=Toolkit.getDefaultToolkit.createImage(new URL(url))
icon.setImage(image)
repaint
}
}
// start actors
ViewUpdater.start()
FeedReceiver.start()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment