1 from Tkinter import *
2 import tkMessageBox
3 import Pmw
4 from teamwork.math.Keys import ObservationKey
5 from teamwork.math.ProbabilityTree import ProbabilityTree
6 from teamwork.widgets.images import loadImages
7 from teamwork.widgets.TreeBuilder import TreeBuilder
8 from teamwork.widgets.ActionDialog import ActionDialog
9
11 """Frame for specifying model of partial observability
12 @ivar images: table of images to use (need to keep this permanently stored)
13 @type images: dict
14 @cvar anyString: label used for a O function LHS that matches against any action
15 @type anyString: str
16 """
17 anyString = 'any'
18
20 self.images = loadImages({'del': 'icons/binocular--minus.png',
21 'add': 'icons/binocular--plus.png',
22 'new': 'icons/chart--plus.png'})
23 optiondefs = (
24 ('balloon',None,Pmw.INITOPT),
25 ('generic',False,Pmw.INITOPT),
26 ('expert', False,None),
27 ('society', {}, None),
28 )
29 self.entity = entity
30 self.defineoptions(kw, optiondefs)
31 Pmw.ScrolledFrame.__init__(self,parent)
32 self.interior().grid_columnconfigure(0,weight=1)
33 if self['generic']:
34 toolbar = Frame(self.interior(),bd=2,relief='raised')
35 toolbar.grid(row=0,column=0,sticky='new')
36
37 self.createcomponent('dialog',(),None,Pmw.PromptDialog,(parent,),
38 title='New observation',entryfield_labelpos='w',
39 label_text='New observation:',
40 defaultbutton = 0,buttons = ('OK', 'Cancel'),
41 command = self.newOmega)
42 self.component('dialog').withdraw()
43
44 button = Label(toolbar)
45 button.bind('<ButtonRelease-1>',self.component('dialog').activate)
46 if self.images.has_key('add'):
47 button.configure(image=self.images['add'],bd=0)
48 else:
49 button.configure(text='Add')
50 button.pack(side='left',ipadx=5,ipady=3)
51 if self['balloon']:
52 self['balloon'].bind(button,'Add new observation symbol')
53
54 button = Label(toolbar)
55 button.bind('<ButtonRelease-1>',self.delete)
56 if self.images.has_key('del'):
57 button.configure(image=self.images['del'],bd=0)
58 else:
59 button.configure(text='Delete')
60 button.pack(side='left',ipadx=5,ipady=3)
61 if self['balloon']:
62 self['balloon'].bind(button,'Delete selected observation symbol')
63
64 self.perfect = IntVar()
65 button = self.createcomponent('observable',(),None,Checkbutton,
66 (self.interior(),),command=self.observable,
67 variable=self.perfect,
68 text='Perfect observations')
69 button.grid(row=1,column=0,sticky='nw',padx=20,pady=20)
70
71 frame = self.createcomponent('details',(),None,Frame,(self.interior(),))
72
73 widget = self.createcomponent('omega',(),None,Pmw.RadioSelect,(frame,),
74 labelpos='nw',label_text='Observations:',
75 buttontype='checkbutton',frame_bd=1,
76 frame_relief='ridge')
77 widget.pack(side='top',anchor='nw',fill='x',padx=20,pady=20)
78
79 table = {}
80 for entry in entity.observations:
81 table[str(entry['actions'])] = entry
82 widget = self.createcomponent('editor',(),None,TreeBuilder,(frame,),
83 orient='horizontal',default=True,
84 menus_leaves=self.entity.omega.keys(),
85 society=self['society'],expert=True,
86 new=self.newO,table=table)
87 widget.interior().grid_columnconfigure(1,weight=1)
88 widget.pack(side='top',anchor='nw',fill='both',padx=20,pady=20)
89
90
91 self.drawOmega()
92 if self.entity.observable():
93 button.select()
94 else:
95 button.deselect()
96 self.observable()
97 if not self['generic']:
98 button.configure(state='disabled')
99 self.initialiseoptions(ObservationFrame)
100
102 """Callback for toggling complete observability
103 """
104 if self.perfect.get():
105 self.component('details').grid_forget()
106 else:
107 self.component('details').grid(row=2,column=0,sticky='enws')
108
110 """Callback for a new observation
111 """
112 self.component('dialog').deactivate()
113 if button == 'OK':
114 omega = self.component('dialog_entryfield').getvalue().strip()
115 key = ObservationKey({'type': omega})
116 if not self.entity.omega.has_key(key):
117 self.entity.omega[key] = True
118 self.drawOmega()
119 self.component('dialog_entryfield').clear()
120
122 """Updates the display of the current set of possible observations
123 """
124 Omega = map(str,self.entity.omega.keys())
125 Omega.sort()
126 widget = self.component('omega')
127 widget.deleteall()
128 for omega in Omega:
129 if omega == str(None) or omega == str(True):
130 widget.add(omega,state='disabled')
131 else:
132 widget.add(omega)
133
135 """Validates the uniqueness of the current symbol
136 """
137 if self.entity.omega.has_key(ObservationKey({'type': omega})):
138 return Pmw.PARTIAL
139 elif omega == str(None) or omega == str(True):
140
141 return Pmw.PARTIAL
142 else:
143 return Pmw.OK
144
145 - def newO(self,key,option,tree):
146 """Callback for creating a new observation function entry
147 """
148 self.entity.observations.append({'actions': option,'tree': tree})
149
151 """Deletes selected observation symbols
152 """
153 selection = self.component('omega').getvalue()
154 if 'None' in selection:
155 tkMessageBox.showerror('Illegal removal','You cannot remove the null observation.')
156 elif 'True' in selection:
157 tkMessageBox.showerror('Illegal removal','You cannot remove the true observation.')
158 elif selection:
159 for omega in selection:
160 key = ObservationKey({'type': omega})
161 del self.entity.omega[key]
162 self.drawOmega()
163 else:
164 tkMessageBox.showerror('No selection','You must first select at least one observation symbol to delete.')
165