ascii_view.py
Go to the documentation of this file.
00001 from diarc.snapkey import gen_snapkey
00002 from diarc.snapkey import parse_snapkey
00003 from diarc.util import TypedDict
00004 from diarc.view import View
00005 from CharGrid import CharGrid
00006 
00007 block_spacing = 5
00008 
00009 class BlockItem(object):
00010     def __init__(self, parent, index):
00011         self.parent = parent
00012         self._index = index
00013         self.left_block = None
00014         self.right_block = None
00015 
00016         # These are populated
00017         self.emitters = list()
00018         self.collectors = list()
00019 
00020         # Layout properties
00021         self._leftCol = None
00022         self._centerCol = None
00023         self._rightCol = None
00024         self._topRow = None
00025         self._centerRow = None
00026         self._botRow = None
00027 
00028 
00029     def release(self):
00030         self.left_block = None
00031         self.right_block = None
00032         for item in self.emitters:
00033             item.release()
00034         for item in self.collectors:
00035             item.release()
00036 
00037     @property
00038     def leftCol(self):
00039         if self._leftCol is None: self.layout()
00040         return self._leftCol
00041         
00042     @property
00043     def centerCol(self):
00044         if self._centerCol is None: self.layout()
00045         return self._centerCol
00046 
00047     @property
00048     def rightCol(self):
00049         if self._rightCol is None: self.layout()
00050         return self._rightCol
00051 
00052     @property
00053     def topRow(self):
00054         if self._topRow is None: self.layout()
00055         return self._topRow
00056 
00057     @property
00058     def centerRow(self):
00059         if self._centerRow is None: self.layout()
00060         return self._centerRow
00061 
00062     @property
00063     def botRow(self):
00064         if self._botRow is None: self.layout()
00065         return self._botRow
00066 
00067     def layout(self):
00068         if self.left_block is None:
00069             self.left_block = self.parent.corner_stone
00070             self.parent.corner_stone.right_block = self
00071 
00072         if None in [self.left_block.topRow,self.left_block.centerRow,self.left_block.topRow]:
00073             self.left_block.layout()
00074         self._topRow = self.left_block.topRow
00075         self._centerRow = self.left_block.centerRow
00076         self._botRow = self.left_block.botRow
00077 
00078         if None in [self.left_block.leftCol,self.left_block.centerCol,self.left_block.rightCol]:
00079             self.left_block.layout()
00080         self._leftCol = self.left_block.rightCol + block_spacing + 1
00081         self._centerCol =  self.leftCol + 2 + 2*len(self.collectors)
00082         self._rightCol = self.centerCol + 2 + 2*len(self.emitters) 
00083 
00084     def draw(self,grid):
00085         """ draw this Block into the grid """
00086         # Draw the left side of the box
00087         grid[(self.topRow,self.leftCol)] = '+-'
00088         grid[(self.centerRow,self.leftCol)] = '| '
00089         grid[(self.botRow,self.leftCol)] = '+-'
00090 
00091         # Draw Collector spacers
00092         grid[(self.topRow,self.leftCol+1)] = "-"*(self.centerCol-self.leftCol-1)
00093         grid[(self.botRow,self.leftCol+1)] = "-"*(self.centerCol-self.leftCol-1)
00094 
00095         # Draw the middle line
00096         grid[(self.topRow,self.centerCol)] = '+-'
00097         grid[(self.centerRow,self.centerCol)] = '| '
00098         grid[(self.botRow,self.centerCol)] = '+-'
00099 
00100         # Draw the emitter spacers
00101         grid[(self.topRow,self.centerCol+1)] = "-"*(self.rightCol-self.centerCol-1)
00102         grid[(self.botRow,self.centerCol+1)] = "-"*(self.rightCol-self.centerCol-1)
00103  
00104         # Draw the right line
00105         grid[(self.topRow,self.rightCol)] = '+'
00106         grid[(self.centerRow,self.rightCol)] = '|'
00107         grid[(self.botRow,self.rightCol)] = '+'
00108 
00109 
00110 class BandItem(object):
00111     def __init__(self, parent, altitude, rank):
00112         self.parent = parent
00113         self._altitude = altitude
00114         self._rank = rank
00115         self.top_band = None
00116         self.bot_band = None
00117         self.left_most_snap = None
00118         self.right_most_snap = None
00119 
00120         # Visual parameters
00121         self._row = None
00122         self._startCol = None
00123         self._endCol = None
00124         self._isUsed = False
00125 
00126     def release(self):
00127         self.top_band = None
00128         self.bot_band = None
00129         self.left_most_snap = None
00130         self.right_most_snap = None
00131 
00132     @property
00133     def row(self):
00134         if self._row is None: self.layout()
00135         return self._row
00136 
00137     @property
00138     def startCol(self):
00139         if self._startCol is None: self.layout()
00140         return self._startCol
00141 
00142     @property
00143     def endCol(self):
00144         if self._endCol is None: self.layout()
00145         return self._endCol
00146 
00147 
00148     def layout(self):
00149         if self.bot_band is None:
00150             if self._altitude > 0:
00151                 self.bot_band = self.parent.corner_stone
00152                 self.parent.corner_stone.top_band = self
00153                 self.parent.corner_stone.layout()
00154                 return
00155             
00156         if self.top_band is None:
00157             if self._altitude > 0:
00158                 self.top_band = self.parent.top_line
00159                 self.parent.top_line.bot_band = self
00160             else:
00161                 self.top_band = self.parent.corner_stone
00162                 self.parent.corner_stone.bot_band = self
00163         else:
00164             if self.top_band.row is None:
00165                 self.top_band.layout()
00166             self._row = self.top_band.row + 1
00167             # Get the snap positions
00168             if self.left_most_snap.col is None:
00169                 self.left_most_snap.layout()
00170             if self.right_most_snap.col is None:
00171                 self.right_most_snap.layout()
00172             self._startCol = self.left_most_snap.col+2
00173             self._endCol = self.right_most_snap.col-2
00174            
00175 
00176     def draw(self,grid):
00177         grid[(self.row,0)] = str(self._altitude)
00178         grid[(self.row,self.startCol)] = '-'*((self.endCol-self.startCol)+1)
00179 
00180 
00181 class SnapItem(object):
00182     def __init__(self, parent, snapkey):
00183         self.parent = parent
00184         self._snapkey = snapkey
00185         self.block_index, self.container_name, self.snap_order = parse_snapkey(snapkey)
00186 
00187         self.block_item = None
00188         self.left_snap = None
00189         self.right_snap = None
00190         self.posBandItem = None
00191         self.negBandItem = None
00192 
00193         # Layout properties
00194         self.col = None
00195         self.centerRow = None
00196         self.posBandRow = None
00197         self.negBandRow = None
00198 
00199     def release(self):
00200         if self.isSource():
00201             self.block_item.emitters.remove(self)
00202         else:
00203             self.block_item.collectors.remove(self)
00204         self.block_item = None
00205         self.left_snap = None
00206         self.right_snap = None
00207         self.posBandItem = None
00208         self.negBandItem = None
00209 
00210     def isSource(self):
00211         return True if self.container_name == "emitter" else False
00212 
00213     def isSink(self):
00214         return True if self.container_name == "collector" else False
00215 
00216     def layout(self):
00217         # Determine your col location
00218         # First, figure out what to offset against
00219         if self.isSource():
00220             self.col = self.block_item.centerCol 
00221         elif self.isSink():
00222             self.col = self.block_item.leftCol 
00223         else:
00224             raise Exception("Snap isnt Source or Sink")
00225 
00226         # Then add the order offset
00227         # TODO: This assumes that there are no skipped order values, which 
00228         # would leave holes when drawing. The correct way would be to get relative 
00229         # ordering of the order values and take into account missing values.
00230         self.col += 2 + 2*self.snap_order
00231 
00232         # Get the center row
00233         self.centerRow = self.block_item.centerRow
00234 
00235         # Get the band rows (may require doing layout)
00236         #TODO: row = posBand.visual.row etc should be calculated here instead of in draw
00237 
00238 
00239     def draw(self,grid):
00240         centerRow = self.centerRow
00241         col = self.col
00242         if self.isSink():
00243             if self.posBandItem:
00244                 # Draw a Positive Sink Snap
00245                 row = self.posBandItem.row
00246                 grid[(centerRow-1,col)] = 'V-'
00247                 grid[(row,col-1)] = '.'
00248                 for i in range(centerRow-2-row):
00249                     grid[(centerRow-2-i,col)] = '|'
00250             if self.negBandItem:
00251                 # Draw a Negative Sink Snap
00252                 row = self.negBandItem.row
00253                 grid[(centerRow+1,col)] = 'A-'
00254                 grid[(row,col+1)] = "'"
00255                 for i in range(row-(centerRow+2)):
00256                     grid[(centerRow+2+i,col)] = '|'
00257         elif self.isSource():
00258             if self.posBandItem:
00259                 # Draw a Positive Source Snap
00260                 row = self.posBandItem.row
00261                 grid[(centerRow-1,col)] = 'A-'
00262                 grid[(row,col+1)] = '.'
00263                 for i in range(centerRow-2-row):
00264                     grid[(centerRow-2-i,col)] = '|'
00265             if self.negBandItem:
00266                 # Draw a Negative Source Snap
00267                 row = self.negBandItem.row
00268                 grid[(centerRow+1,col)] = 'V-'
00269                 grid[(row,col-1)] = "'"
00270                 for i in range(row-(centerRow+2)):
00271                     grid[(centerRow+2+i,col)] = '|'
00272         else:
00273             raise Exception("Snap is not source or sink")
00274 
00275 
00276 class TopLine(object):
00277     def __init__(self):
00278         self.row = 0
00279 
00280         #Adjoining bands
00281         self.below = None
00282 
00283     def layout(self):
00284         self.row = 0
00285 
00286     def draw(self):
00287         pass
00288 
00289 
00290 class CornerStone(object):
00291     """ What everything tries to be relative to """
00292     def __init__(self):
00293         #Adjoining blocks
00294         self.rightBlock = None
00295         # Adjoining bands
00296         self.top_band = None
00297         self.bot_band = None
00298         # Positioning Parameters
00299         self.leftCol = None
00300         self.centerCol = None
00301         self.rightCol = None
00302         self.topRow = None
00303         self.centerRow = None
00304         self.botRow = None
00305 
00306     @property
00307     def row(self):
00308         """ return a calculated row since the spacing here is non-standard. Basically
00309         we return the empty row below the band of Blocks. This is used for band layout """
00310         if not self.botRow:
00311             self.layout()
00312         return self.botRow+1
00313         
00314 
00315     def layout(self):
00316         # TODO: topRow should be replaced with finding height of adjacent bands bottom
00317         if self.top_band is None:
00318             self.topRow = 0
00319             self.centerRow = 1
00320             self.botRow = 2
00321         else:
00322             if self.top_band.row is None:
00323                 self.top_band.layout()
00324             self.topRow = self.top_band.row + 2
00325             self.centerRow = self.topRow+1
00326             self.botRow = self.centerRow+1
00327         
00328         self.leftCol = -block_spacing-1
00329         self.centerCol = -block_spacing-1
00330         self.rightCol = -block_spacing-1
00331 
00332     def draw(self,grid):
00333         # This is not a real thing, don't draw anything
00334         pass
00335 
00336 
00337 
00338 
00339 class AsciiView(View):
00340     def __init__(self):
00341         View.__init__(self)
00342         
00343         # Special layout objects
00344         self.top_line = TopLine()
00345         self.corner_stone = CornerStone()
00346 
00347         # Visual Objects we are tracking
00348         self._block_items = TypedDict(int, BlockItem)
00349         self._band_items = TypedDict(int, BandItem)
00350         self._snap_items = TypedDict(str, SnapItem)
00351 
00352     def add_block_item(self, index):
00353         """ Create new a drawable object to correspond to a Block with this index. """
00354         if not index in self._block_items:
00355             print "Adding block item",index
00356             item = BlockItem(self, index)
00357             self._block_items[index] = item
00358             return item
00359 
00360     def has_block_item(self, index):
00361         return True if index in self._block_items else False
00362 
00363     def set_block_item_settings(self, index, left_index, right_index):
00364         item = self._block_items[index]
00365         item.left_block = self._block_items[left_index] if left_index is not None else None
00366         item.right_block = self._block_items[right_index] if right_index is not None else None
00367 
00368     def set_block_item_attributes(self, index, attributes):
00369         """ Not yet implemented """
00370         pass
00371 
00372     def remove_block_item(self, index):
00373         print "Removing BlockItem %d"%index
00374         self._block_items[index].release()
00375         self._block_items.pop(index)
00376 
00377     def add_band_item(self, altitude, rank):
00378         """ Create a new drawable object to correspond to a Band. """
00379         print "Adding BandItem with altitude %d"%altitude
00380         if altitude in self._band_items:
00381             raise DuplicateItemExistsError("BandItem with altitude %d already exists"%(altitude))
00382         item = BandItem(self, altitude, rank)
00383         self._band_items[altitude] = item
00384         return item
00385 
00386     def has_band_item(self, altitude):
00387         return True if altitude in self._band_items else False
00388 
00389     def remove_band_item(self, altitude):
00390         """ Remove the drawable object to correspond to a band """ 
00391         print "Removing BandItem altitude %d"%altitude
00392         self._band_items[altitude].release()
00393         self._band_items.pop(altitude)
00394 
00395     def get_band_item(self, altitude):
00396         return self._band_items[altitude]
00397     
00398     def set_band_item_settings(self, altitude, rank,
00399                                 top_band_alt, bot_band_alt,
00400                                 leftmost_snapkey, rightmost_snapkey):
00401         item = self._band_items[altitude]
00402         item.top_band = self._band_items[top_band_alt] if top_band_alt is not None else None
00403         item.bot_band = self._band_items[bot_band_alt] if bot_band_alt is not None else None
00404         item.left_most_snap = self._snap_items[leftmost_snapkey]
00405         item.right_most_snap = self._snap_items[rightmost_snapkey]
00406 
00407     def set_band_item_attributes(self, index, attributes):
00408         """ not yet implemented for this style view """
00409         pass
00410 
00411 
00412     def add_snap_item(self, snapkey):
00413         print "Adding SnapItem %s"%snapkey
00414         if snapkey in self._snap_items:
00415             raise DuplicateItemExistsError("SnapItem with snapkey %s already exists"%(snapkey))
00416         item = SnapItem(self, snapkey)
00417         item.block_item = self._block_items[item.block_index]
00418         if item.isSource():
00419             self._block_items[item.block_index].emitters.append(item)
00420         else:
00421             self._block_items[item.block_index].collectors.append(item)
00422         self._snap_items[snapkey] = item
00423         return item
00424 
00425     def remove_snap_item(self, snapkey):
00426         print "Removing SnapItem %s"%snapkey
00427         self._snap_items[snapkey].release()
00428         self._snap_items.pop(snapkey)
00429 
00430     def has_snap_item(self, snapkey):
00431         return True if snapkey in self._snap_items else False
00432 
00433 
00434     def set_snap_item_settings(self, snapkey, left_order, right_order, pos_band_alt, neg_band_alt):
00435         item = self._snap_items[snapkey]
00436         if left_order is not None:
00437             left_snapkey = gen_snapkey(item.block_index,item.container_name,left_order)
00438             item.left_snap = self._snap_items[left_snapkey]
00439         else:
00440             item.left_snap = None
00441         if right_order is not None:
00442             right_snapkey = gen_snapkey(item.block_index,item.container_name,right_order)
00443             item.right_snap = self._snap_items[right_snapkey]
00444         else:
00445             item.right_snap = None
00446         item.posBandItem = self._band_items[pos_band_alt] if pos_band_alt is not None else None
00447         item.negBandItem = self._band_items[neg_band_alt] if neg_band_alt is not None else None
00448 
00449     def set_snap_item_attributes(self, snapkey, attributes):
00450         """ not yet implemented for this style view """
00451         pass
00452 
00453     def update_view(self):
00454         
00455         # Initialize Visual Elements
00456         cornerStone = CornerStone()
00457        
00458         for item in self._band_items.values():
00459             item.layout()
00460 
00461         for item in self._block_items.values():
00462             item.layout()
00463 
00464         for item in self._snap_items.values():
00465             item.layout()
00466 
00467         # Draw
00468         grid = CharGrid()
00469         
00470         for item in self._band_items.values():
00471             item.draw(grid)
00472 
00473         for item in self._block_items.values():
00474             item.draw(grid)
00475 
00476         for item in self._snap_items.values():
00477             item.draw(grid)
00478           
00479         print grid
00480 
00481 
00482 
00483 
00484 class DuplicateItemExistsError(Exception):
00485     """ An Item with the specified parameters already exists """
00486     pass


rqt_graphprofiler
Author(s): Dan Brooks
autogenerated on Thu Jun 6 2019 20:29:31