class MyObject(event.Component): att = event.Attribute() # Props to test basic stuff foo = event.AnyProp(6, settable=True, doc='can be anything') bar = event.StringProp('xx') # not settable # Props to test array mutations eggs = event.ListProp([], settable=True) eggs2 = event.ListProp(settable=True) eggs3 = event.ListProp([3, 4]) # All kinds of props, defaults anyprop = event.AnyProp(doc='can be anything', settable=True) boolprop = event.BoolProp(settable=True) tristateprop = event.TriStateProp(settable=True) intprop = event.IntProp(settable=True) floatprop = event.FloatProp(settable=True) stringprop = event.StringProp(settable=True) tupleprop = event.TupleProp(settable=True) listprop = event.ListProp(settable=True) dictprop = event.DictProp(settable=True) componentprop = event.ComponentProp(settable=True) # can be None # nullprop = event.NullProp(None, settable=True) # eitherprop = event.EitherProp(event.IntProp, event.NoneProp) _privateprop = event.IntProp(settable=True)
class Test1(event.Component): data = event.ListProp([], doc='An array property') @event.action def add(self, i): self._mutate_data([i], 'insert', len(self.data))
class Foo(event.Component): def __init__(self): super().__init__() bars = event.ListProp(settable=True) def disconnect(self, *args): # Detect disconnections super().disconnect(*args) disconnects.append(self)
class Person(event.Component): first_name = event.StringProp('Jane', settable=True) last_name = event.StringProp('Doe', settable=True) children = event.ListProp([], doc='The children of this person') @event.action def add_child(self, child): self._mutate_children(self.children + [child])
class MyDefaults(event.Component): # Custom defaults anyprop2 = event.AnyProp(7, doc='can be anything') boolprop2 = event.BoolProp(True) intprop2 = event.IntProp(-9) floatprop2 = event.FloatProp(800.45) stringprop2 = event.StringProp('heya') tupleprop2 = event.TupleProp((2, 'xx')) listprop2 = event.ListProp([3, 'yy']) dictprop2 = event.DictProp({'foo':3, 'bar': 4}) componentprop2 = event.ComponentProp(None)
class Person(event.Component): first_name = event.StringProp('Jane', settable=True) last_name = event.StringProp('Doe', settable=True) children = event.ListProp([], doc='The children of this person') # Actions @event.action def add_child(self, child): self._mutate_children(self.children + [child]) @event.emitter def eat(self): #self.emit('eat', {'name': self.first_name}) return {'name': self.first_name} # Reactions @event.reaction('first_name:xx', 'last_name') def greet_explitic(self, *events): print('Explicit hello %s %s' % (self.first_name, self.last_name)) @event.reaction def greet_implicit(self): print('Implicit hello %s %s' % (self.first_name, self.last_name)) @event.reaction('children*.first_name') def greetall_explicit(self, *events): print('Explicit hey kids ' + ', '.join(n.first_name for n in self.children) + '!') @event.reaction def greetall_implicit(self): print('Implicit hey kids ' + ', '.join(n.first_name for n in self.children) + '!') @event.reaction('!eat') def track_eating(self, *events): for ev in events: print(ev.name + ' is eating')
class LeafletWidget(ui.Widget): """ A widget that shows a slippy/tile-map using Leaflet. """ layers = event.ListProp([], doc=""" List of tilemap layer tuples: (url, 'Layer'). """) zoom = event.IntProp(8, settable=True, doc=""" Zoom level for the map. """) min_zoom = event.IntProp(0, settable=True, doc=""" self zoom level for the map. """) max_zoom = event.IntProp(18, settable=True, doc=""" Maximum zoom level for the map. """) center = event.FloatPairProp((5.2, 5.5), settable=True, doc=""" The center of the map. """) show_layers = event.BoolProp(False, settable=True, doc=""" Whether to show layers-icon on the top-right of the map. """) show_scale = event.BoolProp(False, settable=True, doc=""" Whether to show scale at bottom-left of map. """) @event.action def add_layer(self, url, name=None): """ Add a layer to the map. """ # Avoid duplicates self.remove_layer(url) if name: self.remove_layer(name) # Add layer layers = self.layers + [(url, name or 'Layer')] self._mutate_layers(layers) @event.action def remove_layer(self, url_or_name): """ Remove a layer from the map by url or name. """ layers = list(self.layers) for i in reversed(range(len(layers))): if url_or_name in layers[i]: layers.pop(i) self._mutate_layers(layers) def _create_dom(self): global L, document node = document.createElement('div') self.mapnode = document.createElement('div') node.appendChild(self.mapnode) self.mapnode.id = 'maproot' self.mapnode.style.position = 'absolute' self.mapnode.style.top = '0px' self.mapnode.style.left = '0px' self.map = L.map(self.mapnode) self.map.on('zoomend', self.map_handle_zoom) self.map.on('moveend', self.map_handle_move) self.map.on('click', self.map_handle_mouse) self.map.on('dblclick', self.map_handle_mouse) # Container to keep track of leaflet layer objects self.layer_container = [] self.layer_control = L.control.layers() self.scale = L.control.scale({'imperial': False, 'maxWidth': 200}) # Set the path for icon images L.Icon.Default.prototype.options.imagePath = '_data/shared/' return node def map_handle_zoom(self, e): global isNaN zoom = self.map.getZoom() if isNaN(zoom): return if zoom != self.zoom: self.set_zoom(zoom) def map_handle_move(self, e): center_coord = self.map.getCenter() center = center_coord.lat, center_coord.lng if center != self.center: self.set_center(center) def map_handle_mouse(self, e): latlng = [e.latlng.lat, e.latlng.lng] xy = [e.layerPoint.x, e.layerPoint.y] self.mouse_event(e.type, latlng, xy) @event.emitter def mouse_event(self, event, latlng, xy): return {'event': event, 'latlng': latlng, 'xy': xy} @event.reaction def __handle_zoom(self): self.map.setZoom(self.zoom) @event.reaction def __handle_min_zoom(self): self.map.setMinZoom(self.min_zoom) @event.reaction def __handle_max_zoom(self): self.map.setMaxZoom(self.max_zoom) @event.reaction def __handle_center(self): self.map.panTo(self.center) @event.reaction def __handle_show_layers(self): if self.show_layers: self.map.addControl(self.layer_control) else: self.map.removeControl(self.layer_control) @event.reaction def __handle_show_scale(self): if self.show_scale: self.map.addControl(self.scale) else: self.map.removeControl(self.scale) @event.reaction def __size_changed(self): size = self.size if size[0] or size[1]: self.mapnode.style.width = size[0] + 'px' self.mapnode.style.height = size[1] + 'px' # Notify the map that it's container's size changed self.map.invalidateSize() @event.reaction def __layers_changed(self): global L for layer in self.layer_container: self.layer_control.removeLayer(layer) if self.map.hasLayer(layer): self.map.removeLayer(layer) for layer_url, layer_name in self.layers: if not layer_url.endswith('.png'): if not layer_url.endswith('/'): layer_url += '/' layer_url += '{z}/{x}/{y}.png' new_layer = L.tileLayer(layer_url) self.layer_container.append(new_layer) self.map.addLayer(new_layer) self.layer_control.addOverlay(new_layer, layer_name)