interactive_graph.jsx 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /**
  2. * This is the main view element.
  3. */
  4. import preact from 'preact';
  5. import NodeInfo from "./node_info.jsx";
  6. /**
  7. * Style definitions which are directly injected (see README.md comments).
  8. */
  9. const style = {
  10. main: {
  11. 'border': '1px solid #cccccc',
  12. 'border-radius': 3,
  13. 'bottom': 3,
  14. 'display': 'flex',
  15. 'flex-direction': 'column',
  16. 'left': 1,
  17. 'position': 'absolute',
  18. 'right': 1,
  19. 'top': 3,
  20. },
  21. controlBar: {
  22. 'background-color': '#eeeeee',
  23. 'padding': '6px 3px 6px 3px',
  24. },
  25. graph: {
  26. 'flexGrow': 1,
  27. 'min-height': 200,
  28. 'min-width': 200,
  29. },
  30. // Filter text input -- negate default bootstrap blocking in IPython
  31. // notebooks.
  32. flt: {
  33. 'display': 'inline-block',
  34. 'padding': 3
  35. },
  36. // Help/information text in the toolbar -- faded to distinguish from controls.
  37. helpText: {
  38. 'color': '#666666',
  39. 'font-size': '9pt',
  40. },
  41. };
  42. export default class InteractiveGraph extends preact.Component {
  43. constructor() {
  44. super();
  45. // Note: This is currently not set, but in the future, it should be
  46. // user-controllable.
  47. this.state.horizontal = true;
  48. this.state.hoverNode = null;
  49. this.state.mousePosition = {x: 0, y: 0};
  50. }
  51. /**
  52. * Obligatory Preact render function.
  53. *
  54. * @param {function} onfilter Function to trigger when the user enters
  55. * text. This is called when the user presses <enter>, or de-focuses the
  56. * element.
  57. * @param {?Object} hoverNode Cytoscape node selected (null if no selection).
  58. * @param {?Object} mousePosition Mouse position, if a node is selected.
  59. * @return {XML} Preact components to render.
  60. */
  61. render({onfilter}, {hoverNode, mousePosition}) {
  62. return (
  63. <div style={style.main}>
  64. <div style={style.controlBar}>
  65. <label>Fuzzy node filter:&nbsp;</label>
  66. <input type="text" style={style.flt} onchange={
  67. (e) => {
  68. onfilter(e.target.value);
  69. }
  70. }/>
  71. <em style={style.helpText}>
  72. &nbsp;&bull;&nbsp;
  73. Hover over a node to view inputs; click to focus/zoom graph.
  74. </em>
  75. </div>
  76. <div ref={(g) => {
  77. this.graph = g;
  78. }} style={style.graph}/>
  79. <NodeInfo selected={hoverNode} mousePosition={mousePosition}/>
  80. </div>
  81. );
  82. }
  83. /**
  84. * Calls the `onmount` property, so the caller (visualize.js) can set up the
  85. * Cytoscape JS graph (since Cytoscape doesn't expose itself as a Preact
  86. * component).
  87. */
  88. componentDidMount() {
  89. this.props.onmount(this, this.graph);
  90. }
  91. /**
  92. * Public API to update the state, when a node is hovered.
  93. *
  94. * @param {!Object} node Cytoscape JS node.
  95. * @param {!Object} position Position of the mouse.
  96. */
  97. showNodeInfo(node, position) {
  98. this.setState({hoverNode: node, mousePosition: position});
  99. }
  100. /**
  101. * Public API to update the state, when a node is un-hovered.
  102. */
  103. hideNodeInfo() {
  104. this.setState({hoverNode: null});
  105. }
  106. }