NodeView.java 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. package view;
  2. import java.awt.BasicStroke;
  3. import java.awt.Color;
  4. import java.awt.Component;
  5. import java.awt.Graphics;
  6. import java.awt.Graphics2D;
  7. import java.awt.event.ComponentEvent;
  8. import java.awt.event.ComponentListener;
  9. import java.awt.event.MouseEvent;
  10. import java.awt.event.MouseListener;
  11. import javax.swing.BorderFactory;
  12. import javax.swing.JFrame;
  13. import javax.swing.JPanel;
  14. import javax.swing.SwingUtilities;
  15. import javax.swing.border.Border;
  16. import bk.LayoutType;
  17. import graph.LayeredGraphNode;
  18. /**
  19. * A drawable representation of a node.
  20. * @author kolja
  21. *
  22. */
  23. public class NodeView extends JPanel implements AnnimatedView, MouseListener {
  24. private static final long serialVersionUID = 1L;
  25. private LayeredGraphNode model;
  26. private LayoutType layout;
  27. private JFrame mainView;
  28. private int originalWidth;
  29. private int originalHeight;
  30. public NodeView( LayeredGraphNode model, LayoutType lt, JFrame mv ) {
  31. mainView = mv;
  32. this.model = model;
  33. layout = lt;
  34. addMouseListener( this );
  35. originalWidth = (int)model.getWidth( lt );
  36. originalHeight = (int)model.getHeight( lt );
  37. }
  38. private synchronized void update()
  39. {
  40. SwingUtilities.invokeLater(new Runnable() {
  41. public void run() {
  42. for( ComponentListener l : mainView.getComponentListeners() )
  43. {
  44. l.componentResized( new ComponentEvent(mainView, 0) );
  45. }
  46. }
  47. });
  48. }
  49. public int getScaledX( int x )
  50. {
  51. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  52. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  53. x *= scale;
  54. return x;
  55. }
  56. public int getScaledY( int y )
  57. {
  58. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  59. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  60. y *= scale;
  61. return y;
  62. }
  63. public void updateTooltipText() {
  64. if( layout != LayoutType.COMBINED )
  65. {
  66. setToolTipText( "<html>Name: " + model.toString() +
  67. "<br>Root: " + model.getRoot( layout ).toString() +
  68. "<br>Shink: " + model.getSink( layout ).toString() +
  69. "<br>Shift: " + model.getShift( layout ) + "</html>" );
  70. }
  71. else
  72. {
  73. setToolTipText( "<html>Name: " + model.toString() +
  74. "<br>result X: " + model.getX( LayoutType.COMBINED ) +
  75. "<br>other layouts: [" + model.getX( LayoutType.LEFTMOST_UPPER ) + "," + model.getX( LayoutType.RIGHTMOST_UPPER ) + ","
  76. + model.getX( LayoutType.LEFTMOST_LOWER ) + "," + model.getX( LayoutType.RIGHTMOST_LOWER ) + "]</html>" );
  77. }
  78. for( Component c : getComponents() )
  79. {
  80. if( !(c instanceof NodeView) )
  81. continue;
  82. ((NodeView)c).updateTooltipText();
  83. }
  84. }
  85. public int getXOffset()
  86. {
  87. int x = 0;
  88. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  89. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  90. x += (getWidth()-50) / 2 - (getWidthOfNeededArea() * scale ) / 2 + 25;
  91. return x;
  92. }
  93. public int getYOffset()
  94. {
  95. int y = 0;
  96. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  97. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  98. y += (getHeight()-50) / 2 - (getHeightOfNeededArea() * scale ) / 2 + 25;
  99. return y;
  100. }
  101. public int getOriginalWidth() {
  102. return originalWidth;
  103. }
  104. public int getOriginalHeight() {
  105. return originalHeight;
  106. }
  107. private int getWidthOfNeededArea() {
  108. int max = 0;
  109. double min = Double.POSITIVE_INFINITY;
  110. for( Component c : getComponents() )
  111. {
  112. if( c instanceof NodeView )
  113. {
  114. max = Math.max( max, ((NodeView)c).getVirtualX() + ((NodeView)c).getOriginalWidth() );
  115. min = Math.min( ((AnnimatedView)c).getVirtualX(), min);
  116. }
  117. }
  118. return max - (int)min;
  119. }
  120. private int getHeightOfNeededArea() {
  121. int max = 0;
  122. double min = Double.POSITIVE_INFINITY;
  123. for( Component c : getComponents() )
  124. {
  125. if( c instanceof NodeView )
  126. {
  127. max = Math.max( max, ((NodeView)c).getVirtualY() + ((NodeView)c).getOriginalHeight() );
  128. min = Math.min( ((AnnimatedView)c).getVirtualY(), min);
  129. }
  130. }
  131. return max - (int)min;
  132. }
  133. @Override
  134. public void doLayout() {
  135. double minX = Double.POSITIVE_INFINITY;
  136. for( Component c : getComponents() )
  137. {
  138. if( !(c instanceof AnnimatedView) )
  139. continue;
  140. minX = Math.min( ((AnnimatedView)c).getVirtualX(), minX);
  141. }
  142. int x = 0;
  143. int y = 0;
  144. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  145. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  146. x += (getWidth()) / 2 - (getWidthOfNeededArea() * scale ) / 2;
  147. y += (getHeight()) / 2 - (getHeightOfNeededArea() * scale ) / 2;
  148. for( Component c : getComponents() )
  149. {
  150. if( !(c instanceof AnnimatedView) )
  151. continue;
  152. AnnimatedView view = (AnnimatedView)c;
  153. c.setLocation( getScaledX( view.getVirtualX() - (int)minX ) + x, getScaledY( view.getVirtualY() ) + y);
  154. if( c instanceof NodeView )
  155. c.setSize( getScaledX( ((NodeView)c).getOriginalWidth() ), getScaledY( ((NodeView)c).getOriginalHeight() ) );
  156. else
  157. c.setSize( getScaledX( view.getVirtualWidth() ), getScaledY( view.getVirtualHeight() ) );
  158. c.doLayout();
  159. }
  160. }
  161. @Override
  162. public void paint( Graphics g )
  163. {
  164. if( layout == LayoutType.COMBINED && model.getColor( null ) == null )
  165. return;
  166. updateTooltipText();
  167. paintComponent( g );
  168. double minX = Double.POSITIVE_INFINITY;
  169. for( Component c : getComponents() )
  170. {
  171. if( !(c instanceof AnnimatedView) )
  172. continue;
  173. minX = Math.min( ((AnnimatedView)c).getVirtualX(), minX);
  174. }
  175. int x = 0;
  176. double scale1 = Math.min( (getWidth()) / (double)getWidthOfNeededArea(), (getHeight()) / (double)getHeightOfNeededArea());
  177. double scale = Math.min( (getWidth()-50*scale1) / (double)getWidthOfNeededArea(), (getHeight()-50*scale1) / (double)getHeightOfNeededArea());
  178. x += (getWidth()-50) / 2 - (getWidthOfNeededArea() * scale ) / 2 + 25;
  179. for( Component c : getComponents() )
  180. {
  181. if( c instanceof NodeView )
  182. {
  183. if( layout != LayoutType.COMBINED )
  184. {
  185. NodeView v = (NodeView)c;
  186. v.renderClass( g.create( getScaledX( v.getPlainVirtualX() - (int)minX - 12 ) + x, c.getY() - getScaledY(12), getScaledX( v.getPlainVirtualWidth() + 22 ), c.getHeight() + getScaledY(22) ) );
  187. }
  188. }
  189. c.paint( g.create( c.getX(), c.getY(), c.getWidth(), c.getHeight() ) );
  190. }
  191. }
  192. public void renderClass( Graphics g ) {
  193. g.setColor( model.getRoot( layout ).getClassColor( layout ) );
  194. if( model.getContainedNodes().size() == 0 && model.getRoot( layout ).getClassColor( layout ) != Color.LIGHT_GRAY )
  195. {
  196. g.setColor( new Color( (g.getColor().getRed() + 500) / 3, (g.getColor().getGreen() + 500) / 3, (g.getColor().getBlue() + 500) / 3 ) );
  197. g.fillRect( 0, 0, g.getClipBounds().width, g.getClipBounds().height );
  198. }
  199. }
  200. @Override
  201. public void paintComponent( Graphics g )
  202. {
  203. Graphics2D g2 = (Graphics2D)g;
  204. g2.setColor( model.getColor( layout ) );
  205. g2.setStroke(new BasicStroke(5));
  206. if( model.getContainedNodes().size() == 0 )
  207. {
  208. if( model.getRoot( layout ) == model )
  209. g2.fillOval( 0, 0, getWidth(), getHeight() );
  210. else
  211. g2.fillRect( 0, 0, getWidth(), getHeight() );
  212. }
  213. boolean selected = model.isSelected( layout );
  214. if( selected )
  215. {
  216. g.setColor( Color.BLACK );
  217. if( model.getContainedNodes().size() > 0 )
  218. g.setColor( Color.GRAY );
  219. g.fillRect( 0, 0, getWidth(), getHeight() );
  220. }
  221. Border linebor = BorderFactory.createLineBorder(model.getColor( layout ), 5);
  222. if( model.getRoot( layout ) != model || model.getContainedNodes().size() != 0 )
  223. linebor.paintBorder( this, g2, 0, 0, getWidth(), getHeight() );
  224. if( model.isMouseOver() && model.getContainedNodes().size() == 0 )
  225. {
  226. g.setColor( Color.WHITE );
  227. g.fillOval( getWidth() / 4, getHeight() / 4, getWidth() / 2, getHeight() / 2 );
  228. }
  229. }
  230. public int getPlainVirtualX() {
  231. return (int)model.getX( layout );
  232. }
  233. @Override
  234. public int getVirtualX() {
  235. if( model.isDummyNode() )
  236. return (int)(model.getX( layout ) + getVirtualWidth() / (3/4.0) );
  237. return (int)model.getX( layout );
  238. }
  239. @Override
  240. public int getVirtualY() {
  241. return (int)model.getY( layout );
  242. }
  243. @Override
  244. public int getVirtualWidth() {
  245. if( model.isDummyNode() )
  246. return (int)(model.getWidth( layout ) / 3);
  247. return (int)model.getWidth( layout );
  248. }
  249. public int getPlainVirtualWidth() {
  250. return (int)model.getWidth( layout );
  251. }
  252. @Override
  253. public int getVirtualHeight() {
  254. return (int)model.getHeight( layout );
  255. }
  256. @Override
  257. public void mouseClicked(MouseEvent e) {}
  258. @Override
  259. public void mousePressed(MouseEvent e) {}
  260. @Override
  261. public void mouseReleased(MouseEvent e) {}
  262. @Override
  263. public void mouseEntered(MouseEvent e) {
  264. model.setMouseOver( true );
  265. update();
  266. }
  267. @Override
  268. public void mouseExited(MouseEvent e) {
  269. model.setMouseOver( false );
  270. update();
  271. }
  272. }