widget_link.py
111 lines
| 3.5 KiB
| text/x-python
|
PythonLexer
Jason Grout
|
r18051 | """Link and DirectionalLink classes. | ||
Jason Grout
|
r19390 | Propagate changes between widgets on the javascript side | ||
Jason Grout
|
r18051 | """ | ||
Min RK
|
r20075 | |||
# Copyright (c) IPython Development Team. | ||||
Jason Grout
|
r18051 | # Distributed under the terms of the Modified BSD License. | ||
from .widget import Widget | ||||
Min RK
|
r20075 | from IPython.testing.skipdoctest import skip_doctest | ||
from IPython.utils.traitlets import Unicode, Tuple, List,Instance, TraitError | ||||
Jason Grout
|
r18051 | |||
Min RK
|
r20075 | class WidgetTraitTuple(Tuple): | ||
"""Traitlet for validating a single (Widget, 'trait_name') pair""" | ||||
def __init__(self, **kwargs): | ||||
super(WidgetTraitTuple, self).__init__(Instance(Widget), Unicode, **kwargs) | ||||
def validate_elements(self, obj, value): | ||||
value = super(WidgetTraitTuple, self).validate_elements(obj, value) | ||||
widget, trait_name = value | ||||
trait = widget.traits().get(trait_name) | ||||
trait_repr = "%s.%s" % (widget.__class__.__name__, trait_name) | ||||
# Can't raise TraitError because the parent will swallow the message | ||||
# and throw it away in a new, less informative TraitError | ||||
if trait is None: | ||||
raise TypeError("No such trait: %s" % trait_repr) | ||||
elif not trait.get_metadata('sync'): | ||||
raise TypeError("%s cannot be synced" % trait_repr) | ||||
return value | ||||
Jason Grout
|
r18051 | |||
class Link(Widget): | ||||
Min RK
|
r20075 | """Link Widget | ||
one trait: | ||||
widgets, a list of (widget, 'trait_name') tuples which should be linked in the frontend. | ||||
""" | ||||
Jason Grout
|
r18051 | _model_name = Unicode('LinkModel', sync=True) | ||
Min RK
|
r20075 | widgets = List(WidgetTraitTuple, sync=True) | ||
Jason Grout
|
r18051 | |||
Min RK
|
r20075 | def __init__(self, widgets, **kwargs): | ||
if len(widgets) < 2: | ||||
raise TypeError("Require at least two widgets to link") | ||||
Jason Grout
|
r18051 | kwargs['widgets'] = widgets | ||
super(Link, self).__init__(**kwargs) | ||||
Jason Grout
|
r19390 | # for compatibility with traitlet links | ||
def unlink(self): | ||||
self.close() | ||||
Sylvain Corlay
|
r18052 | |||
Min RK
|
r20075 | @skip_doctest | ||
Min RK
|
r20230 | def jslink(*args): | ||
Min RK
|
r20075 | """Link traits from different widgets together on the frontend so they remain in sync. | ||
Parameters | ||||
---------- | ||||
*args : two or more (Widget, 'trait_name') tuples that should be kept in sync. | ||||
Examples | ||||
-------- | ||||
>>> c = link((widget1, 'value'), (widget2, 'value'), (widget3, 'value')) | ||||
""" | ||||
Jason Grout
|
r18051 | return Link(widgets=args) | ||
Sylvain Corlay
|
r18052 | |||
class DirectionalLink(Widget): | ||||
Min RK
|
r20075 | """A directional link | ||
source: a (Widget, 'trait_name') tuple for the source trait | ||||
targets: one or more (Widget, 'trait_name') tuples that should be updated | ||||
when the source trait changes. | ||||
""" | ||||
Sylvain Corlay
|
r18052 | _model_name = Unicode('DirectionalLinkModel', sync=True) | ||
Min RK
|
r20075 | targets = List(WidgetTraitTuple, sync=True) | ||
source = WidgetTraitTuple(sync=True) | ||||
Sylvain Corlay
|
r18052 | |||
# Does not quite behave like other widgets but reproduces | ||||
# the behavior of IPython.utils.traitlets.directional_link | ||||
Min RK
|
r20075 | def __init__(self, source, targets, **kwargs): | ||
if len(targets) < 1: | ||||
raise TypeError("Require at least two widgets to link") | ||||
Sylvain Corlay
|
r18052 | kwargs['source'] = source | ||
kwargs['targets'] = targets | ||||
super(DirectionalLink, self).__init__(**kwargs) | ||||
Jason Grout
|
r19390 | # for compatibility with traitlet links | ||
def unlink(self): | ||||
self.close() | ||||
Min RK
|
r20075 | @skip_doctest | ||
Min RK
|
r20230 | def jsdlink(source, *targets): | ||
Min RK
|
r20075 | """Link the trait of a source widget with traits of target widgets in the frontend. | ||
Parameters | ||||
---------- | ||||
source : a (Widget, 'trait_name') tuple for the source trait | ||||
*targets : one or more (Widget, 'trait_name') tuples that should be updated | ||||
when the source trait changes. | ||||
Examples | ||||
-------- | ||||
>>> c = dlink((src_widget, 'value'), (tgt_widget1, 'value'), (tgt_widget2, 'value')) | ||||
""" | ||||
return DirectionalLink(source=source, targets=targets) | ||||
Sylvain Corlay
|
r18052 | |||