2 To use the Options system:
4 1. Create an OptionGroup:
5 options = OptionGroup('MyProg', 'Options')
6 You can also use the handy rox.setup_app_options() in most applications.
9 colour = Option('colour', 'red', options)
10 size = Option('size', 3, options)
12 3. Register any callbacks (notification of options changing):
14 if colour.has_changed:
15 print "The colour is now", colour.value
16 options.add_notify(my_callback)
18 4. Notify any changes from defaults:
21 See OptionsBox for editing options. Do not change the value of options
25 from __future__
import generators
31 """An Option stores a single value. Every option is part of exactly one OptionGroup.
33 The read-only attributes value and int_value can be used to get the current setting
34 for the Option. int_value will be -1 if the value is not a valid integer.
36 The has_changed attribute is used during notify() calls to indicate whether this
37 Option's value has changed since the last notify (or option creation).
38 You may set has_changed = 1 right after creating an option if you want to force
39 notification the first time even if the default is used.
41 def __init__(self
, name
, value
, group
= None):
42 """Create a new option with this name and default value.
43 Add to 'group', or to rox.app_options if no group is given.
44 The value cannot be used until the first notify() call to
47 assert rox
.app_options
48 group
= rox
.app_options
50 self
.has_changed
= 0 # ... since last notify/default
51 self
.default_value
= str(value
)
56 self
.group
._register
(self
)
58 def _set(self
, value
):
59 if self
.value
!= value
:
60 self
.value
= str(value
)
63 if self
.value
== 'True':
65 elif self
.value
== 'False':
68 self
.int_value
= int(float(self
.value
))
72 def _to_xml(self
, parent
):
73 doc
= parent
.ownerDocument
74 node
= doc
.createElement('Option')
75 node
.setAttribute('name', self
.name
)
76 node
.appendChild(doc
.createTextNode(self
.value
))
77 parent
.appendChild(node
)
80 return "<Option %s=%s>" % (self
.name
, self
.value
)
83 def __init__(self
, program
, leaf
):
84 "program/leaf is a Choices pair for the saved options."
85 self
.program
= program
87 self
.pending
= {} # Loaded, but not registered
88 self
.options
= {} # Name -> Option
90 self
.too_late_for_registrations
= 0
92 path
= choices
.load(program
, leaf
)
97 from xml
.dom
import Node
, minidom
99 doc
= minidom
.parse(path
)
101 root
= doc
.documentElement
102 assert root
.localName
== 'Options'
103 for o
in root
.childNodes
:
104 if o
.nodeType
!= Node
.ELEMENT_NODE
:
106 if o
.localName
!= 'Option':
107 print "Warning: Non Option element", o
109 name
= o
.getAttribute('name')
111 value
= o
.childNodes
[0].nodeValue
114 self
.pending
[name
] = value
116 rox
.report_exception()
118 def _register(self
, option
):
119 """Called by Option.__init__."""
120 assert option
.name
not in self
.options
121 assert not self
.too_late_for_registrations
125 self
.options
[name
] = option
127 if name
in self
.pending
:
128 option
._set
(self
.pending
[name
])
129 del self
.pending
[name
]
132 """Save all option values. Usually called by OptionsBox()."""
133 assert self
.too_late_for_registrations
135 path
= choices
.save(self
.program
, self
.leaf
)
137 return # Saving is disabled
139 from xml
.dom
.minidom
import Document
141 root
= doc
.createElement('Options')
142 doc
.appendChild(root
)
147 file = open(path
, 'w')
151 def add_notify(self
, callback
):
152 "Call callback() after one or more options have changed value."
153 assert callback
not in self
.callbacks
155 self
.callbacks
.append(callback
)
157 def remove_notify(self
, callback
):
158 """Remove a callback added with add_notify()."""
159 self
.callbacks
.remove(callback
)
162 """Call this after creating any new options or changing their values."""
163 if not self
.too_late_for_registrations
:
164 self
.too_late_for_registrations
= 1
166 print "Warning: Some options loaded but unused:"
167 for (key
, value
) in self
.pending
.iteritems():
168 print "%s=%s" % (key
, value
)
171 o
._set
(o
.default_value
)
172 map(apply, self
.callbacks
)
174 option
.has_changed
= 0
177 return self
.options
.itervalues()