|
| 1 | +!! WebSockets |
| 2 | +@cha:websockets |
| 3 | + |
| 4 | +DRAFT |
| 5 | + |
| 6 | +!!! Concepts |
| 7 | + |
| 8 | +!!! Architecture |
| 9 | + |
| 10 | +!!! Studying a real case |
| 11 | + |
| 12 | +*https://github.com/TelescopeSt/TelescopeCytoscape* |
| 13 | + |
| 14 | +This project allow one to create a model of visualization (nodes and their |
| 15 | +contents, layouts, interactions, and update mechanism) then to render it |
| 16 | +with the CytoscapeJs visualization framework. |
| 17 | + |
| 18 | +The Seaside part is really small. We just use Seaside to render an empty |
| 19 | +div and initialize a cytoscape visualization inside. We could probably |
| 20 | +do without Seaside but we did this project for a Seaside application. |
| 21 | +(And we use the existing callbacks mechanism). |
| 22 | + |
| 23 | +During the rendering we open a web socket and we generate the initial |
| 24 | +cytoscape visualization inside the empty div generated by Seaside. |
| 25 | + |
| 26 | +Then when the user interact with the visualization, it communicates the |
| 27 | +interactions via the web socket to the Pharo server and if it should |
| 28 | +impact the visualization, commands to do so are sent via the websocket |
| 29 | +to the client. |
| 30 | + |
| 31 | +In this project the main part for the websocket management are: |
| 32 | + |
| 33 | +- TLCytoscapeComponent : The Seaside component registering the |
| 34 | +visualization |
| 35 | +(*https://github.com/TelescopeSt/TelescopeCytoscape/blob/development/src/Telescope-Cytoscape/TLCytoscapeComponent.class.st*) |
| 36 | +- TLCytoscapeWebSocketDelegate : The class managing the websocket server |
| 37 | +side |
| 38 | +(*https://github.com/TelescopeSt/TelescopeCytoscape/blob/development/src/Telescope-Cytoscape/TLCytoscapeWebSocketDelegate.class.st*) |
| 39 | +- CYSFileLibrary>>cytoscapeTelescopeJs : The javascript managing the |
| 40 | +socket client side |
| 41 | +(*https://github.com/TelescopeSt/TelescopeCytoscape/blob/development/src/Telescope-Cytoscape-Libraries/CYSFileLibrary.class.st#L539*) |
| 42 | + |
| 43 | + |
| 44 | +!!! The Component Part |
| 45 | + |
| 46 | +[[[ |
| 47 | +TLCytoscapeComponent >> visuDivId [ |
| 48 | + visuDivId ifNil: [ visuDivId:= self class nextId ]. |
| 49 | + ^ visuDivId |
| 50 | +] |
| 51 | +]]] |
| 52 | + |
| 53 | +[[[ |
| 54 | +TLCytoscapeComponent >> visuDivId: anObject [ |
| 55 | + visuDivId := anObject |
| 56 | +] |
| 57 | +]]] |
| 58 | + |
| 59 | + |
| 60 | + |
| 61 | + |
| 62 | + |
| 63 | +[[[ |
| 64 | +TLCytoscapeComponent >> renderContentOn: html [ |
| 65 | + | visuId div callback | |
| 66 | + visuId := self visuDivId. |
| 67 | + div := html div |
| 68 | + id: visuId; |
| 69 | + style: self style; |
| 70 | + attributeAt: #isTelescopeVisu put: 'true'; |
| 71 | + attributeAt: #'data-port' put: self webSocketPort; |
| 72 | + class: 'telescopeVisu'; |
| 73 | + with: [ html div |
| 74 | + class: 'visualization'; |
| 75 | + style: 'height: 100%; width: 100%;'. |
| 76 | + self waitingMessage value: html. |
| 77 | + self renderOptionalButtonsOn: html ]; |
| 78 | + yourself. |
| 79 | + callback := WAValueCallback new. |
| 80 | + TLCytoscapeWebSocketDelegate |
| 81 | + registerVisualization: self visualization |
| 82 | + underId: visuId |
| 83 | + withCallBack: callback |
| 84 | + callbackUrl: |
| 85 | + {html actionUrl asString. |
| 86 | + (div storeCallback: callback)} |
| 87 | +] |
| 88 | +]]] |
| 89 | + |
| 90 | +[[[ |
| 91 | +TLCytoscapeComponent >> renderOptionalButtonsOn: html [ |
| 92 | + html div |
| 93 | + class: 'fitButton'; |
| 94 | + with: [ self renderResetButtonOn: html. |
| 95 | + self exportStrategy renderDownloadButtonForVisu: self visuDivId on: html ] |
| 96 | +] |
| 97 | + |
| 98 | +]]] |
| 99 | + |
| 100 | +[[[ |
| 101 | +TLCytoscapeComponent >> renderResetButtonOn: html [ |
| 102 | + html anchor |
| 103 | + onClick: 'telescope.visuWithId(' , self visuDivId asString , ').fit();'; |
| 104 | + with: 'Reset' |
| 105 | +] |
| 106 | +]]] |
| 107 | + |
| 108 | + |
| 109 | +!!! Websocket server side |
| 110 | + |
| 111 | +The class managing the websocket server |
| 112 | +side (from *https://github.com/TelescopeSt/TelescopeCytoscape/blob/development/src/Telescope-Cytoscape/TLCytoscapeWebSocketDelegate.class.st*) |
| 113 | + |
| 114 | +[[[ |
| 115 | +ZnWebSocketDelegate subclass: #TLCytoscapeWebSocketDelegate, |
| 116 | + instVars: 'visualizationByIdDictionary websocketByVisu' |
| 117 | + classInstVars: 'singleton development serverPort clientPort' |
| 118 | +]]] |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | +TLCytoscapeWebSocketDelegate class >> registerVisualization: aTLVisualization underId: aDivId withCallBack: aCallBack callbackUrl: callbackUrl [ |
| 123 | + self ensureServerIsRunning. |
| 124 | + self singleton delegate |
| 125 | + registerVisualization: aTLVisualization |
| 126 | + underId: aDivId |
| 127 | + withCallBack: aCallBack |
| 128 | + callbackUrl: callbackUrl |
| 129 | +] |
| 130 | + |
| 131 | + |
| 132 | + |
0 commit comments