File: node20.html

package info (click to toggle)
kiwi 1.9.22-2
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, squeeze, wheezy
  • size: 11,912 kB
  • ctags: 5,549
  • sloc: python: 15,779; ansic: 193; xml: 77; makefile: 57; sh: 18
file content (230 lines) | stat: -rw-r--r-- 9,517 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<link rel="STYLESHEET" href="howto.css" type='text/css' />
<link rel="first" href="howto.html" title='Developing applications with Kiwi' />
<link rel='last' href='about.html' title='About this document...' />
<link rel='help' href='about.html' title='About this document...' />
<link rel="next" href="node21.html" />
<link rel="prev" href="node19.html" />
<link rel="parent" href="node16.html" />
<link rel="next" href="node21.html" />
<meta name='aesop' content='information' />
<title>2.9.4 Customizing Proxies and Models</title>
</head>
<body>
<DIV CLASS="navigation">
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2.9.3 Propagating changes from"
  href="node19.html"><img src='previous.png'
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
<td class='online-navigation'><a rel="parent" title="2.9 Proxies and Models"
  href="node16.html"><img src='up.png'
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
<td class='online-navigation'><a rel="next" title="2.9.5 Using Signal Handlers"
  href="node21.html"><img src='next.png'
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
<td align="center" width="100%">Developing applications with Kiwi</td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node19.html">2.9.3 Propagating changes from</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node21.html">2.9.5 Using Signal Handlers</A>
</div>
<hr /></div>
</DIV>
<!--End of Navigation Panel-->

<H3><A NAME="SECTION000294000000000000000">
2.9.4 Customizing Proxies and Models</A>
</H3>

<P>
From our example, proxy and instance appear to be completely coupled -
even the names of the components and attributes are tied. This is a
precise interpretation of the situation, but in my opinion, this
coupling is not only unavoidable, it is the essence of UI architecture.
Treating the interface as a completely separate entity from the object
it manipulates is, honestly, a bad idea, because <B>the interface is a
representation of the object</B>, and as such, essentially coupled to it.
Would it make sense to remove the <code>url</code> attribute from the model
and <I>not</I> remove it from the interface in question?

<P>
Because the UI is really a representation, however, there are times
where the contents of the widget and its attached proxy attribute must
differ in some way. Often, it is a matter of cardinality: more than one
widget defines a single proxy attribute, or vice-versa; at other times,
the data format in the widget does not match the format in the model
(think of dates, represented by strings in the interface, but stored as
DateTime objects in the object)<A NAME="tex2html7"
  HREF="#foot294"><SUP>7</SUP></A>. The Kiwi Proxy was
designed to cater to these different requirements, using accessor
functions when available.

<P>
Accessors provide an easy way to translate the model value to the
interface value: a pair of <code>get_*()</code> and <code>set_*()</code> functions
implemented in the model that perform internal manipulation of its
variables, removing the need to directly manipulate the instance
variable. You can define accessors for as few or as many model
attributes you want.

<P>
To make the process clearer, it is worth discussing how the model and
the UI are updated. The heuristics for updating a model are:

<P>

<OL>
<LI>If a change happens in the Proxy's widget <code>X</code>, it looks at
the model attached to it.
</LI>
<LI>If the model offers a <code>set_X()</code> method, it is called, with
the new value as its only parameter.
</LI>
<LI>If not, it manipulates the model directly by using
<code>setattr()</code>, which is the equivalent of <code>model.X = value</code>. If
<code>Proxies.set_attr_warnings(True)</code> has been called, a warning like
the following will be printed:

<P>
<div class="verbatim"><pre>
    Kiwi warning: could not find method set_title in model
    &lt;__main__.NewsItem instance at 0x82011ac&gt;, using setattr()
</pre></div>

<P>
</LI>
<LI>The model is updated (If multiple proxies are attached to the
model, special things happen, additionally, as you will see in section
<A href="multipleproxies.html#multipleproxies">2.9</A>).
</LI>
</OL>

<P>
The heuristics for updating the interface widget are:

<P>

<OL>
<LI>On startup, the proxy queries the model for the value for
attribute <code>X</code>.
</LI>
<LI>It tries first using an accessor method <code>get_X()</code>
(which should return a single value). If the accessor does not exist, it
will attempt to access the model's variable directly (using
<code>getattr()</code>). As with <code>setattr()</code> above, a warning will be
printed if attribute warnings are enabled.
</LI>
<LI>The interface is updated with this initial value, and normal
event processing begins.
</LI>
<LI>If a model's state for <code>X</code> is altered (<code>item.X =
"foo"</code>), a notification is sent to the proxy, with the attribute that
was altered. If a callback calls <code>self.update("X")</code>, a notification
is sent to the proxy, with the attribute that was altered.
</LI>
<LI>The proxy receives the notification; it gets the value of <code>X</code>
from the model using the same method as in step 2, and updates the
widget contents accordingly.
</LI>
</OL>

<P>
Summarizing: if you would like to customize the connection between model
and proxy for an attribute, implement accessor functions
(<code>get_foo()</code> and <code>set_foo()</code>) for it. If you would like to
verify that no direct instance manipulations are happening, use the
module function <code>set_attr_warnings()</code> and check the output
printed to the console's standard error.

<P>
Let's extend our previous example to provide an accessor and explain how
things work out (<span class="file">newsform3.py</span>).

<P>
<div class="verbatim"><pre>
    class NewsItem(FrameWork.Model):
        """An instance representing an item of news.
           Attributes: title, author, url"""
        def set_url(self, url):
            """sets the url, prefixing "http://" if missing"""
            http = "http://"
            if len(url) &gt; len(http) and string.find(url, http) != 0:
                url = http + url
            self.url = url
</pre></div>

<P>
In this example, we provide an accessor for setting the url (a "setter")
prefixed by "http://". The accessor is called when the entry's text
changes (for each character inserted or deleted), which is why I have to
check for the length of the url typed in. Note that I don't provide a
<code>get_url()</code> method (a "getter"), which means the raw url would be
loaded from the instance into the interface. In this specific case, this
is not an issue, because data is only loaded from the instance at
instantiation time and when the model attribute is changed. However, for
most cases both setter and getter need to convert to and from the model
format.

<P>
<BR><HR><H4>Footnotes</H4>
<DL>
<DT><A NAME="foot294">... object)</A><A
 HREF="node20.html#tex2html7"><SUP>7</SUP></A></DT>
<DD> Apart from these reasons, some
people insist that it is bad or wrong to manipulate the instance
directly, and that accessors should always be used.

</DD>
</DL>
<DIV CLASS="navigation">
<div class='online-navigation'>
<p></p><hr />
<table align="center" width="100%" cellpadding="0" cellspacing="2">
<tr>
<td class='online-navigation'><a rel="prev" title="2.9.3 Propagating changes from"
  href="node19.html"><img src='previous.png'
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
<td class='online-navigation'><a rel="parent" title="2.9 Proxies and Models"
  href="node16.html"><img src='up.png'
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
<td class='online-navigation'><a rel="next" title="2.9.5 Using Signal Handlers"
  href="node21.html"><img src='next.png'
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
<td align="center" width="100%">Developing applications with Kiwi</td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
<td class='online-navigation'><img src='blank.png'
  border='0' height='32'  alt='' width='32' /></td>
</tr></table>
<div class='online-navigation'>
<b class="navlabel">Previous:</b>
<a class="sectref" rel="prev" href="node19.html">2.9.3 Propagating changes from</A>
<b class="navlabel">Up:</b>
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
<b class="navlabel">Next:</b>
<a class="sectref" rel="next" href="node21.html">2.9.5 Using Signal Handlers</A>
</div>
</div>
<hr />
<span class="release-info">Release 1.9.22, documentation updated on August, 2006.</span>
</DIV>
<!--End of Navigation Panel-->

</BODY>
</HTML>