source: orange/docs/extend-widgets/rst/api.rst @ 11049:f4dd8dbc57bb

Revision 11049:f4dd8dbc57bb, 4.7 KB checked in by Miha Stajdohar <miha.stajdohar@…>, 16 months ago (diff)

From HTML to Sphinx.

Line 
1#############################################
2Orange Widgets Reference Guide for Developers
3#############################################
4
5***********************************
6Channels Definitions, Data Exchange
7***********************************
8
9Input and output channels are defined anywhere within the
10:obj:`__init__` function of a main widget class. The definition
11is used when running a widget, but also when registering your widget
12within Orange Canvas. Channel definitions are optional, depending on
13what your widget does.
14
15Output Channels
16***************
17
18Following is an example that defines two output channels::
19
20    self.outputs = [("Sampled Data", orange.ExampleTable), ("Learner", orange.Learner)]
21
22:obj:`self.outputs` should thus be a list of tuples, within
23each the first element is a name of the channel, and the second the
24type of the tokens that will be passed through. Token types are class
25names; most often these are some Orange classes, but they can also be
26anything you may define as class in Python.
27
28Widgets send the data by using :obj:`self.send` call,
29like::
30
31    self.send("Sampled Data", mydata)
32
33Parameters of :obj:`send` are channel name and a token to be
34send (e.g., a variable that holds the data to be send through the
35channel).
36
37When tokens are send around, the signaling mechanism annotates
38them with a pointer to an object that sent the toke (e.g., a widget
39id). Additionally, this annotation can be coupled with some name
40passed to :obj:`send`, in case you have a widget that can send
41few tokens one after the other and you would like to enable a receiving widget
42recognize these are different tokens (and not updates of the same
43one)::
44
45    id = 10
46    self.send("Sampled Data", mydata, id)
47
48**************
49Input Channels
50**************
51
52An example of the simplest definition of an input channel is::
53
54    self.inputs = [("Data", orange.ExampleTable, self.receiveData)]
55
56Again, :obj:`self.inputs` is a list of tuples, where the
57elements are the name of the channel, followed by a channel type and a
58Python function that will be called with any token received. For the
59channel defined above, a corresponding receiving function would be of
60the type (we would most often define it within the widget class
61defintion, hence :obj:`self` for the first attribute)::
62
63    def receiveData(self, data):
64    # handle data in some way
65
66Any time our widget would receive a token, :obj:`receiveData`
67would be called. Notice there would be no way of knowing anything
68about the sender of the token, hence widget would most often replace
69the previously received token with the new one, and forget about the
70old one.
71
72Widgets can often clear their output by sending a :obj:`None`
73as a token. Also, upon deletion of some widget, this is the way that
74Orange Canvas would inform all directly connected downstream widgets
75about deletion. Similar, when channels connecting two widgets are
76deleted, Orange Canvas would automatically send :obj:`None` to
77the receiving widget. Make sure your widget handles :obj:`None`
78tokens appropriately!`
79
80There are cases when widget would like to know about the origin of
81a token. Say, you would like to input several learners to the
82evaluation widget, how would this distinguish between the learners of
83different origins? Remember (from above) that tokens are actually
84passed around with IDs (pointers to widgets that sent them). To
85declare a widget is interested about these IDs, one needs to define an
86input channel in the following way::
87
88    self.inputs = [("Learners", orange.Learner, self.learner, Multiple)]
89
90where the last argument refers if we have a "Single" (default if not
91specified) or a "Multiple" channel. For the above declared channel, the
92receiving function should include an extra argument for the ID, like::
93
94   def learner(self, learnertoken, tokenid):
95   # handle learnertoken and tokeid in some way
96
97Widgets such as :obj:`OWTestLearners` and alike use such
98schema.
99
100Finally, we may have input channels of the same type. If a widget
101would declare input channels like::
102
103    self.inputs = [("Data", orange.ExampleTable, self.maindata),
104               ("Additional Data", orange.ExampleTable, self.otherdata)]
105
106and we connect this widget in Orange Canvas to a sending widget
107that has a single orange.ExampleTable output channel, Canvas would
108bring up Set Channels dialog. There, a sending widget's channel could
109be connected to both receiving channels. As we would often prefer to
110connect to a single (default) channel instead (still allowing user of
111Orange Canvas to set up a different schema manually), we set that channel
112as the default. We do this by the using the fourth element in the channel
113definition list, like::
114
115    self.inputs = [("Data", orange.ExampleTable, self.maindata, Default),
116               ("Additional Data", orange.ExampleTable, self.otherdata)]
Note: See TracBrowser for help on using the repository browser.