├── .gitignore ├── .vscode ├── cSpell.json ├── gulp.json ├── launch.json ├── settings.json └── tasks.json ├── LICENSE.txt ├── README.md ├── build.sh ├── core ├── api │ ├── api.ts │ ├── layer.ts │ └── stdlib │ │ ├── algorithms.ts │ │ ├── graphs.ts │ │ ├── kary-foundation.ts │ │ └── sortings.ts ├── constants.ts ├── editor │ ├── graph.ts │ ├── selection.ts │ ├── snapobject.ts │ └── svg.ts ├── installer.ts ├── karyfoundation │ ├── comment │ │ └── core.ts │ └── monaco │ │ └── kf-comment-monaco.ts ├── language-tools.ts ├── main.ts ├── objects │ ├── dot │ │ ├── circle.ts │ │ ├── dot.ts │ │ ├── drag-move.ts │ │ ├── drag-start.ts │ │ └── drag-stop.ts │ ├── point.ts │ └── vertex │ │ ├── arrow │ │ ├── interfaces.ts │ │ ├── line.ts │ │ └── loop.ts │ │ ├── vertex-static.ts │ │ └── vertex.ts ├── rendering │ ├── circular.ts │ └── spiral.ts ├── script │ ├── algorithms.ts │ ├── engine.ts │ └── events.ts ├── storage │ └── storage.ts ├── typings │ ├── monaco.d.ts │ ├── node.d.ts │ └── snapsvg.d.ts └── ui │ ├── algorithms-tab │ └── view.ts │ ├── editor-tab │ ├── notebook │ │ ├── programmer.ts │ │ └── say.ts │ └── view.ts │ ├── events.ts │ ├── loader.ts │ ├── programmer-tab │ ├── ribbon.ts │ └── view.ts │ ├── tabs.ts │ └── toolbar.ts ├── designs ├── icon │ ├── icns │ │ └── icon.icns │ ├── icon.iconsproj │ └── icon.sketch ├── opening.sketch ├── toolbar-icons.sketch ├── ui.sketch └── wiki.sketch ├── doc.sh ├── electron └── main.js ├── gulpfile.js ├── javascript ├── graph-monaco.js └── loading-screen.js ├── less.sh ├── libs ├── prism.css └── system.js ├── package.json ├── resources ├── Vegur-R_0_600.eot ├── Vegur-R_0_600.svg ├── Vegur-R_0_600.ttf ├── Vegur-R_0_600.woff ├── kary-logo.png ├── opening-logo.png ├── playbutton.png ├── ribbon-editor-add-loop.png ├── ribbon-editor-connect.png ├── ribbon-editor-remove.png ├── ribbon-editor-select.png ├── ribbon-general-new-file.png ├── ribbon-general-open-file.png ├── ribbon-general-save-file.png ├── ribbon-programmer-comment-line.png ├── ribbon-programmer-comment-section.png ├── ribbon-programmer-run.png ├── sourcecodepro-medium-webfont.woff ├── sourcecodepro-medium-webfont.woff2 ├── toolbar-back.png ├── toolbar-tabs-algorithms.png ├── toolbar-tabs-editor.png └── toolbar-tabs-programmer.png ├── sheets ├── base.less ├── fonts │ ├── source-code-pro.less │ └── vegur.less ├── globals.less ├── libs │ └── kary-scheme.less ├── scroll.less ├── ui.less └── views │ ├── algorithms │ ├── controller.less │ └── view.less │ ├── graph.less │ ├── inspector │ ├── inspector.less │ ├── prompt.less │ ├── say.less │ └── sizings.less │ ├── programmer │ └── monaco.less │ ├── tab-view.less │ └── toolbar │ ├── ribbon.less │ ├── ribbons │ ├── editor.less │ ├── general.less │ └── programmer.less │ ├── tabs.less │ └── toolbar.less ├── tsconfig.json ├── view └── index.html └── wrappers ├── wrappers.d.ts └── wrappers.js /.gitignore: -------------------------------------------------------------------------------- 1 | _compiled/* 2 | _release/* 3 | _documentation/* 4 | node_modules/* 5 | npm-debug.log 6 | www/* -------------------------------------------------------------------------------- /.vscode/cSpell.json: -------------------------------------------------------------------------------- 1 | // cSpell Settings 2 | { 3 | // Version of the setting file. Always 0.1 4 | "version": "0.1", 5 | // language - current active spelling language 6 | "language": "en", 7 | // words - list of words to be always considered correct 8 | "words": [ 9 | "Pouya", 10 | "Kary", 11 | "karyfoundation", 12 | "Toolbar", 13 | "Selectbox", 14 | "Eulerian", 15 | "newdot", 16 | "newdotat", 17 | "newdots", 18 | "howmuch", 19 | "getdot", 20 | "getdots", 21 | "foreachdot", 22 | "foralldots", 23 | "graphfrommatrix", 24 | "countdots", 25 | "movex", 26 | "movey", 27 | "movebx", 28 | "moveby", 29 | "Sortings", 30 | "eulerianpath", 31 | "euleriancycle", 32 | "Micha", 33 | "Hanselmann", 34 | "Sina", 35 | "Bakhtiari", 36 | "posx", 37 | "FIXME", 38 | "Line's", 39 | "mkdirp", 40 | "Standalone", 41 | "onresize", 42 | "prismjs", 43 | "Script's", 44 | "subdirs" 45 | ], 46 | // flagWords - list of words to be always considered incorrect 47 | // This is useful for offensive words and common spelling errors. 48 | // For example "hte" should be "the" 49 | "flagWords": [ 50 | "hte" 51 | ] 52 | } -------------------------------------------------------------------------------- /.vscode/gulp.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "gulp", 4 | "isShellCommand": false, 5 | "args": [ 6 | "--no-color" 7 | ], 8 | "tasks": [ 9 | { 10 | "taskName": "default", 11 | "isBuildCommand": true, 12 | "showOutput": "silent" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "name": "Debug", 6 | "type": "chrome", 7 | "request": "launch", 8 | "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron", 9 | "runtimeArgs": [ 10 | "${workspaceRoot}/_compiled/main.js", 11 | "--enable-logging", 12 | "--remote-debugging-port=9222" 13 | ], 14 | "sourceMaps": false 15 | }, 16 | { 17 | "name": "Attach", 18 | "type": "node", 19 | "request": "attach", 20 | "port": 5858, 21 | "sourceMaps": false, 22 | "outDir": null 23 | } 24 | ] 25 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.fontSize": 14, 3 | "editor.lineHeight": 24, 4 | "editor.fontFamily": "SourceCodePro-Medium", 5 | "editor.tabSize": 4, 6 | "editor.wrappingColumn": 0, 7 | "editor.quickSuggestionsDelay": 0, 8 | "editor.insertSpaces": true, 9 | "alex.enable": true 10 | } -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.1.0", 3 | "command": "bash", 4 | "isShellCommand": false, 5 | "args": [ "build.sh" ], 6 | "showOutput": "silent", 7 | "echoCommand": false 8 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Graph 2 | 3 | [](https://codeclimate.com/github/karyfoundation/graph) 4 | 5 | A very powerful graph programming environment with a powerful graphing engine, powerful high-level API, mathematica notebook like interactive programming, code editor and plugin support. 6 | 7 |  8 | 9 | 10 | #### Helpful Links 11 | - [Contribution Guidlines](https://github.com/karyfoundation/graph/wiki/Getting-Started-on-Development) 12 | - [Graph API](https://github.com/karyfoundation/graph/wiki/API) 13 | - [Building and Running Graph](https://github.com/karyfoundation/graph/wiki/Building-and-Running-Graph) 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | # build 2 | 3 | gulp 4 | 5 | cd ./_compiled 6 | electron main.js 7 | cd .. 8 | -------------------------------------------------------------------------------- /core/api/layer.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /** 8 | * This is a very important module. It provides an 9 | * ***abstraction layer*** over the main `KaryGraph` 10 | * to create a ***simple functional*** layer over for 11 | * the API to reduce complexity when scripting 12 | */ 13 | 14 | namespace KaryGraph.API.AbstractionLayer { 15 | 16 | // 17 | // ─── TYPES ────────────────────────────────────────────────────────────────────── 18 | // 19 | 20 | export type DotObjectOrDotID = Dot | number; 21 | 22 | // 23 | // ─── GET GRAPH VIEW WIDTH ─────────────────────────────────────────────────────── 24 | // 25 | 26 | export function GetGraphViewWidth ( ): number { 27 | return GraphView.node.getBoundingClientRect( ).width; 28 | } 29 | 30 | // 31 | // ─── GET GRAPH VIEW HEIGHT ────────────────────────────────────────────────────── 32 | // 33 | 34 | export function GetGraphViewHeight ( ): number { 35 | return GraphView.node.getBoundingClientRect( ).height; 36 | } 37 | 38 | // 39 | // ─── DOT BY DOT OR ID ─────────────────────────────────────────────────────────── 40 | // 41 | 42 | export function GetDotByDotOrId ( dotOrId: DotObjectOrDotID ): Dot { 43 | if ( typeof ( dotOrId ) === "number" ) { 44 | return GetDotByNumberId( dotOrId ); 45 | } else { 46 | return dotOrId; 47 | } 48 | } 49 | 50 | // 51 | // ─── ADD NEW DOT ──────────────────────────────────────────────────────────────── 52 | // 53 | 54 | /** 55 | * Generates a new random dot on the screen 56 | */ 57 | export function AddNewDot ( ): Dot { 58 | let x = 20 + Random( GraphWidth - 40 ); 59 | let y = 20 + Random( GraphHeight - 40 ); 60 | return new Dot( x, y ); 61 | } 62 | 63 | // 64 | // ─── GET DOT BY NUMBER ID ─────────────────────────────────────────────────────── 65 | // 66 | 67 | export function GetDotByNumberId ( numberId: number ): Dot { 68 | let dot: Dot; 69 | let keys = Object.keys( Storage.Nodes ); 70 | keys.forEach( key => { 71 | if ( ( Storage.Nodes[ key ] ).GetNumberId( ) == numberId ) { 72 | dot = Storage.Nodes[ key ]; 73 | return; 74 | } 75 | }); 76 | return dot; 77 | } 78 | 79 | // 80 | // ─── GET NUMBER OF VERTICES WITH ODD DEGREE ───────────────────────────────────── 81 | // 82 | 83 | export function NumberOfOddVertices ( ): number { 84 | var verticesWithOddDegree: number = 0; 85 | var keys = Object.keys( Storage.Nodes ); 86 | keys.forEach( key => { 87 | if ( ( Storage.Nodes[ key ] ).GetDegree() % 2 ) { 88 | verticesWithOddDegree++; 89 | } 90 | }); 91 | return verticesWithOddDegree; 92 | } 93 | 94 | // 95 | // ─── CLEAR SCREEN ─────────────────────────────────────────────────────────────── 96 | // 97 | 98 | export function Reset ( ) { 99 | Object.keys( Storage.Nodes ).forEach( 100 | key => ( Storage.Nodes[ key ] ).Remove( ) 101 | ); 102 | Dot.ResetNumberIdPlace( ); 103 | } 104 | 105 | // 106 | // ─── CREATE MATRIX OF GRAPH ──────────────────────────────────────────────────── 107 | // 108 | 109 | export function CreateMatrix ( idOrDots: Array ): number[ ][ ] { 110 | var idsLength = idOrDots.length; 111 | var matrix: number[ ][ ] = new Array( idsLength ); 112 | 113 | for ( let row = 0; row < idsLength; row++ ) { 114 | matrix[ row ] = new Array( idsLength ); 115 | var d1 = GetDotByDotOrId( idOrDots[ row ] ); 116 | 117 | for ( let column = 0; column < idsLength; column++ ) { 118 | let d2 = GetDotByDotOrId( idOrDots[ column ] ); 119 | matrix[ row ][ column ] = + d1.IsConnectedTo( d2 ); 120 | } 121 | } 122 | 123 | return matrix; 124 | } 125 | 126 | // 127 | // ─── RENDERING ────────────────────────────────────────────────────────────────── 128 | // 129 | 130 | export function Render ( text: string ) { 131 | switch ( text ) { 132 | case 'circle': 133 | Rendering.RenderCircular(); 134 | break; 135 | case 'spiral': 136 | Rendering.RenderSpiral(); 137 | break; 138 | case 'order': 139 | KaryGraph.API.StandardLibrary.Sortings.Tree( ); 140 | break; 141 | default: 142 | // UI.Console.PrintError(`Graph API: No rendering option ${text}`); 143 | break; 144 | } 145 | } 146 | 147 | // ──────────────────────────────────────────────────────────────────────────────── 148 | 149 | } 150 | -------------------------------------------------------------------------------- /core/api/stdlib/algorithms.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Sina Bakhtiari 5 | // 6 | 7 | namespace KaryGraph.API.StandardLibrary.Algorithms { 8 | 9 | // 10 | // ─── BFS ──────────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export function BFS ( start: Dot, steps: number ) { 14 | let bfs = new Array>( ); 15 | let checked = new Array( ); 16 | 17 | for ( let it = 0; it < KaryGraph.Dot.TotalDots; it++ ) { 18 | checked.push( false ); 19 | } 20 | 21 | let step = 0; 22 | bfs.push( [ start ] ); 23 | checked[ start.GetNumberId( ) ] = true; 24 | 25 | while ( step < steps || steps == -1 ) { 26 | let tmp = new Array( ); 27 | 28 | for ( let it = 0; it < bfs[ bfs.length-1 ].length; it++ ) { 29 | let neighbors = bfs[ bfs.length-1 ][ it ].GetNeighbors( ); 30 | 31 | for ( let nit = 0; nit < neighbors.length; nit++ ) { 32 | 33 | if ( checked[ neighbors[ nit ].GetNumberId( ) ] == false ) { 34 | checked[ neighbors[ nit ].GetNumberId( ) ] = true; 35 | tmp.push( neighbors[ nit ] ); 36 | } 37 | } 38 | } 39 | 40 | if ( tmp.length == 0 ) { 41 | break; 42 | } 43 | 44 | bfs.push( tmp ) ; 45 | step++; 46 | } 47 | 48 | return bfs; 49 | } 50 | 51 | // ──────────────────────────────────────────────────────────────────────────────── 52 | 53 | } 54 | -------------------------------------------------------------------------------- /core/api/stdlib/graphs.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.API.StandardLibrary { 8 | 9 | // 10 | // ─── RND ──────────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export function RND ( ) { 14 | 15 | } 16 | 17 | // 18 | // ─── COMPLETE GRAPH ───────────────────────────────────────────────────────────── 19 | // 20 | 21 | export function CreateCompleteGraph ( size: number ) { 22 | let keys = new Array( ); 23 | 24 | // creating dots 25 | for ( var counter = 0; counter < size; counter++ ) { 26 | keys.push( API.AbstractionLayer.AddNewDot( ).Id ); 27 | } 28 | 29 | // connecting 30 | keys.forEach( key => { 31 | for ( var index = 0; index < size; index++ ) { 32 | var currentDot = keys[ index ]; 33 | if ( currentDot !== key ) { 34 | Storage.Nodes[ key ].ConnectTo( Storage.Nodes[ keys[ index] ] ); 35 | } 36 | } 37 | }); 38 | } 39 | 40 | // ──────────────────────────────────────────────────────────────────────────────── 41 | 42 | } -------------------------------------------------------------------------------- /core/api/stdlib/kary-foundation.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.API.KaryFoundation { 8 | 9 | // 10 | // ─── THE KARY GRAPH ───────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** 14 | * Pretty fun easter that generates a Kary Horse Logo with exact 15 | * properties as the real logo in the center of the screen. 16 | */ 17 | export function CreateKaryHorseGraph ( ) { 18 | // screen sizes 19 | const height = AbstractionLayer.GetGraphViewHeight( ); 20 | const width = AbstractionLayer.GetGraphViewWidth( ); 21 | 22 | /** Creates a function */ 23 | function createFromOrigin ( x: number, y: number ): Dot { 24 | return newdotat( ( width / 2 ) + x, ( height / 2 ) + y); 25 | } 26 | 27 | /** Where the dots are saved. */ 28 | let dots = new Array( 9 ); 29 | 30 | // Creating dots 31 | dots[ 0 ] = createFromOrigin( -185 , -51 ); // 1 32 | dots[ 1 ] = createFromOrigin( -103 , -142 ); // 2 33 | dots[ 2 ] = createFromOrigin( -65 , 5 ); // 3 34 | dots[ 3 ] = createFromOrigin( 118 , 5 ); // 4 35 | dots[ 4 ] = createFromOrigin( 161 , -44 ); // 5 36 | dots[ 5 ] = createFromOrigin( -139 , 135 ); // 6 37 | dots[ 6 ] = createFromOrigin( -6 , 135 ); // 7 38 | dots[ 7 ] = createFromOrigin( 48 , 135 ); // 8 39 | dots[ 8 ] = createFromOrigin( 181 , 135 ); // 9 40 | 41 | // Connecting 42 | connect([ dots[ 0 ], dots[ 1 ], dots[ 2 ], dots[ 3 ], dots[ 4 ] ]); 43 | connect([ dots[ 5 ], dots[ 2 ], dots[ 6 ]]); 44 | connect([ dots[ 7 ], dots[ 3 ], dots[ 8 ]]); 45 | } 46 | 47 | // ──────────────────────────────────────────────────────────────────────────────── 48 | 49 | } -------------------------------------------------------------------------------- /core/api/stdlib/sortings.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Micha Hanselmann 5 | // 6 | 7 | namespace KaryGraph.API.StandardLibrary.Sortings { 8 | 9 | // 10 | // ─── CLASSIC TREE ─────────────────────────────────────────────────────── 11 | // 12 | 13 | export function Tree ( ): boolean { 14 | 15 | // vars 16 | var map = new Map( ); 17 | var keys = Object.keys( Storage.Nodes ); 18 | var layers: number = 0; 19 | 20 | // create tree map 21 | keys.forEach( key => { 22 | var dot = Storage.Nodes[ key ]; 23 | if ( dot.NumberOfInputs( ) == 0 ) { 24 | var children = dot.GetChildren( ); 25 | if ( children == -1 ) return false; 26 | map.set( dot, children ); 27 | } 28 | }); 29 | 30 | // count layers 31 | function dive ( map: any, layer: number ) { 32 | if (layer > layers) layers = layer; 33 | for ( var [ key, value ] of map.entries() ) { 34 | if ( value.size > 0 ) dive( value, layer + 1 ); 35 | } 36 | } 37 | dive( map, 1 ); 38 | 39 | // move dots 40 | function moveDots ( map: any, width: number, positionY: number, xOff: number ) { 41 | var count = map.size; 42 | var x = 0; 43 | for ( var [ key, value ] of map.entries( ) ) { 44 | var positionX = width / count * x++ + (width / count / 2) + xOff; 45 | ( key ).MoveTo( positionX, positionY ); 46 | if ( value.size > 0 ) { 47 | moveDots( 48 | value, 49 | width / count, 50 | positionY + GraphHeight / layers, 51 | positionX - (width / count / 2 ) 52 | ); 53 | } 54 | } 55 | } 56 | 57 | moveDots( 58 | map, 59 | GraphWidth, 60 | GraphHeight / layers - ( GraphHeight / layers / 2 ), 61 | 0 62 | ); 63 | 64 | return true; 65 | } 66 | 67 | // ──────────────────────────────────────────────────────────────────────── 68 | 69 | } 70 | -------------------------------------------------------------------------------- /core/constants.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── GRAPH VIEW ───────────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Id of main Snap Paper for the Graph */ 14 | export const GraphViewId = 'GraphView'; 15 | 16 | // 17 | // ─── GRAPH ────────────────────────────────────────────────────────────────────── 18 | // 19 | 20 | /** Color of the graph */ 21 | export const GraphColor = '#171717'; 22 | 23 | /** Color of the selected parts of the graph */ 24 | export const GraphSelectColor = '#A200FF'; 25 | 26 | // 27 | // ─── CIRCLE ───────────────────────────────────────────────────────────────────── 28 | // 29 | 30 | /** Radius of the node circles */ 31 | export const CircleRadius = 7; 32 | 33 | /** Radius of the node circles when dragging */ 34 | export const CircleRadiusAtDrag = 6; 35 | 36 | /** Font size of the don't *number* label */ 37 | export const DotNumberLabelFontSize = 10; 38 | 39 | /** X displacement of *number* label */ 40 | export const DotNumberLabelDisplacementX = 3; 41 | 42 | /** Y displacement of *number* label */ 43 | export const DotNumberLabelDisplacementY = 16; 44 | 45 | /** Time of changing the size of node circle from normal to drag mode */ 46 | export const CircleAnimationDurationAtStart = 40; 47 | 48 | /** Time of changing the size of node circle from drag to normal mode */ 49 | export const CircleAnimationDurationAtStop = 100; 50 | 51 | // 52 | // ─── LINE ─────────────────────────────────────────────────────────────────────── 53 | // 54 | 55 | /** Width of the vertices */ 56 | export const LineWidth = 2; 57 | 58 | // 59 | // ─── LOOPARROW ────────────────────────────────────────────────────────────────── 60 | // 61 | 62 | export const LoopArrowDisplacementX = -5; 63 | 64 | export const LoopArrowDisplacementY = -5; 65 | 66 | export const LoopArrowRadius = 10; 67 | 68 | // 69 | // ─── GRAPH USER FOLDER ────────────────────────────────────────────────────────── 70 | // 71 | 72 | export const GraphUserFolderPath = 'graph'; 73 | 74 | export const GraphUserFolderForAlgorithms = 'algorithms'; 75 | 76 | export const GraphUserFolderForLibraries = 'libs'; 77 | 78 | // 79 | // ─── TOOLBAR ──────────────────────────────────────────────────────────────────── 80 | // 81 | 82 | /** Id of the move icon */ 83 | export const ToolbarIconMove = 'icon-move'; 84 | 85 | /** Id of the remove icon */ 86 | export const ToolbarIconRemove = 'icon-remove'; 87 | 88 | /** Id of the edit icon */ 89 | export const ToolbarIconEdit = 'icon-edit'; 90 | 91 | /** Id of the select icon */ 92 | export const ToolbarIconSelect = 'icon-select'; 93 | 94 | /** 95 | * Applying this class to an icon will make the icon will make the 96 | * icon look big to indicate it's active state. Use the function: 97 | * `KaryGraph.UI.Toolbar.ChangeIconToActiveMode( iconId: string )` 98 | * for making the icon you want active 99 | */ 100 | export const ToolbarActiveIconClass = 'icon-active'; 101 | 102 | // 103 | // ─── SELECTIONBOX ─────────────────────────────────────────────────────────────── 104 | // 105 | 106 | /** Background color of the select box */ 107 | export const SelectBoxColor = "#E2AEFF"; 108 | 109 | /** Opacity of the *SelectBox* so that the select nodes can be seen */ 110 | export const SelectBoxOpacity = 0.5; 111 | 112 | // 113 | // ─── CONSOLE ──────────────────────────────────────────────────────────────────── 114 | // 115 | 116 | /** Id of the main div containing the console. */ 117 | export const ConsoleId = "console"; 118 | 119 | // 120 | // ─── PROGRAMMER ───────────────────────────────────────────────────────────────── 121 | // 122 | 123 | /** Id of the main div containing the notebook. */ 124 | export const NotebookId = "ProgrammerNotebook"; 125 | 126 | export const NotebookPromptClass = "notebook-prompt"; 127 | 128 | export const NotebookPromptInputClass = "notebook-prompt-input"; 129 | 130 | export const NotebookError = "notebook-error"; 131 | 132 | export const NotebookResultRowClass = 'notebook-row'; 133 | 134 | export const NotebookResultCodeClass = 'notebook-row-code'; 135 | 136 | export const NotebookResultSayBaseCase = 'notebook-row-say-base'; 137 | 138 | export const NotebookSayBoxClass = 'notebook-say-row'; 139 | 140 | // 141 | // ─── SAY IMPLEMENTATIONS ──────────────────────────────────────────────────────── 142 | // 143 | 144 | export const SayStringClass = 'say-string'; 145 | 146 | // 147 | // ─── TABS ─────────────────────────────────────────────────────────────────────── 148 | // 149 | 150 | export const TabsContainer = 'header-tabs'; 151 | 152 | export const EditorTabContainerClass = 'editor-tab'; 153 | 154 | // 155 | // ─── TAB VIEWS ────────────────────────────────────────────────────────────────── 156 | // 157 | 158 | export const ProgrammerTabId = 'ProgrammerView'; 159 | 160 | export const EditorTabId = 'EditorView'; 161 | 162 | export const AlgorithmsTabId = 'AlgorithmsView'; 163 | 164 | // 165 | // ─── MONACO ───────────────────────────────────────────────────────────────────── 166 | // 167 | 168 | export const MonacoPlaceholderDiv = 'monaco-placeholder'; 169 | 170 | // 171 | // ─── RIBBONS ──────────────────────────────────────────────────────────────────── 172 | // 173 | 174 | export const EditorRibbonIconsId = 'ribbon-editor'; 175 | 176 | export const ProgrammerRibbonIconsId = 'ribbon-programmer'; 177 | 178 | // 179 | // ─── ALGORITHMS ───────────────────────────────────────────────────────────────── 180 | // 181 | 182 | export const AlgorithmsPackageName = 'graph.json'; 183 | 184 | export const AlgorithmsControlContainerId = 'controllers-container'; 185 | 186 | export const AlgorithmsControllerClass = 'algorithm-controller'; 187 | 188 | export const AlgorithmsControllerTitleClass = 'algorithm-controller-title'; 189 | 190 | export const AlgorithmsControllerAuthorClass = 'algorithm-controller-author'; 191 | 192 | export const AlgorithmsControllerDescriptionClass = 'algorithm-controller-description'; 193 | 194 | export const AlgorithmsControllerRunButtonClass = 'algorithm-controller-run-button'; 195 | 196 | // ──────────────────────────────────────────────────────────────────────────────── 197 | 198 | } -------------------------------------------------------------------------------- /core/editor/graph.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── GENERATE RANDOM NODES ────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Generates some random nodes on the screen */ 14 | export function GenerateSomeRandomNodes ( howManyNodes: number ) { 15 | // defs 16 | const baseUnit = 120; 17 | const widthUnit = Math.floor( GraphWidth / baseUnit ); 18 | const heightUnit = Math.floor( GraphHeight / baseUnit ); 19 | const paddingLeftRight = 1; 20 | const paddingTopBottom = 1; 21 | 22 | // places map 23 | var map: Array = CreatePlacesArray( widthUnit, heightUnit ); 24 | 25 | // funcs 26 | function isPlaceNotTakenAt ( x: number, y: number ) { 27 | return ( map[ ( widthUnit * y ) + x ] == 0 ); 28 | } 29 | 30 | function takeMapAt ( x: number, y: number ) { 31 | map[ ( widthUnit * y ) + x ] = 1; 32 | } 33 | 34 | function ComputeRealXCoordinate ( unit: number ) { 35 | return ( GraphWidth / ( widthUnit + 3 * paddingLeftRight ) ) * ( unit + 2 * paddingLeftRight ); 36 | } 37 | 38 | function ComputeRealYCoordinate ( unit: number ) { 39 | return ( GraphHeight / ( heightUnit + 2 * paddingTopBottom ) ) * ( unit + paddingTopBottom ); 40 | } 41 | 42 | // body 43 | var counter = 0; 44 | while ( counter < howManyNodes ) { 45 | var x: number = Random( widthUnit ); 46 | var y: number = Random( heightUnit ); 47 | if ( isPlaceNotTakenAt( x, y ) ) { 48 | new Dot( 49 | ComputeRealXCoordinate( x ), 50 | ComputeRealYCoordinate( y ) 51 | ); 52 | takeMapAt( x , y ); 53 | counter++; 54 | } 55 | } 56 | } 57 | 58 | // 59 | // ─── RANDOM NUMBER GENERATOR ──────────────────────────────────────────────────── 60 | // 61 | 62 | /** Gets a random number in range of ***0..input*** */ 63 | export function Random ( input: number ) { 64 | return Math.floor( Math.random( ) * input ); 65 | } 66 | 67 | // 68 | // ─── CONNECT NODES RANDOMLY ───────────────────────────────────────────────────── 69 | // 70 | 71 | /** Connects some of the dots to each other randomly */ 72 | export function AddRandomConnections ( howManyTimes: number ) { 73 | // generate 74 | for ( var index = 0; index < howManyTimes; ) { 75 | var d1 = GetRandomDot( ); 76 | var d2 = GetRandomDot( ); 77 | if ( d1.ConnectTo( d2 ) ) { 78 | index++; 79 | } 80 | } 81 | } 82 | 83 | // 84 | // ─── CREATE PLACES ARRAY ──────────────────────────────────────────────────────── 85 | // 86 | 87 | /** Populates the places array */ 88 | function CreatePlacesArray ( w: number, h: number ): Array { 89 | var result = new Array ( ); 90 | for ( var counter = 0; counter < ( w * h ); counter++ ) { 91 | result.push( 0 ); 92 | } 93 | return result; 94 | } 95 | 96 | // 97 | // ─── GET RANDOM DOT ───────────────────────────────────────────────────────────── 98 | // 99 | 100 | /** Picks up a dot randomly */ 101 | function GetRandomDot ( ) { 102 | var keys = Object.keys( Storage.Nodes ); 103 | return Storage.Nodes[ keys[ Random( keys.length ) ] ]; 104 | } 105 | 106 | // ──────────────────────────────────────────────────────────────────────────────── 107 | 108 | } -------------------------------------------------------------------------------- /core/editor/selection.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | /** 10 | * Selection - Creates a selection box and at the end of the selection 11 | * creates a list of selected nodes 12 | */ 13 | export class SelectionBox { 14 | 15 | // 16 | // ─── DEFS ──────────────────────────────────────────────────────── 17 | // 18 | 19 | /** Keeps the *X coordinates* of start of the selection box. */ 20 | private X: number; 21 | 22 | /** Keeps the *Y coordinates* of end of the selection box .*/ 23 | private Y: number; 24 | 25 | /** Keeps the *width* of the selection box. */ 26 | private Width: number; 27 | 28 | /** Keeps the *height* of the selection box. */ 29 | private Height: number; 30 | 31 | /** The *Snap rect* that represents the selection box on the screen. */ 32 | private Rect: ISnapObject; 33 | 34 | // 35 | // ─── INIT ──────────────────────────────────────────────────────── 36 | // 37 | 38 | /** Starts a SelectionBox at the given coordinates. */ 39 | constructor( startingX: number, startingY: number ) { 40 | this.X = startingX; 41 | this.Y = startingY; 42 | this.Width = 100; 43 | this.Height = 100; 44 | this.InitRect( ); 45 | } 46 | 47 | // 48 | // ─── INIT THE SNAP BOX ─────────────────────────────────────────── 49 | // 50 | 51 | /** Initializes the Snap Rect object associated with the SelectionBox */ 52 | private InitRect( ) { 53 | let rect = GraphView.rect( this.X, this.Y, this.Width, this.Height ); 54 | rect.attr({ 55 | fill: SelectBoxColor, 56 | fillOpacity: SelectBoxOpacity, 57 | }); 58 | this.Rect = rect; 59 | } 60 | 61 | // 62 | // ─── MOVE MOUSE ────────────────────────────────────────────────── 63 | // 64 | 65 | /** At the point of mouse move event this function must be called. */ 66 | public MoveMouse( mouseX: number, mouseY: number ) { 67 | 68 | } 69 | 70 | // ───────────────────────────────────────────────────────────────── 71 | 72 | } 73 | } -------------------------------------------------------------------------------- /core/editor/snapobject.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── ATTRIBUTE ────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | interface ISnapAttributesFunction { 14 | ( attributes: any ); 15 | } 16 | 17 | // 18 | // ─── ANIMATION ────────────────────────────────────────────────────────────────── 19 | // 20 | 21 | interface ISnapAnimateFunction { 22 | ( attributes: any , duration: number ) 23 | } 24 | 25 | // 26 | // ─── DATA ─────────────────────────────────────────────────────────────────────── 27 | // 28 | 29 | interface ISnapDataFunction { 30 | ( string, any? ) 31 | } 32 | 33 | // 34 | // ─── DRAG MOVE ────────────────────────────────────────────────────────────────── 35 | // 36 | 37 | interface ISnapDragMoveFunction { 38 | ( dx: number, dy: number, posx: number, posy: number ) 39 | } 40 | 41 | // 42 | // ─── DRAG ─────────────────────────────────────────────────────────────────────── 43 | // 44 | 45 | interface ISnapDragFunction { 46 | ( move: ISnapDragMoveFunction, start: Function, stop: Function ) 47 | } 48 | 49 | // 50 | // ─── SNAP OBJECT ──────────────────────────────────────────────────────────────── 51 | // 52 | 53 | /** Implements Snap Objects (circle, line,... ) */ 54 | export interface ISnapObject { 55 | /** Changes the attributes of the object */ 56 | attr: ISnapAttributesFunction; 57 | 58 | /** Animates the object */ 59 | animate: ISnapAnimateFunction; 60 | 61 | /** removes the object */ 62 | remove(); 63 | 64 | /** drag implementation */ 65 | drag: ISnapDragFunction; 66 | data: ISnapDataFunction; 67 | id: string; 68 | 69 | } 70 | 71 | // 72 | // ─── SNAP GROUP ───────────────────────────────────────────────────────────────── 73 | // 74 | 75 | interface ISnapAddFunction { 76 | ( ISnapObject ) 77 | } 78 | 79 | export interface ISnapGroup { 80 | add: ISnapAddFunction 81 | } 82 | 83 | // ──────────────────────────────────────────────────────────────────────────────── 84 | 85 | } -------------------------------------------------------------------------------- /core/editor/svg.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── ADD EVENT TO SVG ─────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Adds an ***event*** to the ***element*** */ 14 | export function AddEventOnClick ( element: ISnapObject, event: string ) { 15 | document.getElementById( element.id ).setAttribute( 'onClick', event ); 16 | } 17 | 18 | // ──────────────────────────────────────────────────────────────────────────────── 19 | 20 | } -------------------------------------------------------------------------------- /core/installer.ts: -------------------------------------------------------------------------------- 1 | // 2 | // Copyright 2016 Kary Foundation, Inc. 3 | // Author: Pouya Kary 4 | // 5 | 6 | namespace KaryGraph.Installer { 7 | 8 | // 9 | // ─── INSTALL OUTER DEPENDENCIES ───────────────────────────────────────────────── 10 | // 11 | 12 | /** This module checks the graph folder and it's subdirs to exists, if not 13 | * it'll make them */ 14 | export function ConfigureGraphFolder ( ) { 15 | let base = JoinPath([ GetHomeDir( ), GraphUserFolderPath ]); 16 | CheckAndCreateDir( base ); 17 | CheckAndCreateDir( JoinPath([ base, GraphUserFolderForAlgorithms ])); 18 | CheckAndCreateDir( JoinPath([ base, GraphUserFolderForLibraries ])); 19 | } 20 | 21 | // 22 | // ─── CHECK AND CREATE ─────────────────────────────────────────────────────────── 23 | // 24 | 25 | function CheckAndCreateDir ( address ) { 26 | if ( !FSExistsSync( address ) ) { 27 | MakeDirSync( address ); 28 | } 29 | } 30 | 31 | // ──────────────────────────────────────────────────────────────────────────────── 32 | 33 | } -------------------------------------------------------------------------------- /core/karyfoundation/comment/core.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryFoundation.Comment { 8 | 9 | // 10 | // ─── GLOBALS ──────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export enum Style { Section, Ending }; 14 | 15 | // 16 | // ─── MAIN ─────────────────────────────────────────────────────────────────────── 17 | // 18 | 19 | export function Generate ( style: Style, 20 | languageCharacter: string, 21 | tabSize: number, 22 | insertSpaces: boolean, 23 | text?: string, 24 | flag?: number ): string { 25 | 26 | // here 27 | oneLineCommentSign = languageCharacter; 28 | currentLineString = text; 29 | currentTabSize = tabSize; 30 | currentInsertSpacesStatus = insertSpaces; 31 | 32 | // line processing... 33 | processCurrentLine( ); 34 | 35 | // switcher 36 | switch ( style ) { 37 | case Style.Section: 38 | return generateSectionCommentBasedOnIndentation( ); 39 | 40 | case Style.Ending: 41 | return onGenerateLineComment( ); 42 | 43 | default: return undefined; 44 | } 45 | } 46 | 47 | // 48 | // ─── CONSTANTS ────────────────────────────────────────────────────────────────── 49 | // 50 | 51 | const commentLineCharacter = '\u2500'; 52 | const lineFormat = /^\s*([a-z ]|[0-9][0-9\.]*)+\s*$/i; 53 | 54 | // 55 | // ─── INTERFACES ───────────────────────────────────────────────────────────────── 56 | // 57 | 58 | interface IFirstLineSpacings { 59 | tabs: number; 60 | spaces: number; 61 | } 62 | 63 | // 64 | // ─── DEFS ─────────────────────────────────────────────────────────────────────── 65 | // 66 | 67 | // Environmental information 68 | var oneLineCommentSign: string; 69 | var currentLineString: string; 70 | var currentInsertSpacesStatus: boolean; 71 | var currentTabSize: number; 72 | 73 | // Information for processing... 74 | var linesFirstSpacing: IFirstLineSpacings; 75 | var realIndentationSize: number; 76 | var relativeIndentationSize: number; 77 | 78 | // 79 | // ─── PROCESS CURRENT LINE ─────────────────────────────────────────────────────── 80 | // 81 | 82 | function processCurrentLine ( ) { 83 | linesFirstSpacing = getFirstSpacingOfTheLine( ); 84 | realIndentationSize = getRealIndentationSize( ); 85 | relativeIndentationSize = getKFCSRelativeIndentation( realIndentationSize ); 86 | } 87 | 88 | // 89 | // ─── GET SPACING FOR THE FIRST OF THE LINE ────────────────────────────────────── 90 | // 91 | 92 | function getFirstSpacingOfTheLine ( ) { 93 | let tabs = 0; 94 | let spaces = 0; 95 | let index = 0; 96 | 97 | while ( index < currentLineString.length ) { 98 | switch ( currentLineString[ index ] ) { 99 | case '\t': 100 | tabs++; 101 | index++; 102 | break; 103 | 104 | case ' ': 105 | spaces++; 106 | index++; 107 | break; 108 | 109 | default: 110 | return { 'tabs': tabs, 'spaces': spaces }; 111 | } 112 | } 113 | return { 'tabs': tabs, 'spaces': spaces }; 114 | } 115 | 116 | // 117 | // ─── GET INDENTATION SIZE ─────────────────────────────────────────────────────── 118 | // 119 | 120 | function getRealIndentationSize ( ) { 121 | return linesFirstSpacing.tabs + Math.floor( linesFirstSpacing.spaces / currentTabSize ); 122 | } 123 | 124 | // 125 | // ─── GET RELATIVE INDENTATION SIZE ────────────────────────────────────────────── 126 | // 127 | 128 | function getKFCSRelativeIndentation ( realIndentation ) { 129 | return Math.floor( realIndentation / 2 ); 130 | } 131 | 132 | // 133 | // ─── INDENT BASED ON THE INDENTATION INFO ─────────────────────────────────────── 134 | // 135 | 136 | function generateIndentation ( ) { 137 | return repeat( ' ' , linesFirstSpacing.spaces ) + computeTabs( linesFirstSpacing.tabs ); 138 | } 139 | 140 | // 141 | // ─── REPEAT TEXT ──────────────────────────────────────────────────────────────── 142 | // 143 | 144 | function repeat ( text, times ) { 145 | let result = ''; 146 | for ( let index = 0; index < times; index ++ ) { 147 | result += text; 148 | } 149 | return result; 150 | } 151 | 152 | // 153 | // ─── GET TAB ──────────────────────────────────────────────────────────────────── 154 | // 155 | 156 | function computeTabs ( tabs ) { 157 | if ( currentInsertSpacesStatus ) { 158 | return repeat( ' ' , currentTabSize * tabs ); 159 | } else { 160 | return repeat( '\t' , tabs ); 161 | } 162 | } 163 | 164 | // 165 | // ─── GENERATE ADDITIONAL SPACINGS ─────────────────────────────────────────────── 166 | // 167 | 168 | function generateAdditionalSpacingsForComments ( ) { 169 | let spacings = `\n${ generateIndentation( ) }`; 170 | if ( relativeIndentationSize < 2 ) { 171 | spacings += computeTabs( 1 ); 172 | } 173 | return spacings; 174 | } 175 | 176 | // ──────────────────────────────────────────────────────────────────────────────── 177 | 178 | 179 | 180 | // 181 | // ────────────────────────────────────────────────────────────────────────── II ────────── 182 | // :::::: S E L E C T I O N C O M M E N T : : : : : : : : 183 | // ──────────────────────────────────────────────────────────────────────────────────── 184 | // 185 | 186 | // 187 | // ─── GENERATE COMMENT ─────────────────────────────────────────────────────────── 188 | // 189 | 190 | function generateSectionComment ( width ) { 191 | const text = currentLineString.toUpperCase( ).trim( ); 192 | const indentationText = generateIndentation( ); 193 | 194 | // line 1 195 | let result = `${ indentationText }${ oneLineCommentSign }\n`; 196 | 197 | // line 2 198 | result += `${ indentationText }${ oneLineCommentSign } ${ repeat( commentLineCharacter , 3 )} ${ text } ${ repeat( commentLineCharacter, width - text.length - 5 ) }\n`; 199 | 200 | // line 3 201 | result += `${ indentationText }${ oneLineCommentSign }\n` 202 | 203 | // done 204 | return result; 205 | } 206 | 207 | // 208 | // ─── GENERATE INSECTION COMMENTS ──────────────────────────────────────────────── 209 | // 210 | 211 | function generateInSectionComments ( ) { 212 | const text = currentLineString.toUpperCase( ).trim( ); 213 | const indentationText = generateIndentation( ); 214 | 215 | // line 1 216 | let result = `${ indentationText }${ oneLineCommentSign }\n`; 217 | 218 | // line 2 219 | result += `${ indentationText }${ oneLineCommentSign } ${ text }\n`; 220 | 221 | // line 3 222 | result += `${ indentationText }${ oneLineCommentSign }\n` 223 | 224 | // done 225 | return result; 226 | } 227 | 228 | 229 | // 230 | // ─── GENERATE COMMENT BASED ON INDENTATION ────────────────────────────────────── 231 | // 232 | 233 | function generateSectionCommentBasedOnIndentation ( ): string { 234 | 235 | let comment; 236 | 237 | switch ( relativeIndentationSize ) { 238 | case 0: 239 | comment = generateSectionComment( 80 ); 240 | break; 241 | case 1: 242 | comment = generateSectionComment( 65 ); 243 | break; 244 | default: 245 | comment = generateInSectionComments( ); 246 | break; 247 | } 248 | 249 | return comment + generateAdditionalSpacingsForComments( ); 250 | } 251 | 252 | // ──────────────────────────────────────────────────────────────────────────────── 253 | 254 | 255 | 256 | 257 | // 258 | // ──────────────────────────────────────────────────────────────── III ────────── 259 | // :::::: L I N E C O M M E N T : : : : : : : : 260 | // ────────────────────────────────────────────────────────────────────────── 261 | // 262 | 263 | // 264 | // ─── GENERATE LINE COMMENT ────────────────────────────────────────────────────── 265 | // 266 | 267 | function generateLineComment ( width ) { 268 | return `${ generateIndentation( ) }${ oneLineCommentSign } ${ repeat( commentLineCharacter, width - 1) }\n`; 269 | } 270 | 271 | // 272 | // ─── GENERATE SEPARATOR COMMENTS ──────────────────────────────────────────────── 273 | // 274 | 275 | function generateSeparatorComments ( ) { 276 | return `${ generateIndentation( ) }${ oneLineCommentSign } • • • • •`; 277 | } 278 | 279 | // 280 | // ─── ON GENERATE LINE ─────────────────────────────────────────────────────────── 281 | // 282 | 283 | function onGenerateLineComment ( ): string { 284 | switch ( relativeIndentationSize ) { 285 | case 0: 286 | return generateLineComment( 80 ); 287 | case 1: 288 | return generateLineComment( 65 ); 289 | default: 290 | return generateSeparatorComments( ); 291 | } 292 | } 293 | 294 | // ──────────────────────────────────────────────────────────────────────────────── 295 | 296 | } -------------------------------------------------------------------------------- /core/karyfoundation/monaco/kf-comment-monaco.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryFoundation.Monaco { 8 | 9 | // 10 | // ─── MAIN ─────────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export function AddSupportingMonacoTools ( editor: monaco.editor.IStandaloneCodeEditor ) { 14 | AddSectionCommentCommand( editor ); 15 | AddLineCommentCommand( editor ); 16 | } 17 | 18 | 19 | // 20 | // ─── CONSTANTS ────────────────────────────────────────────────────────────────── 21 | // 22 | 23 | const lineFormat = /^\s*([a-z ]|[0-9][0-9\.]*)+\s*$/i; 24 | 25 | // 26 | // ─── ADD KARY SECTION COMMENT COMMAND ─────────────────────────────────────────── 27 | // 28 | 29 | function AddSectionCommentCommand ( editor: monaco.editor.IStandaloneCodeEditor ) { 30 | editor.addAction({ 31 | id: 'kary-comment-insert-section-comment', 32 | label: 'Insert Section Comment', 33 | keybindings: [ monaco.KeyMod.Alt | monaco.KeyCode.KEY_Y ], 34 | keybindingContext: null, 35 | enablement: { 36 | textFocus: true 37 | }, 38 | 39 | run: function ( ed ) { 40 | ExecuteAddComment( ed, Comment.Style.Section ); 41 | return null; 42 | } 43 | }); 44 | } 45 | 46 | // 47 | // ─── ADD KARY LINE COMMENT COMMAND ────────────────────────────────────────────── 48 | // 49 | 50 | function AddLineCommentCommand ( editor: monaco.editor.IStandaloneCodeEditor ) { 51 | editor.addAction({ 52 | id: 'kary-comment-insert-line-comment', 53 | label: 'Insert Line Comment', 54 | keybindings: [ monaco.KeyMod.Alt | monaco.KeyCode.KEY_L ], 55 | keybindingContext: null, 56 | enablement: { 57 | textFocus: true 58 | }, 59 | 60 | run: function ( ed ) { 61 | ExecuteAddComment( ed, Comment.Style.Ending ); 62 | return null; 63 | } 64 | }); 65 | } 66 | 67 | // 68 | // ─── ADD COMMENT TO MONACO ────────────────────────────────────────────────────── 69 | // 70 | 71 | export function ExecuteAddComment ( editor: monaco.editor.ICommonCodeEditor, 72 | style: Comment.Style ) { 73 | 74 | if ( Comment.Style.Section === style ) { 75 | makeCommentWithFormula( editor, line => { 76 | return Comment.Generate( 77 | Comment.Style.Section, 78 | '//', 4, true, line 79 | ) 80 | }); 81 | } else { 82 | makeCommentWithFormula( editor, line => { 83 | return Comment.Generate( 84 | Comment.Style.Ending, 85 | '//', 4, true, line 86 | ) 87 | }); 88 | } 89 | } 90 | 91 | // 92 | // ─── MAKE COMMENT WITH FORMULA ────────────────────────────────────────────────── 93 | // 94 | 95 | function makeCommentWithFormula ( ed: monaco.editor.ICommonCodeEditor, 96 | formula: ( line: string ) => string ) { 97 | 98 | // env info 99 | let position = ed.getPosition( ); 100 | let line = getLine( ed.getValue( ), position.lineNumber ); 101 | 102 | // running generator 103 | let comment = formula( line ); 104 | 105 | // performing the replace 106 | replaceComment( ed, comment, line.length + 1, position.lineNumber ); 107 | cancelSelection( ed ); 108 | } 109 | 110 | // 111 | // ─── REPLACE COMMENT ──────────────────────────────────────────────────────────── 112 | // 113 | 114 | function replaceComment ( ed: monaco.editor.ICommonCodeEditor, 115 | comment: string, 116 | lineLength: number, 117 | lineNumber: number ) { 118 | 119 | ed.executeEdits( "org.karyfoundation.comment-monaco", [{ 120 | identifier: { 121 | major: 0, 122 | minor: 0 123 | }, 124 | 125 | range: new monaco.Range( 126 | lineNumber, 0, 127 | lineNumber, lineLength 128 | ), 129 | 130 | text: comment, 131 | forceMoveMarkers: false 132 | }]); 133 | 134 | } 135 | 136 | // 137 | // ─── CANCEL SELECTION ─────────────────────────────────────────────────────────── 138 | // 139 | 140 | function cancelSelection ( ed: monaco.editor.ICommonCodeEditor ) { 141 | let endingPosition = ed.getPosition( ); 142 | ed.setSelection({ 143 | startLineNumber: endingPosition.lineNumber, 144 | startColumn: endingPosition.column, 145 | endLineNumber: endingPosition.lineNumber, 146 | endColumn: endingPosition.column, 147 | }); 148 | } 149 | 150 | // 151 | // ─── GET LINE ─────────────────────────────────────────────────────────────────── 152 | // 153 | 154 | function getLine ( text: string, line: number ): string { 155 | return text.split('\n')[ line - 1 ]; 156 | } 157 | 158 | // ──────────────────────────────────────────────────────────────────────────────── 159 | 160 | } 161 | -------------------------------------------------------------------------------- /core/language-tools.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.LanguageTools { 8 | 9 | // 10 | // ─── ARRAY EXISTS ─────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export function ArrayExists ( array: any[ ], element: any ): boolean { 14 | array.forEach( item => { 15 | if ( item === element ) { 16 | return true; 17 | } 18 | }); 19 | return false; 20 | } 21 | 22 | // ──────────────────────────────────────────────────────────────────────────────── 23 | 24 | } -------------------------------------------------------------------------------- /core/main.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /** 8 | * **Kary Graph** - A full featured Graph Theory Studio 9 | */ 10 | namespace KaryGraph { 11 | 12 | // 13 | // ─── INIT ─────────────────────────────────────────────────────────────────────── 14 | // 15 | 16 | /** 17 | * "T H E W H O L E W O R L D **_S T A R T S_** F R O M H E R E" 18 | */ 19 | export function INIT ( ) { 20 | InitScreenInformation( ); 21 | UI.Programmer.INIT( ); 22 | UI.LoadImagesAtStart( ); 23 | ScriptEngine.Algorithms.LoadAlgorithms( ); 24 | Installer.ConfigureGraphFolder( ); 25 | RenderStartingGraph( ); 26 | } 27 | 28 | // 29 | // ─── INIT GRAPH SCRIPT ────────────────────────────────────────────────────────── 30 | // 31 | 32 | /** 33 | * A simple script that happens at start of the software so that 34 | * user has something to see... 35 | */ 36 | function RenderStartingGraph ( ) { 37 | // Just remember this is the only place that using API 38 | // inside namespace "KaryGraph" is acceptable... 39 | API.KaryFoundation.CreateKaryHorseGraph( ); 40 | } 41 | 42 | // ──────────────────────────────────────────────────────────────────────────────── 43 | 44 | } 45 | 46 | -------------------------------------------------------------------------------- /core/objects/dot/circle.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.Circle { 8 | 9 | // 10 | // ─── GENERATOR ────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Generates a standard circle object */ 14 | export function Create ( x: number, y: number ): ISnapObject { 15 | 16 | // the circle 17 | var circle = GraphView.circle( x, y, CircleRadius ); 18 | 19 | // adding the drag functions 20 | circle.drag( CircleDragOnMove, CircleDragOnStart, CircleDragOnStop ); 21 | 22 | // applying style 23 | circle.attr({ 24 | fill: GraphColor 25 | }); 26 | 27 | // done 28 | return circle; 29 | } 30 | 31 | // 32 | // ─── GET ARRAY INDEX ──────────────────────────────────────────────────────────── 33 | // 34 | 35 | function GetArrayIndexBasedOnModes( ): number { 36 | switch ( UI.Toolbar.ToolbarMode ) { 37 | case UI.Toolbar.ToolbarModeEnum.Move: 38 | return 0; 39 | case UI.Toolbar.ToolbarModeEnum.Remove: 40 | return 1; 41 | case UI.Toolbar.ToolbarModeEnum.Edit: 42 | return 2; 43 | case UI.Toolbar.ToolbarModeEnum.Select: 44 | return 3; 45 | } 46 | } 47 | 48 | // 49 | // ─── EVENT HANDLERS ───────────────────────────────────────────────────────────── 50 | // 51 | 52 | // 53 | // ─── ON MOVE ───────────────────────────────────────────────────── 54 | // 55 | 56 | var CircleDragOnMove = function ( dx: number, 57 | dy: number, 58 | posx: number, 59 | posy: number ) { 60 | 61 | var func = DragMoveFunctions[ GetArrayIndexBasedOnModes( ) ]; 62 | func( ( this ) , dx, dy, posx, posy ); 63 | } 64 | 65 | // 66 | // ─── ON START ──────────────────────────────────────────────────── 67 | // 68 | 69 | var CircleDragOnStart = function ( ) { 70 | var func = DragStartFunctions[ GetArrayIndexBasedOnModes( ) ]; 71 | func( ( this ) ); 72 | } 73 | 74 | // 75 | // ─── ON STOP ───────────────────────────────────────────────────── 76 | // 77 | 78 | var CircleDragOnStop = function ( ) { 79 | var func = DragStopFunctions[ GetArrayIndexBasedOnModes( ) ]; 80 | func( ( this ) ); 81 | } 82 | 83 | // ───────────────────────────────────────────────────────────────── 84 | 85 | // 86 | // ─── FOR EACH CYCLE DO ────────────────────────────────────────────────────────── 87 | // 88 | 89 | export function ForeachCircle( func: ( circle: ISnapObject ) => void ) { 90 | var keys = Object.keys( Storage.Nodes ); 91 | keys.forEach( dotId => { 92 | func( ( Storage.Nodes[ dotId ] ).SnapCircle ); 93 | }); 94 | } 95 | 96 | // 97 | // ─── RESET ALL THE COLORS ─────────────────────────────────────────────────────── 98 | // 99 | 100 | export function ResetCircleColors( ) { 101 | ForeachCircle( circle => { 102 | circle.attr({ 103 | fill: GraphColor 104 | }); 105 | }); 106 | } 107 | 108 | // ──────────────────────────────────────────────────────────────────────────────── 109 | 110 | } -------------------------------------------------------------------------------- /core/objects/dot/dot.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DOT OBJECT ───────────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Dot object contains information on the nodes of the graph */ 14 | export class Dot { 15 | 16 | // 17 | // ─── GLOBALS ───────────────────────────────────────────────────── 18 | // 19 | 20 | /** For counting how many nodes are created. */ 21 | static TotalDots : number = 0; 22 | 23 | static DisplayNumberLabels : boolean = true; 24 | 25 | // 26 | // ─── DEFS ──────────────────────────────────────────────────────── 27 | // 28 | 29 | /** To be used as the hash key in dictionaries */ 30 | public Id: string; 31 | 32 | /** For displaying the object */ 33 | public SnapCircle: ISnapObject; 34 | 35 | /** Snap Label */ 36 | public SnapNumberLabel: ISnapObject; 37 | 38 | /** 39 | * Keeps the Inputs of the dot 40 | * Inputs = { 41 | * **Connected Dot Id** : ***Snap Line Object*** 42 | * } 43 | */ 44 | private Inputs: Array; 45 | 46 | /** 47 | * Keeps the Outputs of the dot 48 | * Inputs = { 49 | * **Connected Dot Id** : ***Snap Line Object*** 50 | * } 51 | */ 52 | private Outputs: Array; 53 | 54 | /** 55 | * X Coordinates of the dot 56 | * ***Changing won't make effect, use MoveTo instead*** 57 | */ 58 | public Position: Point; 59 | 60 | /** Unique number id of the dot */ 61 | private NumberId: number; 62 | 63 | /** Optional label of the dot */ 64 | private Label: string; 65 | 66 | // 67 | // ─── CONSTRUCTOR ───────────────────────────────────────────────── 68 | // 69 | 70 | constructor ( x: number, y: number ) { 71 | 72 | // basic allocation 73 | this.Position = new Point( x, y ); 74 | this.Label = ''; 75 | 76 | // generating the circle 77 | this.SnapCircle = Circle.Create( x, y ); 78 | 79 | // Initializing the ID 80 | this.Id = this.SnapCircle.id; 81 | 82 | // number id 83 | this.NumberId = ++Dot.TotalDots; 84 | 85 | // the snap svg 86 | if ( Dot.DisplayNumberLabels ) { 87 | this.SnapNumberLabel = this.CreateNumberLabel( ); 88 | } 89 | 90 | // inputs and outputs 91 | this.Inputs = new Array ( ); 92 | this.Outputs = new Array ( ); 93 | 94 | // Adding self to the Graph 95 | Storage.Nodes[ this.Id ] = this; 96 | } 97 | 98 | // 99 | // ─── GET NUMBER ID ─────────────────────────────────────────────── 100 | // 101 | 102 | public GetNumberId ( ): number { 103 | return this.NumberId; 104 | } 105 | 106 | // 107 | // ─── RESET TOTAL DOTS ──────────────────────────────────────────── 108 | // 109 | 110 | public static ResetNumberIdPlace ( ) { 111 | Dot.TotalDots = 0; 112 | } 113 | 114 | // 115 | // ─── REMOVER ───────────────────────────────────────────────────── 116 | // 117 | 118 | /** 119 | * Removes the class. Remove the connections 120 | * and Snap objects and the other parts 121 | */ 122 | public Remove ( ) { 123 | 124 | // remove the circle 125 | this.SnapCircle.remove( ); 126 | 127 | // remove the label 128 | if ( this.SnapNumberLabel != null ) 129 | this.SnapNumberLabel.remove( ); 130 | 131 | // remove the connections 132 | this.RemoveInputConnection( ); 133 | this.RemoveOutputConnection( ); 134 | 135 | // removing self 136 | delete Storage.Nodes[ this.Id ]; 137 | } 138 | 139 | // 140 | // ─── REMOVE CONNECTION FROM INPUT ──────────────────────────────── 141 | // 142 | 143 | /** Removes a input connection and lines of the dot */ 144 | public RemoveInputConnection ( ) { 145 | this.Inputs.forEach( dotKey => { 146 | this.DisconnectInput( dotKey ); 147 | }); 148 | } 149 | 150 | // 151 | // ─── REMOVE OUTPUT CONNECTION ──────────────────────────────────── 152 | // 153 | 154 | /** Removes a output connection and lines of the dot */ 155 | public RemoveOutputConnection ( ) { 156 | this.Outputs.forEach( dotKey => { 157 | this.DisconnectOutput( dotKey ); 158 | }); 159 | } 160 | 161 | // 162 | // ─── DISCONNECT FROM ───────────────────────────────────────────── 163 | // 164 | 165 | /** Disconnect dot from Dot */ 166 | public DisconnectFrom ( dot: Dot ): boolean { 167 | var res = false; 168 | if ( LanguageTools.ArrayExists( this.Inputs, dot.Id ) ) { 169 | this.DisconnectInput( dot.Id ); 170 | res = true; 171 | } else if ( LanguageTools.ArrayExists( this.Outputs, dot.Id ) ) { 172 | this.DisconnectOutput( dot.Id ); 173 | res = true; 174 | } 175 | return res; 176 | } 177 | 178 | // 179 | // ─── DISCONNECT INPUT ──────────────────────────────────────────── 180 | // 181 | 182 | /** Disconnects input dot */ 183 | private DisconnectInput ( dotID: string ) { 184 | if ( ( Storage.Connections[ dotID + this.Id ] ) != undefined ) { 185 | ( Storage.Connections[ dotID + this.Id ] ).Remove( ); 186 | } 187 | 188 | if ( Storage.Nodes[ dotID ] != undefined 189 | && Storage.Nodes[ dotID ].Outputs[ this.Id ] != undefined ) { 190 | delete Storage.Nodes[ dotID ].Outputs[ this.Id ]; 191 | } 192 | 193 | if ( this.Inputs[ dotID ] != undefined ) { 194 | delete this.Inputs[ dotID ]; 195 | } 196 | } 197 | 198 | // 199 | // ─── DISCONNECT OUTPUT ─────────────────────────────────────────── 200 | // 201 | 202 | /** Disconnects output dot */ 203 | private DisconnectOutput ( dotID: string ) { 204 | if ( ( Storage.Connections[ this.Id + dotID ] ) != undefined ) { 205 | ( Storage.Connections[ this.Id + dotID ] ).Remove( ); 206 | } 207 | 208 | if ( Storage.Nodes[ dotID ] != undefined 209 | && Storage.Nodes[ dotID ].Inputs[ this.Id ] != undefined ) { 210 | delete Storage.Nodes[ dotID ].Inputs[ this.Id ]; 211 | } 212 | 213 | if ( this.Outputs[ dotID ] != undefined ) { 214 | delete this.Outputs[ dotID ]; 215 | } 216 | } 217 | 218 | // 219 | // ─── CONNECT TO ────────────────────────────────────────────────── 220 | // 221 | 222 | /** Connects a ***Dot*** object */ 223 | public ConnectTo ( dotToBeConnected: Dot ) { 224 | let vertex = new Vertex( this, dotToBeConnected ); 225 | this.Outputs.push( dotToBeConnected.Id ); 226 | dotToBeConnected.Inputs.push( this.Id ); 227 | } 228 | 229 | // 230 | // ─── CHECK IF CONNECTED TO ─────────────────────────────────────── 231 | // 232 | 233 | public IsConnectedTo ( dot: Dot ): boolean { 234 | if ( this.Outputs[ dot.Id ] != undefined ) { 235 | return true; 236 | } else if ( this.Inputs[ dot.Id ] != undefined ) { 237 | return true; 238 | } 239 | return false; 240 | } 241 | 242 | // 243 | // ─── NUMBER OF INPUTS ──────────────────────────────────────────── 244 | // 245 | 246 | public NumberOfInputs ( ): number { 247 | return Object.keys( this.Inputs ).length; 248 | } 249 | 250 | // 251 | // ─── NUMBER OF OUTPUTS ─────────────────────────────────────────── 252 | // 253 | 254 | public NumberOfOutputs ( ): number { 255 | return Object.keys( this.Outputs ).length; 256 | } 257 | 258 | // 259 | // ─── GET ALL CHILDREN ──────────────────────────────────────────── 260 | // 261 | 262 | public GetChildren ( ids?: number[ ] ): any { 263 | if ( !ids ) var ids: number[ ] = [ ]; 264 | var map = new Map(); 265 | var keys = Object.keys( Storage.Nodes ); 266 | 267 | keys.forEach( key => { 268 | var dot = Storage.Nodes[ key ]; 269 | if ( this.Outputs[ dot.Id ] != undefined ) { 270 | if ( ids.indexOf( dot.GetNumberId( ) ) != -1 ) { 271 | return -1 272 | } 273 | 274 | ids.push( dot.GetNumberId( ) ); 275 | var children = dot.GetChildren( ids ); 276 | 277 | if ( children == -1 ) { 278 | return -1 279 | } 280 | 281 | map.set( dot, children ); 282 | } 283 | }); 284 | return map; 285 | } 286 | 287 | // 288 | // ─── DEGREE OF VERTEX ──────────────────────────────────────────── 289 | // 290 | 291 | public GetDegree ( ): number { 292 | return this.NumberOfInputs() + this.NumberOfOutputs(); 293 | } 294 | 295 | // 296 | // ─── GET NEIGHBORS ─────────────────────────────────────────────── 297 | // 298 | 299 | public GetNeighbors ( ): KaryGraph.Dot[ ] { 300 | var neighbors: KaryGraph.Dot[ ] = [ ]; 301 | 302 | this.Inputs.forEach( input => { 303 | neighbors.push(Storage.Nodes[input]); 304 | }); 305 | 306 | this.Outputs.forEach( output => { 307 | neighbors.push(Storage.Nodes[output]); 308 | }); 309 | 310 | return neighbors; 311 | } 312 | 313 | // 314 | // ─── MOVE TO ───────────────────────────────────────────────────── 315 | // 316 | 317 | /** 318 | * Moves the coordinations of the object. 319 | */ 320 | public MoveTo ( x: number, y: number ) { 321 | this.Position.X = x; 322 | this.Position.Y = y; 323 | this.SnapCircle.attr({ 324 | cx: x, cy: y 325 | }); 326 | this.MoveNumberLabel(); 327 | this.ApplyTransformationToOutputs( ); 328 | this.ApplyTransformationToInputs( ); 329 | } 330 | 331 | // 332 | // ─── APPLY TRANSFORMATION ON OUTPUTS ───────────────────────────── 333 | // 334 | 335 | /** Transforms the output connections when the dot is moved. */ 336 | private ApplyTransformationToOutputs ( ) { 337 | this.Outputs.forEach( outputID => { 338 | ( Storage.Connections[ this.Id + outputID ]).MoveStart( this.Position ); 339 | }); 340 | } 341 | 342 | // 343 | // ─── APPLY TRANSFORMATION ON INPUTS ────────────────────────────── 344 | // 345 | 346 | /** Transforms the input connections when the dot is moved. */ 347 | private ApplyTransformationToInputs ( ) { 348 | this.Inputs.forEach( inputID => { 349 | ( Storage.Connections[ inputID + this.Id ]).MoveEnd( this.Position ); 350 | }); 351 | } 352 | 353 | // 354 | // ─── INIT LABEL ────────────────────────────────────────────────── 355 | // 356 | 357 | /** Creates a Snap Label object to present the graph node number */ 358 | private CreateNumberLabel ( ) : ISnapObject { 359 | var label = GraphView.text( 360 | this.Position.X - DotNumberLabelDisplacementX, 361 | this.Position.Y - DotNumberLabelDisplacementY, 362 | this.NumberId.toString( ) 363 | ); 364 | 365 | label.attr({ 366 | 'font-size': DotNumberLabelFontSize, 367 | 'fill': GraphColor 368 | }); 369 | 370 | return label; 371 | } 372 | 373 | // 374 | // ─── MOVE NUMBER LABEL ─────────────────────────────────────────── 375 | // 376 | 377 | /** Moves the Number Label when the dot is moved */ 378 | private MoveNumberLabel ( ) { 379 | if ( Dot.DisplayNumberLabels ) { 380 | this.SnapNumberLabel.attr({ 381 | x: this.Position.X - DotNumberLabelDisplacementX, 382 | y: this.Position.Y - DotNumberLabelDisplacementY 383 | }); 384 | } 385 | } 386 | 387 | // ───────────────────────────────────────────────────────────────── 388 | 389 | } 390 | 391 | // ──────────────────────────────────────────────────────────────────────────────── 392 | 393 | } 394 | -------------------------------------------------------------------------------- /core/objects/dot/drag-move.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DRAG MOVE FUNCTION LIST ──────────────────────────────────────────────────── 11 | // 12 | 13 | export const DragMoveFunctions = [ 14 | DragModeFunctionMoveMode, 15 | DragModeFunctionRemoveMode, 16 | DragModeFunctionEditMode, 17 | DragModeFunctionSelectMode 18 | ]; 19 | 20 | // 21 | // ─── DRAG MOVE - MOVE MODE ────────────────────────────────────────────────────── 22 | // 23 | 24 | export function DragModeFunctionMoveMode( circle: ISnapObject, dx: number, 25 | dy: number, posx: number, posy: number ) { 26 | posy -= GraphMarginTop; 27 | ( Storage.Nodes[ circle.id ] ).MoveTo( posx , posy ); 28 | 29 | ScriptEngine.EventHandler.RunEvents( 'OnMove', circle.id ); 30 | } 31 | 32 | // 33 | // ─── DRAG MOVE - REMOVE MODE ──────────────────────────────────────────────────── 34 | // 35 | 36 | export function DragModeFunctionRemoveMode( circle: ISnapObject, dx: number, 37 | dy: number, posx: number, posy: number ) { 38 | 39 | ScriptEngine.EventHandler.RunEvents( 'OnRemove', circle.id ); 40 | } 41 | 42 | // 43 | // ─── DRAG MOVE - EDIT MOVE ────────────────────────────────────────────────────── 44 | // 45 | 46 | export function DragModeFunctionEditMode( circle: ISnapObject, dx: number, 47 | dy: number, posx: number, posy: number ) { 48 | 49 | ScriptEngine.EventHandler.RunEvents( 'OnMove', circle.id ); 50 | } 51 | 52 | // 53 | // ─── DRAG MOVE - SELECT MOVE ──────────────────────────────────────────────────── 54 | // 55 | 56 | export function DragModeFunctionSelectMode( circle: ISnapObject, dx: number, 57 | dy: number, posx: number, posy: number ) { 58 | 59 | ScriptEngine.EventHandler.RunEvents( 'OnSelect', circle.id ); 60 | } 61 | 62 | // ──────────────────────────────────────────────────────────────────────────────── 63 | 64 | } -------------------------------------------------------------------------------- /core/objects/dot/drag-start.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DRAG START FUNCTION LIST ─────────────────────────────────────────────────── 11 | // 12 | 13 | export const DragStartFunctions = [ 14 | DragStartFunctionMoveMode, 15 | DragStartFunctionRemoveMode, 16 | DragStartFunctionEditMode, 17 | DragStartFunctionSelectMode 18 | ]; 19 | 20 | // 21 | // ─── DRAG START - MOVE MODE ───────────────────────────────────────────────────── 22 | // 23 | 24 | export function DragStartFunctionMoveMode( circle: ISnapObject ) { 25 | circle.animate( { "r": CircleRadiusAtDrag }, CircleAnimationDurationAtStart ); 26 | } 27 | 28 | // 29 | // ─── DRAG START - REMOVE MODE ─────────────────────────────────────────────────── 30 | // 31 | 32 | export function DragStartFunctionRemoveMode( circle: ISnapObject ) { 33 | var dot = ( Storage.Nodes[ circle.id ] ); 34 | dot.Remove(); 35 | dot = dot; 36 | } 37 | 38 | // 39 | // ─── DRAG START - EDIT MOVE ───────────────────────────────────────────────────── 40 | // 41 | 42 | export function DragStartFunctionEditMode( circle: ISnapObject ) { 43 | Circle.ResetCircleColors(); 44 | circle.attr({ 45 | fill: GraphSelectColor 46 | }); 47 | } 48 | 49 | // 50 | // ─── DRAG START - SELECT MOVE ─────────────────────────────────────────────────── 51 | // 52 | 53 | export function DragStartFunctionSelectMode( circle: ISnapObject ) { 54 | 55 | } 56 | 57 | // ──────────────────────────────────────────────────────────────────────────────── 58 | 59 | } -------------------------------------------------------------------------------- /core/objects/dot/drag-stop.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DRAG START FUNCTION LIST ─────────────────────────────────────────────────── 11 | // 12 | 13 | export const DragStopFunctions = [ 14 | DragStopFunctionMoveMode, 15 | DragStopFunctionRemoveMode, 16 | DragStopFunctionEditMode, 17 | DragStopFunctionSelectMode 18 | ]; 19 | 20 | // 21 | // ─── DRAG START - MOVE MODE ───────────────────────────────────────────────────── 22 | // 23 | 24 | export function DragStopFunctionMoveMode( circle: ISnapObject ) { 25 | circle.animate( { "r": CircleRadius }, CircleAnimationDurationAtStop ); 26 | } 27 | 28 | // 29 | // ─── DRAG START - REMOVE MODE ─────────────────────────────────────────────────── 30 | // 31 | 32 | export function DragStopFunctionRemoveMode( circle: ISnapObject ) { 33 | 34 | } 35 | 36 | // 37 | // ─── DRAG START - EDIT MOVE ───────────────────────────────────────────────────── 38 | // 39 | 40 | export function DragStopFunctionEditMode( circle: ISnapObject ) { 41 | 42 | } 43 | 44 | // 45 | // ─── DRAG START - SELECT MOVE ─────────────────────────────────────────────────── 46 | // 47 | 48 | export function DragStopFunctionSelectMode( circle: ISnapObject ) { 49 | 50 | } 51 | 52 | // ──────────────────────────────────────────────────────────────────────────────── 53 | 54 | } -------------------------------------------------------------------------------- /core/objects/point.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── POINT OBJECT ─────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export class Point { 14 | 15 | // 16 | // ─── DEFS ──────────────────────────────────────────────────────── 17 | // 18 | 19 | /** _Horizontal_ coordinate of the point. */ 20 | public X: number; 21 | 22 | /** _Vertical_ coordinate of the point. */ 23 | public Y: number; 24 | 25 | // 26 | // ─── CONSTRUCTOR ───────────────────────────────────────────────── 27 | // 28 | 29 | constructor ( x: number, y: number ) { 30 | this.X = x; 31 | this.Y = y; 32 | } 33 | 34 | // ───────────────────────────────────────────────────────────────── 35 | 36 | } 37 | 38 | // ──────────────────────────────────────────────────────────────────────────────── 39 | 40 | } -------------------------------------------------------------------------------- /core/objects/vertex/arrow/interfaces.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── ARROW BASE INTERFACE ─────────────────────────────────────────────────────── 11 | // 12 | 13 | /** 14 | * Implements the shared properties between _arrow objects_ 15 | * to implement a bridge between different arrow objects 16 | * and the _Vertex_ object. 17 | */ 18 | export interface IArrow { 19 | 20 | // 21 | // ─── BASE CLASS TOOLS ──────────────────────────────────────────── 22 | // 23 | 24 | /** Removes the Arrow objects and deletes the memory for it. */ 25 | Remove ( ); 26 | 27 | // 28 | // ─── MOVEMENTS ─────────────────────────────────────────────────── 29 | // 30 | 31 | /** Moves _start_ of the arrow object to the given _position_ */ 32 | MoveStart ( position: Point ); 33 | 34 | /** Moves _end_ of the arrow object to the given _position_ */ 35 | MoveEnd ( position: Point ); 36 | 37 | // ───────────────────────────────────────────────────────────────── 38 | 39 | } 40 | 41 | // ──────────────────────────────────────────────────────────────────────────────── 42 | 43 | } -------------------------------------------------------------------------------- /core/objects/vertex/arrow/line.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DIRECTED LINE OBJECT ─────────────────────────────────────────────────────── 11 | // 12 | 13 | export class LineArrow implements IArrow { 14 | 15 | // 16 | // ─── DEFS ──────────────────────────────────────────────────────── 17 | // 18 | 19 | /** Holds the line */ 20 | private SnapLine: ISnapObject; 21 | 22 | /** Holds the arrow ending */ 23 | private SnapArrowEnding: ISnapObject; 24 | 25 | /** Holds the Vertex parts to together */ 26 | private SnapGroup: ISnapGroup; 27 | 28 | // 29 | // ─── CONSTRUCTOR ───────────────────────────────────────────────── 30 | // 31 | 32 | constructor ( start: Point, end: Point ) { 33 | this.InitSnapObject( start, end ); 34 | } 35 | 36 | // 37 | // ─── INIT LINE OBJECT ──────────────────────────────────────────── 38 | // 39 | 40 | /** Creates an Snap line for the arrow */ 41 | private InitSnapObject ( start: Point, end: Point ) { 42 | this.SnapLine = GraphView.line( 43 | start.X, start.Y, end.X, end.Y 44 | ); 45 | this.SnapLine.attr({ 46 | stroke: GraphColor, 47 | strokeWidth: LineWidth 48 | }); 49 | GraphLines.add( this.SnapLine ); 50 | } 51 | 52 | // 53 | // ─── REMOVE ────────────────────────────────────────────────────── 54 | // 55 | 56 | public Remove ( ) { 57 | this.SnapLine.remove( ); 58 | this.SnapArrowEnding.remove( ); 59 | } 60 | 61 | // 62 | // ─── MOVE START OF THE ARROW ───────────────────────────────────── 63 | // 64 | 65 | /** Moves the start of the vertex to the given Point. */ 66 | public MoveStart ( position: Point ) { 67 | this.SnapLine.attr({ 68 | x1: position.X, y1: position.Y 69 | }); 70 | } 71 | 72 | // 73 | // ─── MOVE END OF THE ARROW ─────────────────────────────────────── 74 | // 75 | 76 | /** Moves the end of the vertex to the given Point. */ 77 | public MoveEnd ( position: Point ) { 78 | this.SnapLine.attr({ 79 | x2: position.X, y2: position.Y 80 | }); 81 | } 82 | 83 | // ───────────────────────────────────────────────────────────────── 84 | 85 | } 86 | 87 | // ──────────────────────────────────────────────────────────────────────────────── 88 | 89 | } -------------------------------------------------------------------------------- /core/objects/vertex/arrow/loop.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph { 8 | 9 | // 10 | // ─── DIRECTED LOOP OBJECT ─────────────────────────────────────────────────────── 11 | // 12 | 13 | export class LoopArrow implements IArrow { 14 | 15 | // 16 | // ─── DEFS ──────────────────────────────────────────────────────── 17 | // 18 | 19 | /** Holds the Circle */ 20 | private SnapCircle: ISnapObject; 21 | 22 | /** Holds the arrow ending */ 23 | private SnapArrowEnding: ISnapObject; 24 | 25 | /** Holds the Vertex parts to together */ 26 | private SnapGroup: ISnapGroup; 27 | 28 | // 29 | // ─── CONSTRUCTOR ───────────────────────────────────────────────── 30 | // 31 | 32 | constructor ( position: Point ) { 33 | this.InitSnapObject( position ); 34 | } 35 | 36 | // 37 | // ─── INIT LINE OBJECT ──────────────────────────────────────────── 38 | // 39 | 40 | /** Creates an Snap line for the arrow */ 41 | private InitSnapObject ( position: Point ) { 42 | this.SnapCircle = GraphView.circle( 43 | position.X + LoopArrowDisplacementX, 44 | position.Y + LoopArrowDisplacementY, 45 | LoopArrowRadius 46 | ); 47 | GraphLines.add( this.SnapCircle ); 48 | } 49 | 50 | // 51 | // ─── REMOVE ────────────────────────────────────────────────────── 52 | // 53 | 54 | public Remove ( ) { 55 | this.SnapCircle.remove( ); 56 | this.SnapArrowEnding.remove( ); 57 | } 58 | 59 | // 60 | // ─── MOVE START OF THE ARROW ───────────────────────────────────── 61 | // 62 | 63 | /** Moves the start of the vertex to the given Point. */ 64 | public MoveStart ( position: Point ) { 65 | this.SnapCircle.attr({ 66 | x1: position.X, y1: position.Y 67 | }); 68 | } 69 | 70 | // 71 | // ─── MOVE END OF THE ARROW ─────────────────────────────────────── 72 | // 73 | 74 | /** Moves the end of the vertex to the given Point. */ 75 | public MoveEnd ( position: Point ) { 76 | this.SnapCircle.attr({ 77 | x2: position.X, y2: position.Y 78 | }); 79 | } 80 | 81 | // ───────────────────────────────────────────────────────────────── 82 | 83 | } 84 | 85 | // ──────────────────────────────────────────────────────────────────────────────── 86 | 87 | } -------------------------------------------------------------------------------- /core/objects/vertex/vertex-static.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.VertexStatic { 8 | 9 | // 10 | // ─── GENERATE VERTEX ID ───────────────────────────────────────────────────────── 11 | // 12 | 13 | /** 14 | * Returns the id associated to a vertex in `KaryGraph.Storage.Connections` 15 | * by ***Starting*** and ***Ending*** dots of the vertex. 16 | */ 17 | export function GetId ( start: Dot, end: Dot ): string { 18 | return start.Id + end.Id; 19 | } 20 | 21 | // ──────────────────────────────────────────────────────────────────────────────── 22 | 23 | } -------------------------------------------------------------------------------- /core/objects/vertex/vertex.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | module KaryGraph { 8 | 9 | // 10 | // ─── VERTEX CLASS ─────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export class Vertex { 14 | 15 | // 16 | // ─── VARIABLES ─────────────────────────────────────────────────── 17 | // 18 | 19 | /** Unique id of the object */ 20 | public Id: string; 21 | 22 | /** Line object representing the line */ 23 | private Arrow: IArrow; 24 | 25 | /** Starting dot */ 26 | private StartDot: Dot; 27 | 28 | /** Ending dot */ 29 | private EndDot: Dot; 30 | 31 | /** Line's start coordination */ 32 | private Start: Point; 33 | 34 | /** Line's end coordination */ 35 | private End: Point; 36 | 37 | // 38 | // ─── CONSTRUCTOR ───────────────────────────────────────────────── 39 | // 40 | 41 | constructor ( startDot: Dot, endDot: Dot ) { 42 | // start 43 | this.StartDot = startDot; 44 | this.Start = startDot.Position; 45 | 46 | // end 47 | this.EndDot = endDot; 48 | this.End = endDot.Position; 49 | 50 | // init line object 51 | this.InitArrow( ); 52 | 53 | // registering self 54 | Storage.Connections[ this.GetStorageId( ) ] = this; 55 | } 56 | 57 | // 58 | // ─── REMOVER ───────────────────────────────────────────────────── 59 | // 60 | 61 | public Remove ( ) { 62 | this.Arrow.Remove( ); 63 | delete Storage.Connections[ this.GetStorageId( ) ]; 64 | delete this; 65 | } 66 | 67 | // 68 | // ─── CREATE THE OBJECT ─────────────────────────────────────────── 69 | // 70 | 71 | /** Initializes the arrow object for representing the object */ 72 | private InitArrow ( ) { 73 | if ( this.EndDot === this.StartDot ) { 74 | this.Arrow = new LoopArrow( this.Start ); 75 | } else { 76 | this.Arrow = new LineArrow( this.Start, this.End ); 77 | } 78 | } 79 | 80 | // 81 | // ─── MOVE START ────────────────────────────────────────────────── 82 | // 83 | 84 | /** Moves the start of the arrow to _x_ and _y_ */ 85 | public MoveStart ( position: Point ) { 86 | this.Start = position; 87 | this.Arrow.MoveStart( position ); 88 | } 89 | 90 | // 91 | // ─── MOVE END POINT ────────────────────────────────────────────── 92 | // 93 | 94 | /** Moves the end of the arrow to _x_ and _y_ */ 95 | public MoveEnd ( position: Point ) { 96 | this.End = position; 97 | this.Arrow.MoveEnd( position ); 98 | } 99 | 100 | // 101 | // ─── GET STORAGE ID ────────────────────────────────────────────── 102 | // 103 | 104 | public GetStorageId ( ): string { 105 | return this.StartDot.Id + this.EndDot.Id; 106 | } 107 | 108 | // ───────────────────────────────────────────────────────────────── 109 | 110 | } 111 | 112 | // ──────────────────────────────────────────────────────────────────────────────── 113 | 114 | } -------------------------------------------------------------------------------- /core/rendering/circular.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.Rendering { 8 | 9 | // 10 | // ─── CIRCULAR RENDERING ───────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Rearranges the dots in a circular way */ 14 | export function RenderCircular ( ) { 15 | 16 | // defs 17 | let keys = Object.keys( Storage.Nodes ); 18 | let radius = GetRadius( ); 19 | let originX = GraphWidth / 2; 20 | let originY = GraphHeight / 2; 21 | let count = keys.length; 22 | let unit = 360 / count; 23 | 24 | // funcs 25 | function computeX ( index: number ) { 26 | return originX + Math.sin( ToRadians( count * index ) ) * radius; 27 | } 28 | 29 | function computeY ( index: number ) { 30 | return originY + Math.cos( ToRadians( count * index ) ) * radius; 31 | } 32 | 33 | // body 34 | for ( var i = 0; i < count; i++ ) { 35 | let x = computeX( i ); 36 | let y = computeY( i ); 37 | ( Storage.Nodes[ keys[ i ] ] ).MoveTo( x, y ); 38 | } 39 | } 40 | 41 | // 42 | // ─── GET RADIUS ───────────────────────────────────────────────────────────────── 43 | // 44 | 45 | function GetRadius ( ): number { 46 | return 0.35 * Math.min( GraphHeight, GraphWidth ); 47 | } 48 | 49 | // 50 | // ─── TO RADIANS ───────────────────────────────────────────────────────────────── 51 | // 52 | 53 | /** Converts degrees to radians */ 54 | function ToRadians ( angle: number ): number { 55 | return angle * ( Math.PI / 180 ); 56 | } 57 | 58 | // ──────────────────────────────────────────────────────────────────────────────── 59 | 60 | } -------------------------------------------------------------------------------- /core/rendering/spiral.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Micha Hanselmann 5 | // 6 | 7 | namespace KaryGraph.Rendering { 8 | 9 | // 10 | // ─── SPIRAL RENDERING ─────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Rearrange dots in a spiral way */ 14 | export function RenderSpiral ( ) { 15 | 16 | // 17 | // ─── ENUMS ─────────────────────────────────────────────────────── 18 | // 19 | 20 | enum Direction { 21 | Top, Left, Down, Right 22 | } 23 | 24 | // 25 | // ─── DEFS ──────────────────────────────────────────────────────── 26 | // 27 | 28 | var x = GraphWidth / 2; 29 | var y = GraphHeight / 2; 30 | var iteration = 0; 31 | var direction = Direction.Top; 32 | var target = 1; 33 | var add = 2; 34 | 35 | // 36 | // ─── MOVE ──────────────────────────────────────────────────────── 37 | // 38 | 39 | Object.keys( Storage.Nodes ).forEach( key => { 40 | 41 | // • • • • • 42 | var dot: Dot = ( Storage.Nodes[ key ] ); 43 | 44 | // • • • • • 45 | dot.MoveTo( x, y ); 46 | 47 | // • • • • • 48 | switch ( direction ) { 49 | case Direction.Top: 50 | y -= 40; 51 | break; 52 | case Direction.Left: 53 | x -= 40; 54 | break; 55 | case Direction.Down: 56 | y += 40; 57 | break; 58 | case Direction.Right: 59 | x += 40; 60 | break; 61 | } 62 | 63 | // • • • • • 64 | iteration++; 65 | 66 | // • • • • • 67 | if ( iteration == target ) { 68 | direction = ( direction == 3 ) ? direction = 0 : direction += 1; 69 | target += add++; 70 | } 71 | }); 72 | 73 | // ───────────────────────────────────────────────────────────────── 74 | } 75 | 76 | // ──────────────────────────────────────────────────────────────────────────────── 77 | 78 | } -------------------------------------------------------------------------------- /core/script/algorithms.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.ScriptEngine.Algorithms { 8 | 9 | // 10 | // ─── INTERFACES ───────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export interface IAlgorithmManifest { 14 | handle: string; 15 | name: string; 16 | main: string; 17 | author: string; 18 | description: string; 19 | } 20 | 21 | export interface IAlgorithm { 22 | ( args: Object ): void; 23 | } 24 | 25 | export interface IAlgorithmObject { 26 | manifest: IAlgorithmManifest; 27 | algorithm: IAlgorithm; 28 | } 29 | 30 | // 31 | // ─── EXECUTE ALGORITHM ────────────────────────────────────────────────────────── 32 | // 33 | 34 | export function ExecuteAlgorithm ( handle: string ) { 35 | console.log('here'); 36 | let algorithm = Storage.Algorithms[ handle ]; 37 | algorithm({ }); 38 | } 39 | 40 | // 41 | // ─── LOAD ALGORITHMS ──────────────────────────────────────────────────────────── 42 | // 43 | 44 | export function LoadAlgorithms ( ) { 45 | let algDir = JoinPath([ 46 | GetHomeDir( ), GraphUserFolderPath, GraphUserFolderForAlgorithms ]); 47 | 48 | if ( FSExistsSync( algDir ) ) { 49 | ReadDir( algDir, ( err, directories ) => { 50 | if ( err ) { 51 | console.error('Could not load algorithms.'); 52 | return; 53 | } 54 | 55 | directories.forEach( dir => { 56 | let fullPath = JoinPath([ algDir, dir ]); 57 | if ( FSStatsSync( fullPath ).isDirectory( ) ) { 58 | try { 59 | LoadAlgorithm( fullPath ); 60 | } catch ( err ) { 61 | console.error(`Couldn't load algorithm: ${ dir }`); 62 | } 63 | } 64 | }); 65 | 66 | document.getElementById( AlgorithmsControlContainerId ).innerHTML += 67 | ''; 68 | }); 69 | } 70 | } 71 | 72 | // 73 | // ─── LOAD SINGLE ALGORITHM ────────────────────────────────────────────────────── 74 | // 75 | 76 | function LoadAlgorithm ( address: string ) { 77 | // getting the manifest 78 | let manifest = LoadAlgorithmsManifest( address ); 79 | 80 | // loading the algorithm 81 | let mainFilePath = JoinPath([ address, manifest.main ]); 82 | if ( !FSExistsSync( mainFilePath ) ) return; 83 | 84 | // algorithms 85 | let algorithm: IAlgorithm; 86 | try { 87 | algorithm = NodeRequire( mainFilePath ); 88 | } catch ( error ) { 89 | console.error("Couldn't load the algorithm script"); 90 | return; 91 | } 92 | 93 | let algorithmObject: IAlgorithmObject = { 94 | algorithm: algorithm, 95 | manifest: manifest 96 | }; 97 | 98 | // storing the algorithm 99 | Storage.Algorithms[ NormalizeHandle( manifest.handle ) ] = algorithm; 100 | 101 | // making a control 102 | try { 103 | UI.AlgorithmsTab.MakeAlgorithmControlView( algorithmObject ); 104 | } catch ( error ) { 105 | console.log(`Couldn't make controller view for ${ manifest.name }.`); 106 | console.log( error ); 107 | } 108 | } 109 | 110 | // 111 | // ─── LOAD PREFERENCES ─────────────────────────────────────────────────────────── 112 | // 113 | 114 | function LoadAlgorithmsManifest ( algorithmsAddress: string ) { 115 | let manifestPath = JoinPath([ algorithmsAddress, AlgorithmsPackageName ]); 116 | if ( FSExistsSync( manifestPath ) ) { 117 | return JSON.parse( ReadFileSync( manifestPath ) ); 118 | } else { 119 | return undefined; 120 | } 121 | } 122 | 123 | // 124 | // ─── NORMALIZE HANDLE ─────────────────────────────────────────────────────────── 125 | // 126 | 127 | export function NormalizeHandle ( handle: string ) { 128 | return handle.replace( /\./g , '-' ); 129 | } 130 | 131 | // ──────────────────────────────────────────────────────────────────────────────── 132 | 133 | } -------------------------------------------------------------------------------- /core/script/engine.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.ScriptEngine { 8 | 9 | // 10 | // ─── STATUS VARS ──────────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Shows the status of runtime, good run or bad run. */ 14 | export var RunStatus: boolean = true; 15 | 16 | // 17 | // ─── RUNTIME RESULTS ──────────────────────────────────────────────────────────── 18 | // 19 | 20 | export interface ICodeRuntimeResults { 21 | result?: any; 22 | error?: string; 23 | success: boolean; 24 | } 25 | 26 | // 27 | // ─── RUNNER ───────────────────────────────────────────────────────────────────── 28 | // 29 | 30 | /** 31 | * Runs a js code a returns the ***evaluation***, and then sets 32 | * the ***run status*** to what true or false based on if it 33 | * was with success or not. 34 | */ 35 | 36 | export function Run ( script: string ): ICodeRuntimeResults { 37 | try { 38 | RunStatus = true; 39 | return { 40 | success: true, 41 | result: eval( script ) 42 | } 43 | } catch ( err ) { 44 | return { 45 | success: false, 46 | error: err.toString( ) 47 | } 48 | } 49 | } 50 | 51 | // ──────────────────────────────────────────────────────────────────────────────── 52 | 53 | } -------------------------------------------------------------------------------- /core/script/events.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // Copyright 2016 Kary Foundation, Inc. 5 | // Author: Pouya Kary 6 | // 7 | 8 | namespace KaryGraph.ScriptEngine.EventHandler { 9 | 10 | // 11 | // ─── INTERFACES ───────────────────────────────────────────────────────────────── 12 | // 13 | 14 | export interface IDotEventFunction { 15 | ( dotId: string ): void; 16 | }; 17 | 18 | export interface IDotEvents { 19 | [key: string]: IDotEventFunction[ ]; 20 | } 21 | 22 | 23 | // 24 | // ─── EVENT RUNNER ─────────────────────────────────────────────────────────────── 25 | // 26 | 27 | export function RunEvents ( kind: string, dotId: string ) { 28 | Storage.DotEvents[ kind ].forEach( eventFunc => { 29 | try { 30 | eventFunc( Storage.Nodes[ dotId ]); 31 | } catch ( e ) {}; 32 | }); 33 | } 34 | 35 | // ──────────────────────────────────────────────────────────────────────────────── 36 | 37 | } -------------------------------------------------------------------------------- /core/storage/storage.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /** 8 | * This name space is used to store all the Graph's ***model information***. 9 | */ 10 | namespace KaryGraph.Storage { 11 | 12 | // 13 | // ─── CONNECTIONS ──────────────────────────────────────────────────────────────── 14 | // 15 | /** Contains all the vector objects associated to their ids. */ 16 | export var Connections = { }; 17 | 18 | // 19 | // ─── NODES ────────────────────────────────────────────────────────────────────── 20 | // 21 | 22 | /** Contains all the dot objects associated to their ids. */ 23 | export var Nodes = { }; 24 | 25 | // 26 | // ─── ALGORITHMS ───────────────────────────────────────────────────────────────── 27 | // 28 | 29 | /** Contains all the algorithm extension objects. */ 30 | export var Algorithms = { }; 31 | 32 | // 33 | // ─── DOT EVENT STORAGE ────────────────────────────────────────────────────────── 34 | // 35 | 36 | export var DotEvents: ScriptEngine.EventHandler.IDotEvents = { 37 | OnMove: new Array ( ), 38 | OnSelect: new Array ( ), 39 | OnDrag: new Array ( ), 40 | OnRemove: new Array ( ), 41 | }; 42 | 43 | // ──────────────────────────────────────────────────────────────────────────────── 44 | 45 | } -------------------------------------------------------------------------------- /core/typings/snapsvg.d.ts: -------------------------------------------------------------------------------- 1 | // Type definitions for Snap.svg Javascript SVG library 0.2.0 2 | // Project: http://snapsvg.io/ 3 | // Definitions by: Kenneth M 4 | 5 | // JavaScript Docs http://snapsvg.io/docs 6 | // Version 0.2.0 (TypeScript 1.0) 7 | 8 | 9 | interface Filter { 10 | blur(x:number,y?:number):string; 11 | shadow(dx:number,dy:number,blur?:number,color?:string):string; 12 | grayscale(amount:number):string; 13 | sepia(amount:number):string; 14 | saturate(amount:number):string; 15 | hueRotate(angle:number):string; 16 | invert(amount:number):string; 17 | brightness(amount:number):string; 18 | contrast(amount:number):string; 19 | } 20 | 21 | interface Path { 22 | getTotalLength(path:string):number; 23 | getPointAtLength(path:string,length:number):Object; 24 | getSubpath(path:string,from:number,to:number):string; 25 | findDotsAtSegment(p1x:number,p1y:number,c1x:number, 26 | c1y:number,c2x:number,c2y:number, 27 | p2x:number,p2y:number,t:number):Object; 28 | bezierBBox(...args:number[]):Object; 29 | bezierBBox(bez:Array):Object; 30 | isPointInsideBBox(bbox:string,x:string,y:string):boolean; 31 | isBBoxIntersect(bbox1:string,bbox2:string):boolean; 32 | intersection(path1:string,path2:string):Array; 33 | isPointInside(path:string,x:number,y:number):boolean; 34 | getBBox(path:string):Object; 35 | toRelative(path:string):Array; 36 | toAbsolute(path:string):Array; 37 | toCubic(pathString:string):Array; 38 | toCubic(pathString:Array):Array; 39 | map(path:string,matrix:Matrix):string; 40 | map(path:string,matrix:Object):string; 41 | } 42 | 43 | interface Matrix { 44 | add(a:number,b:number,c:number,d:number,e:number,f:number):void; 45 | add(matrix:Matrix):void; 46 | add(matrix:Object):void; 47 | 48 | invert():Matrix; 49 | clone():Matrix; 50 | translate(x:number,y:number):void; 51 | scale(x:number,y?:number,cx?:number,cy?:number):void; 52 | rotate(a:number,x:number,y:number):void; 53 | x(x:number,y:number):number; 54 | y(x:number,y:number):number; 55 | 56 | split():Object; 57 | toTransformString():string; 58 | 59 | } 60 | 61 | interface Fragment { 62 | select():Snap.Element; 63 | selectAll():Snap.Element; 64 | } 65 | 66 | interface Paper extends Snap.Element { 67 | 68 | 69 | el(name:string, attr:Object):Snap.Element; 70 | rect(x:number,y:number,width:number,height:number,rx?:number,ry?:number):Object; 71 | circle(x:number,y:number,r:number):Object; 72 | image(src:string,x:number,y:number,width:number,height:number):Object; 73 | ellipse(x:number,y:number,rx:number,ry:number):Object; 74 | path(pathString?:string):void; 75 | g(varargs?:any):Object; 76 | group(varargs:any):Object; 77 | text(x:number,y:number,text:string):Object; 78 | text(x:number,y:number,text:Array):Object; 79 | line(x1:number,y1:number,x2:number,y2:number):Object; 80 | polyline(varargs:any[]):Object; 81 | polygon(varargs:any[]):Object; 82 | gradient(gradient:string):Object; 83 | filter(filstr:string):Snap.Element; 84 | clear():void; 85 | node: Element; 86 | } 87 | 88 | declare function mina(a:number, A:number, b:number, B:number, get:Function, set:Function, easing?:Function):Object; 89 | declare module mina { 90 | 91 | export function time():number; 92 | export function getById(id:string):Object; 93 | export function linear(n:number):number; 94 | export function easeout(n:number):number; 95 | export function easein(n:number):number; 96 | export function easeinout(n:number):number; 97 | export function backin(n:number):number; 98 | export function backout(n:number):number; 99 | export function elastic(n:number):number; 100 | export function bounce(n:number):number; 101 | export function filter(filstr:string):Object; 102 | } 103 | 104 | declare function Snap(width:number,height:number):Paper; 105 | declare function Snap(query:string):Paper; 106 | declare function Snap(DOM:SVGElement):Paper; 107 | 108 | declare module Snap { 109 | export var filter:Filter; 110 | export var path:Path; 111 | 112 | export function format(token:string,json:Object):string; 113 | export function rad(deg:number):number; 114 | export function deg(rad:number):number; 115 | export function angle(x1:number,y1:number,x2:number,y2:number,x3?:number,y3?:number):number; 116 | export function is(o:any,type:string):boolean; 117 | export function snapTo(values:Array,value:number,tolerance?:number):number; 118 | 119 | export function Matrix(a:number,b:number,c:number,d:number,e:number,f:number):Matrix; 120 | export function Matrix(svgMatrix:SVGMatrix):Matrix; 121 | 122 | export function getRGB(color:string):Object; 123 | export function hsb(h:number,s:number,b:number):string; 124 | export function hsl(h:number,s:number,l:number):string; 125 | export function rgb(r:number,g:number,b:number):string; 126 | export function color(clr:string):Object; 127 | export function hsb2rgb(h:number,s:number,v:number):Object; 128 | export function hsl2rgb(h:number,s:number,l:number):Object; 129 | export function rgb2hsb(r:number,g:number,b:number):Object; 130 | export function rgb2hsl(r:number,g:number,b:number):Object; 131 | 132 | export function parsePathString(pathString:string):Array; 133 | export function parsePathString(pathString:Array):Array; 134 | export function parseTransformString(TString:string):Array; 135 | export function parseTransformString(TString:Array):Array; 136 | export function select(query:string):Snap.Element; 137 | export function selectAll(query:string):any; 138 | export function attr(params:string):any; 139 | export function attr(params:Object):any; 140 | export function animate(from:number,to:number,setter:Function,duration:number,easing:Function,callback:Function):Object; 141 | export function animate(from:Array,to:Array,setter:Function,duration:number,easing:Function,callback:Function):Object; 142 | export function animate(from:number,to:Array,setter:Function,duration:number,easing:Function,callback:Function):Object; 143 | export function animate(from:Array,to:number,setter:Function,duration:number,easing:Function,callback:Function):Object; 144 | export function parse(svg:string):Fragment; 145 | export function fragment(varargs:any):Fragment; 146 | export function ajax(url:string,postData:string,callback:Function,scope?:Object):XMLHttpRequest; 147 | export function ajax(url:string,postData:Object,callback:Function,scope?:Object):XMLHttpRequest; 148 | export function ajax(url:string,callback:Function,scope?:Object):XMLHttpRequest; 149 | export function load(url:string,callback:Function,scope?:Object):XMLHttpRequest; 150 | export function getElementByPoint(x:number,y:number):Object; 151 | export function plugin(f:Function):void; 152 | 153 | export interface Element { 154 | constructor(); 155 | getBBox():Object; 156 | transform(tstr:string):Snap.Element; 157 | parent():Snap.Element; 158 | add():void; 159 | 160 | append(el:Snap.Element):Snap.Element; 161 | appendTo(el:Snap.Element):Snap.Element; 162 | prepend(el:Snap.Element):Snap.Element; 163 | prependTo(el:Snap.Element):Snap.Element; 164 | before(el:Snap.Element):Snap.Element; 165 | after(el:Snap.Element):Snap.Element; 166 | insertBefore(el:Snap.Element):Snap.Element; 167 | insertAfter(el:Snap.Element):Snap.Element; 168 | remove():Snap.Element; 169 | select(query:string):Snap.Element; 170 | selectAll(query:string):any; 171 | asPX(attr:string,value?:string):Snap.Element; 172 | use():Snap.Element; 173 | clone():Snap.Element; 174 | toDefs():Snap.Element; 175 | pattern(x:any,y:any,width:any,height:any):Snap.Element; 176 | marker(x:number,y:number,width:number,height:number,refX:number,refY:number):Snap.Element; 177 | animation(attr:Object,duration:number,easing?:Function,callback?:Function):Object; 178 | inAnim():Object; 179 | animate(attrs:Object,duration:number,easing?:Function,callback?:Function):Snap.Element; 180 | // animate(from:Array,duration:number,easing:Function,callback:Function):Object; 181 | // animate(from:number,duration:number,easing:Function,callback:Function):Object; 182 | stop():Snap.Element; 183 | data(key:string,value?:any):any; 184 | removeData(key?:string):Object; 185 | outerSVG():string; 186 | innerSVG():string; 187 | 188 | click(handler:Function):Object; 189 | unclick(handler:Function):Object; 190 | dblclick(handler:Function):Object; 191 | undblclick(handler:Function):Object; 192 | mousedown(handler:Function):Object; 193 | unmousedown(handler:Function):Object; 194 | mousemove(handler:Function):Object; 195 | unmousemove(handler:Function):Object; 196 | mouseout(handler:Function):Object; 197 | unmouseout(handler:Function):Object; 198 | mouseover(handler:Function):Object; 199 | unmouseover(handler:Function):Object; 200 | mouseup(handler:Function):Object; 201 | unmouseup(handler:Function):Object; 202 | touchstart(handler:Function):Object; 203 | untouchstart(handler:Function):Object; 204 | touchmove(handler:Function):Object; 205 | untouchmove(handler:Function):Object; 206 | touchend(handler:Function):Object; 207 | untouchend(handler:Function):Object; 208 | touchcancel(handler:Function):Object; 209 | untouchcancel(handler:Function):Object; 210 | hover(f_in:Function,f_out:Function,icontext?:Object,ocontext?:Object):Object; 211 | unhover(f_in:Function,f_out:Function):Object; 212 | drag(onmove:Function,onstart:Function,onend:Function,mcontext?:Object,scontext?:Object,econtext?:Object):Object; 213 | undrag():void; 214 | 215 | getTotalLength():number; 216 | getPointAtLength(length:number):Object; 217 | getSubpath(from:number,to:number):string; 218 | } 219 | 220 | export interface Set { 221 | push(...args:any[]):Snap.Element; 222 | pop(...args:any[]):Snap.Element; 223 | forEach(callback:Function,thisArg:Object):Object; 224 | clear(); 225 | splice(index:number,cont:number,insertion?:Object[]):Object; 226 | exclude(element:Snap.Element):boolean; 227 | } 228 | } -------------------------------------------------------------------------------- /core/ui/algorithms-tab/view.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.UI.AlgorithmsTab { 8 | 9 | // 10 | // ─── MAKE AN ALGORITHM CONTROL VIEW ───────────────────────────────────────────── 11 | // 12 | 13 | export function MakeAlgorithmControlView ( 14 | algorithmObject: ScriptEngine.Algorithms.IAlgorithmObject ) { 15 | let view = MakeViewForAlgorithm( algorithmObject ); 16 | document.getElementById( AlgorithmsControlContainerId ).appendChild( view ); 17 | } 18 | 19 | // 20 | // ─── GET CONTROLLER ID ────────────────────────────────────────────────────────── 21 | // 22 | 23 | export function GetControllerId ( handle: string ) { 24 | return 'algorithm-box-' + handle; 25 | } 26 | 27 | // 28 | // ─── MAKE ALGORITHM VIEW ELEMENTS ─────────────────────────────────────────────── 29 | // 30 | 31 | function MakeViewForAlgorithm ( 32 | algorithmObject: ScriptEngine.Algorithms.IAlgorithmObject ) { 33 | 34 | // main box 35 | let controller = document.createElement('div'); 36 | controller.className = AlgorithmsControllerClass; 37 | controller.id = GetControllerId( algorithmObject.manifest.handle ); 38 | 39 | // Title 40 | controller.appendChild( MakeElement( 41 | AlgorithmsControllerTitleClass, 42 | algorithmObject.manifest.name 43 | )); 44 | 45 | // Author 46 | controller.appendChild( MakeElement( 47 | AlgorithmsControllerAuthorClass, 48 | algorithmObject.manifest.author 49 | )); 50 | 51 | // Description 52 | controller.appendChild( MakeElement( 53 | AlgorithmsControllerDescriptionClass, 54 | algorithmObject.manifest.description 55 | )); 56 | 57 | // Run Button 58 | controller.appendChild( 59 | MakeRunButton( algorithmObject.manifest.handle ) 60 | ); 61 | 62 | return controller; 63 | } 64 | 65 | // 66 | // ─── RUN BUTTON ───────────────────────────────────────────────────────────────── 67 | // 68 | 69 | function MakeRunButton ( handle: string ) { 70 | let button = document.createElement('div'); 71 | button.className = AlgorithmsControllerRunButtonClass; 72 | button.innerText = 'Run'; 73 | 74 | let normalHandle = ScriptEngine.Algorithms.NormalizeHandle( handle ); 75 | button.setAttribute('onclick', 76 | `KaryGraph.ScriptEngine.Algorithms.ExecuteAlgorithm("${ normalHandle }");` 77 | ); 78 | return button; 79 | } 80 | 81 | // 82 | // ─── MAKE ELEMENT ─────────────────────────────────────────────────────────────── 83 | // 84 | 85 | function MakeElement ( cls: string, text: string ) { 86 | let element = document.createElement('div'); 87 | element.className = cls; 88 | element.innerText = text; 89 | return element; 90 | } 91 | 92 | // ──────────────────────────────────────────────────────────────────────────────── 93 | 94 | } -------------------------------------------------------------------------------- /core/ui/editor-tab/notebook/programmer.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /** This module is responsible for the */ 8 | namespace KaryGraph.UI.Programmer { 9 | 10 | // 11 | // ─── DEFS ─────────────────────────────────────────────────────────────────────── 12 | // 13 | 14 | /** The main notebook view */ 15 | var notebook: HTMLDivElement; 16 | 17 | /** Current prompt */ 18 | var prompt: HTMLDivElement; 19 | 20 | /** Input of the prompt */ 21 | var promptInput: HTMLInputElement; 22 | 23 | /** Commands History Array */ 24 | var promptHistory:Array; 25 | 26 | /** Commands History Cursor */ 27 | var promptHistoryCursor:number; 28 | 29 | // 30 | // ─── INIT NOTEBOOK ────────────────────────────────────────────────────────────── 31 | // 32 | 33 | /** Starts the notebook view at start. */ 34 | export function INIT ( ) { 35 | notebook = document.getElementById( NotebookId ); 36 | ClearScreen( ); 37 | StartPrompt( ); 38 | } 39 | 40 | // 41 | // ─── RESTART SCREEN ───────────────────────────────────────────────────────────── 42 | // 43 | 44 | export function ClearNotebookScreen ( ) { 45 | ClearScreen( ); 46 | StartPrompt( ); 47 | } 48 | 49 | // 50 | // ─── CLEAR SCREEN ─────────────────────────────────────────────────────────────── 51 | // 52 | 53 | /** Cleans the screen of the notebook and restarts the code of the notebook*/ 54 | function ClearScreen ( ) { 55 | notebook.innerHTML = ''; 56 | } 57 | 58 | // 59 | // ─── START PROMPT ─────────────────────────────────────────────────────────────── 60 | // 61 | 62 | /** Initializes a prompt into the notebook */ 63 | function StartPrompt ( ) { 64 | CreateThePrompt( ); 65 | notebook.appendChild( prompt ); 66 | promptHistory = new Array(); 67 | promptHistoryCursor = -1; 68 | } 69 | 70 | // 71 | // ─── CREATE PROMPT ────────────────────────────────────────────────────────────── 72 | // 73 | 74 | /** Creates the corresponding object that presents the prompt. */ 75 | function CreateThePrompt ( ) { 76 | // Prompt Object 77 | prompt = document.createElement( 'div' ); 78 | prompt.className = NotebookPromptClass; 79 | // Prompt Input Object 80 | promptInput = document.createElement( 'input' ); 81 | promptInput.className = NotebookPromptInputClass; 82 | /** We have two different methods on purpose, do not try to merge them! */ 83 | promptInput.addEventListener( 'keypress' , OnPromptEnterClicked ); 84 | promptInput.addEventListener( 'keydown' , OnPromptArrowsClicked ); 85 | // Prompt 86 | prompt.appendChild( promptInput ); 87 | } 88 | 89 | // 90 | // ─── ON PROMPT ENTER ──────────────────────────────────────────────────────────── 91 | // 92 | 93 | /** Starts when the enter key is pressed on the input */ 94 | function OnPromptEnterClicked ( ev: KeyboardEvent ) { 95 | // if ( !ev.metaKey ) return; 96 | let key = ev.which || ev.keyCode; 97 | if ( key === 13 ) { 98 | /** Enter/Return Key */ 99 | let code = FetchAndResetInput( ); 100 | if ( code === '' ) return; 101 | promptHistory.push(code); 102 | promptHistoryCursor++; 103 | let result = RunAndGenerateResults( code ); 104 | let html = GenerateResultRowHTML( code , result ); 105 | AppendRow( html ); 106 | } 107 | } 108 | 109 | // 110 | // ─── ON PROMPT ARROWS ─────────────────────────────────────────────────────────── 111 | // 112 | 113 | 114 | /** Starts when the arrow keys is pressed on the input */ 115 | function OnPromptArrowsClicked ( ev: KeyboardEvent ) { 116 | // if ( !ev.metaKey ) return; 117 | let key = ev.which || ev.keyCode; 118 | if ( key === 38 ) { 119 | /** Up Arrow Key */ 120 | if ( promptHistoryCursor > -1 ) { 121 | ResetAndSetInput( promptHistory[ promptHistoryCursor ] ); 122 | promptHistoryCursor--; 123 | } 124 | } else if ( key === 40 ) { 125 | /** Down Arrow Key */ 126 | if ( promptHistoryCursor + 2 < promptHistory.length ) { 127 | ResetAndSetInput( promptHistory[ promptHistoryCursor + 2 ] ); 128 | promptHistoryCursor++; 129 | } else { 130 | promptHistoryCursor = promptHistory.length-1; 131 | ResetAndSetInput(''); 132 | } 133 | } 134 | } 135 | 136 | // 137 | // ─── APPEND ROW ───────────────────────────────────────────────────────────────── 138 | // 139 | 140 | function AppendRow ( html: string ) { 141 | let row = document.createElement('div'); 142 | row.className = NotebookResultRowClass; 143 | row.innerHTML = html; 144 | notebook.insertBefore( row , prompt ); 145 | } 146 | 147 | // 148 | // ─── RESET AND SET INPUT VALUSE ───────────────────────────────────────────────── 149 | // 150 | 151 | /** Resets and sets the input box value */ 152 | function ResetAndSetInput ( inputValue: string ) { 153 | promptInput.value = inputValue; 154 | } 155 | 156 | // 157 | // ─── FETCH AND RESET INPUT VALUE ──────────────────────────────────────────────── 158 | // 159 | 160 | /** Fetches and resets the input box value */ 161 | function FetchAndResetInput ( ): string { 162 | let result = promptInput.value; 163 | promptInput.value = ''; 164 | return result; 165 | } 166 | 167 | // 168 | // ─── GENERATE ROW ─────────────────────────────────────────────────────────────── 169 | // 170 | 171 | function GenerateResultRowHTML ( code: string, result: string ): string { 172 | let highlightedCode = PrismHighlight( code ); 173 | return `${ highlightedCode }` + 174 | `${ result }`; 175 | } 176 | 177 | // 178 | // ─── RUN AND GENERATE RESULTS ─────────────────────────────────────────────────── 179 | // 180 | 181 | function RunAndGenerateResults ( code: string ) { 182 | let runResults = KaryGraph.ScriptEngine.Run( code ); 183 | if ( runResults.success ) { 184 | return KaryGraph.UI.Programmer.GenerateSayHTML( runResults.result ); 185 | } else { 186 | return `${ runResults.error }` 187 | } 188 | } 189 | 190 | // ──────────────────────────────────────────────────────────────────────────────── 191 | 192 | } -------------------------------------------------------------------------------- /core/ui/editor-tab/notebook/say.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /** 8 | * Programmer's ***Notebook View*** must have different ways to 9 | * show that view. this namespace implements different systems for 10 | * the say. 11 | */ 12 | 13 | 14 | namespace KaryGraph.UI.Programmer { 15 | 16 | // 17 | // ─── SAY MAIN ─────────────────────────────────────────────────────────────────── 18 | // 19 | 20 | export function GenerateSayHTML ( input: any ): string { 21 | 22 | // if were going to have an undefined type. 23 | if ( input == undefined ) { 24 | return SayImplementations.SayUndefined( ); 25 | } 26 | 27 | // number 28 | if ( typeof( input ) === "number" ) { 29 | return SayImplementations.SayNumber( input ); 30 | } 31 | 32 | // if we have type 33 | switch ( input.constructor.name ) { 34 | 35 | case "Dot": 36 | return SayImplementations.SayDot( input ); 37 | 38 | case "String": 39 | return SayImplementations.SayString( input ); 40 | 41 | case "Array": 42 | if ( input[ 0 ].constructor.name == "Array" ) { 43 | // Matrix 44 | return SayImplementations.SayMatrix( input ); 45 | } else { 46 | // Normal Array 47 | return SayImplementations.SayArray( input ); 48 | } 49 | 50 | default: 51 | return SayImplementations.SayObject( input ); 52 | } 53 | } 54 | 55 | // ──────────────────────────────────────────────────────────────────────────────── 56 | 57 | } 58 | 59 | 60 | 61 | 62 | namespace KaryGraph.UI.Programmer.SayImplementations { 63 | 64 | // 65 | // ────────────────────────────────────────────────────────────────────────────── I ────────── 66 | // :::::: S A Y I M P L E M E N T A T I O N S : : : : : : : : 67 | // ──────────────────────────────────────────────────────────────────────────────────────── 68 | // 69 | 70 | // 71 | // ─── DOT ──────────────────────────────────────────────────────────────────────── 72 | // 73 | 74 | export function SayDot ( input: Dot ): string { 75 | return ( 76 | `${ input.GetNumberId( ) }` + 77 | '' 78 | ); 79 | } 80 | 81 | // 82 | // ─── UNDEFINED ────────────────────────────────────────────────────────────────── 83 | // 84 | 85 | export function SayUndefined ( ): string { 86 | return ''; 87 | } 88 | 89 | // 90 | // ─── SAY TEXT ─────────────────────────────────────────────────────────────────── 91 | // 92 | 93 | export function SayString ( input: string ): string { 94 | return `"${ input }"`; 95 | } 96 | 97 | // 98 | // ─── NUMBER ───────────────────────────────────────────────────────────────────── 99 | // 100 | 101 | export function SayNumber ( input: number ): string { 102 | return `${ input }`; 103 | } 104 | 105 | // 106 | // ─── ARRAY ────────────────────────────────────────────────────────────────────── 107 | // 108 | 109 | export function SayArray ( input: Array ) { 110 | let row = ''; 111 | for ( let index = 0; index < input.length; index++ ) { 112 | row += ( `` + 113 | `${ index }` + 114 | `${ ArraySayEncoder( input[ index ] ) }` + 115 | '' ); 116 | } 117 | return `${ row }`; 118 | } 119 | 120 | // 121 | // ─── MATRIX ───────────────────────────────────────────────────────────────────── 122 | // 123 | 124 | export function SayMatrix ( input: number[ ][ ] ) { 125 | let matrixHTML = ''; 126 | for ( let rowCounter = 0; rowCounter < input.length; rowCounter++ ) { 127 | let row = input[ rowCounter ]; 128 | let rowHTML = '' 129 | for ( let columnCounter = 0; columnCounter < row.length; columnCounter++ ) { 130 | let cell = row[ columnCounter ]; 131 | rowHTML += `${ cell }` 132 | } 133 | matrixHTML += `${ rowHTML }` 134 | } 135 | return `${ matrixHTML}` 136 | } 137 | 138 | // 139 | // ─── OBJECT ───────────────────────────────────────────────────────────────────── 140 | // 141 | 142 | export function SayObject ( input: Object ): string { 143 | return `${ input.toString() }`; 144 | } 145 | 146 | // ──────────────────────────────────────────────────────────────────────────────── 147 | 148 | 149 | 150 | 151 | 152 | // 153 | // ────────────────────────────────────────────────── I ────────── 154 | // :::::: T O O L S : : : : : : : : 155 | // ──────────────────────────────────────────────────────────── 156 | // 157 | 158 | // 159 | // ─── ARRAY SWITCHER ───────────────────────────────────────────────────────────── 160 | // 161 | 162 | function ArraySayEncoder( input: any ): string { 163 | if ( typeof( input ) === "number" ) { 164 | return SayNumber( input ); 165 | } 166 | 167 | switch ( input.constructor.name ) { 168 | case "Dot": 169 | return SayDot( input ); 170 | case "String": 171 | return SayString( input ); 172 | default: 173 | return input; 174 | } 175 | } 176 | 177 | // ──────────────────────────────────────────────────────────────────────────────── 178 | 179 | } -------------------------------------------------------------------------------- /core/ui/editor-tab/view.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // Copyright 2016 Kary Foundation, Inc. 5 | // Author: Pouya Kary 6 | // 7 | 8 | namespace KaryGraph { 9 | 10 | // 11 | // ─── GRAPH ────────────────────────────────────────────────────────────────────── 12 | // 13 | 14 | /** 15 | * Main ***memory*** containing the graph. Designed in 16 | * a MVVC model in mind structure of this any type is: 17 | * ``` 18 | * Graph = { 19 | * DotObjectId : Dot 20 | * } 21 | * ``` 22 | */ 23 | export var Graph: any; 24 | 25 | // 26 | // ─── PAPER ────────────────────────────────────────────────────────────────────── 27 | // 28 | 29 | /** 30 | * The **main** view, a ***Snap SVG Paper*** containing 31 | * the whole model. 32 | */ 33 | export var GraphView: Paper; 34 | 35 | /** Width of the graph paper */ 36 | export var GraphWidth: number; 37 | 38 | /** Height of the graph paper */ 39 | export var GraphHeight: number; 40 | 41 | /** Graphs distance to the window top */ 42 | export var GraphMarginTop: number; 43 | 44 | // 45 | // ─── GROUPS ───────────────────────────────────────────────────────────────────── 46 | // 47 | 48 | /** Where the lines are stored within the paper */ 49 | export var GraphLines: ISnapGroup; 50 | 51 | /** Where the circles are stored within the paper */ 52 | export var GraphCircles: ISnapGroup; 53 | 54 | // 55 | // ─── INIT WINDOW SIZES ────────────────────────────────────────────────────────── 56 | // 57 | 58 | /** 59 | * At the *start* of the window, this function initializes 60 | * the window properties. 61 | */ 62 | export function InitScreenInformation ( ) { 63 | 64 | // The paper 65 | GraphView = Snap(`#${ GraphViewId }`); 66 | 67 | // Groups (notice the order...) 68 | GraphLines = GraphView.g(); 69 | 70 | // the memory 71 | Graph = { }; 72 | 73 | // getting the paper... 74 | var paperObject = document.getElementById( GraphViewId ); 75 | var paperStyle = window.getComputedStyle( paperObject, null ); 76 | 77 | // computing numbers we need... 78 | GraphWidth = parseInt( paperStyle.getPropertyValue('width') ); 79 | GraphHeight = parseInt( paperStyle.getPropertyValue('height') ); 80 | GraphMarginTop = paperObject.getBoundingClientRect().top; 81 | } 82 | 83 | // 84 | // ─── SCREEN CLICK EVENTS ──────────────────────────────────────────────────────── 85 | // 86 | 87 | // ──────────────────────────────────────────────────────────────────────────────── 88 | 89 | } -------------------------------------------------------------------------------- /core/ui/events.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // Copyright 2016 Kary Foundation, Inc. 5 | // Author: Pouya Kary 6 | // 7 | 8 | namespace KaryGraph.UI.Events { 9 | 10 | // 11 | // ─── WINDOW RESIZE ────────────────────────────────────────────────────────────── 12 | // 13 | 14 | window.onresize = event => { 15 | ProgrammerTab.Editor.layout( ); 16 | }; 17 | 18 | // ──────────────────────────────────────────────────────────────────────────────── 19 | 20 | } -------------------------------------------------------------------------------- /core/ui/loader.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.UI { 8 | 9 | // 10 | // ─── LOAD IMAGES ──────────────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Loads some of the necessary images to remove image loading lags. */ 14 | export function LoadImagesAtStart ( ) { 15 | const listOfImages = [ 16 | 'toolbar-tabs-algorithms.png', 17 | 'toolbar-tabs-programmer.png', 18 | ]; 19 | listOfImages.forEach( imageResource => { 20 | let tempImage = new Image( ); 21 | tempImage.src = imageResource; 22 | }) 23 | } 24 | 25 | // ──────────────────────────────────────────────────────────────────────────────── 26 | 27 | } -------------------------------------------------------------------------------- /core/ui/programmer-tab/ribbon.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.UI.ProgrammerTab.Ribbon { 8 | 9 | // 10 | // ─── ON RUN BUTTON CLICKED ────────────────────────────────────────────────────── 11 | // 12 | 13 | /** Run Button */ 14 | export function OnRunButtonClicked ( ) { 15 | let runResult = ScriptEngine.Run( 16 | UI.ProgrammerTab.Editor.getValue( ) 17 | ); 18 | UI.Tabs.EditorTabsOnClick( ); 19 | if ( !runResult.success ) { 20 | alert( runResult.error ); 21 | } 22 | } 23 | 24 | // ──────────────────────────────────────────────────────────────────────────────── 25 | 26 | } -------------------------------------------------------------------------------- /core/ui/programmer-tab/view.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.UI.ProgrammerTab { 8 | 9 | // 10 | // ─── GLOBALS ──────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | export var Editor: monaco.editor.IStandaloneCodeEditor; 14 | 15 | // 16 | // ─── INIT MONACO ──────────────────────────────────────────────────────────────── 17 | // 18 | 19 | export function ApplyAdditionalMonacoInitialization ( ) { 20 | KaryFoundation.Monaco.AddSupportingMonacoTools( Editor ); 21 | SetSampleCode( ); 22 | } 23 | 24 | // 25 | // ─── ADD COMMENT BUTTONS ──────────────────────────────────────────────────────── 26 | // 27 | 28 | export function OnAddSectionCommentButtonClicked ( ) { 29 | KaryFoundation.Monaco.ExecuteAddComment( Editor, KaryFoundation.Comment.Style.Section ); 30 | Editor.focus( ); 31 | } 32 | 33 | export function OnAddEndingCommentButtonClicked ( ) { 34 | KaryFoundation.Monaco.ExecuteAddComment( Editor, KaryFoundation.Comment.Style.Ending ); 35 | Editor.focus( ); 36 | } 37 | 38 | // 39 | // ─── GENERATE SAMPLE CODE ─────────────────────────────────────────────────────── 40 | // 41 | 42 | function SetSampleCode ( ) { 43 | let sampleCode = [ 44 | '', 45 | generateSectionComment('welcome'), 46 | ' ', 47 | ' // Hello there! Welcome to Graph!', 48 | ' // it really is easy to code for graph, all you need is some', 49 | ' // sweet portion of javascript and a one time checking out at', 50 | ' // this API documentation:', 51 | ' // https://github.com/karyfoundation/graph/wiki/API', 52 | '', 53 | ' let size = 10;', 54 | ' newdots( size );', 55 | ' for ( let i = 0; i < size; i++ ) {', 56 | ' connect([ rnd( size ), rnd( size ) ]);', 57 | ' }', 58 | '', 59 | generateLineComment( ) 60 | ].join('\n'); 61 | 62 | Editor.setValue( sampleCode ); 63 | } 64 | 65 | // 66 | // ─── GENERATE SECTION COMMENT ─────────────────────────────────────────────────── 67 | // 68 | 69 | function generateSectionComment ( text: string ) { 70 | return KaryFoundation.Comment.Generate( 71 | KaryFoundation.Comment.Style.Section, 72 | '//', 4, true, text 73 | ).trim( ); 74 | } 75 | 76 | // 77 | // ─── GENERATE LINE COMMENT ────────────────────────────────────────────────────── 78 | // 79 | 80 | function generateLineComment ( ) { 81 | return KaryFoundation.Comment.Generate( 82 | KaryFoundation.Comment.Style.Ending, 83 | '//', 4, true, '' 84 | ) 85 | } 86 | 87 | // ──────────────────────────────────────────────────────────────────────────────── 88 | 89 | } -------------------------------------------------------------------------------- /core/ui/tabs.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | namespace KaryGraph.UI.Tabs { 8 | 9 | // 10 | // ─── ENUMS ────────────────────────────────────────────────────────────────────── 11 | // 12 | 13 | enum TabOptions { Editor, Programmer, Algorithms }; 14 | 15 | // 16 | // ─── TABS ON CLICK ────────────────────────────────────────────────────────────── 17 | // 18 | 19 | export function EditorTabsOnClick ( ) { 20 | ChangeToTab( TabOptions.Editor ); 21 | } 22 | 23 | export function ProgrammerTabsOnClick ( ) { 24 | ChangeToTab( TabOptions.Programmer ); 25 | } 26 | 27 | export function AlgorithmsTabsOnClick ( ) { 28 | ChangeToTab( TabOptions.Algorithms ); 29 | } 30 | 31 | // 32 | // ─── CHANGE TO TAB ────────────────────────────────────────────────────────────── 33 | // 34 | 35 | function ChangeToTab ( tab: TabOptions ) { 36 | let tabContainer = document.getElementById( TabsContainer ); 37 | 38 | // editor tab 39 | let editorTabView = document.getElementById( EditorTabId ); 40 | let programmerTabView = document.getElementById( ProgrammerTabId ); 41 | let algorithmsTabView = document.getElementById( AlgorithmsTabId ); 42 | 43 | // switcher 44 | switch ( tab ) { 45 | // Editor 46 | case TabOptions.Editor: 47 | tabContainer.className = 'editor-tab'; 48 | 49 | editorTabView.hidden = false; 50 | programmerTabView.hidden = true; 51 | algorithmsTabView.hidden = true; 52 | break; 53 | 54 | 55 | // Programmer 56 | case TabOptions.Programmer: 57 | tabContainer.className = 'programmer-tab'; 58 | 59 | editorTabView.hidden = true; 60 | programmerTabView.hidden = false; 61 | algorithmsTabView.hidden = true; 62 | break; 63 | 64 | 65 | // Preferences 66 | case TabOptions.Algorithms: 67 | tabContainer.className = 'algorithms-tab'; 68 | 69 | editorTabView.hidden = true; 70 | programmerTabView.hidden = true; 71 | algorithmsTabView.hidden = false; 72 | break; 73 | } 74 | } 75 | 76 | // ──────────────────────────────────────────────────────────────────────────────── 77 | 78 | } -------------------------------------------------------------------------------- /core/ui/toolbar.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | /// 8 | 9 | namespace KaryGraph.UI.Toolbar { 10 | 11 | // 12 | // ─── TOOLBAR MODE ─────────────────────────────────────────────────────────────── 13 | // 14 | 15 | export enum ToolbarModeEnum { 16 | Move, Remove, Edit, Select 17 | } 18 | 19 | /** To get the mode of the toolbar */ 20 | export var ToolbarMode = ToolbarModeEnum.Move; 21 | 22 | // ──────────────────────────────────────────────────────────────────────────────── 23 | } -------------------------------------------------------------------------------- /designs/icon/icns/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/icon/icns/icon.icns -------------------------------------------------------------------------------- /designs/icon/icon.iconsproj: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/icon/icon.iconsproj -------------------------------------------------------------------------------- /designs/icon/icon.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/icon/icon.sketch -------------------------------------------------------------------------------- /designs/opening.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/opening.sketch -------------------------------------------------------------------------------- /designs/toolbar-icons.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/toolbar-icons.sketch -------------------------------------------------------------------------------- /designs/ui.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/ui.sketch -------------------------------------------------------------------------------- /designs/wiki.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/designs/wiki.sketch -------------------------------------------------------------------------------- /doc.sh: -------------------------------------------------------------------------------- 1 | typedoc --out _documentation core --name "Kary Graph - Core & API" --theme minimal 2 | -------------------------------------------------------------------------------- /electron/main.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | 8 | 'use strict'; 9 | 10 | // 11 | // ─── DEFS ─────────────────────────────────────────────────────────────────────── 12 | // 13 | 14 | const electron = require( 'electron' ); 15 | const app = electron.app; 16 | const BrowserWindow = electron.BrowserWindow; 17 | 18 | // 19 | // ─── GENERATE MAIN WINDOW ─────────────────────────────────────────────────────── 20 | // 21 | 22 | let mainWindow; 23 | 24 | function createWindow ( ) { 25 | const window_width = 1100; 26 | const window_height = 640; 27 | mainWindow = new BrowserWindow({ 28 | width: window_width, minWidth: window_width - 150, 29 | height: window_height, minHeight: window_height - 100, 30 | backgroundColor: 'white' 31 | }); 32 | 33 | //mainWindow.openDevTools( ); 34 | 35 | mainWindow.loadURL( 'file://' + __dirname + '/index.html' ); 36 | 37 | mainWindow.on( 'closed' , function( ) { 38 | mainWindow = null; 39 | app.quit( ); 40 | }); 41 | } 42 | 43 | // 44 | // ─── ON READY ─────────────────────────────────────────────────────────────────── 45 | // 46 | 47 | app.on( 'ready' , createWindow ); 48 | 49 | // ──────────────────────────────────────────────────────────────────────────────── 50 | -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | var gulp = require('gulp'); 12 | var exec = require('child_process').exec; 13 | var util = require('util'); 14 | var fs = require('fs-extra'); 15 | var path = require('path'); 16 | var ugly = require('gulp-uglify'); 17 | var less = require('less'); 18 | var mv = require('mv'); 19 | 20 | // 21 | // ─── P ────────────────────────────────────────────────────────────────────────── 22 | // 23 | 24 | function p ( message ) { 25 | console.log( message ); 26 | } 27 | 28 | // 29 | // ─── CONSTS ───────────────────────────────────────────────────────────────────── 30 | // 31 | 32 | const resultDirPath = '_compiled'; 33 | 34 | // 35 | // ─── TOOLS ────────────────────────────────────────────────────────────────────── 36 | // 37 | 38 | /** Run shell commands easy! */ 39 | function shell ( command , callback ) { 40 | exec( command, err => { 41 | if ( err ) return callback( err ); 42 | callback( ); 43 | }); 44 | } 45 | 46 | // 47 | // ─── COPY DIR FILES ───────────────────────────────────────────────────────────── 48 | // 49 | 50 | /** Copy to binary from dir */ 51 | function copyToBinaryFromDir ( dir ) { 52 | fs.readdir( dir , ( err , files ) => { 53 | // if error 54 | if ( err ) { 55 | console.log(`Could not get files from directory ${ dir }`); 56 | } 57 | // if right 58 | files.forEach( name => { 59 | copyFile( 60 | getLocalPath( path.join( dir , name ) ), 61 | getLocalPath( path.join( resultDirPath , name ) ) 62 | ); 63 | }); 64 | }); 65 | } 66 | 67 | // 68 | // ─── COPY SINGLE FILE ─────────────────────────────────────────────────────────── 69 | // 70 | 71 | /** Copy file `A` to `B` */ 72 | function copyFile ( A, B ) { 73 | if ( /\.DS_Store/.test( A ) ) { 74 | return; 75 | } 76 | fs.copy( A, B, err => { 77 | if ( err ) { 78 | console.log(`Could not copy file ${ A }`); 79 | } 80 | }); 81 | } 82 | 83 | // 84 | // ─── GET LOCAL PATH ───────────────────────────────────────────────────────────── 85 | // 86 | 87 | /** Get Local Path in the current directory */ 88 | function getLocalPath ( address ) { 89 | return path.join( __dirname , address ); 90 | } 91 | 92 | // 93 | // ─── COMPILING TYPE SCRIPT ────────────────────────────────────────────────────── 94 | // 95 | 96 | /** Compiles the TypeScript code */ 97 | gulp.task('typescript', callback => { 98 | shell('tsc', callback); 99 | }); 100 | 101 | // 102 | // ─── UGLIFYING ────────────────────────────────────────────────────────────────── 103 | // 104 | 105 | /** Minify the result code from TypeScript */ 106 | gulp.task( 'minifyCore', ['typescript'], callback => { 107 | callback(); 108 | }); 109 | 110 | // 111 | // ─── COPY FILES ───────────────────────────────────────────────────────────────── 112 | // 113 | 114 | /** Copies static resource files into the result directory */ 115 | gulp.task( 'copyResourceFiles', callback => { 116 | copyToBinaryFromDir( 'resources' ); 117 | copyToBinaryFromDir( 'view' ); 118 | copyToBinaryFromDir( 'electron' ); 119 | copyToBinaryFromDir( 'wrappers' ); 120 | copyToBinaryFromDir( 'libs' ); 121 | copyToBinaryFromDir( 'javascript' ); 122 | copyToBinaryFromDir( path.join( 'node_modules', 'monaco-editor', 'min' ) ); 123 | callback(); 124 | }); 125 | 126 | // 127 | // ─── COPY NODE RESOURCES ──────────────────────────────────────────────────────── 128 | // 129 | 130 | gulp.task( 'resources', ['copyResourceFiles'], callback => { 131 | // fixing monaco folders name 132 | /*mv( 133 | path.join( resultDirPath , 'vs' ), 134 | path.join( resultDirPath , 'monaco' ), 135 | { 136 | mkdirp: true, 137 | clobber: false 138 | }, 139 | error => { 140 | if ( error ) { 141 | console.log('could not fix the name of monaco folder...'); 142 | } 143 | } 144 | );*/ 145 | }); 146 | 147 | // 148 | // ─── SHEETS ───────────────────────────────────────────────────────────────────── 149 | // 150 | 151 | /** Compiles the Less style sheets */ 152 | gulp.task( 'sheets', callback => { 153 | try { 154 | let lessSourceCode = fs.readFileSync( 155 | path.join( __dirname, 'sheets', 'ui.less' ), 'utf8' ); 156 | 157 | less.render( lessSourceCode, ( err, output ) => { 158 | if ( err ) { 159 | console.log(`Less failure: ${ err }`); return; 160 | } 161 | fs.writeFile( 162 | path.join( __dirname, '_compiled/style.css' ), 163 | output.css, 164 | error => { 165 | if ( error ) { 166 | console.log('could not store the less file'); 167 | } else { 168 | console.log('compiled less source codes successfully...'); 169 | callback(); 170 | } 171 | } 172 | ); 173 | }); 174 | } catch ( err ) { 175 | console.log('Compiling less failed ' + err ); 176 | } 177 | }); 178 | 179 | // 180 | // ─── MAIN ─────────────────────────────────────────────────────────────────────── 181 | // 182 | 183 | /** Where everything starts */ 184 | gulp.task('default', ['typescript', 'resources', 'sheets']); 185 | 186 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /javascript/graph-monaco.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── MONACO STARTER ───────────────────────────────────────────────────────────── 9 | // 10 | 11 | function GraphInitMonacoOnStart ( ) { 12 | 13 | function uriFromPath ( _path ) { 14 | var pathName = path.resolve( _path ).replace( /\\/g, '/' ); 15 | if ( pathName.length > 0 && pathName.charAt( 0 ) !== '/' ) { 16 | pathName = '/' + pathName; 17 | } 18 | return encodeURI( 'file://' + pathName ); 19 | } 20 | 21 | require.config({ 22 | baseUrl: uriFromPath( __dirname ) 23 | }); 24 | 25 | // workaround monaco-css not understanding the environment 26 | self.module = undefined; 27 | 28 | // workaround monaco-typescript not understanding the environment 29 | self.process.browser = true; 30 | 31 | try { 32 | require([ 'vs/editor/editor.main' ], function ( ) { 33 | KaryGraph.UI.ProgrammerTab.Editor = monaco.editor.create( 34 | document.getElementById( 'monaco-placeholder' ), { 35 | value: '', 36 | language: 'javascript', 37 | fontFamily: 'GraphSourceCodePro', 38 | fontSize: 13, 39 | lineHeight: 24 40 | } 41 | ); 42 | }); 43 | } catch ( error ) { 44 | console.log(`could not load monaco: ${ error }`); 45 | } 46 | } 47 | 48 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /javascript/loading-screen.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── SMOOTHLY CANCELS THE LOADING SCREEN WHEN LOADED ──────────────────────────── 9 | // 10 | 11 | function CancelLoadingScreenAfterCompleteLoad ( ) { 12 | setTimeout(( ) => { 13 | setTimeout(( ) => { 14 | KaryGraph.UI.ProgrammerTab.ApplyAdditionalMonacoInitialization( ); 15 | let loadingView = document.getElementById('loading-view'); 16 | loadingView.className = 'dead-loading-view'; 17 | setTimeout(( ) => { 18 | loadingView.remove( ); 19 | }, 2000); 20 | }, 1300 ); 21 | }); 22 | } 23 | 24 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /less.sh: -------------------------------------------------------------------------------- 1 | lessc sheets/ui.less _compiled/style.css -------------------------------------------------------------------------------- /libs/prism.css: -------------------------------------------------------------------------------- 1 | /* http://prismjs.com/download.html?themes=prism-coy&languages=clike+javascript */ 2 | /** 3 | * prism.js Coy theme for JavaScript, CoffeeScript, CSS and HTML 4 | * Based on https://github.com/tshedor/workshop-wp-theme (Example: http://workshop.kansan.com/category/sessions/basics or http://workshop.timshedor.com/category/sessions/basics); 5 | * @author Tim Shedor 6 | */ 7 | 8 | code[class*="language-"], 9 | pre[class*="language-"] { 10 | color: black; 11 | background: none; 12 | font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; 13 | text-align: left; 14 | white-space: pre; 15 | word-spacing: normal; 16 | word-break: normal; 17 | word-wrap: normal; 18 | line-height: 1.5; 19 | 20 | -moz-tab-size: 4; 21 | -o-tab-size: 4; 22 | tab-size: 4; 23 | 24 | -webkit-hyphens: none; 25 | -moz-hyphens: none; 26 | -ms-hyphens: none; 27 | hyphens: none; 28 | } 29 | 30 | /* Code blocks */ 31 | pre[class*="language-"] { 32 | position: relative; 33 | margin: .5em 0; 34 | -webkit-box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf; 35 | -moz-box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf; 36 | box-shadow: -1px 0px 0px 0px #358ccb, 0px 0px 0px 1px #dfdfdf; 37 | border-left: 10px solid #358ccb; 38 | background-color: #fdfdfd; 39 | background-image: -webkit-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); 40 | background-image: -moz-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); 41 | background-image: -ms-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); 42 | background-image: -o-linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); 43 | background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.04) 50%); 44 | background-size: 3em 3em; 45 | background-origin: content-box; 46 | overflow: visible; 47 | padding: 0; 48 | } 49 | 50 | code[class*="language"] { 51 | max-height: inherit; 52 | height: 100%; 53 | padding: 0 1em; 54 | display: block; 55 | overflow: auto; 56 | } 57 | 58 | /* Margin bottom to accomodate shadow */ 59 | :not(pre) > code[class*="language-"], 60 | pre[class*="language-"] { 61 | background-color: #fdfdfd; 62 | -webkit-box-sizing: border-box; 63 | -moz-box-sizing: border-box; 64 | box-sizing: border-box; 65 | margin-bottom: 1em; 66 | } 67 | 68 | /* Inline code */ 69 | :not(pre) > code[class*="language-"] { 70 | position: relative; 71 | padding: .2em; 72 | -webkit-border-radius: 0.3em; 73 | -moz-border-radius: 0.3em; 74 | -ms-border-radius: 0.3em; 75 | -o-border-radius: 0.3em; 76 | border-radius: 0.3em; 77 | color: #c92c2c; 78 | border: 1px solid rgba(0, 0, 0, 0.1); 79 | display: inline; 80 | white-space: normal; 81 | } 82 | 83 | pre[class*="language-"]:before, 84 | pre[class*="language-"]:after { 85 | content: ''; 86 | z-index: -2; 87 | display: block; 88 | position: absolute; 89 | bottom: 0.75em; 90 | left: 0.18em; 91 | width: 40%; 92 | height: 20%; 93 | max-height: 13em; 94 | -webkit-box-shadow: 0px 13px 8px #979797; 95 | -moz-box-shadow: 0px 13px 8px #979797; 96 | box-shadow: 0px 13px 8px #979797; 97 | -webkit-transform: rotate(-2deg); 98 | -moz-transform: rotate(-2deg); 99 | -ms-transform: rotate(-2deg); 100 | -o-transform: rotate(-2deg); 101 | transform: rotate(-2deg); 102 | } 103 | 104 | :not(pre) > code[class*="language-"]:after, 105 | pre[class*="language-"]:after { 106 | right: 0.75em; 107 | left: auto; 108 | -webkit-transform: rotate(2deg); 109 | -moz-transform: rotate(2deg); 110 | -ms-transform: rotate(2deg); 111 | -o-transform: rotate(2deg); 112 | transform: rotate(2deg); 113 | } 114 | 115 | .token.comment, 116 | .token.block-comment, 117 | .token.prolog, 118 | .token.doctype, 119 | .token.cdata { 120 | color: #7D8B99; 121 | } 122 | 123 | .token.punctuation { 124 | color: #5F6364; 125 | } 126 | 127 | .token.property, 128 | .token.tag, 129 | .token.boolean, 130 | .token.number, 131 | .token.function-name, 132 | .token.constant, 133 | .token.symbol, 134 | .token.deleted { 135 | color: #007AE0; 136 | } 137 | 138 | .token.selector, 139 | .token.attr-name, 140 | .token.string, 141 | .token.char, 142 | .token.function, 143 | .token.builtin, 144 | .token.inserted { 145 | color: black; 146 | } 147 | 148 | .token.operator, 149 | .token.entity, 150 | .token.url, 151 | .token.variable { 152 | color: black; 153 | } 154 | 155 | .token.atrule, 156 | .token.attr-value, 157 | .token.keyword, 158 | .token.class-name { 159 | color: #B400B8; 160 | } 161 | 162 | .token.regex, 163 | .token.important { 164 | color: #e90; 165 | } 166 | 167 | .language-css .token.string, 168 | .style .token.string { 169 | color: #a67f59; 170 | background: rgba(255, 255, 255, 0.5); 171 | } 172 | 173 | .token.important { 174 | font-weight: normal; 175 | } 176 | 177 | .token.bold { 178 | font-weight: bold; 179 | } 180 | .token.italic { 181 | font-style: italic; 182 | } 183 | 184 | .token.entity { 185 | cursor: help; 186 | } 187 | 188 | .namespace { 189 | opacity: .7; 190 | } 191 | 192 | @media screen and (max-width: 767px) { 193 | pre[class*="language-"]:before, 194 | pre[class*="language-"]:after { 195 | bottom: 14px; 196 | -webkit-box-shadow: none; 197 | -moz-box-shadow: none; 198 | box-shadow: none; 199 | } 200 | 201 | } 202 | 203 | /* Plugin styles */ 204 | .token.tab:not(:empty):before, 205 | .token.cr:before, 206 | .token.lf:before { 207 | color: #e0d7d1; 208 | } 209 | 210 | /* Plugin styles: Line Numbers */ 211 | pre[class*="language-"].line-numbers { 212 | padding-left: 0; 213 | } 214 | 215 | pre[class*="language-"].line-numbers code { 216 | padding-left: 3.8em; 217 | } 218 | 219 | pre[class*="language-"].line-numbers .line-numbers-rows { 220 | left: 0; 221 | } 222 | 223 | /* Plugin styles: Line Highlight */ 224 | pre[class*="language-"][data-line] { 225 | padding-top: 0; 226 | padding-bottom: 0; 227 | padding-left: 0; 228 | } 229 | pre[data-line] code { 230 | position: relative; 231 | padding-left: 4em; 232 | } 233 | pre .line-highlight { 234 | margin-top: 0; 235 | } 236 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "graph", 3 | "productName": "Kary Graph", 4 | "author": "Kary Foundation", 5 | "main": "main.js", 6 | "description": "The most powerful programming environments for graphs!", 7 | "homepage": "https://github.com/karyfoundation/graph", 8 | "license": "Apache-2.0", 9 | "version": "0.1.0", 10 | "scripts": { 11 | "start": "electron ./_compiled/main.js --enable-logging", 12 | "dev": "NODE_ENV='development' npm run start", 13 | "dist": "node_modules/.bin/build --mac --x64 --version=1.3.3" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/karyfoundation/graph" 18 | }, 19 | "build": { 20 | "appId": "org.karyfoundation.graph", 21 | "copyright": "Copyright 2016 by Kary Foundation, Inc. All right reserved.", 22 | "dmg": { 23 | "contents": [ 24 | { 25 | "x": 410, 26 | "y": 220, 27 | "type": "link", 28 | "path": "/Applications" 29 | }, 30 | { 31 | "x": 130, 32 | "y": 220, 33 | "type": "file" 34 | } 35 | ] 36 | } 37 | }, 38 | "dependencies": { 39 | "monaco-editor": "^0.5.3", 40 | "prismjs": "^1.5.1", 41 | "snapsvg": "^0.4.0" 42 | }, 43 | "devDependencies": { 44 | "electron-builder": "^5.30.0", 45 | "electron-packager": "^7.7.0", 46 | "electron-prebuilt": "^1.3.3", 47 | "fs-extra": "0.30.0", 48 | "gulp": "3.9.1", 49 | "gulp-cli": "1.2.1", 50 | "gulp-uglify": "1.5.3", 51 | "less": "2.7.1", 52 | "mv": "^2.1.1", 53 | "sloc": "0.1.10", 54 | "typescript": "1.8.10", 55 | "uglifyjs": "2.4.10" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /resources/Vegur-R_0_600.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/Vegur-R_0_600.eot -------------------------------------------------------------------------------- /resources/Vegur-R_0_600.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/Vegur-R_0_600.ttf -------------------------------------------------------------------------------- /resources/Vegur-R_0_600.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/Vegur-R_0_600.woff -------------------------------------------------------------------------------- /resources/kary-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/kary-logo.png -------------------------------------------------------------------------------- /resources/opening-logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/opening-logo.png -------------------------------------------------------------------------------- /resources/playbutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/playbutton.png -------------------------------------------------------------------------------- /resources/ribbon-editor-add-loop.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-editor-add-loop.png -------------------------------------------------------------------------------- /resources/ribbon-editor-connect.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-editor-connect.png -------------------------------------------------------------------------------- /resources/ribbon-editor-remove.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-editor-remove.png -------------------------------------------------------------------------------- /resources/ribbon-editor-select.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-editor-select.png -------------------------------------------------------------------------------- /resources/ribbon-general-new-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-general-new-file.png -------------------------------------------------------------------------------- /resources/ribbon-general-open-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-general-open-file.png -------------------------------------------------------------------------------- /resources/ribbon-general-save-file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-general-save-file.png -------------------------------------------------------------------------------- /resources/ribbon-programmer-comment-line.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-programmer-comment-line.png -------------------------------------------------------------------------------- /resources/ribbon-programmer-comment-section.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-programmer-comment-section.png -------------------------------------------------------------------------------- /resources/ribbon-programmer-run.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/ribbon-programmer-run.png -------------------------------------------------------------------------------- /resources/sourcecodepro-medium-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/sourcecodepro-medium-webfont.woff -------------------------------------------------------------------------------- /resources/sourcecodepro-medium-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/sourcecodepro-medium-webfont.woff2 -------------------------------------------------------------------------------- /resources/toolbar-back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/toolbar-back.png -------------------------------------------------------------------------------- /resources/toolbar-tabs-algorithms.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/toolbar-tabs-algorithms.png -------------------------------------------------------------------------------- /resources/toolbar-tabs-editor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/toolbar-tabs-editor.png -------------------------------------------------------------------------------- /resources/toolbar-tabs-programmer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pouyakary/Graph/ca18d866c8d8b0f0c1e7ee70152bd9c2db1420f2/resources/toolbar-tabs-programmer.png -------------------------------------------------------------------------------- /sheets/base.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import 'globals'; 12 | 13 | // 14 | // ─── BASE ─────────────────────────────────────────────────────────────────────── 15 | // 16 | 17 | html { 18 | background-color: @color-1; 19 | font-family: @font-sans-serif; 20 | font-size: @base-font-size; 21 | overflow: hidden; 22 | min-height: 400px; 23 | min-width: 300px; 24 | } 25 | 26 | body { 27 | margin: 0; 28 | } 29 | 30 | :focus { 31 | outline-color: transparent; 32 | outline-style: none; 33 | } 34 | 35 | input { 36 | font-size: 1rem; 37 | } 38 | 39 | // 40 | // ─── UNSELECTABLE ─────────────────────────────────────────────────────────────── 41 | // 42 | 43 | .unselectable { 44 | -webkit-touch-callout: none; 45 | -webkit-user-select: none; 46 | -khtml-user-select: none; 47 | -moz-user-select: none; 48 | -ms-user-select: none; 49 | user-select: none; 50 | } 51 | 52 | // 53 | // ─── LOADING VIEW ─────────────────────────────────────────────────────────────── 54 | // 55 | 56 | #loading-view { 57 | position: fixed; 58 | top: 0; 59 | left: 0; 60 | padding-top: ~'calc( 50vh - 60px )'; 61 | height: 100vh; 62 | width: 100vw; 63 | background-color: white; 64 | color: @kary-light-red; 65 | font-size: 3rem; 66 | text-align: center; 67 | overflow: hidden; 68 | } 69 | 70 | .dead-loading-view { 71 | opacity: 0; 72 | transition-duration: 0.7s; 73 | } 74 | 75 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/fonts/source-code-pro.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../globals'; 12 | 13 | // 14 | // ─── FONT LOADER ──────────────────────────────────────────────────────────────── 15 | // 16 | 17 | @font-face { 18 | font-family: @source-code-pro-typeface; 19 | src: url('sourcecodepro-medium-webfont.woff2') format('woff2'), 20 | url('sourcecodepro-medium-webfont.woff') format('woff'); 21 | font-weight: normal; 22 | font-style: normal; 23 | } 24 | 25 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/fonts/vegur.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../globals'; 12 | 13 | // 14 | // ─── FONT LOADER ──────────────────────────────────────────────────────────────── 15 | // 16 | 17 | @font-face { 18 | font-family: @vogur-typeface; 19 | src: url("Vegur-R_0_600.eot?") format("eot"), 20 | url("Vegur-R_0_600.woff") format("woff"), 21 | url("Vegur-R_0_600.ttf") format("truetype"), 22 | url("Vegur-R_0_600.svg#Vegur-Regular") format("svg"); 23 | font-weight: normal; 24 | font-style: normal; 25 | } 26 | 27 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/globals.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── HEADER HEIGHT ────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @header-height: 29px; 12 | 13 | // 14 | // ─── FONT NAMES ───────────────────────────────────────────────────────────────── 15 | // 16 | 17 | @source-code-pro-typeface: 'GraphSourceCodePro'; 18 | 19 | @vogur-typeface: 'GraphVegurLight'; 20 | 21 | // 22 | // ─── GLOBALS ──────────────────────────────────────────────────────────────────── 23 | // 24 | 25 | @color-1: @kary-light-background; 26 | @color-2: white; 27 | @color-3: @kary-light-foreground; 28 | @color-4: @kary-light-blue; 29 | 30 | @font-sans-serif: @vogur-typeface; 31 | @base-font-size: 12px; 32 | 33 | @mono-type: @source-code-pro-typeface; 34 | 35 | @inspector-width: 298px; 36 | 37 | // 38 | // ─── SIZING ───────────────────────────────────────────────────────────────────── 39 | // 40 | 41 | @header-padding-top: 4px; 42 | 43 | @icon-box-size: 30px; 44 | @icon-size: 23px; 45 | @active-icon-size: 28px; 46 | 47 | @toolbar-padding-top: 10px; 48 | 49 | @notebook-blue-color: @kary-light-blue; 50 | 51 | @toolbar-tabs-width: 580px; 52 | 53 | @ribbon-height: 70px; 54 | 55 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/libs/kary-scheme.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Kary Foundation's Brand Color Scheme 4 | // Copyright 2016 Kary Foundation, Inc - All Rights Reserved. 5 | // 6 | // IMPORTANT 7 | // Premission to use this color scheme is ONLY granted for use within Kary 8 | // Foundation Branded Projects. As a brand property you get no right to use 9 | // this theme with any other project. 10 | // 11 | 12 | // 13 | // ─── KARY FOUNDATION LIGHT ────────────────────────────────────────────────────── 14 | // 15 | 16 | @kary-light-orange: #B36D00; 17 | @kary-light-red: #C03207; 18 | @kary-light-magenta: #9F0D97; 19 | @kary-light-blue: #2A75C0; 20 | @kary-light-green: #317410; 21 | 22 | @kary-light-foreground: #141414; 23 | @kary-light-comment: #BBB7B5; 24 | @kary-light-background: #F5F5F5; 25 | 26 | @kary-light-selection: #C2E8F4; 27 | @kary-light-highlights: #ECECEC; 28 | 29 | // 30 | // ─── KARY FOUNDATION DARK ─────────────────────────────────────────────────────── 31 | // 32 | 33 | @kary-dark-orange: #B48337; 34 | @kary-dark-red: #D17051; 35 | @kary-dark-magenta: #A47097; 36 | @kary-dark-blue: #668BB7; 37 | @kary-dark-green: #6F985A; 38 | 39 | @kary-dark-foreground: #C1C1C1; 40 | @kary-dark-comment: #5D5D5D; 41 | @kary-dark-background: #141414; 42 | 43 | @kary-dark-selcetion: #1B424E; 44 | @kary-dark-highlights: #1B1B1B; 45 | 46 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/scroll.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── SCROLL BAR SIZES ─────────────────────────────────────────────────────────── 9 | // 10 | 11 | @scroll-border: 4px; 12 | @scroll-size: 5px; 13 | 14 | // 15 | // ─── SCROLL BAR ───────────────────────────────────────────────────────────────── 16 | // 17 | 18 | ::-webkit-scrollbar { 19 | width: @scroll-size + 2 * @scroll-border; 20 | height: @scroll-size; 21 | } 22 | 23 | ::-webkit-scrollbar-thumb { 24 | height: @scroll-size; 25 | border: @scroll-border solid rgba(0, 0, 0, 0); 26 | background-clip: padding-box; 27 | border-radius: @scroll-size; 28 | background-color: rgba( 0, 0, 0, 0.1 ); 29 | } 30 | 31 | ::-webkit-scrollbar-buttom { 32 | width: 0; 33 | height: 0; 34 | display: none; 35 | } 36 | 37 | ::-webkit-scrollbar-corner { 38 | background-color: transparent; 39 | } 40 | 41 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/ui.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import 'sheets/base'; 12 | @import 'sheets/globals'; 13 | @import 'sheets/scroll'; 14 | 15 | @import 'sheets/fonts/vegur'; 16 | @import 'sheets/fonts/source-code-pro'; 17 | 18 | @import 'sheets/views/graph'; 19 | @import 'sheets/views/tab-view'; 20 | 21 | @import 'sheets/views/programmer/monaco'; 22 | 23 | @import 'sheets/views/algorithms/view'; 24 | @import 'sheets/views/algorithms/controller'; 25 | 26 | @import 'sheets/views/toolbar/toolbar'; 27 | @import 'sheets/views/toolbar/tabs'; 28 | @import 'sheets/views/toolbar/ribbon'; 29 | 30 | @import 'sheets/views/toolbar/ribbons/general'; 31 | @import 'sheets/views/toolbar/ribbons/editor'; 32 | @import 'sheets/views/toolbar/ribbons/programmer'; 33 | 34 | @import 'sheets/views/inspector/inspector'; 35 | @import 'sheets/views/inspector/prompt'; 36 | @import 'sheets/views/inspector/say'; 37 | 38 | // ──────────────────────────────────────────────────────────────────────────────── 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /sheets/views/algorithms/controller.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../libs/kary-scheme'; 12 | 13 | // 14 | // ─── CONTROLLER MAIN ──────────────────────────────────────────────────────────── 15 | // 16 | 17 | .algorithm-controller { 18 | background: white; 19 | box-shadow: 0 0 20px rgba(0, 0, 0, 0.05); 20 | border-radius: 5px; 21 | padding: 17px 20px 10px 20px; 22 | margin: 40px 0 0 40px; 23 | float: left; 24 | width: 270px; 25 | clear: right; 26 | } 27 | 28 | // 29 | // ─── TITLE ────────────────────────────────────────────────────────────────────── 30 | // 31 | 32 | .algorithm-controller-title { 33 | color: @kary-light-magenta; 34 | font-size: 1.8rem; 35 | } 36 | 37 | // 38 | // ─── AUTHOR ───────────────────────────────────────────────────────────────────── 39 | // 40 | 41 | .algorithm-controller-author { 42 | color: @kary-light-blue; 43 | font-size: 13px; 44 | padding: 5px 0 10px 0; 45 | } 46 | 47 | // 48 | // ─── DESCRIPTION ──────────────────────────────────────────────────────────────── 49 | // 50 | 51 | .algorithm-controller-description { 52 | color: @kary-light-foreground; 53 | font-size: 13px; 54 | line-height: 1.3; 55 | } 56 | 57 | // 58 | // ─── RUN BUTTON ───────────────────────────────────────────────────────────────── 59 | // 60 | 61 | .algorithm-controller-run-button { 62 | padding: 8px 40px 7px 40px; 63 | color: @kary-light-background; 64 | background: #4CB81B; 65 | border-radius: 100px; 66 | width: fit-content; 67 | margin: 10px 0 10px 0; 68 | font-size: 14px; 69 | } 70 | 71 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/algorithms/view.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── ALGORITHM VIEW ───────────────────────────────────────────────────────────── 9 | // 10 | 11 | #AlgorithmsView { 12 | overflow-y: scroll; 13 | height: calc( ~'100vh' - 139px ); 14 | padding-bottom: 100px; 15 | } 16 | 17 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/graph.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../globals'; 12 | 13 | // 14 | // ─── GRAPH AND RIBBON HALF ────────────────────────────────────────────────────── 15 | // 16 | 17 | #graph-and-ribbon-half { 18 | @width: @inspector-width + 2px; 19 | width: calc( ~'100vw' - @width ); 20 | float: left; 21 | } 22 | 23 | // 24 | // ─── GRAPH VIEW ───────────────────────────────────────────────────────────────── 25 | // 26 | 27 | #GraphView { 28 | width: 100%; 29 | height: ~'calc( 100vh - 110px )'; 30 | } 31 | 32 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/inspector/inspector.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../globals'; 12 | @import 'sizings'; 13 | @import '../../libs/kary-scheme'; 14 | 15 | // 16 | // ─── SCRIPT EDITOR ────────────────────────────────────────────────────────────── 17 | // 18 | 19 | #inspector { 20 | width: @inspector-width; 21 | height: ~'calc( 100vh - 39px )'; 22 | float: left; 23 | background-color: #ddd; 24 | border-left: 2px @kary-light-background solid; 25 | } 26 | 27 | .inspector-section { 28 | } 29 | 30 | .inspector-section-title { 31 | border-top-left-radius: @inspector-border-radius; 32 | border-top-right-radius: @inspector-border-radius; 33 | border-bottom: 2px solid @kary-light-background; 34 | } 35 | 36 | .inspector-section-title-text { 37 | background-color: white; 38 | width: @inspector-width; 39 | padding: 5px; 40 | padding-left: 10px; 41 | padding-top: 7px; 42 | color: @kary-light-magenta; 43 | font-size: 1.1rem; 44 | // text-transform: uppercase; 45 | // letter-spacing: 4px; 46 | float: left; 47 | } 48 | 49 | .inspector-section-title-icon { 50 | margin-top: 2px; 51 | margin-right: 6px; 52 | width: 28px; 53 | height: 28px; 54 | float: right; 55 | } 56 | 57 | .inspector-section-body { 58 | background-color: #eee; 59 | font-size: 1.1rem; 60 | } 61 | 62 | // ──────────────────────────────────────────────────────────────────────────────── 63 | -------------------------------------------------------------------------------- /sheets/views/inspector/prompt.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../globals'; 12 | @import 'sizings'; 13 | 14 | // 15 | // ─── PROMPT ───────────────────────────────────────────────────────────────────── 16 | // 17 | 18 | .notebook { 19 | height: calc( ~'100vh' - 69px ); 20 | background-color: white; 21 | padding: @inspector-width-padding; 22 | overflow-y: scroll; 23 | overflow-x: hidden; 24 | } 25 | 26 | .notebook-row { 27 | font-family: @mono-type; 28 | font-size: 1rem; 29 | border-left: 2px solid #eee; 30 | padding-left: 7px; 31 | margin-bottom: 7px; 32 | height: fit-content; 33 | width: @inspector-width - 2 * @inspector-width-padding; 34 | overflow-x: scroll; 35 | } 36 | 37 | .notebook-row-code { 38 | color: @kary-light-foreground; 39 | overflow-x: scroll; 40 | width: max-content; 41 | height: fit-content; 42 | } 43 | 44 | .notebook-row-result { 45 | color: @kary-light-foreground; 46 | overflow-x: scroll; 47 | width: max-content; 48 | height: fit-content; 49 | } 50 | 51 | .notebook-row-say-base { 52 | border-left: 2px solid @kary-light-blue; 53 | padding-left: 10px; 54 | width: fit-content; 55 | overflow: visible; 56 | height: fit-content; 57 | } 58 | 59 | .notebook-say-row { 60 | height: fit-content; 61 | overflow-x: scroll; 62 | } 63 | 64 | .notebook-prompt { 65 | border-left: 2px solid @kary-light-red; 66 | padding-left: 7px; 67 | } 68 | 69 | .notebook-prompt input { 70 | font-family: @mono-type; 71 | font-size: 1rem; 72 | border: none; 73 | width: 100%; 74 | } 75 | 76 | .notebook-error { 77 | color: @kary-light-red; 78 | } 79 | 80 | // ────────────────────────────────────────────────────────────────────────────────ß -------------------------------------------------------------------------------- /sheets/views/inspector/say.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../globals'; 12 | 13 | // 14 | // ─── SAY IMPLEMENTATIONS ──────────────────────────────────────────────────────── 15 | // 16 | 17 | .say-dot { 18 | width: auto; 19 | font-size: 0.8rem; 20 | padding-left: 4px; 21 | } 22 | 23 | .say-dot-dot { 24 | width: 14px; 25 | height: 14px; 26 | background-color: black; 27 | border-radius: 8px; 28 | margin-top: 2px; 29 | } 30 | 31 | .say-string { 32 | color: black; 33 | font-size: 1.3rem; 34 | font-family: @font-sans-serif; 35 | } 36 | 37 | .say-number { 38 | font-size: 1.3rem; 39 | color: @notebook-blue-color; 40 | } 41 | 42 | .say-array { 43 | overflow-x: scroll; 44 | font-family: @font-sans-serif; 45 | border: 0; 46 | } 47 | 48 | .say-array-index { 49 | color: #C7C7C7; 50 | font-size: 0.8rem; 51 | font-weight: bold; 52 | overflow: hidden; 53 | border-top-left-radius: 3px; 54 | border-top-right-radius: 3px; 55 | text-align: center; 56 | padding: 2px; 57 | } 58 | 59 | .say-array-cell { 60 | position: relative; 61 | margin-top: 0; 62 | background-color: #F5F5F5; 63 | border-radius: 3px; 64 | padding-bottom: 6px; 65 | } 66 | 67 | .say-array-value { 68 | padding-left: 6px; 69 | padding-right: 6px; 70 | } 71 | 72 | .say-matrix { 73 | text-align: center; 74 | font-family: 'GraphSourceCodePro'; 75 | font-size: 0.9rem; 76 | padding-left: 1px; 77 | border-image-slice: 22 22 22 22; 78 | border-image-width: 20px 20px 20px 20px; 79 | border-image-outset: 0px 0px 0px 0px; 80 | border-image-repeat: stretch stretch; 81 | border-image-source: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACEAAABKCAYAAAA11z32AAAAAXNSR0IArs4c6QAAAJpJREFUaAXt2jEKg0AARUE3t9wT7jENFtO5IEhSPZsHRtkw/NKx1jqPm2vOOW5uv7q1O+vY/vDquOcvX+d/nj/+uyf7E2yTSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAtokkCGibSIKAjt13Vv/82OsLo94UYanCbyYAAAAASUVORK5CYII="); 82 | } 83 | 84 | // ──────────────────────────────────────────────────────────────────────────────── 85 | -------------------------------------------------------------------------------- /sheets/views/inspector/sizings.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // ─── GLOBAL SIZINGS ───────────────────────────────────────────────────────────── 4 | // 5 | 6 | @inspector-width-padding: 15px; 7 | @inspector-border-radius: 7px; 8 | 9 | // ──────────────────────────────────────────────────────────────────────────────── 10 | -------------------------------------------------------------------------------- /sheets/views/programmer/monaco.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../libs/kary-scheme'; 12 | 13 | // 14 | // ─── MONACO CURSOR ────────────────────────────────────────────────────────────── 15 | // 16 | 17 | .monaco-editor .cursor { 18 | background: @kary-light-blue; 19 | } 20 | 21 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/tab-view.less: -------------------------------------------------------------------------------- 1 | 2 | 3 | // 4 | // Copyright 2016 Kary Foundation, Inc. 5 | // Author: Pouya Kary 6 | // 7 | 8 | // 9 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 10 | // 11 | 12 | @import '../globals'; 13 | 14 | // 15 | // ─── TAB VIEW ─────────────────────────────────────────────────────────────────── 16 | // 17 | 18 | .tab-view { 19 | width: 100vw; 20 | height: calc( ~'100vh' - 52px - @ribbon-height ); 21 | } 22 | 23 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/toolbar/ribbon.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORTS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../libs/kary-scheme'; 12 | 13 | // 14 | // ─── RIBBON BAR MAIN ──────────────────────────────────────────────────────────── 15 | // 16 | 17 | @ribbon-border-size: 4px; 18 | @ribbon-border-bottom-size: 1px; 19 | .ribbon { 20 | width: 100%; 21 | height: @ribbon-height; 22 | background: white; 23 | border-bottom: #f5f5f5 1px solid; 24 | } 25 | 26 | // 27 | // ─── RIBBON ICON ──────────────────────────────────────────────────────────────── 28 | // 29 | 30 | .ribbon-icon { 31 | background-position: top center; 32 | background-size: 34px 34px; 33 | background-repeat: no-repeat; 34 | margin: 8px 5px 0 5px; 35 | padding-top: 41px; 36 | width: max-content; 37 | min-width: 46px; 38 | text-align: center; 39 | color: @kary-light-foreground; 40 | float: left; 41 | padding-bottom: 6px; 42 | border-bottom-width: 3px; 43 | border-bottom-style: solid; 44 | border-bottom-color: transparent; 45 | } 46 | 47 | // 48 | // ─── RIBBON HOVER ─────────────────────────────────────────────────────────────── 49 | // 50 | 51 | .ribbon-icon:hover { 52 | border-bottom-color: #ccc; 53 | } 54 | 55 | // 56 | // ─── SEPARATOR ────────────────────────────────────────────────────────────────── 57 | // 58 | 59 | .ribbon-separator { 60 | @margin-tob-bottom: 8px; 61 | width: 2px; 62 | height: @ribbon-height - 2 * @margin-tob-bottom; 63 | margin: @margin-tob-bottom 8px @margin-tob-bottom 8px; 64 | background: #EEE; 65 | float: left; 66 | } 67 | 68 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/toolbar/ribbons/editor.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── SELECT ICON ──────────────────────────────────────────────────────────────── 9 | // 10 | 11 | #ribbon-editor-select-icon { 12 | background-image: url('ribbon-editor-select.png'); 13 | } 14 | 15 | // 16 | // ─── CONNECT ICON ─────────────────────────────────────────────────────────────── 17 | // 18 | 19 | #ribbon-editor-connect-icon { 20 | background-image: url('ribbon-editor-connect.png'); 21 | } 22 | 23 | // 24 | // ─── REMOVE ICON ──────────────────────────────────────────────────────────────── 25 | // 26 | 27 | #ribbon-editor-remove-icon { 28 | background-image: url('ribbon-editor-remove.png'); 29 | } 30 | 31 | // 32 | // ─── ADD LOOP ICON ────────────────────────────────────────────────────────────── 33 | // 34 | 35 | #ribbon-editor-add-loop-icon { 36 | background-image: url('ribbon-editor-add-loop.png'); 37 | } 38 | 39 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/toolbar/ribbons/general.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── NEW FILE ICON ────────────────────────────────────────────────────────────── 9 | // 10 | 11 | #ribbon-general-new-file { 12 | background-image: url('ribbon-general-new-file.png'); 13 | } 14 | 15 | // 16 | // ─── OPEN FILE ICON ───────────────────────────────────────────────────────────── 17 | // 18 | 19 | #ribbon-general-open-file { 20 | background-image: url('ribbon-general-open-file.png'); 21 | } 22 | 23 | // 24 | // ─── SAVE FILE ICON ───────────────────────────────────────────────────────────── 25 | // 26 | 27 | #ribbon-general-save-file { 28 | background-image: url('ribbon-general-save-file.png'); 29 | } 30 | 31 | // ──────────────────────────────────────────────────────────────────────────────── 32 | -------------------------------------------------------------------------------- /sheets/views/toolbar/ribbons/programmer.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── RUN ICON ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | #ribbon-programmer-run-icon { 12 | background-image: url('ribbon-programmer-run.png'); 13 | } 14 | 15 | // 16 | // ─── INSERT SECTION COMMENT ICON ──────────────────────────────────────────────── 17 | // 18 | 19 | #ribbon-programmer-comment-section { 20 | background-image: url('ribbon-programmer-comment-section.png'); 21 | } 22 | 23 | // 24 | // ─── INSERT LINE COMMENT ICON ─────────────────────────────────────────────────── 25 | // 26 | 27 | #ribbon-programmer-comment-line { 28 | background-image: url('ribbon-programmer-comment-line.png'); 29 | } 30 | 31 | // ──────────────────────────────────────────────────────────────────────────────── 32 | -------------------------------------------------------------------------------- /sheets/views/toolbar/tabs.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── IMPORT ───────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../globals'; 12 | 13 | // 14 | // ─── MAIN TABS VIEW ───────────────────────────────────────────────────────────── 15 | // 16 | 17 | #header-tabs { 18 | margin-left: 20px; 19 | float: left; 20 | background-size: contain; 21 | background-position: left; 22 | background-repeat: no-repeat; 23 | width: @toolbar-tabs-width; 24 | height: @header-height; 25 | } 26 | 27 | // 28 | // ─── TAB INVISIBLE MAPS ───────────────────────────────────────────────────────── 29 | // 30 | 31 | .invisible-tab { 32 | height: 30px; 33 | width: 102px; 34 | position: fixed; 35 | top: 9; 36 | } 37 | 38 | @tab-x-difference: 102px; 39 | @tab-x-start: 27px; 40 | 41 | #editor-tab-invisible { 42 | left: @tab-x-start; 43 | } 44 | 45 | #programmer-tab-invisible { 46 | left: @tab-x-start + @tab-x-difference; 47 | } 48 | 49 | #preferences-tab-invisible { 50 | left: @tab-x-start + 2 * @tab-x-difference; 51 | } 52 | 53 | // 54 | // ─── TABS ─────────────────────────────────────────────────────────────────────── 55 | // 56 | 57 | .editor-tab { 58 | background-image: url('toolbar-tabs-editor.png'); 59 | } 60 | 61 | .programmer-tab { 62 | background-image: url('toolbar-tabs-programmer.png'); 63 | } 64 | 65 | .algorithms-tab { 66 | background-image: url('toolbar-tabs-algorithms.png'); 67 | } 68 | 69 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /sheets/views/toolbar/toolbar.less: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── INCLUDES ─────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | @import '../../globals'; 12 | @import '../../libs/kary-scheme'; 13 | 14 | // 15 | // ─── HEADING ──────────────────────────────────────────────────────────────────── 16 | // 17 | 18 | .heading { 19 | background-size: contain; 20 | background-position: left bottom; 21 | background-repeat: no-repeat; 22 | padding-top: 6px; 23 | padding-bottom: 6px; 24 | //padding-left: 20px; 25 | padding-right: 20px; 26 | font-size: 1.8rem; 27 | color: @kary-light-foreground; 28 | height: @header-height - 6px; 29 | background-color: @color-2; 30 | overflow: hidden; 31 | border-bottom: @ribbon-border-size solid #B12CA8; 32 | } 33 | 34 | // 35 | // ─── HEADER ───────────────────────────────────────────────────────────────────── 36 | // 37 | 38 | #header-left { 39 | float: left; 40 | } 41 | 42 | #header-right { 43 | float: right; 44 | color: @color-4; 45 | padding-top: 0.25rem; 46 | font-size: 1.2rem; 47 | } 48 | 49 | // 50 | // ─── TOOLBAR ──────────────────────────────────────────────────────────────────── 51 | // 52 | 53 | .icon { 54 | float: left; 55 | height: @icon-box-size; 56 | width: @icon-box-size; 57 | margin-left: 10px; 58 | margin-top: 4px; 59 | background-size: contain; 60 | background-position: center; 61 | background-repeat: no-repeat; 62 | background-size: @icon-size @icon-size; 63 | } 64 | 65 | .icon:hover{ 66 | 67 | } 68 | 69 | .icon-active { 70 | background-size: @active-icon-size @active-icon-size; 71 | } 72 | 73 | #icon-move { 74 | margin-left: 30px; 75 | background-image: url('cursor.png'); 76 | } 77 | 78 | #icon-edit { 79 | background-image: url('edit.png'); 80 | } 81 | 82 | #icon-remove { 83 | background-image: url('remove.png'); 84 | } 85 | 86 | #icon-select { 87 | background-image: url('select.png'); 88 | } 89 | 90 | // 91 | // ─── STATUS BAR ───────────────────────────────────────────────────────────────── 92 | // 93 | 94 | #status-view { 95 | float: left; 96 | margin-left: @icon-size; 97 | margin-top: 11px; 98 | font-size: 1.2rem; 99 | color: @kary-light-orange; 100 | } 101 | 102 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "system", 4 | "target": "es6", 5 | "noImplicitAny": false, 6 | "sourceMap": false, 7 | "outFile": "_compiled/core.js", 8 | "removeComments": true 9 | }, 10 | "exclude": [ 11 | "node_modules" 12 | ] 13 | } -------------------------------------------------------------------------------- /view/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Graph 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 28 | 29 | 30 | 32 | 33 | 34 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | New 51 | Open 52 | Save 53 | 54 | 55 | 56 | Select 57 | Connect 58 | Remove 59 | Add Loop 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | Notebook 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | New 88 | Open 89 | Save 90 | 91 | 92 | 93 | 95 | Run 96 | 97 | 98 | 99 | Section 101 | 102 | Ending 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 136 | 137 | 138 | 139 | 140 | 144 | 145 | 146 | -------------------------------------------------------------------------------- /wrappers/wrappers.d.ts: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── NODE FS ──────────────────────────────────────────────────────────────────── 9 | // 10 | 11 | declare function JoinPath ( addresses: string[ ] ): string; 12 | 13 | // ──────────────────────────────────────────────────────────────────────────────── 14 | 15 | declare function ReadFile ( address: string, 16 | func: ( error: NodeJS.ErrnoException, 17 | data: string ) => void 18 | ); 19 | 20 | // ──────────────────────────────────────────────────────────────────────────────── 21 | 22 | declare function ReadFileSync ( address: string ): string; 23 | 24 | // ──────────────────────────────────────────────────────────────────────────────── 25 | 26 | declare function ReadDir ( address: string, 27 | func: ( error: NodeJS.ErrnoException, 28 | files: string[] ) => void 29 | ); 30 | 31 | // ──────────────────────────────────────────────────────────────────────────────── 32 | 33 | declare function ReadDirSync ( address: string ): string[ ]; 34 | 35 | // ──────────────────────────────────────────────────────────────────────────────── 36 | 37 | declare function FSStatsSync ( address: string ): IFSStatsResult; 38 | 39 | // ──────────────────────────────────────────────────────────────────────────────── 40 | 41 | declare function FSExistsSync ( address: string ): boolean; 42 | 43 | // ──────────────────────────────────────────────────────────────────────────────── 44 | 45 | declare function MakeDirSync ( address ); 46 | 47 | // 48 | // ─── PRISM JS ─────────────────────────────────────────────────────────────────── 49 | // 50 | 51 | declare function PrismHighlight ( code: string ): string; 52 | 53 | // 54 | // ─── GET HOME DIR ─────────────────────────────────────────────────────────────── 55 | // 56 | 57 | declare function GetHomeDir ( ): string; 58 | 59 | // 60 | // ─── NODE REQUIRE ─────────────────────────────────────────────────────────────── 61 | // 62 | 63 | declare function NodeRequire ( module: string ): Object; 64 | 65 | // ──────────────────────────────────────────────────────────────────────────────── 66 | 67 | 68 | 69 | // 70 | // ─── NODE INNER DEFS ──────────────────────────────────────────────────────────── 71 | // 72 | 73 | interface IFSStatsResult { 74 | isFile ( ): boolean; 75 | isDirectory ( ): boolean; 76 | isBlockDevice ( ): boolean; 77 | isCharacterDevice ( ): boolean; 78 | isSymbolicLink ( ): boolean; 79 | isFIFO ( ): boolean; 80 | isSocket ( ): boolean; 81 | } 82 | 83 | // ──────────────────────────────────────────────────────────────────────────────── -------------------------------------------------------------------------------- /wrappers/wrappers.js: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // Copyright 2016 Kary Foundation, Inc. 4 | // Author: Pouya Kary 5 | // 6 | 7 | // 8 | // ─── VERY IMPORTANT MESSAGE ───────────────────────────────────────────────────── 9 | // Graph uses TypeScript's own module system not CommonJS and that makes loading & 10 | // using node modules impossible inside the 'KaryGraph' and other modules of the 11 | // same kind. Hence this wrappers are used to provide a very simple bridge for 12 | // providing node functionality inside the core modules. 13 | // 14 | 15 | // 16 | // ─── PRISM HIGHLIGHTING WRAPPER ───────────────────────────────────────────────── 17 | // 18 | 19 | function PrismHighlight ( code ) { 20 | return Prism.highlight( code, Prism.languages.javascript ); 21 | } 22 | 23 | // 24 | // ─── NODE JS COMMON TOOLS ─────────────────────────────────────────────────────── 25 | // 26 | 27 | function JoinPath ( addresses ) { 28 | let result = ''; 29 | addresses.forEach( address => { 30 | result = path.join( result , address ); 31 | }); 32 | return result; 33 | } 34 | 35 | // 36 | // ─── NODE READ FILE ───────────────────────────────────────────────────────────── 37 | // 38 | 39 | function ReadFile ( address, callback ) { 40 | fs.readFile( address, 'utf8 ', callback ); 41 | } 42 | 43 | function ReadFileSync ( address ) { 44 | return fs.readFileSync( address, 'utf8' ); 45 | } 46 | 47 | // 48 | // ─── GET DIRECTORY ────────────────────────────────────────────────────────────── 49 | // 50 | 51 | function ReadDir ( address, callback ) { 52 | fs.readdir( address , callback ); 53 | } 54 | 55 | function ReadDirSync ( address ) { 56 | return fs.readdirSync( address ); 57 | } 58 | 59 | // 60 | // ─── MKDIR SYNC ───────────────────────────────────────────────────────────────── 61 | // 62 | 63 | function MakeDirSync ( address) { 64 | fs.mkdirSync( address ); 65 | } 66 | 67 | // 68 | // ─── FS STATS ─────────────────────────────────────────────────────────────────── 69 | // 70 | 71 | function FSStatsSync ( address ) { 72 | return fs.statSync( address ); 73 | } 74 | 75 | // 76 | // ─── FS EXISTS ────────────────────────────────────────────────────────────────── 77 | // 78 | 79 | function FSExistsSync ( address ) { 80 | return fs.existsSync( address ); 81 | } 82 | 83 | // 84 | // ─── GET HOME DIR ─────────────────────────────────────────────────────────────── 85 | // 86 | 87 | function GetHomeDir ( ) { 88 | return process.env.HOME; 89 | } 90 | 91 | // 92 | // ─── NODE REQUIRE ─────────────────────────────────────────────────────────────── 93 | // 94 | 95 | var NodeRequire = require; 96 | 97 | // ──────────────────────────────────────────────────────────────────────────────── --------------------------------------------------------------------------------