1
"""
2
Defines Button and button-like widgets which allow triggering events
3
or merely toggling between on-off states.
4
"""
5 7
from __future__ import absolute_import, division, unicode_literals
6

7 7
from functools import partial
8

9 7
import param
10

11 7
from bokeh.models import (
12
    Button as _BkButton, Toggle as _BkToggle, Dropdown as _BkDropdown
13
)
14

15 7
from .base import Widget
16

17

18 7
class _ButtonBase(Widget):
19

20 7
    button_type = param.ObjectSelector(default='default', objects=[
21
        'default', 'primary', 'success', 'warning', 'danger'])
22

23 7
    _rename = {'name': 'label'}
24

25 7
    __abstract = True
26

27

28 7
class _ClickButton(_ButtonBase):
29

30 7
    __abstract = True
31

32 7
    _event = 'button_click'
33

34 7
    def _get_model(self, doc, root=None, parent=None, comm=None):
35 7
        model = super(_ClickButton, self)._get_model(doc, root, parent, comm)
36 7
        ref = (root or model).ref['id']
37 7
        model.on_click(partial(self._server_click, doc, ref))
38 7
        return model
39

40 7
    def js_on_click(self, args={}, code=""):
41
        """
42
        Allows defining a JS callback to be triggered when the button
43
        is clicked.
44

45
        Arguments
46
        ----------
47
        args: dict
48
          A mapping of objects to make available to the JS callback
49
        code: str
50
          The Javascript code to execute when the button is clicked.
51

52
        Returns
53
        -------
54
        callback: Callback
55
          The Callback which can be used to disable the callback.
56
        """
57 7
        from ..links import Callback
58 7
        return Callback(self, code={'event:'+self._event: code}, args=args)
59

60 7
    def jscallback(self, args={}, **callbacks):
61
        """
62
        Allows defining a JS callback to be triggered when a property
63
        changes on the source object. The keyword arguments define the
64
        properties that trigger a callback and the JS code that gets
65
        executed.
66

67
        Arguments
68
        ----------
69
        args: dict
70
          A mapping of objects to make available to the JS callback
71
        **callbacks: dict
72
          A mapping between properties on the source model and the code
73
          to execute when that property changes
74

75
        Returns
76
        -------
77
        callback: Callback
78
          The Callback which can be used to disable the callback.
79
        """
80 7
        from ..links import Callback
81 7
        for k, v in list(callbacks.items()):
82 7
            if k == 'clicks':
83 7
                k = 'event:'+self._event
84 7
            callbacks[k] = self._rename.get(v, v)
85 7
        return Callback(self, code=callbacks, args=args)
86

87

88 7
class Button(_ClickButton):
89

90 7
    clicks = param.Integer(default=0)
91

92 7
    _rename = {'clicks': None, 'name': 'label'}
93

94 7
    _widget_type = _BkButton
95

96 7
    def _server_click(self, doc, ref, event):
97 0
        self._events.update({"clicks": self.clicks+1})
98 0
        if not self._processing:
99 0
            self._processing = True
100 0
            if doc.session_context:
101 0
                doc.add_timeout_callback(partial(self._change_event, doc), self._debounce)
102
            else:
103 0
                self._change_event(doc)
104

105 7
    def _process_property_change(self, msg):
106 7
        msg = super(Button, self)._process_property_change(msg)
107 7
        if 'clicks' in msg:
108 7
            msg['clicks'] = self.clicks + 1
109 7
        return msg
110

111 7
    def on_click(self, callback):
112 7
        self.param.watch(callback, 'clicks', onlychanged=False)
113

114

115 7
class Toggle(_ButtonBase):
116

117 7
    value = param.Boolean(default=False, doc="""
118
        Whether the button is currently toggled.""")
119

120 7
    _rename = {'value': 'active', 'name': 'label'}
121

122 7
    _supports_embed = True
123

124 7
    _widget_type = _BkToggle
125

126 7
    def _get_embed_state(self, root, values=None, max_opts=3):
127 0
        return (self, self._models[root.ref['id']][0], [False, True],
128
                lambda x: x.active, 'active', 'cb_obj.active')
129

130

131 7
class MenuButton(_ClickButton):
132

133 7
    clicked = param.String(default=None, doc="""
134
      Last menu item that was clicked.""")
135

136 7
    items = param.List(default=[], doc="""
137
      Menu items in the dropdown. Allows strings, tuples of the form
138
      (title, value) or Nones to separate groups of items.""")
139

140 7
    split = param.Boolean(default=False, doc="""
141
      Whether to add separate dropdown area to button.""")
142

143 7
    _widget_type = _BkDropdown
144

145 7
    _rename = {'name': 'label', 'items': 'menu', 'clicked': None}
146

147 7
    _event = 'menu_item_click'
148

149 7
    def on_click(self, callback):
150 0
        self.param.watch(callback, 'clicked', onlychanged=False)
151

152 7
    def _server_click(self, doc, ref, event):
153 0
        self._events.update({"clicked": event.item})
154 0
        if not self._processing:
155 0
            self._processing = True
156 0
            if doc.session_context:
157 0
                doc.add_timeout_callback(partial(self._change_event, doc), self._debounce)
158
            else:
159 0
                self._change_event(doc)

Read our documentation on viewing source code .

Loading