|
| 1 | +Class { |
| 2 | + #name : 'FASTCFGVisualizationBuilder', |
| 3 | + #superclass : 'Object', |
| 4 | + #instVars : [ |
| 5 | + 'canvas' |
| 6 | + ], |
| 7 | + #category : 'FAST-Python-Tools-CFG/DataFlow', |
| 8 | + #package : 'FAST-Python-Tools', |
| 9 | + #tag : 'CFG/DataFlow' |
| 10 | +} |
| 11 | + |
| 12 | +{ #category : 'instance creation' } |
| 13 | +FASTCFGVisualizationBuilder class >> on: aStartBlock [ |
| 14 | + |
| 15 | + ^ self new openOn: aStartBlock |
| 16 | +] |
| 17 | + |
| 18 | +{ #category : 'instance creation' } |
| 19 | +FASTCFGVisualizationBuilder >> attachLineText: lineShape [ |
| 20 | + |
| 21 | + lineShape model key nextBlockForValues do: [ :valueNextBlock | |
| 22 | + | label | |
| 23 | + valueNextBlock value = lineShape model value ifTrue: [ |
| 24 | + label := RSLabel new text: valueNextBlock key asString. |
| 25 | + RSLocation new |
| 26 | + center; |
| 27 | + stick: label on: lineShape. |
| 28 | + canvas add: label ] ] |
| 29 | +] |
| 30 | + |
| 31 | +{ #category : 'hooks' } |
| 32 | +FASTCFGVisualizationBuilder >> basicBlockShape: aBasicBlock [ |
| 33 | + |
| 34 | + | shape | |
| 35 | + shape := aBasicBlock isStart |
| 36 | + ifTrue: [ |
| 37 | + aBasicBlock isFinal |
| 38 | + ifTrue: [ self startAndFinalBlockShape ] |
| 39 | + ifFalse: [ self startBlockShape ] ] |
| 40 | + ifFalse: [ |
| 41 | + aBasicBlock isFinal |
| 42 | + ifTrue: [ self finalBlockShape ] |
| 43 | + ifFalse: [ self normalBlockShape ] ]. |
| 44 | + aBasicBlock isConditional ifTrue: [ shape color: self conditionalBlockColor ]. |
| 45 | + ^ shape |
| 46 | +] |
| 47 | + |
| 48 | +{ #category : 'instance creation' } |
| 49 | +FASTCFGVisualizationBuilder >> buildLegend [ |
| 50 | + |
| 51 | + | legend | |
| 52 | + legend := RSLegend new. |
| 53 | + legend container: canvas. |
| 54 | + legend onDemand. |
| 55 | + legend title: 'Legend'. |
| 56 | + legend text: 'Start block' withShape: self startBlockShape. |
| 57 | + legend text: 'Final block' withShape: self finalBlockShape. |
| 58 | + legend text: 'start & final block' withShape: self startAndFinalBlockShape. |
| 59 | + legend text: 'Normal block' withShape: self normalBlockShape. |
| 60 | + legend text: 'Conditional block' withShape: (self normalBlockShape color: self conditionalBlockColor). |
| 61 | + legend build |
| 62 | +] |
| 63 | + |
| 64 | +{ #category : 'instance creation' } |
| 65 | +FASTCFGVisualizationBuilder >> buildLines: shapes [ |
| 66 | + |
| 67 | + | marker bldr | |
| 68 | + marker := RSArrowedLine new defaultHead. |
| 69 | + |
| 70 | + bldr := RSLineBuilder arrowedLine. |
| 71 | + bldr |
| 72 | + verticalBezier ; "Bezier lines" |
| 73 | + markerEnd: marker ; "Bezier lines" |
| 74 | + withBorderAttachPoint; |
| 75 | + shapes: shapes; |
| 76 | + canvas: canvas; |
| 77 | + connectToAll: [ :block | block nextBlocks ]. |
| 78 | + |
| 79 | + bldr shape markerMid: (RSLabel new text: 'true'). |
| 80 | + |
| 81 | + canvas lines do: [ :lineModel | |
| 82 | + lineModel model key isConditional |
| 83 | + ifTrue: [ self attachLineText: lineModel ] ] |
| 84 | +] |
| 85 | + |
| 86 | +{ #category : 'hooks' } |
| 87 | +FASTCFGVisualizationBuilder >> conditionalBlockColor [ |
| 88 | + |
| 89 | + ^ Color blue |
| 90 | +] |
| 91 | + |
| 92 | +{ #category : 'hooks' } |
| 93 | +FASTCFGVisualizationBuilder >> finalBlockShape [ |
| 94 | + |
| 95 | + ^ RSEllipse new |
| 96 | + radius: 10; |
| 97 | + color: Color transparent; |
| 98 | + border: (RSBorder new |
| 99 | + width: 4; |
| 100 | + color: Color black; |
| 101 | + yourself); |
| 102 | + yourself |
| 103 | +] |
| 104 | + |
| 105 | +{ #category : 'hooks' } |
| 106 | +FASTCFGVisualizationBuilder >> normalBlockShape [ |
| 107 | + |
| 108 | + ^ RSBox new |
| 109 | + size: 20; |
| 110 | + yourself |
| 111 | +] |
| 112 | + |
| 113 | +{ #category : 'instance creation' } |
| 114 | +FASTCFGVisualizationBuilder >> openOn: aCFGNode [ |
| 115 | + |
| 116 | + | shapes | |
| 117 | + canvas := RSCanvas new. |
| 118 | + shapes := aCFGNode withAllFollowingBlocks collect: [ :bb | self shapeFor: bb ]. |
| 119 | + |
| 120 | + self buildLines: shapes. |
| 121 | + |
| 122 | + canvas addAll: shapes. |
| 123 | + [ RSTreeLayout on: shapes ] valueWithin: 5 seconds onTimeout: [ self inform: 'Tree layout computation takes too long. Aborted' ]. |
| 124 | + |
| 125 | + self buildLegend. |
| 126 | + |
| 127 | + canvas @ RSCanvasController new noLegend. |
| 128 | + |
| 129 | + ^ canvas |
| 130 | +] |
| 131 | + |
| 132 | +{ #category : 'hooks' } |
| 133 | +FASTCFGVisualizationBuilder >> shapeFor: aBasicBlock [ |
| 134 | + |
| 135 | + | shape | |
| 136 | + shape := self basicBlockShape: aBasicBlock. |
| 137 | + |
| 138 | + shape model: aBasicBlock. |
| 139 | + shape @ (RSPopup text: [ :block | block sourceCode ]). |
| 140 | + shape @ RSDraggable. |
| 141 | + |
| 142 | + ^ shape |
| 143 | +] |
| 144 | + |
| 145 | +{ #category : 'hooks' } |
| 146 | +FASTCFGVisualizationBuilder >> startAndFinalBlockShape [ |
| 147 | + |
| 148 | + ^ RSComposite new |
| 149 | + add: self finalBlockShape; |
| 150 | + add: (RSEllipse new |
| 151 | + radius: 5; |
| 152 | + color: Color black; |
| 153 | + yourself); |
| 154 | + adjustToChildren; |
| 155 | + yourself |
| 156 | +] |
| 157 | + |
| 158 | +{ #category : 'hooks' } |
| 159 | +FASTCFGVisualizationBuilder >> startBlockShape [ |
| 160 | + |
| 161 | + ^ RSEllipse new |
| 162 | + radius: 10; |
| 163 | + color: Color black; |
| 164 | + yourself |
| 165 | +] |
0 commit comments