PseudoCodeLines.java 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. package view;
  2. import java.awt.Color;
  3. import java.awt.Component;
  4. import java.awt.Dimension;
  5. import java.awt.Graphics;
  6. import java.awt.Graphics2D;
  7. import java.awt.Rectangle;
  8. import java.awt.RenderingHints;
  9. import java.awt.event.MouseEvent;
  10. import java.awt.event.MouseListener;
  11. import javax.swing.ImageIcon;
  12. import javax.swing.JComponent;
  13. import javax.swing.JScrollPane;
  14. import javax.swing.JTree;
  15. import javax.swing.JViewport;
  16. import javax.swing.tree.TreeNode;
  17. import javax.swing.tree.TreePath;
  18. import animation.PseudoCodeNode;
  19. /**
  20. * JComponent used to draw line numbers. This JComponent should be added as a row header view in a JScrollPane. Based upon the
  21. * LineNumberModel provided, this component will draw the line numbers as needed.
  22. * @author Greg Cope
  23. *
  24. */
  25. public class PseudoCodeLines extends JComponent implements MouseListener{
  26. static final long serialVersionUID = 432143214L;
  27. //pixel padding on left and right
  28. private static final int HORIZONTAL_PADDING = 1;
  29. //pixel padding on left and right
  30. private static final int VERTICAL_PADDING = 3;
  31. private static ImageIcon currentLine = new ImageIcon( PseudoCodeNode.class.getResource( "/img/current_line.png" ) );
  32. private JTree tree;
  33. /**
  34. * Constructs a new Component with no model
  35. */
  36. public PseudoCodeLines( JTree t ){
  37. super();
  38. tree = t;
  39. this.addMouseListener( this );
  40. }
  41. /**
  42. * Checks and adjusts the width of this component based upon the line numbers
  43. */
  44. public void adjustWidth(){
  45. int max = getLineNumber( (TreeNode)tree.getPathForRow( tree.getRowCount() - 1 ).getLastPathComponent() );
  46. if ( getGraphics() == null ){
  47. return;
  48. }
  49. int width = getGraphics().getFontMetrics().stringWidth(String.valueOf(max)) + 2 * HORIZONTAL_PADDING + 30;
  50. JComponent c = (JComponent)getParent();
  51. if (c == null){//not within a container
  52. return;
  53. }
  54. Dimension dimension = c.getPreferredSize();
  55. if ( c instanceof JViewport ){//do some climbing up the component tree to get the main JScrollPane view
  56. JViewport view = (JViewport)c;
  57. Component parent = view.getParent();
  58. if ( parent != null && parent instanceof JScrollPane){
  59. JScrollPane scroller = (JScrollPane)view.getParent();
  60. dimension = scroller.getViewport().getView().getPreferredSize();
  61. }
  62. }
  63. if ( width > super.getPreferredSize().width || width < super.getPreferredSize().width){
  64. setPreferredSize(new Dimension(width + 2*HORIZONTAL_PADDING, dimension.height));
  65. revalidate();
  66. repaint();
  67. }
  68. }
  69. @Override
  70. public Dimension getPreferredSize()
  71. {
  72. return super.getPreferredSize();
  73. }
  74. private int countChildren( TreeNode treeNode )
  75. {
  76. if( treeNode.isLeaf() )
  77. return 0;
  78. else
  79. {
  80. int sum = 0;
  81. for( int i = 0; i < treeNode.getChildCount(); i++ )
  82. {
  83. sum += countChildren( treeNode.getChildAt( i ) ) + 1;
  84. }
  85. return sum;
  86. }
  87. }
  88. private int getLineNumber( TreeNode treeNode )
  89. {
  90. TreeNode parent = treeNode.getParent();
  91. if( parent == null )
  92. return 1;
  93. int sum = getLineNumber( parent ) + 1;
  94. for( int i = 0; i < parent.getChildCount(); i++ )
  95. {
  96. if( i == parent.getIndex( treeNode ) )
  97. return sum;
  98. sum += countChildren( parent.getChildAt( i ) ) + 1;
  99. }
  100. return 0;
  101. }
  102. @Override
  103. public void paintComponent(Graphics g){
  104. adjustWidth();
  105. super.paintComponent(g);
  106. Graphics2D g2d = (Graphics2D)g;
  107. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
  108. g.setColor(RenderHelper.BACKGROUND_COLOR);
  109. g2d.fillRect(0, 0, getWidth(), getHeight());
  110. g.setColor(RenderHelper.FOREGROUND_COLOR);
  111. for ( int i = 0; i < tree.getRowCount(); i++ ){
  112. PseudoCodeNode node = (PseudoCodeNode)tree.getPathForRow( i ).getLastPathComponent();
  113. int number = getLineNumber( node );
  114. Rectangle rect = tree.getRowBounds( i );
  115. String text = String.valueOf( number );
  116. int yPosition = rect.y + rect.height / 2 + 4;
  117. if( !node.hasSelectedSubnode() && node.isSelected() )
  118. g.drawImage( currentLine.getImage(), HORIZONTAL_PADDING, rect.y + rect.height / 2 - 10, 20, 20, null );
  119. g2d.drawString( text, HORIZONTAL_PADDING * 2 + 20, yPosition );
  120. if( node.hasBreakPoint() )
  121. {
  122. Color c = g.getColor();
  123. g.setColor( new Color (0xe7887a) );
  124. g.fillOval( getWidth() - HORIZONTAL_PADDING - 10, rect.y + rect.height / 2 - 5, 10, 10 );
  125. g.setColor( c );
  126. }
  127. }
  128. }
  129. private int getRowNumber( int y ) {
  130. int curr = 0;
  131. int res = -1;
  132. for ( int i = 0; i < tree.getRowCount(); i++ ){
  133. Rectangle rect = tree.getRowBounds( i );
  134. if( y > curr && y < rect.y + rect.height )
  135. {
  136. res = i;
  137. break;
  138. }
  139. curr = rect.y + rect.height;
  140. }
  141. return res;
  142. }
  143. @Override
  144. public void mouseClicked(MouseEvent e) {
  145. int rNum = getRowNumber( e.getY() );
  146. if( rNum < 0 )
  147. return;
  148. TreePath path = tree.getPathForRow( rNum );
  149. if( path == null )
  150. return;
  151. ((PseudoCodeNode)path.getLastPathComponent()).setBreakPoint( !((PseudoCodeNode)path.getLastPathComponent()).hasBreakPoint() );
  152. tree.repaint();
  153. }
  154. @Override
  155. public void mousePressed(MouseEvent e) {}
  156. @Override
  157. public void mouseReleased(MouseEvent e) {}
  158. @Override
  159. public void mouseEntered(MouseEvent e) {}
  160. @Override
  161. public void mouseExited(MouseEvent e) {}
  162. }