pathdiagram.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. define( function ( require, exports, module ) {
  2. var Class = require( 'core/class' );
  3. var Query = require( '../pathdiagram/dataquery' );
  4. var Connection = require( '../graffle/bezierconnection' );
  5. var Group = require( 'graphic/group' );
  6. var Text = require( 'graphic/text' );
  7. var LevelContainer = require( '../pathdiagram/levelcontainer' );
  8. var colors = require( '../pathdiagram/colors' );
  9. var R_SIZE = LevelContainer.RECT_SIZE;
  10. var margin = 100;
  11. function sign( number ) {
  12. if ( number === 0 ) {
  13. return 0;
  14. }
  15. return number > 0 ? 1 : -1;
  16. }
  17. var PathDiagram = Class.createClass( {
  18. base: Group,
  19. constructor: function ( keyword ) {
  20. this.callBase();
  21. this.levels = [
  22. new LevelContainer( -2 ),
  23. new LevelContainer( -1 ),
  24. new LevelContainer( 0 ),
  25. new LevelContainer( 1 ),
  26. new LevelContainer( 2 )
  27. ];
  28. this.headLevel = 0;
  29. this.tailLevel = 0;
  30. this.render();
  31. this.bind();
  32. this.showKeyword(keyword);
  33. },
  34. render: function () {
  35. for ( var name in this.levels ) {
  36. this.addShape( this.levels[ name ] );
  37. }
  38. return this;
  39. },
  40. getLevelContainer: function ( level ) {
  41. return this.levels[ level + 2 ];
  42. },
  43. showKeyword: function (keyword) {
  44. this.currentPath = keyword ? Query.search(keyword) : Query.random();
  45. this.getLevelContainer(0).render( [ this.currentPath ], -R_SIZE.width / 2, 0 );
  46. setTimeout( function() {
  47. this.getLevelContainer(0).select(0);
  48. }.bind(this));
  49. },
  50. bind: function () {
  51. var levels = this.levels;
  52. this.on( 'selected', function ( e ) {
  53. if ( e.pathNode ) {
  54. if ( e.level > 0 ) {
  55. this.tailLevel = e.level;
  56. }
  57. if ( e.level < 0 ) {
  58. this.headLevel = e.level;
  59. }
  60. } else {
  61. if (e.level > 0) {
  62. this.tailLevel = e.level - 1;
  63. }
  64. else if (e.level < 0 ) {
  65. this.headLevel = e.level + 1;
  66. }
  67. }
  68. this.updateConnection(e.pathNode, e.lastPathNode);
  69. this.updateCurrentPath();
  70. this.updateLevels();
  71. } );
  72. },
  73. updateConnection: function( current, last ) {
  74. if(last && last.connection) {
  75. last.connection.stroke(colors.get('connect-stroke'), 1);
  76. }
  77. if(current && current.connection) {
  78. this.removeShape(current.connection).addShape(current.connection);
  79. current.connection.stroke(colors.get('connect-stroke-active'), 3);
  80. }
  81. },
  82. updateCurrentPath: function() {
  83. var data = {
  84. seq: [],
  85. length: 0
  86. };
  87. for(var level = this.headLevel; level <= this.tailLevel; level++) {
  88. data.seq.push(this.getLevelContainer(level).levelWord);
  89. data.length++;
  90. }
  91. this.currentPath = data;
  92. },
  93. updateLevels: function() {
  94. var headClear = this.headLevel,
  95. tailClear = this.tailLevel;
  96. while(headClear >= -2) {
  97. this.renderLevel(--headClear);
  98. }
  99. while(tailClear <= 2) {
  100. this.renderLevel(++tailClear);
  101. }
  102. },
  103. clearLevelContainer: function( container ) {
  104. var nodes = container.getPathNodes();
  105. for(var i = 0; i < nodes.length; i++) {
  106. nodes[i].connection.remove();
  107. }
  108. container.clear();
  109. },
  110. renderLevel: function ( level ) {
  111. var container = this.getLevelContainer( level );
  112. var parent, dir, pbox, nbox, x, y, stream;
  113. if ( !container ) {
  114. return;
  115. }
  116. if(level < this.headLevel || level > this.tailLevel) {
  117. this.clearLevelContainer(container);
  118. if(level < this.headLevel - 1 || level > this.tailLevel + 1) {
  119. return;
  120. }
  121. }
  122. // 1 = right, -1 = left
  123. dir = sign( level );
  124. parent = this.getLevelContainer( level - dir );
  125. pbox = parent.getRenderBox();
  126. nbox = parent.getSelected().getRenderBox();
  127. x = pbox.x + dir * ( R_SIZE.width + margin );
  128. y = nbox.y;
  129. if ( level === 0 ) {
  130. stream = [ this.currentPath ];
  131. } else if ( level > 0 ) {
  132. stream = Query.downstream( this.currentPath );
  133. } else if ( level < 0 ) {
  134. stream = Query.upstream( this.currentPath );
  135. }
  136. container.render( stream, x, y );
  137. this.renderConnection( container, parent, dir );
  138. },
  139. renderConnection: function ( container, parent, dir ) {
  140. var childNodes = container.getPathNodes();
  141. var parentNode = parent.getSelected();
  142. var i, connection;
  143. for ( i = 0; i < childNodes.length; i++ ) {
  144. if ( dir === 1 ) {
  145. connection = new Connection( parentNode, childNodes[ i ] );
  146. } else if ( dir === -1 ) {
  147. connection = new Connection( childNodes[ i ], parentNode );
  148. }
  149. if(connection) {
  150. this.addShape( childNodes[i].connection = connection );
  151. connection.stroke( colors.get( 'connect-stroke' ), 1 ).fill( 'none' );
  152. }
  153. }
  154. }
  155. } );
  156. return PathDiagram;
  157. } );