~ubuntu-branches/ubuntu/raring/kiwi/raring

« back to all changes in this revision

Viewing changes to doc/howto/node20.html

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2007-01-30 09:52:28 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20070130095228-n0mkqlt82e74twqc
Tags: 1.9.12-0ubuntu1
* New upstream release.
* debian/patches/03_epyrun_use_local_modules.patch:
  - updated.
* debian/control:
  - moved python-support from Build-Depends to Build-Depends-Indep.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
 
2
<html>
 
3
<head>
 
4
<link rel="STYLESHEET" href="howto.css" type='text/css' />
 
5
<link rel="first" href="howto.html" title='Developing applications with Kiwi' />
 
6
<link rel='last' href='about.html' title='About this document...' />
 
7
<link rel='help' href='about.html' title='About this document...' />
 
8
<link rel="next" href="node21.html" />
 
9
<link rel="prev" href="node19.html" />
 
10
<link rel="parent" href="node16.html" />
 
11
<link rel="next" href="node21.html" />
 
12
<meta name='aesop' content='information' />
 
13
<title>2.9.4 Customizing Proxies and Models</title>
 
14
</head>
 
15
<body>
 
16
<DIV CLASS="navigation">
 
17
<div id='top-navigation-panel' xml:id='top-navigation-panel'>
 
18
<table align="center" width="100%" cellpadding="0" cellspacing="2">
 
19
<tr>
 
20
<td class='online-navigation'><a rel="prev" title="2.9.3 Propagating changes from"
 
21
  href="node19.html"><img src='previous.png'
 
22
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
 
23
<td class='online-navigation'><a rel="parent" title="2.9 Proxies and Models"
 
24
  href="node16.html"><img src='up.png'
 
25
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
 
26
<td class='online-navigation'><a rel="next" title="2.9.5 Using Signal Handlers"
 
27
  href="node21.html"><img src='next.png'
 
28
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
 
29
<td align="center" width="100%">Developing applications with Kiwi</td>
 
30
<td class='online-navigation'><img src='blank.png'
 
31
  border='0' height='32'  alt='' width='32' /></td>
 
32
<td class='online-navigation'><img src='blank.png'
 
33
  border='0' height='32'  alt='' width='32' /></td>
 
34
<td class='online-navigation'><img src='blank.png'
 
35
  border='0' height='32'  alt='' width='32' /></td>
 
36
</tr></table>
 
37
<div class='online-navigation'>
 
38
<b class="navlabel">Previous:</b>
 
39
<a class="sectref" rel="prev" href="node19.html">2.9.3 Propagating changes from</A>
 
40
<b class="navlabel">Up:</b>
 
41
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
 
42
<b class="navlabel">Next:</b>
 
43
<a class="sectref" rel="next" href="node21.html">2.9.5 Using Signal Handlers</A>
 
44
</div>
 
45
<hr /></div>
 
46
</DIV>
 
47
<!--End of Navigation Panel-->
 
48
 
 
49
<H3><A NAME="SECTION000294000000000000000">
 
50
2.9.4 Customizing Proxies and Models</A>
 
51
</H3>
 
52
 
 
53
<P>
 
54
From our example, proxy and instance appear to be completely coupled -
 
55
even the names of the components and attributes are tied. This is a
 
56
precise interpretation of the situation, but in my opinion, this
 
57
coupling is not only unavoidable, it is the essence of UI architecture.
 
58
Treating the interface as a completely separate entity from the object
 
59
it manipulates is, honestly, a bad idea, because <B>the interface is a
 
60
representation of the object</B>, and as such, essentially coupled to it.
 
61
Would it make sense to remove the <code>url</code> attribute from the model
 
62
and <I>not</I> remove it from the interface in question?
 
63
 
 
64
<P>
 
65
Because the UI is really a representation, however, there are times
 
66
where the contents of the widget and its attached proxy attribute must
 
67
differ in some way. Often, it is a matter of cardinality: more than one
 
68
widget defines a single proxy attribute, or vice-versa; at other times,
 
69
the data format in the widget does not match the format in the model
 
70
(think of dates, represented by strings in the interface, but stored as
 
71
DateTime objects in the object)<A NAME="tex2html7"
 
72
  HREF="#foot294"><SUP>7</SUP></A>. The Kiwi Proxy was
 
73
designed to cater to these different requirements, using accessor
 
74
functions when available.
 
75
 
 
76
<P>
 
77
Accessors provide an easy way to translate the model value to the
 
78
interface value: a pair of <code>get_*()</code> and <code>set_*()</code> functions
 
79
implemented in the model that perform internal manipulation of its
 
80
variables, removing the need to directly manipulate the instance
 
81
variable. You can define accessors for as few or as many model
 
82
attributes you want.
 
83
 
 
84
<P>
 
85
To make the process clearer, it is worth discussing how the model and
 
86
the UI are updated. The heuristics for updating a model are:
 
87
 
 
88
<P>
 
89
 
 
90
<OL>
 
91
<LI>If a change happens in the Proxy's widget <code>X</code>, it looks at
 
92
the model attached to it.
 
93
</LI>
 
94
<LI>If the model offers a <code>set_X()</code> method, it is called, with
 
95
the new value as its only parameter.
 
96
</LI>
 
97
<LI>If not, it manipulates the model directly by using
 
98
<code>setattr()</code>, which is the equivalent of <code>model.X = value</code>. If
 
99
<code>Proxies.set_attr_warnings(True)</code> has been called, a warning like
 
100
the following will be printed:
 
101
 
 
102
<P>
 
103
<div class="verbatim"><pre>
 
104
    Kiwi warning: could not find method set_title in model
 
105
    &lt;__main__.NewsItem instance at 0x82011ac&gt;, using setattr()
 
106
</pre></div>
 
107
 
 
108
<P>
 
109
</LI>
 
110
<LI>The model is updated (If multiple proxies are attached to the
 
111
model, special things happen, additionally, as you will see in section
 
112
<A href="multipleproxies.html#multipleproxies">2.9</A>).
 
113
</LI>
 
114
</OL>
 
115
 
 
116
<P>
 
117
The heuristics for updating the interface widget are:
 
118
 
 
119
<P>
 
120
 
 
121
<OL>
 
122
<LI>On startup, the proxy queries the model for the value for
 
123
attribute <code>X</code>.
 
124
</LI>
 
125
<LI>It tries first using an accessor method <code>get_X()</code>
 
126
(which should return a single value). If the accessor does not exist, it
 
127
will attempt to access the model's variable directly (using
 
128
<code>getattr()</code>). As with <code>setattr()</code> above, a warning will be
 
129
printed if attribute warnings are enabled.
 
130
</LI>
 
131
<LI>The interface is updated with this initial value, and normal
 
132
event processing begins.
 
133
</LI>
 
134
<LI>If a model's state for <code>X</code> is altered (<code>item.X =
 
135
"foo"</code>), a notification is sent to the proxy, with the attribute that
 
136
was altered. If a callback calls <code>self.update("X")</code>, a notification
 
137
is sent to the proxy, with the attribute that was altered.
 
138
</LI>
 
139
<LI>The proxy receives the notification; it gets the value of <code>X</code>
 
140
from the model using the same method as in step 2, and updates the
 
141
widget contents accordingly.
 
142
</LI>
 
143
</OL>
 
144
 
 
145
<P>
 
146
Summarizing: if you would like to customize the connection between model
 
147
and proxy for an attribute, implement accessor functions
 
148
(<code>get_foo()</code> and <code>set_foo()</code>) for it. If you would like to
 
149
verify that no direct instance manipulations are happening, use the
 
150
module function <code>set_attr_warnings()</code> and check the output
 
151
printed to the console's standard error.
 
152
 
 
153
<P>
 
154
Let's extend our previous example to provide an accessor and explain how
 
155
things work out (<span class="file">newsform3.py</span>).
 
156
 
 
157
<P>
 
158
<div class="verbatim"><pre>
 
159
    class NewsItem(FrameWork.Model):
 
160
        """An instance representing an item of news.
 
161
           Attributes: title, author, url"""
 
162
        def set_url(self, url):
 
163
            """sets the url, prefixing "http://" if missing"""
 
164
            http = "http://"
 
165
            if len(url) &gt; len(http) and string.find(url, http) != 0:
 
166
                url = http + url
 
167
            self.url = url
 
168
</pre></div>
 
169
 
 
170
<P>
 
171
In this example, we provide an accessor for setting the url (a "setter")
 
172
prefixed by "http://". The accessor is called when the entry's text
 
173
changes (for each character inserted or deleted), which is why I have to
 
174
check for the length of the url typed in. Note that I don't provide a
 
175
<code>get_url()</code> method (a "getter"), which means the raw url would be
 
176
loaded from the instance into the interface. In this specific case, this
 
177
is not an issue, because data is only loaded from the instance at
 
178
instantiation time and when the model attribute is changed. However, for
 
179
most cases both setter and getter need to convert to and from the model
 
180
format.
 
181
 
 
182
<P>
 
183
<BR><HR><H4>Footnotes</H4>
 
184
<DL>
 
185
<DT><A NAME="foot294">... object)</A><A
 
186
 HREF="node20.html#tex2html7"><SUP>7</SUP></A></DT>
 
187
<DD> Apart from these reasons, some
 
188
people insist that it is bad or wrong to manipulate the instance
 
189
directly, and that accessors should always be used.
 
190
 
 
191
</DD>
 
192
</DL>
 
193
<DIV CLASS="navigation">
 
194
<div class='online-navigation'>
 
195
<p></p><hr />
 
196
<table align="center" width="100%" cellpadding="0" cellspacing="2">
 
197
<tr>
 
198
<td class='online-navigation'><a rel="prev" title="2.9.3 Propagating changes from"
 
199
  href="node19.html"><img src='previous.png'
 
200
  border='0' height='32'  alt='Previous Page' width='32' /></A></td>
 
201
<td class='online-navigation'><a rel="parent" title="2.9 Proxies and Models"
 
202
  href="node16.html"><img src='up.png'
 
203
  border='0' height='32'  alt='Up One Level' width='32' /></A></td>
 
204
<td class='online-navigation'><a rel="next" title="2.9.5 Using Signal Handlers"
 
205
  href="node21.html"><img src='next.png'
 
206
  border='0' height='32'  alt='Next Page' width='32' /></A></td>
 
207
<td align="center" width="100%">Developing applications with Kiwi</td>
 
208
<td class='online-navigation'><img src='blank.png'
 
209
  border='0' height='32'  alt='' width='32' /></td>
 
210
<td class='online-navigation'><img src='blank.png'
 
211
  border='0' height='32'  alt='' width='32' /></td>
 
212
<td class='online-navigation'><img src='blank.png'
 
213
  border='0' height='32'  alt='' width='32' /></td>
 
214
</tr></table>
 
215
<div class='online-navigation'>
 
216
<b class="navlabel">Previous:</b>
 
217
<a class="sectref" rel="prev" href="node19.html">2.9.3 Propagating changes from</A>
 
218
<b class="navlabel">Up:</b>
 
219
<a class="sectref" rel="parent" href="node16.html">2.9 Proxies and Models</A>
 
220
<b class="navlabel">Next:</b>
 
221
<a class="sectref" rel="next" href="node21.html">2.9.5 Using Signal Handlers</A>
 
222
</div>
 
223
</div>
 
224
<hr />
 
225
<span class="release-info">Release 1.9.12, documentation updated on August, 2006.</span>
 
226
</DIV>
 
227
<!--End of Navigation Panel-->
 
228
 
 
229
</BODY>
 
230
</HTML>