Scala #033: Publisher

中級篇

Java.use(better, src=Scala) # ソースコードの歩き方《中級篇》
ソースコードの歩き方《Scala2.8.0》

《著》小粒ちゃん@湘南組、小粒ちゃん@博多組《監修》小泉ひよ子とタマゴ倶楽部
第1版♪2010/07/14

Scala #033: Publisher

》作業中です《

■ ボタンを選択する


 30:     for (e <- items.toArray) {
 31:       contents += new Button(e) {
 32:         Command.listenTo(this)
 33:       }
 34:     }

ボタンを選択(クリック)すると、Command が Button に呼応します。

 50:   object Command extends Publisher {
 51:     reactions += {
 52:       case ButtonClicked(source) =>
 53:         val value = source.text
 54:         update(value)
 55:     }
 56:   }

ボタンをクリックすると、イベント ButtonClicked が発生するので、それに反応する処理を記述します。

@
22	abstract class AbstractButton extends Component with Action.Trigger.Wrapper with Publisher {
23	  override lazy val peer: JAbstractButton = new JAbstractButton with SuperMixin {}
   ...
43	  peer.addActionListener(Swing.ActionListener { e =>
44	    publish(ButtonClicked(AbstractButton.this))
45	  })
scala.swing.Publisher
31	trait Publisher extends Reactor {
32	  import Reactions._
33	 
34	  protected val listeners = new RefSet[Reaction] {
35	    import scala.ref._
36	    val underlying = new HashSet[Reference[Reaction]]
37	    protected def Ref(a: Reaction) = a match {
38	      case a: StronglyReferenced => new StrongReference[Reaction](a) with super.Ref[Reaction]
39	      case _ => new WeakReference[Reaction](a, referenceQueue) with super.Ref[Reaction]
40	    }
41	  }
42	
43	  private[swing] def subscribe(listener: Reaction) { listeners += listener }
44	  private[swing] def unsubscribe(listener: Reaction) { listeners -= listener }
45	 
46	  /**
47	   * Notify all registered reactions.
48	   */
49	  def publish(e: Event) { for (l <- listeners) l(e) }
50	 
51	  listenTo(this)
52	}
scala.collection.mutable.Publisher
29	trait Publisher[Evt] { 
30	
31	  type Pub <: Publisher[Evt]
32	  type Sub = Subscriber[Evt, Pub]
33	  type Filter = Evt => Boolean
34	
35	  /** The publisher itself of type `Pub'. Implemented by a cast from `this' here.
36	   *  Needs to be overridden if the actual publisher is different from `this'.
37	   */
38	  protected val self: Pub = this.asInstanceOf[Pub]
39	 
40	  private val filters = new HashMap[Sub, Set[Filter]] with MultiMap[Sub, Filter]
41	  private val suspended = new HashSet[Sub]
42	
43	  def subscribe(sub: Sub) { subscribe(sub, event => true) }
44	  def subscribe(sub: Sub, filter: Filter) { filters.addBinding(sub, filter) }
45	  def suspendSubscription(sub: Sub) { suspended += sub }
46	  def activateSubscription(sub: Sub) { suspended -= sub }
47	  def removeSubscription(sub: Sub) { filters -= sub }
48	  def removeSubscriptions() { filters.clear }
49	
50	  protected def publish(event: Evt) {
51	    filters.keys.foreach(sub =>
52	      if (!suspended.contains(sub) &&
53	          filters.entryExists(sub, p => p(event)))
54	        sub.notify(self, event)
55	    )
56	  }
57	
58	  /** Checks if two publishers are structurally identical.
59	   *
60	   *  @return true, iff both publishers contain the same sequence of elements.
61	   */
62	  override def equals(obj: Any): Boolean = obj match {
63	    case that: Publisher[_] => filters == that.filters && suspended == that.suspended
64	    case _                  => false
65	  }
66	}


関連記事

TOP

Last updated♪2010/10/19