<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Tutorial for flexx.event - properties and events
Step1:  Events
In flexx.event, events are represented with dictionary objects that
provide information about the event (such as what button was pressed,
or the new value of a property). A custom Dict class is used that inherits from dict and allows attribute access,
e.g. ev.button as an alternative to ev['button'].
Reactions
Events originate from Component objects. When an event is emitted, it can be reacted upon.
Step2:  Note how the reaction is connected using a "connection string", which (in this case) indicates we connect to the type "foo" event of the object. The connection string allows some powerful mechanics, as we will see later in this tutorial. Here, we prefixed the connection string with "!", to supress a warning that Flexx would otherwise give, because it does not know about the "foo" event.
Also note how the reaction accepts multiple events at once. This means that in situations where we only care about something being changed, we can skip "duplicate" events. In situation where each individual event needs processing, use for ev in events
Step3:  A reaction can also connect to multiple events
Step4:  Properties
Properties represent the state of a component.
Step5:  Properties can also be set during initialization.
Step6:  Properties are readonly. This may seem like a limitation at first, but it helps make apps more predictable, especially as they become larger. Properties can be mutated using actions. In the above example, a setter action was created automatically because we specified setter=True in the definition of the property.
Actions
Actions are special functions that are invoked asynchronously, i.e. when they are invoked (called) the action itself is applied in a futre iteration of the event loop. (The %gui asyncio at the top of the notebook makes sure that Flexx' event loop is running.)
Step7:  The action above mutates the foo property. Properties can only be mutated by actions. This ensures that the state of a component (and of the whole app) is consistent during the handling of reactions.
Emitters
Emitters make it easy to generate events from specific input (e.g. an event from another kind of event system) and act as a placeholder for the docs of public events.
Step8:  Implicit reactions
Implicit reactions make it easy to write concise code that needs to keep track of state. To create an implicit reaction, simply provide no connection strings. The reaction will now automatically track all properties that the reaction is accessing. This even works dynamically, e.g. when accessing a property on each element in a list property, the reaction will automatically "reconnect" when the list changes.
Step9:  Labels
Labels are a feature that makes it possible to infuence the order by
which event handlers are called, and provide a means to disconnect
specific (groups of) handlers. The label is part of the connection
string
Step10:  Dynamism
Dynamism is a concept that allows one to connect to events for which the source can change. It essentially allows events to be connected automatically, which greatly reduced boilerplate code. I makes it easy to connect different parts of an application in a robust way.
Step11:  Updating the count property on any of its children will invoke the callback
Step12:  We also connected to the children property, so that the handler is also invoked when the children are added/removed
Step13:  Naturally, when the count on new children changes ...
<ASSISTANT_TASK:>
Python Code:
%gui asyncio
from flexx import event
Explanation: Tutorial for flexx.event - properties and events
End of explanation
class MyObject(event.Component):
    
    @event.reaction('!foo')
    def on_foo(self, *events):
        print('received the foo event %i times' % len(events))
ob = MyObject()
for i in range(3):
    ob.emit('foo', {})
Explanation: Events
In flexx.event, events are represented with dictionary objects that
provide information about the event (such as what button was pressed,
or the new value of a property). A custom Dict class is used that inherits from dict and allows attribute access,
e.g. ev.button as an alternative to ev['button'].
Reactions
Events originate from Component objects. When an event is emitted, it can be reacted upon.
End of explanation
ob.on_foo()
Explanation: Note how the reaction is connected using a "connection string", which (in this case) indicates we connect to the type "foo" event of the object. The connection string allows some powerful mechanics, as we will see later in this tutorial. Here, we prefixed the connection string with "!", to supress a warning that Flexx would otherwise give, because it does not know about the "foo" event.
Also note how the reaction accepts multiple events at once. This means that in situations where we only care about something being changed, we can skip "duplicate" events. In situation where each individual event needs processing, use for ev in events: ....
Reactions can also be used as normal methods:
End of explanation
class MyObject(event.Component):
        
    @event.reaction('!foo', '!bar')
    def on_foo_or_bar(self, *events):
        for ev in events:
            print('received the %s event' % ev.type)
ob = MyObject()
ob.emit('foo', {}); ob.emit('foo', {}); ob.emit('bar', {})
Explanation: A reaction can also connect to multiple events:
End of explanation
class MyObject(event.Component):
    
    foo = event.IntProp(2, settable=True)
        
    @event.reaction('foo')
    def on_foo(self, *events):
        print('foo changed from', events[0].old_value, 'to', events[-1].new_value)
ob = MyObject()
ob.set_foo(7)
print(ob.foo)
Explanation: Properties
Properties represent the state of a component.
End of explanation
ob = MyObject(foo=12)
Explanation: Properties can also be set during initialization.
End of explanation
class MyObject(event.Component):
    
    foo = event.IntProp(2, settable=True)
    
    @event.action
    def increase_foo(self):
        self._mutate_foo(self.foo + 1)
    
    @event.reaction('foo')
    def on_foo(self, *events):
        print('foo changed from', events[0].old_value, 'to', events[-1].new_value)
ob = MyObject()
ob.increase_foo()
Explanation: Properties are readonly. This may seem like a limitation at first, but it helps make apps more predictable, especially as they become larger. Properties can be mutated using actions. In the above example, a setter action was created automatically because we specified setter=True in the definition of the property.
Actions
Actions are special functions that are invoked asynchronously, i.e. when they are invoked (called) the action itself is applied in a futre iteration of the event loop. (The %gui asyncio at the top of the notebook makes sure that Flexx' event loop is running.)
End of explanation
class MyObject(event.Component):
    @event.emitter
    def mouse_down(self, js_event):
        ''' Event emitted when the mouse is pressed down. '''
        return dict(button=js_event['button'])
    
    @event.reaction('mouse_down')
    def on_bar(self, *events):
        for ev in events:
            print('detected mouse_down, button', ev.button)
ob = MyObject()
ob.mouse_down({'button': 1})
ob.mouse_down({'button': 2})
Explanation: The action above mutates the foo property. Properties can only be mutated by actions. This ensures that the state of a component (and of the whole app) is consistent during the handling of reactions.
Emitters
Emitters make it easy to generate events from specific input (e.g. an event from another kind of event system) and act as a placeholder for the docs of public events.
End of explanation
class MyObject(event.Component):
    
    foo = event.IntProp(2, settable=True)
      
    @event.reaction
    def on_foo(self):
        print('foo changed is now', self.foo)
ob = MyObject()
ob.set_foo(99)
Explanation: Implicit reactions
Implicit reactions make it easy to write concise code that needs to keep track of state. To create an implicit reaction, simply provide no connection strings. The reaction will now automatically track all properties that the reaction is accessing. This even works dynamically, e.g. when accessing a property on each element in a list property, the reaction will automatically "reconnect" when the list changes.
End of explanation
class MyObject(event.Component):
    @event.reaction('!foo:bb')
    def foo_handler1(self, *events):
        print('foo B')
    @event.reaction('!foo:cc')
    def foo_handler2(self, *events):
        print('foo C')
    
    @event.reaction('!foo:aa')
    def foo_handler3(self, *events):
        print('foo A')
ob = MyObject()
ob.emit('foo', {})
ob.disconnect('foo:bb')
ob.emit('foo', {})
Explanation: Labels
Labels are a feature that makes it possible to infuence the order by
which event handlers are called, and provide a means to disconnect
specific (groups of) handlers. The label is part of the connection
string: 'foo.bar:label'.
End of explanation
class Root(event.Component):
    children = event.TupleProp([], settable=True)
    
    @event.reaction('children', 'children*.count')
    def update_total_count(self, *events):
        total_count = sum([child.count for child in self.children])
        print('total count is', total_count)
class Sub(event.Component):    
    count = event.IntProp(0, settable=True)
root = Root()
sub1, sub2, sub3 = Sub(count=1), Sub(count=2), Sub(count=3)
root.set_children([sub1, sub2, sub3])
Explanation: Dynamism
Dynamism is a concept that allows one to connect to events for which the source can change. It essentially allows events to be connected automatically, which greatly reduced boilerplate code. I makes it easy to connect different parts of an application in a robust way.
End of explanation
sub1.set_count(100)
Explanation: Updating the count property on any of its children will invoke the callback:
End of explanation
root.set_children([sub2, sub3])
Explanation: We also connected to the children property, so that the handler is also invoked when the children are added/removed:
End of explanation
sub4 = Sub()
root.set_children([sub3, sub4])
sub4.set_count(10)
sub1.set_count(1000)  # no update, sub1 is not part of root's children
Explanation: Naturally, when the count on new children changes ...
End of explanation
<END_TASK>