This file is indexed.

/usr/share/doc/python-pmw-doc/html/howtobuild.html is in python-pmw-doc 1.3.2-6build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
    <html>
    <head>
    <meta name="description" content="Pmw - a toolkit for building high-level compound widgets in Python">
    <meta name="content" content="python, megawidget, mega widget, compound widget, gui, tkinter">
    <title>How to build Pmw megawidgets</title>
    </head>

    <body bgcolor="#ffffff" text="#000000" link="#0000ee"
	vlink="551a8b" alink="ff0000">

    <h1 ALIGN="CENTER">How to build Pmw megawidgets</h1>
    
<center><P ALIGN="CENTER">
<IMG SRC = blue_line.gif ALT = "" WIDTH=320 HEIGHT=5>
</p></center>

<dl>
<dt> <h3>Introduction</h3></dt><dd>
<p>
  This document briefly describes how to design and code Pmw
  megawidgets by inheriting from the Pmw base classes.  It shows step
  by step how to build a simple example megawidget.  This megawidget
  allows the user to select one of a range of numbers and it also
  indicates if the selected number is greater than a given threshold.

</p>

</dd>
<dt> <h3>Choosing the components</h3></dt><dd>

<p>
  The megawidget will be built using a Tkinter.Scale widget to allow
  the user to select a number in a range, and a Tkinter.Frame widget
  to act as an indicator, displaying red (say) if the selected number
  exceeds the threshold.  It will look something like this:

</p>

<center><P ALIGN="CENTER">
  <IMG SRC = scale1.gif ALT = "Scale 2" WIDTH=70 HEIGHT=244>
</p></center>
  
<p>
  The programmer using this megawidget will need access to the scale
  widget, since they will need to set the scale's range.  Therefore
  the scale will be made a component of the megawidget.  The
  programmer will probably not need access to the indicator frame,
  but, just in case the need arises to change the borderwidth or
  relief of the indicator, we will make it a component too.  This
  illustrates a convention about components - for maximum
  configurability, make all sub-widgets components.

</p>

</dd>
<dt> <h3>Choosing the options</h3></dt><dd>

<p>
  Apart from the component options now available through the scale and indicator
  components, the megawidget will need a few options of its own.  It
  will need a <strong>threshold</strong> option to set the threshold. 
  It may also need options to set the colors of the indicator when the
  selected value is both above and below the threshold.  Other options
  could be <strong>orient</strong> or <strong>indicatorpos</strong> to
  specify the relative position of components and
  <strong>margin</strong>, <strong>padx</strong> or
  <strong>pady</strong> to specify spacing between and around the
  components.  For this example, we will define three options -
  <strong>threshold</strong>, <strong>colors</strong> and
  <strong>value</strong>.  The <strong>colors</strong> option will be
  a 2-element sequence specifying two colors (below threshold, above
  threshold).  The <strong>value</strong> option will be the initial
  value of the scale.

</p>

</dd>
<dt> <h3>Coding the megawidget</h3></dt><dd>

<p>
  The first things to do are to decide on a name for the new
  megawidget, decide which base class to inherit from and to begin to
  write the constructor.  Most Pmw megawidgets are derived from either
  Pmw.MegaWidget, Pmw.MegaToplevel or Pmw.Dialog.  In this case, since
  the widget is not to be contained within its own toplevel window, we
  will inherit from Pmw.MegaWidget.  The constructors of megawidgets
  take one argument (the widget to use as the parent of the
  megawidget's hull, defaulting to the root window) and any number of
  keyword arguments.

</p>

<pre>
class ThresholdScale(Pmw.MegaWidget):
    """ Megawidget containing a scale and an indicator.
    """
 
    def __init__(self, parent = None, **kw):
</pre>

<p>
  Next, we need to define the options supplied by this megawidget. 
  Each option is specified by a 3-element sequence.  The first element
  is the option's name.  The second element is the default value.  The
  third element is either a callback function,
  <strong>Pmw.INITOPT</strong> or <strong>None</strong>.  In the first
  case, the function is called at the end of construction (during the 
  call to <code>self.inialiseoptions</code>) and also
  whenever the option is set by a call to
  <code>configure</code>.  <strong>Pmw.INITOPT</strong> indicates that
  the option is an initialisation option - it cannot be set by calling
  <code>configure</code>.  <strong>None</strong> indicates that the
  option can be set by calling <code>configure</code>, but that there
  is no callback function.

</p>

<p>
  The call to <code>self.defineoptions</code> also includes the
  keyword arguments passed in to the constructor.  The value given to
  any option specified in the keywords will override the default
  value.

</p>

<pre>
        # Define the megawidget options.
        optiondefs = (
            ('colors',    ('green', 'red'), None),
            ('threshold', 50,               None),
            ('value',     None,             Pmw.INITOPT),
        )
        self.defineoptions(kw, optiondefs)
</pre>

<p>
  After defining the options, the constructor of the base class should
  be called.  The options need to be defined first so that a derived
  class can redefine the default value of an option defined in a base
  class.  This is because the value specified by the derived class
  must be made available before the base class constructor is called.
  The keyword
  arguments should not be passed into the base class constructor since
  they have already been dealt with in the previous step.

</p>

<pre>
        # Initialise base class (after defining options).
        Pmw.MegaWidget.__init__(self, parent)
</pre>

<p>
  Now we should create the components.  The components are created as
  children (or grandchildren ...) of the megawidget's interior.

</p>

<pre>
        # Create the components.
        interior = self.interior()
</pre>

<p>
  The first component to create is the indicator.  The
  <code>createcomponent</code> method creates the sub-widget and
  registers the widget as a component of this megawidget.  It takes
  five arguments plus any number of keyword arguments.  The arguments
  are name, aliases, group, class and constructor arguments.  See the
  <a href="MegaArchetype.html">Pmw.MegaArchetype reference manual</a>)
  for full details.

</p>

<pre>
        # Create the indicator component.
        self.indicator = self.createcomponent('indicator',
                (), None,
                Tkinter.Frame, (interior,),
                        width = 16,
                        height = 16,
                        borderwidth = 2,
                        relief = 'raised')
        self.indicator.grid()
</pre>

<p>
  The scale component is created in a similar way.  In this case, the
  initial value of the scale is also set to the value of the
  <strong>value</strong> initialisation option.

</p>

<pre>
        # Create the scale component.
        self.scale = self.createcomponent('scale',
                (), None,
                Tkinter.Scale, (interior,),
                        command = self._doCommand,
                        tickinterval = 20,
                        length = 200,
                        from_ = 100,
                        to = 0,
                        showvalue = 0)
        self.scale.grid()
 
        value = self['value']
        if value is not None:
            self.scale.set(value)
</pre>

<p>
  At the end of the constructor, the <code>initialiseoptions</code>
  method is called to check that all keyword arguments have been used
  (that is, the caller did not specify any unknown or misspelled
  options) and to call the option callback functions.

</p>

<pre>
        # Check keywords and initialise options.
        self.initialiseoptions()
</pre>

<p>
  All other methods must now be defined.  In this case, only one
  method is required - a method called whenever the scale changes and
  which sets the indicator color according to the threshold.

</p>

<pre>
    def _doCommand(self, valueStr):
        if self.scale.get() > self['threshold']:
            color = self['colors'][1]
        else:
            color = self['colors'][0]
        self.indicator.configure(background = color)
</pre>

<p>
  To complete the megawidget, methods from other classes can be
  copied into this class.  In this case, all Tkinter.Scale methods
  not already defined by the megawidget are made available as methods
  of this class and are forwarded to the scale component.  Note that
  the third argument to <code>Pmw.forwardmethods</code> is the name of
  the instance variable referring to the Tkinter.Scale widget and not
  the name of the component.  This function is called outside of and
  after the class definition.

</p>

<pre>
Pmw.forwardmethods(ThresholdScale, Tkinter.Scale, 'scale')
</pre>

<p>
    <strong>Important note:</strong> If a megawidget defines options
    using <code>defineoptions()</code>, then this method must be
    called in the megawidget constructor before the call to the base
    class constructor and a matching call to
    <code>initialiseoptions()</code> must made at the end of the
    constructor.  For example:

</p>
<pre>
    def __init__(self, parent = None, **kw):
	optionDefs = ...
	self.defineoptions(kw, optionDefs)
	BaseClass.__init__(self, parent)
	...
	self.initialiseoptions()
</pre>

</dd>
<dt> <h3>Creating instances of the megawidget</h3></dt><dd>

<p>
  The code below creates two of our example megawidgets.  The first is
  created with default values for all options.  The second is created
  with new values for the options.  It also redefines some of the
  options of the components.

</p>

<dl>
<dd>
<pre>
# Create and pack two ThresholdScale megawidgets.
mega1 = ThresholdScale()
mega1.pack(side = 'left', padx = 10, pady = 10)

mega2 = ThresholdScale(
        colors = ('green', 'yellow'),
        threshold = 75,
        value = 80,
        indicator_width = 32,
        scale_width = 25)
mega2.pack(side = 'left', padx = 10, pady = 10)
</pre>
</dd>
</dl>

<center><P ALIGN="CENTER">
  <IMG SRC = scale2.gif ALT = "Scale 1" WIDTH=150 HEIGHT=244>
</p></center>
  
</dd>
<dt> <h3>The complete code</h3></dt><dd>

<p>
  The complete code for this example can be seen
  <a href="example.py">here</a>.

</p>

</dd>
<dt> <h3>Exercises</h3></dt><dd>

<p>
  These exercises build on the example presented so far.

</p>

<ol>
  <li>
    Change the call to create <code>mega1</code> so that the scale
    widget displays the current value next to the slider.  (You may
    need to look at the Tk scale manual page to find which option to
    the <strong>scale</strong> component to set.)  You will be able to
    do this without modifying the ThresholdScale class code.

  </li>
  <li>
    Add a Tkinter.Label component between the indicator and scale
    components.  Modify the <code>_doCommand</code> method so that it
    displays the current value of the scale in this label.

  </li>
  <li>
    Modify the <strong>colors</strong> and <strong>threshold</strong>
    options so that they both accept a tuple.  Now implement multiple
    thresholds, so that the indicator displays one of several colors,
    depending on the value of the scale.

  </li>
  <li>
    Add an <strong>orient</strong> initialisation option and lay out
    the components horizontally or vertically depending on its value.

  </li>
  <li>
    Read the description of the <code>createlabel()</code> method in
    the <a href="MegaArchetype.html">Pmw.MegaArchetype reference
    manual</a> and add <strong>labelpos</strong> and
    <strong>labelmargin</strong> initialisation options which allow
    the creation of a label for the megawidget.

  </li>
</ol>

<p>
  An example of how these changes can be made can be seen
  <a href="exercises.py">here</a>.

</p>

</dd>
<dt> <h3>Contributing your megawidgets to Pmw</h3></dt><dd>

<p>
  If you have completed a megawidget that may be useful to others, you
  may like to consider contributing it to Pmw.  See
  <a href="starting.html#contributions">Contributions welcome</a> for
  how to contribute.

</p>

</dd>
<dt> <h3>Pmw coding conventions</h3></dt><dd>

<p>
As a final note, the Pmw code makes an attempt to follow these coding
conventions.
</p>

<ul>
  <li>
    Class names: initial of each word is upper case (including first word).

  </li>
  <li>
    Public method and function names: all in lower case.

  </li>
  <li>
    Megawidget options: all in lower case.

  </li>
  <li>
    Megawidget component names: all in lower case.

  </li>
  <li>
    Function arguments: initial of each word is upper case (except first word).

  </li>
  <li>
    Private names:  initial of each word is upper case (except first
    word if not a class)

  </li>
  <li>
    Underscores as word separators are only used when overriding
    Tkinter methods of same name.

  </li>
  <li>
    Indent is four spaces.

  </li>
  <li>
    Continuation lines are indented by eight spaces, so that they
    won't be confused with a following nested code block. 
    Continuation lines should be used when a statement, which would
    normally be written on one line, is longer than 80 characters. 
    Examples are "if" statements which contain many conditions and
    function calls with many arguments.

  </li>
  <li>

    Surround <code>=</code> with spaces when used with keyword
    parameters in function calls.

  </li>
  <li>

    Multi-line function calls should have one keyword parameter per
    line.

  </li>
</ul>
</dd>
</dl>


    <center><P ALIGN="CENTER">
    <IMG SRC = blue_line.gif ALT = "" WIDTH=320 HEIGHT=5>
    </p></center>
    

    <font size=-1>
    <center><P ALIGN="CENTER">
    Pmw 1.3 -
     7 Aug 2007
     - <a href="index.html">Home</a>
    
    </p></center>
    </font>

    </body>
    </html>