1 import string
2 from Tkinter import *
3 import tkMessageBox
4 import Pmw
5 from teamwork.math.Keys import StateKey,ActionKey
6 from teamwork.widgets.pmfScale import PMFScale
7 from teamwork.widgets.multiscale import MultiScale
8 from teamwork.widgets.images import loadImages
9 from teamwork.reward.goal import PWLGoal,maxGoal,minGoal
10 from teamwork.reward.MinMaxGoal import MinMaxGoal
11 from teamwork.agent.Generic import GenericModel
12 from teamwork.widgets.TreeBuilder import TreeBuilder
13
15 lockLabels = ['Lock','Unlock']
16 defaultLock = 1
17 resolution = 0.01
18
19 - def __init__(self,parent,entity,balloon,**kw):
20
21 self.images = loadImages({'del': 'icons/trophy--minus.png',
22 'new': 'icons/trophy--plus.png',})
23 optiondefs = (
24 ('balloon',None,Pmw.INITOPT),
25 ('society',None,None),
26 ('expert',0,self.setExpert),
27 ('generic',False,None),
28 )
29 self.defineoptions(kw, optiondefs)
30 self.normalizing = {}
31 self.entity = entity
32 self.features = {}
33 fr = Pmw.ScrolledFrame.__init__(self,parent)
34 self.interior().grid_columnconfigure(0,weight=1)
35
36 toolbar = self.createcomponent('toolbar',(),None,Frame,(self.interior(),),
37 bd=2,relief='raised')
38 toolbar.grid(row=0,column=0,sticky='ew')
39 if self['generic']:
40
41 button = Label(toolbar)
42 button.bind('<ButtonRelease-1>',self.promptNew)
43 if self.images.has_key('new'):
44 button.configure(image=self.images['new'],bd=0)
45 else:
46 button.configure(text='New goal')
47 button.pack(side='left',ipadx=5,ipady=3)
48 if self['balloon']:
49 self['balloon'].bind(button,'Add new goal')
50
51 widget = self.createcomponent('scale',(),None,PMFScale,(self.interior(),),
52 distribution=entity.goals,
53 expand=self.expand,collapse=self.collapse,
54 viewprobs=True,floatdomain=False)
55 widget.grid(row=1,column=0,sticky='news')
56 self.initialiseoptions()
57
59 try:
60 dialog = self.component('dialog')
61 except KeyError:
62 dialog = self.createDialog()
63
64 options = self['society'].keys()
65 options.sort()
66 options.append('self')
67 if isinstance(self.entity,GenericModel):
68 options += self.entity.getRelationships()
69 else:
70 options += self.entity.relationships.keys()
71 if len(options) == 0:
72 raise UserWarning,self.entity.ancestry()
73 dialog.component('entity_listbox').delete(0,END)
74 for option in options:
75 dialog.component('entity_listbox').insert(END,option)
76 dialog.component('feature').configure(menubutton_state='normal')
77 dialog.activate()
78
80 for name in self.components():
81 if 'Goal' in name:
82 self.component(name).configure(state=state)
83
106
116
118 """Redraws all of the goal widgets"""
119 widget = self.component('scale')
120 disabled = widget.cget('state') == 'disabled'
121 widget.configure(state='normal')
122 widget.setDistribution()
123 if disabled:
124 widget.configure(state='disabled')
125
127 """Updates the display in response to the current expert mode"""
128 pass
129
131 if not name:
132 name = self.component('dialog_entity').get()
133 if not name:
134 return
135 self.features = {}
136 if name == 'self':
137 eList = [self.entity.name]
138 else:
139 if isinstance(self.entity,GenericModel):
140 remaining = self.entity.ancestors()
141 else:
142 remaining = [self.entity.name]
143 for agent in remaining:
144 try:
145 eList = self['society'][agent].relationships[name][:]
146 break
147 except KeyError:
148 pass
149 else:
150 eList = [name]
151 if isinstance(self.entity,GenericModel):
152 while len(eList) > 0:
153 entity = self['society'][eList.pop()]
154 for feature in entity.getStateFeatures():
155 if not self.features.has_key(feature):
156 self.features[feature] = {'type':'state',
157 'key':feature}
158 for option in entity.actions.getOptions():
159 for action in option:
160 if not self.features.has_key(action['type']):
161 entry = {'type':'actActor',
162 'key':action['type']}
163 self.features[action['type']] = entry
164 eList += entity.parentModels
165 elif self['society']:
166 for feature in self['society'][name].getStateFeatures():
167 self.features[feature] = {'type':'state','key':feature}
168 features = self.features.keys()
169 features.sort()
170 self.component('dialog_feature').setitems(features)
171 if len(features) > 0:
172 self.component('dialog_feature').invoke(features[0])
173
174 - def add(self,button='OK'):
175 self.component('dialog').deactivate()
176 if button == 'OK':
177 direction = self.component('dialog_direction').getvalue().lower()
178 entity = self.component('dialog_entity').get()
179 feature = self.features[self.component('dialog_feature').getvalue()]
180 if len(feature) == 0:
181 tkMessageBox.showerror('No Feature','The selected entity has no state features to min/maximize.')
182 return
183 if feature['type'] == 'state':
184 key = StateKey({'entity': entity, 'feature': feature['key']})
185 elif feature['type'] == 'actActor':
186 key = ActionKey({'entity': entity, 'type': feature['key'],
187 'object': None})
188 else:
189 raise NotImplementedError,'Unable to put goals on %s' % \
190 (feature['type'])
191 if direction == 'complex':
192 goal = PWLGoal()
193 goal.keys.append(key)
194 elif direction == 'minimize':
195 goal = minGoal(key)
196 else:
197 goal = maxGoal(key)
198 for other in self.entity.getGoals():
199 if goal.keys == other.keys:
200 msg = '%s already has a goal for %s' % \
201 (self.entity.ancestry(),','.join(map(str,(goal.keys))))
202 tkMessageBox.showerror('Goal exists',msg)
203 break
204 else:
205 if len(self.entity.getGoals()) == 0:
206 self.entity.setGoalWeight(goal,1.,False)
207 else:
208 self.entity.setGoalWeight(goal,0.,False)
209 self.component('scale').setDistribution()
210
212
213 palette = Pmw.Color.getdefaultpalette(self.interior())
214 dialog = self.createcomponent('dialog',(),None,Pmw.Dialog,
215 (self.interior(),),
216 buttons=('OK','Cancel'),
217 command=self.add,defaultbutton=0)
218 dialog.withdraw()
219 options = ['Maximize','Minimize','Complex']
220 widget = dialog.createcomponent('direction',(),'New Goal',
221 Pmw.OptionMenu,(dialog.interior(),),
222 items=options,
223 menubutton_width=max(map(len,options)),
224 labelpos='nw',label_text='Direction:')
225 widget.pack(side='left',pady=10,padx=10)
226 widget = dialog.createcomponent('entity',(),'New Goal',
227 Pmw.ComboBox,(dialog.interior(),),
228 labelpos='nw',label_text='Entity:',
229 entry_state='disabled',
230 entry_disabledforeground=palette['foreground'],
231 entry_disabledbackground=palette['background'],
232 selectioncommand=self.selectEntity,
233 )
234 widget.pack(side='left',fill='x',expand='yes')
235 widget = dialog.createcomponent('feature',(),'New Goal',
236 Pmw.OptionMenu,
237 (dialog.interior(),),
238 labelpos='nw',
239 label_text='Feature:')
240 widget.pack(side='left',fill='x',expand='yes')
241 return dialog
242
244 table = {}
245 for condition,tree in goal.dependency:
246 table[str(condition)] = {'actions': condition, 'tree': tree}
247 tree = self.createcomponent(str(goal),(),'Editor',TreeBuilder,
248 (frame,),society=self['society'],
249 orient='horizontal',expert=True,
250 key=goal.toKey(),font=('Helvetica',10),
251 treeWidth=250,new=self.newDependency,
252 table=table)
253 tree.pack(side='left',fill='both',expand='yes')
254
256 self.destroycomponent(str(goal))
257
259 """Callback when a new action dependency is created
260 """
261 for goal in self.entity.getGoals():
262 if goal.keys == [key]:
263 break
264 else:
265 raise NameError,'Unable to find goal on %s' % (str(key))
266 goal.addDependency(condition,tree)
267