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 }