<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>pocket_ruby/fw/util/lang/hash.rb</filename>
    </added>
    <added>
      <filename>pocket_ruby/fw/util/lang/hash_test.rb</filename>
    </added>
    <added>
      <filename>pocket_ruby/fw/util/lang/lang.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -2,7 +2,7 @@
 module PocketRuby
 
   class Block
-    @@fields = {}
+    @@fields ||= {}
 
     attr_accessor :name, :object
 </diff>
      <filename>pocket_ruby/fw/ui/blocks/block.rb</filename>
    </modified>
    <modified>
      <diff>@@ -45,6 +45,7 @@ class BlockTest &lt; Test::Unit::TestCase
   def test_get_block_fields
     author = Author.new
     assert_equal(['name'], Block.fields_of(author))
+    assert_equal(['name'], Block.fields_of(Author))
   end
 
   def test_get_raw</diff>
      <filename>pocket_ruby/fw/ui/blocks/block_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -39,6 +39,10 @@ module PocketRuby
       end
     end
 
+    def env= env
+      @env = env || raise('Aaaaa, No env!')          
+    end
+
     def execute
       raise 'implement me!'
     end
@@ -75,6 +79,7 @@ module PocketRuby
       return nil if !point
       
       point.app = self.app
+      point.params = self.params
       point.env = self.env
 
       tail = self.tail.dup</diff>
      <filename>pocket_ruby/fw/ui/structure/site_structure.rb</filename>
    </modified>
    <modified>
      <diff>@@ -136,7 +136,7 @@ class SiteStructureTest &lt; Test::Unit::TestCase
     }
     begin
       node.execute
-    rescue (ResponseException =&gt; e)
+    rescue ResponseException =&gt; e
       #its okay
     end
     assert_equal 1, PostHandler.handled_times</diff>
      <filename>pocket_ruby/fw/ui/structure/site_structure_test.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,7 +15,7 @@ class View
         e.src = link e.src
       end
     }
-    t.on('script'){ |e|
+    t.on('js'){ |e|
       if e.src
         e.src = link e.src
       end</diff>
      <filename>pocket_ruby/fw/ui/template/view.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,58 +1,118 @@
 module PocketRuby
+
+  class EventResponse &lt; Exception
+    attr_accessor :event
+    def initialize event
+      @event = event
+    end
+  end
+
   class Event
+    #include Lang
+
+    @@subscriptions ||= Hash.new
+    @@published_events ||= Hash.new
+
+    attr_accessor :name, :params
+
+    def initialize name, *params
+      @name, @params = name, params
+    end
+
+    def self.respond event
+      raise EventResponse.new(event) 
+    end
+
     def self.on global_event, &amp;block
-      Event.subscribe self, global_event, &amp;block
+      self.subscribe self, global_event, &amp;block
     end
 
     def self.fire global_event, *args
-      Event.notify_listeners(self, global_event, *args)
+      self.notify_listeners(self, global_event, *args)
+    end
+
+    def self.detach global_event, &amp;block
+      self.unsubscribe self, global_event, &amp;block
+    end    
+
+    def self.detach_all
+      @@subscriptions[self] = {}
     end
 
+
+
     def self.publish who, event
-      @@published_events ||= {}
-      @@published_events[who] = []
-      @@published_events[who] &lt;&lt; event
+      @@published_events[self] ||= {}
+      @@published_events[self][who] = []
+      @@published_events[self][who] &lt;&lt; event
     end
 
     def self.enable what
       what.class_eval('def on event_name, &amp;block
-        Event.subscribe(self, event_name, &amp;block)
+        '+self.to_s+'.subscribe(self, event_name, &amp;block)
       end')
 
       what.class_eval('def fire event_name, *args
-        Event.notify_listeners(self, event_name, *args)
+        '+self.to_s+'.notify_listeners(self, event_name, *args)
       end')
     end
 
     def self.list publisher_class
-      @@published_events[publisher_class]
+      @@published_events[self] or return []       
+      @@published_events[self][publisher_class]
     end
 
+    
+
     def self.notify_listeners sender, event_name, *args
+      response_events = []
       (listeners sender, event_name).each { |subscriber|
-        subscriber.call(*args)
+        begin
+          subscriber.call(*args)
+        rescue EventResponse =&gt; response
+          response_events &lt;&lt; response.event
+        end
       }
+      response_events
     end
 
     def self.subscribe subject, event, &amp;block
       event = event.to_s
       check_allowed subject, event
-      @@subscriptions ||= {}
-      @@subscriptions[subject] ||= {}
-      @@subscriptions[subject][event] ||= []
-      @@subscriptions[subject][event] &lt;&lt; block
+      @@subscriptions[self] ||= {}      
+      @@subscriptions[self][subject] ||= {}
+      @@subscriptions[self][subject][event] ||= []
+      unless @@subscriptions[self][subject][event].include? block
+        @@subscriptions[self][subject][event] &lt;&lt; block
+      end
     end
 
+    def self.unsubscribe subject, event, &amp;block
+      event = event.to_s
+      check_allowed subject, event
+      @@subscriptions || return
+      @@subscriptions[self] || return
+      @@subscriptions[self][subject]  || return
+      @@subscriptions[self][subject][event]  || return
+      @@subscriptions[self][subject][event] = @@subscriptions[self][subject][event] - [block]
+    end
+
+
     def self.listeners subject, event
       @@subscriptions ||= {}
-      @@subscriptions[subject] or return []
-      @@subscriptions[subject][event] or return []
+      @@subscriptions[self] or return []
+      @@subscriptions[self][subject] or return []
+      @@subscriptions[self][subject][event] or return []
     end
 
     def self.check_allowed publisher, event
-      if (@@published_events[publisher.class]) &amp;&amp; !(@@published_events[publisher.class].include? event)
+      if (@@published_events[self][publisher.class]) &amp;&amp; !(@@published_events[self][publisher.class].include? event)
         raise ArgumentError.new &quot;The publisher doesn\'t know event '#{event}'.&quot;
       end
     end
   end
+
+  class TestEvent &lt; Event
+  end
+
 end
\ No newline at end of file</diff>
      <filename>pocket_ruby/fw/util/event.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,27 +1,34 @@
 
-class EventEnabledRepo
-    Event.enable(self)
-    
-    def persist object
-      fire('persist', object)
-    end
-    
-    def event_with_param object
-      fire('event_with_param', object)
-    end
-end
 
-class EventPublisher
-    Event.enable(self)
-    Event.publish(self, 'event_that_was_published')
-    
-    def event_that_was_published
-      fire('event_that_was_published')
-    end
+class EventTest &lt; Test::Unit::TestCase
 
-end
+  Event = Event::TestEvent
 
-class EventTest &lt; Test::Unit::TestCase
+  class EventEnabledRepo
+      Event.enable(self)
+
+      def persist object
+        fire('persist', object)
+      end
+
+      def event_with_param object
+        fire('event_with_param', object)
+      end
+  end
+
+  class EventPublisher
+      Event.enable(self)
+      Event.publish(self, 'event_that_was_published')
+
+      def event_that_was_published
+        fire('event_that_was_published')
+      end
+  end
+
+
+  def setup
+    Event.detach_all
+  end
 
   def test_listeners_subscribtion
     r = EventEnabledRepo.new
@@ -100,5 +107,59 @@ class EventTest &lt; Test::Unit::TestCase
     assert okay
   end
 
+  def test_subscribe_with_same_listener_only_once
+    n = 0
+    callback = lambda { n+=1 }
+    Event.on('test:increment', &amp;callback)
+    Event.on('test:increment', &amp;callback)
+    Event.fire('test:increment')
+    assert_equal 1, n
+  end
+
+  def test_detached_listener_does_not_get_called
+    n = 0
+    listener = lambda { n+=1 }
+    Event.on('test:increment2', &amp;listener)
+    Event.detach('test:increment2', &amp;listener)
+    Event.fire('test:increment2')
+    assert_equal 0, n
+  end
+
+  def test_event_response_on_event
+    response = Event.new('response')
+    callback = lambda { Event.respond(response) }
+    Event.on('test:event_that_causes_reply', &amp;callback)
+    assert_equal [response], Event.fire('test:event_that_causes_reply')
+    Event.detach('test:event_that_causes_reply', &amp;callback)
+  end
+
+  def test_detach_all
+    called = 0
+    Event.on('test:event') { called += 1 }
+    Event.detach_all
+    Event.fire('test:event')
+    assert_equal 0, called
+  end
+
+
+  class DifferentEvent &lt; Event; end
+
+  def test_different_events_have_separate_subscriptions
+    called = 0
+    Event.on('test:event') { called += 1 }
+    DifferentEvent.fire('test:event')
+    assert_equal 0, called
+    Event.fire('test:event')
+    assert_equal 1, called
+  end
+
+  def test_different_events_have_separate_subscriptions
+    called = 0
+    Event.on('test:event') { called += 1 }
+    DifferentEvent.detach_all
+    Event.fire('test:event')
+    assert_equal 1, called
+  end
+
 end
 </diff>
      <filename>pocket_ruby/fw/util/event_test.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>e5deeb9a2c3435d8beb5361de7938a372833b762</id>
    </parent>
  </parents>
  <author>
    <name>Michal Hantl</name>
    <email>michal.hantl@gmail.com</email>
  </author>
  <url>http://github.com/hakunin/pocket-ruby/commit/e5ca1eb175ed7b31d1ffe54edde8ed0b4013b223</url>
  <id>e5ca1eb175ed7b31d1ffe54edde8ed0b4013b223</id>
  <committed-date>2009-10-07T23:51:48-07:00</committed-date>
  <authored-date>2009-10-07T23:51:48-07:00</authored-date>
  <message>fun with events</message>
  <tree>991c48a33a62c10cf7c5013afc5b3e673492c78a</tree>
  <committer>
    <name>Michal Hantl</name>
    <email>michal.hantl@gmail.com</email>
  </committer>
</commit>
