Package SimPy :: Module GUIDebug
[hide private]
[frames] | no frames]

Source Code for Module SimPy.GUIDebug

  1  from Tkinter import * 
  2  from SimPy.SimulationStep import now,Globals 
  3   
  4  # Creates and controls the GUI of the program 
5 -class GUIController(object):
6
7 - def __init__(self):
8 self.root = Tk() 9 self.root.withdraw() 10 11 self.saveNextEvent() 12 13 self.eventWin = EventWindow(self) 14 self.wlist = [] 15 self.plist = [] 16 self.rlist = []
17 18 # Adds a new Window to the GUI
19 - def addNewWindow(self,obj,name,hook):
20 self.wlist += [GenericWindow(obj,hook,self,name)]
21 22 # Adds a new Process to the GUI
23 - def addNewProcess(self,obj,name,hook):
24 self.plist += [ProcessWindow(obj,hook,self,name)]
25 26 # Adds a new Resource to the GUI
27 - def addNewResource(self,obj,name,hook):
28 self.rlist += [ResourceWindow(obj,hook,self,name)]
29 30 # Updates all the windows currently up
31 - def updateAllWindows(self):
32 33 for w in self.wlist: w.update() 34 for p in self.plist: p.update() 35 for r in self.rlist: r.update() 36 if self.eventWin.window: self.eventWin.update() 37 38 self.organizeWindows() 39 40 self.saveNextEvent()
41 42 # removes all instances of window in lists
43 - def removeWindow(self, w):
44 f = lambda win: win is not w 45 self.wlist = filter(f,self.wlist) 46 self.plist = filter(f,self.plist) 47 self.rlist = filter(f,self.rlist)
48 49 # save next event to be run
50 - def saveNextEvent(self):
51 #from SimPy.SimulationTrace import _e 52 53 tempList=[] 54 tempList[:]=Globals.sim._timestamps 55 tempList.sort() 56 57 for ev in tempList: 58 59 # return only event notices which are not cancelled 60 if ev[3]: continue 61 62 # save next event 63 self.nextEvent = ev 64 return 65 66 self.nextEvent = (None,None,None,None)
67
68 - def organizeWindows(self):
69 70 # event window 71 eventWindowHeight = 0 72 73 # only organize event window only if it exists 74 if self.eventWin.window: 75 eventWindowHeight = 40 + 20 * self.eventWin.table.size() 76 self.eventWin.setWindowSize(500, eventWindowHeight ,20,40) 77 78 # generic windows 79 count = -1 80 81 for win in self.wlist: 82 count += 1 83 84 (w,h,x,y) = win.getWindowSize() 85 win.setWindowSize(w, h, 20, 40 + eventWindowHeight + 40 ) 86 87 eventWindowHeight += h + 40 88 89 # process windows 90 xCount = -1 91 yCount = 0 92 93 for p in self.plist: 94 xCount += 1 95 96 yCoord = 40 + 150 * xCount 97 xCoord = 550 + 210 * yCount 98 99 p.setWindowSize(200,120, xCoord, yCoord ) 100 101 if yCoord >= 600: 102 xCount = -1 103 yCount += 1 104 105 # resource windows 106 count = -1 107 for r in self.rlist: 108 count += 1 109 110 windowHeight = 0 111 windowHeight += 20 # capacity title 112 windowHeight += 105 # empty table sizes 113 114 windowHeight += (r.activeT.size() + r.waitT.size()) * 17 # add size for each row 115 116 r.setWindowSize(200, windowHeight , 20 + 220 * count , 40 + eventWindowHeight + 40)
117 118 119 120 # Creates a basic window that shows a user made hook.
121 -class GenericWindow(object):
122
123 - def __init__(self, obj, hook, guiCtrl, title=None):
124 self.window = Toplevel() 125 self.window.protocol("WM_DELETE_WINDOW", self._destroyWindow) 126 self.obj = obj 127 self.hook = hook 128 self.guiCtrl = guiCtrl 129 if not title: 130 self.title = "%s%s" % (type(obj),id(obj)) 131 else: 132 self.title = title 133 self.initGUI()
134 135
136 - def setWindowSize(self,w,h,x,y):
137 newG = "%dx%d+%d+%d" % (w,h,x,y) 138 self.window.geometry(newG)
139
140 - def setWindowOrigin(self,x,y):
141 (w,h,xx,yy) = self.getWindowSize() 142 newG = "%dx%d+%d+%d" % (w,h,x,y) 143 self.window.geometry(newG)
144
145 - def getWindowSize(self):
146 g = self.window.geometry() 147 return [int(i) for i in g.replace('+','x').split('x')]
148
149 - def _destroyWindow(self):
150 self.window.destroy() 151 self.window = None 152 self.guiCtrl.removeWindow(self)
153 154 # Creates the window
155 - def initGUI(self):
156 self.window.title(self.title) 157 txt = self.hook() 158 if txt != "": txt += '\n' 159 self.hookTxt = Label(self.window,text=txt,justify=LEFT) 160 self.hookTxt.pack()
161 162 # Updates the window
163 - def update(self):
164 txt = self.hook() 165 if txt != "": txt += '\n' 166 self.hookTxt["text"] = txt
167 168 # Class that creates the event window for the simulation that 169 # displays the time and event.
170 -class EventWindow(GenericWindow):
171
172 - def __init__(self, guiCtrl):
173 self.window = Toplevel() 174 self.window.protocol("WM_DELETE_WINDOW", self._destroyWindow) 175 self.guiCtrl = guiCtrl 176 self.initGUI()
177 178 # Creates the initial window using a two column window with a 179 # status bar on the bottom
180 - def initGUI(self):
181 self.window.title("Event List") 182 # Creates the table 183 self.table = MultiListbox(self.window,(('', 1), ('Time',15), 184 ('Process',20),('Next Line',5))) 185 # Adds the status bar to display the current simulation time 186 self.status = StatusBar(self.window) 187 self.status.pack(side=TOP, fill=X) 188 189 self.update()
190 191 # Updates the window
192 - def update(self):
193 self.updateETable() 194 self.updateStatus()
195 196 # Updates the status bar
197 - def updateStatus(self):
198 self.status.set(" Current Time: %s",now())
199 200 # Updates the table
201 - def updateETable(self):
202 #from SimPy.SimulationStep import _e 203 self.table.delete(0,self.table.size()) 204 205 tempList=[] 206 tempList[:]=Globals.sim._timestamps 207 tempList.sort() 208 209 ev = self.guiCtrl.nextEvent 210 211 nextLine = 0 212 if( ev[2] ): 213 if( ev[2]._nextpoint ): 214 nextLine = ev[2]._nextpoint.gi_frame.f_lineno 215 216 if ev[0]: 217 self.table.insert(END,(' >>', 218 str(ev[0]), ev[2].name, nextLine )) 219 220 count = -1 221 for ev in tempList: 222 223 # return only event notices which are not cancelled 224 if ev[3]: continue 225 226 count += 1 227 228 currentEvent = '' 229 #if count == 0 and now() == ev[0]: 230 # currentEvent = ' >>' 231 232 nextLine = 0 233 if( ev[2] ): 234 if( ev[2]._nextpoint ): 235 nextLine = ev[2]._nextpoint.gi_frame.f_lineno 236 237 self.table.insert(END,(currentEvent, 238 str(ev[0]), ev[2].name, nextLine )) 239 240 self.table.pack(expand=YES,fill=BOTH)
241 242 # Creates a Process Window that shows the status, Next Event time, 243 # if the Process is currently interupted, and an optional user hook.
244 -class ProcessWindow(GenericWindow):
245
246 - def __init__(self, obj, hook, guiCtrl, name):
247 self.proc = obj 248 if name: 249 obj.name = name 250 GenericWindow.__init__(self, obj, hook, guiCtrl, "Process")
251 252 # Initializes the window
253 - def initGUI(self):
254 Label(self.window,text="%s" % (self.proc.name)).pack() 255 # Creates the table 256 self.table = MultiListbox(self.window,((None,10),(None,15))) 257 self.status = StatusBar(self.window) 258 self.status.pack(side=BOTTOM, fill=X) 259 260 GenericWindow.initGUI(self) 261 self.setWindowSize(0,0,-1000,-1000) 262 263 self.update()
264 265 # Updates the window
266 - def update(self):
267 268 # If the process has been terminated close the window 269 if self.proc.terminated(): 270 self._destroyWindow() 271 return 272 273 if self.isRunning(): 274 self.status.label["text"] = "Running!" 275 self.status.label["fg"] = "red"#"green" 276 else: 277 self.status.label["text"] = "" 278 self.status.label["fg"] = "white" 279 280 self.table.delete(0,self.table.size()) 281 282 if self.proc.active() == False: 283 status = "Passive" 284 else: 285 status = "Active" 286 287 if self.proc._nextTime: 288 nextEvent = self.proc._nextTime 289 else: 290 nextEvent = "" 291 292 if self.proc.interrupted() == True: 293 interrupted = "True" 294 else: 295 interrupted = "False" 296 297 self.table.insert(END,(" Status:", status)) 298 self.table.insert(END,(" Next Event:", nextEvent)) 299 self.table.insert(END,(" Interrupted:", interrupted )) 300 301 self.table.pack(expand=YES,fill=BOTH) 302 303 GenericWindow.update(self)
304
305 - def isRunning(self):
306 return self.guiCtrl.nextEvent[2] is self.proc
307 308 # Creates a Resource Window that displays the capacity, waitQ, 309 # activeQ and an optional user hook
310 -class ResourceWindow(GenericWindow):
311
312 - def __init__(self,obj,hook,guiCtrl,name):
313 self.resource = obj 314 if name: 315 obj.name = name 316 GenericWindow.__init__(self,obj,hook, guiCtrl,"Resource")
317 318 # Initializes the window with the two tables for the waitQ and activeQ
319 - def initGUI(self):
320 Label(self.window,text="%s\tCapacity: %d" % (self.resource.name,self.resource.capacity)).pack() 321 322 self.activeT = MultiListbox(self.window,(('#',5),('ActiveQ',20))) 323 self.waitT = MultiListbox(self.window,(('#',5),('WaitQ',20))) 324 self.updateQTables() 325 326 GenericWindow.initGUI(self) 327 self.setWindowSize(0,0,-1000,-1000)
328 329 # Updates the window
330 - def update(self):
331 GenericWindow.update(self) 332 self.updateQTables()
333 334 # Updates the waitQ and activeQ tables
335 - def updateQTables(self):
336 self.activeT.delete(0,END) 337 self.waitT.delete(0,END) 338 # Update the activeQ 339 for i in range(len(self.resource.activeQ)): 340 col1 = '%d' % (i+1) 341 col2 = self.resource.activeQ[i].name 342 self.activeT.insert(END,(" " + col1,col2)) 343 # Update the waitQ 344 for i in range(len(self.resource.waitQ)): 345 col1 = '%d' % (i+1) 346 col2 = self.resource.waitQ[i].name 347 self.waitT.insert(END,(" " + col1,col2)) 348 349 self.activeT.pack(expand=YES,fill=BOTH) 350 self.waitT.pack(expand=YES,fill=BOTH) 351 self.window.update()
352 353 # A class that creates a multilistbox with a scrollbar
354 -class MultiListbox(Frame):
355 - def __init__(self, master, lists):
356 Frame.__init__(self, master) 357 self.lists = [] 358 for l,w in lists: 359 frame = Frame(self); frame.pack(side=LEFT, expand=YES, fill=BOTH) 360 361 if l is None: 362 None 363 elif l is '': 364 Label(frame, text='', borderwidth=1, relief=FLAT).pack(fill=X) 365 else: 366 Label(frame, text=l, borderwidth=1, relief=SOLID).pack(fill=X) 367 368 lb = Listbox(frame, width=w, height=0, borderwidth=0, selectborderwidth=0, 369 relief=FLAT, exportselection=FALSE) 370 lb.pack(expand=YES, fill=BOTH) 371 self.lists.append(lb) 372 frame = Frame(self); frame.pack(side=LEFT, fill=Y) 373 Label(frame, borderwidth=1, relief=RAISED).pack(fill=X) 374 sb = Scrollbar(frame, orient=VERTICAL, command=self._scroll) 375 sb.pack(expand=YES, fill=Y) 376 self.lists[0]['yscrollcommand']=sb.set
377
378 - def _select(self, y):
379 row = self.lists[0].nearest(y) 380 self.selection_clear(0, END) 381 self.selection_set(row) 382 return 'break'
383
384 - def _button2(self, x, y):
385 for l in self.lists: l.scan_mark(x, y) 386 return 'break'
387
388 - def _b2motion(self, x, y):
389 for l in self.lists: l.scan_dragto(x, y) 390 return 'break'
391
392 - def _scroll(self, *args):
393 for l in self.lists: 394 apply(l.yview, args)
395
396 - def curselection(self):
397 return self.lists[0].curselection()
398
399 - def delete(self, first, last=None):
400 for l in self.lists: 401 l.delete(first, last)
402
403 - def get(self, first, last=None):
404 result = [] 405 for l in self.lists: 406 result.append(l.get(first,last)) 407 if last: return apply(map, [None] + result) 408 return result
409
410 - def index(self, index):
411 self.lists[0].index(index)
412
413 - def insert(self, index, *elements):
414 for e in elements: 415 i = 0 416 for l in self.lists: 417 l.insert(index, e[i]) 418 i = i + 1
419
420 - def size(self):
421 return self.lists[0].size()
422
423 - def see(self, index):
424 for l in self.lists: 425 l.see(index)
426
427 - def selection_anchor(self, index):
428 for l in self.lists: 429 l.selection_anchor(index)
430
431 - def selection_clear(self, first, last=None):
432 for l in self.lists: 433 l.selection_clear(first, last)
434
435 - def selection_includes(self, index):
436 return self.lists[0].selection_includes(index)
437
438 - def selection_set(self, first, last=None):
439 for l in self.lists: 440 l.selection_set(first, last)
441 442 # Creates a statusbar
443 -class StatusBar(Frame):
444
445 - def __init__(self, master):
446 Frame.__init__(self, master) 447 self.label = Label(self, bd=1, relief=SUNKEN, anchor=W) 448 self.label.pack(fill=X)
449
450 - def set(self, format, *args):
451 self.label.config(text=format % args) 452 self.label.update_idletasks()
453
454 - def clear(self):
455 self.label.config(text="") 456 self.label.update_idletasks()
457