PseudoCodeRenderer.java 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package view;
  2. import java.awt.Color;
  3. import java.awt.Component;
  4. import java.awt.Dimension;
  5. import java.awt.Font;
  6. import java.awt.Graphics2D;
  7. import java.awt.image.BufferedImage;
  8. import javax.swing.ImageIcon;
  9. import javax.swing.JTree;
  10. import javax.swing.tree.DefaultTreeCellRenderer;
  11. import javax.swing.tree.TreeNode;
  12. import animation.Memory;
  13. import animation.Memory.MemoryType;
  14. import animation.PseudoCodeNode;
  15. import graph.LayeredGraphEdge;
  16. import graph.LayeredGraphNode;
  17. import lib.TextLayoutHelper;
  18. /**
  19. * A tree-like display of pseudocode.
  20. * Extends {@link DefaultTreeCellRenderer}
  21. * @author kolja
  22. *
  23. */
  24. public class PseudoCodeRenderer extends DefaultTreeCellRenderer {
  25. private static final long serialVersionUID = 1L;
  26. private static ImageIcon currentLine = new ImageIcon( PseudoCodeNode.class.getResource( "/img/current_line.png" ) );
  27. private Color specialColor = null;
  28. private Memory mem;
  29. private String toolTip = "";
  30. public void setMemory( Memory m )
  31. {
  32. mem = m;
  33. }
  34. @Override
  35. public Color getBackgroundNonSelectionColor() {
  36. if(specialColor != null) {
  37. return specialColor;
  38. } else {
  39. return RenderHelper.BACKGROUND_COLOR;
  40. }
  41. }
  42. @Override
  43. public Color getForeground() {
  44. return new Color(0xa9b7c6);
  45. }
  46. private int countChildren( TreeNode treeNode )
  47. {
  48. if( treeNode.isLeaf() )
  49. return 0;
  50. else
  51. {
  52. int sum = 0;
  53. for( int i = 0; i < treeNode.getChildCount(); i++ )
  54. {
  55. sum += countChildren( treeNode.getChildAt( i ) ) + 1;
  56. }
  57. return sum;
  58. }
  59. }
  60. private int getLineNumber( TreeNode treeNode )
  61. {
  62. TreeNode parent = treeNode.getParent();
  63. if( parent == null )
  64. return 1;
  65. int sum = getLineNumber( parent ) + 1;
  66. for( int i = 0; i < parent.getChildCount(); i++ )
  67. {
  68. if( i == parent.getIndex( treeNode ) )
  69. return sum;
  70. sum += countChildren( parent.getChildAt( i ) ) + 1;
  71. }
  72. return 0;
  73. }
  74. @Override
  75. public Font getFont() {
  76. return new Font("Monospaced", Font.PLAIN, 12);
  77. }
  78. @Override
  79. public String getToolTipText()
  80. {
  81. return toolTip;
  82. }
  83. @Override
  84. public Component getTreeCellRendererComponent(JTree tree, Object value, boolean arg2, boolean arg3, boolean arg4, int arg5, boolean arg6) {
  85. PseudoCodeNode node = (PseudoCodeNode) value;
  86. int width = 10;
  87. if( !node.hasSelectedSubnode() && node.isSelected() )
  88. width += 25;
  89. if( node.hasBreakPoint() )
  90. width += 15;
  91. String line = "" + getLineNumber( (TreeNode) value );
  92. width += tree.getFontMetrics( this.getFont() ).stringWidth( line );
  93. this.setPreferredSize( new Dimension( width + tree.getFontMetrics( this.getFont() ).stringWidth( (String)node.getUserObject() ) + 5, 30 ) );
  94. this.setSize( new Dimension( width + tree.getFontMetrics( this.getFont() ).stringWidth( (String)node.getUserObject() ) + 5, 30 ) );
  95. this.doLayout();
  96. BufferedImage rowNumerImg = new BufferedImage( width, 30, BufferedImage.TYPE_INT_ARGB );
  97. Graphics2D g = (Graphics2D) rowNumerImg.getGraphics();
  98. int x = 5;
  99. if( !node.hasSelectedSubnode() && node.isSelected() )
  100. {
  101. g.drawImage( currentLine.getImage(), x, 5, 20, 20, null );
  102. x += 25;
  103. }
  104. g.setColor( RenderHelper.CURRENT_LINE_COLOR );
  105. g.drawString( line, x, 20 );
  106. x += g.getFontMetrics().stringWidth( line ) + 5;
  107. if( node.hasBreakPoint() )
  108. {
  109. g.setColor( new Color (0xe7887a) );
  110. g.fillOval(x, 10, 10, 10 );
  111. }
  112. g.dispose();
  113. this.setClosedIcon( new ImageIcon( rowNumerImg ) );
  114. this.setOpenIcon( new ImageIcon( rowNumerImg ) );
  115. this.setLeafIcon( new ImageIcon( rowNumerImg ) );
  116. super.getTreeCellRendererComponent(tree, value, arg2, arg3, arg4, arg5, arg6);
  117. specialColor = null;
  118. if(node.isSelected()) {
  119. specialColor = new Color(0x2d6099);
  120. } else if (node.hasBreakPoint()) {
  121. specialColor = RenderHelper.BREAKPOINT_COLOR;
  122. }
  123. setText((String)node.getUserObject());
  124. toolTip = "<html>";
  125. for( String var : TextLayoutHelper.getVariables( (String)node.getUserObject() ) )
  126. {
  127. if( mem != null && mem.isSomewhereDefined( var, MemoryType.LOCAL ) )
  128. {
  129. Object val = mem.read( var, MemoryType.LOCAL );
  130. toolTip += var + "=" + val.toString() + "<br>";
  131. }
  132. }
  133. if( toolTip.equals( "<html>" ) )
  134. toolTip += "no variables found in the stack";
  135. else
  136. toolTip = toolTip.substring( 0, toolTip.length() - 4 );
  137. toolTip += "</html>";
  138. return this;
  139. }
  140. }