source: orange/Orange/doc/extend-widgets/reference.htm @ 9671:a7b056375472

Revision 9671:a7b056375472, 5.2 KB checked in by anze <anze.staric@…>, 2 years ago (diff)

Moved orange to Orange (part 2)

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