├── .gitattributes ├── .gitignore ├── JSON_Export ├── farbric_with_text.json ├── simple.json └── with_picture_svg_json.json ├── PSDs ├── icon.psd ├── project_bg.psd └── startup.psd ├── README.md ├── css ├── app.css ├── app_dark.css ├── font-awesome.min.css ├── galaxy.theme.css ├── macos.theme.css ├── material.theme.css ├── ruler.css ├── style.css └── vanilla.theme.css ├── floido.jpg ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf ├── fontawesome-webfont.woff ├── fontawesome-webfont.woff2 ├── photon-entypo.eot ├── photon-entypo.svg ├── photon-entypo.ttf └── photon-entypo.woff ├── iOS_Fontlist.txt ├── icons ├── icon.png ├── mac │ └── icon.icns ├── png │ ├── 1024x1024.png │ ├── 128x128.png │ ├── 16x16.png │ ├── 24x24.png │ ├── 256x256.png │ ├── 32x32.png │ ├── 48x48.png │ ├── 512x512.png │ ├── 64x64.png │ └── 96x96.png ├── project_bg.png ├── project_bg_sm.png ├── startup.png └── win │ └── icon.ico ├── images ├── bg.png ├── escheresque.png ├── fab.png ├── honey_im_subtle.png ├── icons.svg ├── squareLoader.gif ├── thumbnail-flows.png ├── thumbnail-loading.png ├── thumbnail-paging.png ├── thumbnail-scrolling.png ├── thumbnail-states.png ├── thumbnail-tutorial.png ├── thumbnail-tutorial2.png └── woman.png ├── index 2.html ├── index.html ├── js ├── additionJs │ ├── aligning_guidelines.js │ ├── centering_guidelines.js │ ├── electAngular.js │ ├── helpers.js │ ├── jsFromIndex.js │ ├── keymaster.js │ ├── paster.js │ ├── utils.js │ └── xel.min.js ├── angular │ └── angular.min.js ├── bootstrap │ └── bootstrap.min_not_used.js ├── controllers │ └── kitchensinkController │ │ ├── CanvasControlsController.js │ │ ├── FontsController.js │ │ ├── LayersController.js │ │ ├── LeftTabsController.js │ │ ├── PagesController.js │ │ ├── RightTabsController.js │ │ ├── bgContrlController.js │ │ └── projectListController.js ├── direcives │ └── kitchensinkDirectives │ │ ├── app_config_not_used.js │ │ ├── bindValueToDirective.js │ │ ├── edObjectsPanelSortableDirective.js │ │ └── objectButtonsEnabledDirective.js ├── fabric │ └── fabric.min.js ├── jquery │ ├── jquery-ui.min.js │ ├── jquery.min.js │ └── jquery.nestable.js ├── objects │ ├── ObjectsPanelController.js │ └── ObjectsPanelSortableDirective.js ├── ruler │ ├── ruler.js │ ├── rulerConstructor.js │ ├── rulerGuideLine.js │ ├── ruler_demo.js │ └── utils.js └── service │ ├── electangularServiceIpc.js │ ├── electronService.js │ ├── leftPanelTabService.js │ └── rightPanelTabService.js ├── lib └── font_definitions.js ├── main.js ├── main_ok.js ├── menu └── mainmenu.js ├── package-lock.json ├── package.json ├── project └── assets │ ├── proj_thumbnails │ ├── page1.png │ ├── page2.png │ ├── page3.png │ └── page4.png │ └── thumbnails │ ├── page1.png │ ├── page2.png │ ├── page3.png │ └── page4.png ├── templates ├── actions_menu 2.html ├── actions_menu.html ├── assests.html ├── export.html ├── inspectorTab.html ├── layers.html ├── layout_menu.html ├── page_menu.html ├── pages.html ├── project_menu.html ├── style_menu.html ├── templates.html ├── text_menu.html └── toolbar.html └── windows ├── index.html ├── project.html ├── settings.html └── simulator.html /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .idea/workspace.xml 3 | .idea/watcherTasks.xml 4 | .idea/vcs.xml 5 | .idea/modules.xml 6 | .idea/misc.xml 7 | .idea/floido-designer.iml 8 | js/webcomponents-lite_not_used.js 9 | js/v1.7.fabric.min_not_used.js 10 | js/undoredo_not_used.js 11 | js/csi.min_not_used.js 12 | project/assets/.DS_Store 13 | js/index_not_used.js 14 | js/v2.3.fabric.min_not_used.js 15 | project/.DS_Store 16 | .DS_Store 17 | .DS_Store 18 | .DS_Store 19 | .DS_Store 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /JSON_Export/farbric_with_text.json: -------------------------------------------------------------------------------- 1 | {"version":"2.0.0-beta7","objects":[{"type":"i-text","version":"2.0.0-beta7","originX":"left","originY":"top","left":100,"top":150,"width":230.05,"height":228.71,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"text":"lorem ipsum\ndolor\nsit Amet\nconsectetur","fontSize":40,"fontWeight":"normal","fontFamily":"Helvetica","fontStyle":"normal","lineHeight":1.16,"underline":false,"overline":false,"linethrough":false,"textAlign":"left","textBackgroundColor":"","charSpacing":0,"styles":{"0":{"0":{"fill":"red","fontSize":20},"1":{"fill":"red","fontSize":30},"2":{"fill":"red","fontSize":40},"3":{"fill":"red","fontSize":50},"4":{"fill":"red","fontSize":60},"6":{"textBackgroundColor":"yellow"},"7":{"textBackgroundColor":"yellow"},"8":{"textBackgroundColor":"yellow"},"9":{"textBackgroundColor":"yellow"}},"1":{"0":{"textDecoration":"underline"},"1":{"textDecoration":"underline"},"2":{"fill":"green","fontStyle":"italic","textDecoration":"underline"},"3":{"fill":"green","fontStyle":"italic","textDecoration":"underline"},"4":{"fill":"green","fontStyle":"italic","textDecoration":"underline"}},"2":{"0":{"fill":"blue","fontWeight":"bold"},"1":{"fill":"blue","fontWeight":"bold"},"2":{"fill":"blue","fontWeight":"bold"},"4":{"fontFamily":"Courier","textDecoration":"line-through"},"5":{"fontFamily":"Courier","textDecoration":"line-through"},"6":{"fontFamily":"Courier","textDecoration":"line-through"},"7":{"fontFamily":"Courier","textDecoration":"line-through"}},"3":{"0":{"fontFamily":"Impact","fill":"#666","textDecoration":"line-through"},"1":{"fontFamily":"Impact","fill":"#666","textDecoration":"line-through"},"2":{"fontFamily":"Impact","fill":"#666","textDecoration":"line-through"},"3":{"fontFamily":"Impact","fill":"#666","textDecoration":"line-through"},"4":{"fontFamily":"Impact","fill":"#666","textDecoration":"line-through"}}}},{"type":"i-text","version":"2.0.0-beta7","originX":"left","originY":"top","left":400,"top":150,"width":124.53,"height":150.06,"fill":"#333","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"text":"foo bar\nbaz\nquux","fontSize":40,"fontWeight":"normal","fontFamily":"Helvetica","fontStyle":"normal","lineHeight":1.16,"underline":false,"overline":false,"linethrough":false,"textAlign":"left","textBackgroundColor":"","charSpacing":0,"styles":{"0":{"0":{"fill":"red"},"1":{"fill":"red"},"2":{"fill":"red"}},"2":{"0":{"fill":"blue"},"1":{"fill":"blue"},"2":{"fill":"blue"},"3":{"fill":"blue"}}}},{"type":"rect","version":"2.0.0-beta7","originX":"left","originY":"top","left":579,"top":454,"width":50,"height":50,"fill":"#3b380c","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":0.8,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"rx":0,"ry":0},{"type":"circle","version":"2.0.0-beta7","originX":"left","originY":"top","left":563,"top":22,"width":100,"height":100,"fill":"#c89ffd","stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1,"scaleY":1,"angle":0,"flipX":false,"flipY":false,"opacity":0.8,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"radius":50,"startAngle":0,"endAngle":6.283185307179586},{"type":"ellipse","version":"2.0.0-beta7","originX":"left","originY":"top","left":477,"top":255,"width":170,"height":110,"fill":{"type":"linear","coords":{"x1":115,"y1":208.63636363636363,"x2":285,"y2":208.63636363636363},"colorStops":[{"offset":1,"color":"rgb(255,0,0)","opacity":1},{"offset":0,"color":"rgb(255,255,0)","opacity":1}],"offsetX":-115,"offsetY":-135,"gradientTransform":[1,0,0,0.6470588235294118,0,0]},"stroke":null,"strokeWidth":1,"strokeDashArray":null,"strokeLineCap":"butt","strokeLineJoin":"miter","strokeMiterLimit":10,"scaleX":1.41,"scaleY":1.41,"angle":-6,"flipX":false,"flipY":false,"opacity":1,"shadow":null,"visible":true,"clipTo":null,"backgroundColor":"","fillRule":"nonzero","globalCompositeOperation":"source-over","transformMatrix":null,"skewX":0,"skewY":0,"rx":85,"ry":55}],"background":"lightgrey"} -------------------------------------------------------------------------------- /JSON_Export/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "state": { 3 | "objects": [{ 4 | "type": "circle", 5 | "originX": "left", 6 | "originY": "top", 7 | "left": 530.21, 8 | "top": 94.73, 9 | "width": 144, 10 | "height": 144, 11 | "fill": "#f5ab35", 12 | "stroke": null, 13 | "strokeWidth": 5, 14 | "strokeDashArray": null, 15 | "strokeLineCap": "butt", 16 | "strokeLineJoin": "miter", 17 | "strokeMiterLimit": 10, 18 | "scaleX": 1, 19 | "scaleY": 1, 20 | "angle": 0, 21 | "flipX": false, 22 | "flipY": false, 23 | "opacity": 1, 24 | "shadow": null, 25 | "visible": true, 26 | "clipTo": null, 27 | "backgroundColor": "", 28 | "fillRule": "nonzero", 29 | "globalCompositeOperation": "source-over", 30 | "transformMatrix": null, 31 | "skewX": 0, 32 | "skewY": 0, 33 | "radius": 72, 34 | "startAngle": 0, 35 | "endAngle": 6.283185307179586, 36 | "selectable": true, 37 | "name": "circle" 38 | }, { 39 | "type": "rect", 40 | "originX": "left", 41 | "originY": "top", 42 | "left": 151.67, 43 | "top": 178.84, 44 | "width": 140, 45 | "height": 140, 46 | "fill": "#22a7f0", 47 | "stroke": null, 48 | "strokeWidth": 5, 49 | "strokeDashArray": null, 50 | "strokeLineCap": "butt", 51 | "strokeLineJoin": "miter", 52 | "strokeMiterLimit": 10, 53 | "scaleX": 1.94, 54 | "scaleY": 1.94, 55 | "angle": 0, 56 | "flipX": false, 57 | "flipY": false, 58 | "opacity": 1, 59 | "shadow": null, 60 | "visible": true, 61 | "clipTo": null, 62 | "backgroundColor": "", 63 | "fillRule": "nonzero", 64 | "globalCompositeOperation": "source-over", 65 | "transformMatrix": null, 66 | "skewX": 0, 67 | "skewY": 0, 68 | "rx": 0, 69 | "ry": 0, 70 | "selectable": true, 71 | "name": "rect" 72 | }], 73 | "background": "#c26363" 74 | }, 75 | "index": 4, 76 | "canvasWidth": 800, 77 | "canvasHeight": 600 78 | } 79 | -------------------------------------------------------------------------------- /PSDs/icon.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/PSDs/icon.psd -------------------------------------------------------------------------------- /PSDs/project_bg.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/PSDs/project_bg.psd -------------------------------------------------------------------------------- /PSDs/startup.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/PSDs/startup.psd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # floido designer 2 | 3 | **floido designer** is powerful visual editor based on open source libraries like electron, AngularJS, FabricJS and Xel widget toolkit for the UI. The final output of floido will be a serialized JSON file that you can use for your specific needs. 4 | 5 | **floido designer** is using the fabric.js canvas to insert, edit and style all type of contents, like text, JPEG, PNG, SVG and movie files. 6 | 7 | **floido designer** will be a desktop application using electron and will be targeted for OSX in the first step. 8 | 9 | # Setup 10 | 11 | Prerequisite: you should have node anf git installed on your system. 12 | 13 | 1. Install Electron Version 1.7.4 (1.7.4) – we need some of the beta functions for the XEL toolit 14 | 15 | 2. Clone or download the floido repository 16 | 17 | 3. run npm install for the node modules 18 | 19 | 4. Open terminal and cd in your local floido repository 20 | 21 | 5. run "electron ." 22 | 23 | You can also open the index.html with the newest chrome version using a local server. 24 | 25 | # Screenshots 26 | 27 | ![](https://github.com/sandor/floido/blob/master/floido.jpg) 28 | 29 | # Links 30 | 31 | [electron](https://electron.atom.io) 32 | 33 | [AngularJS](https://angularjs.org) 34 | 35 | [FabricJS](http://fabricjs.com) 36 | 37 | [XEL-toolkit](https://xel-toolkit.org/fallback.html) 38 | 39 |
40 | 41 | # MIT License 42 | 43 | Copyright (c) 2008-2015 Printio (Juriy Zaytsev, Maxim Chernyak) 44 | 45 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /css/ruler.css: -------------------------------------------------------------------------------- 1 | .rul_cornerTL, 2 | .rul_cornerTR { 3 | border-bottom: 1px solid rgba(206, 219, 236, .5) 4 | } 5 | .rul_cornerBL, 6 | .rul_cornerTL { 7 | border-right: 1px solid rgba(206, 219, 236, .5) 8 | } 9 | 10 | .rul_cornerBL, 11 | .rul_cornerBR { 12 | bottom: 1px; 13 | border-top: 1px solid rgba(206, 219, 236, .5) 14 | } 15 | .rul_cornerBR, 16 | .rul_cornerTR { 17 | right: 1px; 18 | border-left: 1px solid rgba(206, 219, 236, .5) 19 | } 20 | 21 | /* changed CSS to "top: 0;" */ 22 | 23 | 24 | .rul_wrapper { 25 | position: absolute; 26 | top: 0; 27 | height: 100%; 28 | width: 100%; 29 | overflow: hidden; 30 | pointer-events: none 31 | } 32 | .rul_corner, 33 | .rul_line, 34 | .rul_ruler { 35 | pointer-events: all; 36 | position: absolute 37 | } 38 | .rul_wrapper * { 39 | -webkit-user-select: none; 40 | -moz-user-select: none; 41 | -ms-user-select: none; 42 | -o-user-select: none; 43 | user-select: none 44 | } 45 | .rul_ruler { 46 | display: block; 47 | border: 1px solid rgba(206, 219, 236, .5); 48 | filter: blur(0); 49 | -webkit-filter: blur(0); 50 | z-index: 8 51 | } 52 | 53 | /* changed some CSS for a nice X in the corner */ 54 | 55 | .rul_corner { 56 | /* background-color: #fff;*/ 57 | background: #7E858E; 58 | width: 26px; 59 | height: 25px; 60 | position: relative; 61 | z-index: 11; 62 | cursor: pointer 63 | } 64 | 65 | .rul_corner:hover { 66 | background-color: #d3d3d3 67 | } 68 | 69 | .rul_corner:after { 70 | content: ''; 71 | height: 12px; 72 | border-left: 2px solid #fff; 73 | position: absolute; 74 | transform: rotate(45deg); 75 | left: 12px; 76 | top: 6px; 77 | } 78 | 79 | .rul_corner:before { 80 | content: ''; 81 | height: 12px; 82 | border-left: 2px solid #fff; 83 | position: absolute; 84 | transform: rotate(-45deg); 85 | left: 12px; 86 | top: 6px; 87 | } 88 | 89 | .rul_cornerTL { 90 | top: 0; 91 | left: 0 92 | } 93 | .rul_cornerTR { 94 | top: 1px 95 | } 96 | .rul_cornerBL { 97 | left: 1px 98 | } 99 | .rul_ruler_Vertical { 100 | cursor: ew-resize; 101 | border-left: none 102 | } 103 | .rul_ruler_Horizontal { 104 | cursor: ns-resize; 105 | border-top: none 106 | } 107 | .rul_line { 108 | color: transparent; 109 | background-color: transparent; 110 | border-bottom: 1px solid #3BB7C7; 111 | border-left: 1px solid #3BB7C7; 112 | z-index: 1000 113 | } 114 | .rul_line_dragged { 115 | border: 1px dotted #6B7587 116 | } 117 | .rul_line:hover { 118 | border-bottom: 1px solid #236E77; 119 | border-left: 1px solid #236E77 120 | } 121 | .rul_lineVer { 122 | top: 0; 123 | bottom: 0 124 | } 125 | .rul_lineVer:hover { 126 | cursor: ew-resize 127 | } 128 | .rul_lineHor { 129 | right: 0; 130 | left: 0 131 | } 132 | .rul_lineHor:hover { 133 | cursor: ns-resize 134 | } 135 | .rul_tooltip:after { 136 | background: #fff; 137 | color: #000; 138 | border: 1px solid gray; 139 | font-size: 10px; 140 | content: attr(data-tip); 141 | top: 50%; 142 | left: 50%; 143 | margin-top: 1px; 144 | margin-left: 1px; 145 | padding: 2px 5px; 146 | position: absolute; 147 | z-index: 10001; 148 | min-width: 45px 149 | } 150 | 151 | /* changed CSS to "top: 0;" */ 152 | 153 | .rul_tracker { 154 | height: 1px; 155 | width: 1px; 156 | background: #000; 157 | position: absolute; 158 | top: 0; 159 | pointer-events: none 160 | } 161 | -------------------------------------------------------------------------------- /css/style.css: -------------------------------------------------------------------------------- 1 | 2 | .image-builder-container { 3 | position: relative; 4 | } 5 | .image-builder-container .image-builder { 6 | background: transparent; 7 | box-sizing: border-box; 8 | border: 0; 9 | min-height: 100vh; 10 | min-width: 100%; 11 | text-align: center; 12 | position: relative; 13 | overflow-x: auto; 14 | overflow-y: auto; 15 | } 16 | .image-builder-container .image-builder .image-cover { 17 | left: 0; 18 | right: 0; 19 | bottom: 0; 20 | top: 0; 21 | position: absolute; 22 | z-index: 2; 23 | } 24 | .image-builder-container .image-builder .fabric-container { 25 | background: white; 26 | border-radius: 1px; 27 | box-shadow: 0 1px 4px -1px rgba(0, 0, 0, 0.4); 28 | display: inline-block; 29 | margin: 50px; 30 | position: relative; 31 | vertical-align: middle; 32 | z-index: 0; 33 | } 34 | .image-builder-container .image-loading { 35 | background: rgba(255, 255, 255, 0.4); 36 | position: absolute; 37 | top: 0; 38 | bottom: 0; 39 | left: 0; 40 | right: 0; 41 | z-index: 1; 42 | } 43 | .image-builder-container .image-loading .loading-indicator { 44 | background: white; 45 | background-image: url(/images/squareLoader.gif); 46 | background-repeat: no-repeat; 47 | background-position: center; 48 | border-radius: 10px; 49 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2); 50 | margin: 300px auto 0; 51 | height: 160px; 52 | width: 160px; 53 | } 54 | .image-builder-container .object-controls-container { 55 | position: relative; 56 | } 57 | .image-builder-container .object-controls-container .object-controls { 58 | position: absolute; 59 | z-index: 1; 60 | background: white; 61 | left: -250px; 62 | top: 0px; 63 | padding: 5px; 64 | width: 240px; 65 | } 66 | .image-builder-container .object-controls-container .object-controls textarea { 67 | font-size: 12px; 68 | } 69 | .object-font-family-preview { 70 | text-transform: capitalize; 71 | } 72 | -------------------------------------------------------------------------------- /floido.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/floido.jpg -------------------------------------------------------------------------------- /fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /fonts/photon-entypo.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/photon-entypo.eot -------------------------------------------------------------------------------- /fonts/photon-entypo.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/photon-entypo.ttf -------------------------------------------------------------------------------- /fonts/photon-entypo.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/fonts/photon-entypo.woff -------------------------------------------------------------------------------- /iOS_Fontlist.txt: -------------------------------------------------------------------------------- 1 | {name: 'American Typewriter', 2 | value: "American Typewriter", 3 | type: 'iOS'}, 4 | 5 | {name: 'Arial', 6 | value: "Arial", 7 | type: 'iOS'}, 8 | 9 | {name: 'Arial Rounded MT Bold', 10 | value: "Arial Rounded MT Bold", 11 | type: 'iOS'}, 12 | 13 | {name: 'Avenir', 14 | value: "Avenir", 15 | type: 'iOS'}, 16 | 17 | {name: 'Avenir Next', 18 | value: "Avenir Next", 19 | type: 'iOS'}, 20 | 21 | {name: 'Avenir Next Condensed', 22 | value: "Avenir Next Condensed", 23 | type: 'iOS'}, 24 | 25 | {name: 'Baskerville', 26 | value: "Baskerville", 27 | type: 'iOS'}, 28 | 29 | {name: 'Bodoni 72', 30 | value: "Bodoni 72", 31 | type: 'iOS'}, 32 | 33 | {name: 'Bodoni 72 Oldstyle', 34 | value: "Bodoni 72 Oldstyle", 35 | type: 'iOS'}, 36 | 37 | {name: 'Bodoni 72 Smallcaps', 38 | value: "Bodoni 72 Smallcaps", 39 | type: 'iOS'}, 40 | 41 | {name: 'Bodoni Ornaments', 42 | value: "Bodoni Orvaluents", 43 | type: 'iOS'}, 44 | 45 | {name: 'Bradly Hand Bold', 46 | value: "Bradly Hand Bold", 47 | type: 'iOS'}, 48 | 49 | {name: 'Chalkboard SE', 50 | value: "Chalkboard SE", 51 | type: 'iOS'}, 52 | 53 | {name: 'Chalkduster', 54 | value: "Chalkduster", 55 | type: 'iOS'}, 56 | 57 | {name: 'Cochin', 58 | value: "Cochin", 59 | type: 'iOS'}, 60 | 61 | {name: 'Copperplate', 62 | value: "Copperplate", 63 | type: 'iOS'}, 64 | 65 | {name: 'Courier', 66 | value: "Courier", 67 | type: 'iOS'}, 68 | 69 | {name: 'Courier New', 70 | value: "Courier New", 71 | type: 'iOS'}, 72 | 73 | {name: 'Futura', 74 | value: "Futura", 75 | type: 'iOS'}, 76 | 77 | {name: 'Geeza Pro', 78 | value: "Geeza Pro", 79 | type: 'iOS'}, 80 | 81 | {name: 'Georgia', 82 | value: "Georgia", 83 | type: 'iOS'}, 84 | 85 | {name: 'Gill Sans', 86 | value: "Gill Sans", 87 | type: 'iOS'}, 88 | 89 | {name: 'Helvetica', 90 | value: "Helvetica", 91 | type: 'iOS'}, 92 | 93 | {name: 'Helvetica Neue', 94 | value: "Helvetica Neue", 95 | type: 'iOS'}, 96 | 97 | {name: 'Marker Felt', 98 | value: "Marker Felt", 99 | type: 'iOS'}, 100 | 101 | {name: 'Optima', 102 | value: "Optima", 103 | type: 'iOS'}, 104 | 105 | {name: 'Palatino', 106 | value: "Palatino", 107 | type: 'iOS'}, 108 | 109 | {name: 'Papyrus', 110 | value: "Papyrus", 111 | type: 'iOS'}, 112 | 113 | {name: 'Papyrus Condensed', 114 | value: "Papyrus Condensed", 115 | type: 'iOS'}, 116 | 117 | {name: 'Symbol', 118 | value: "Symbol", 119 | type: 'iOS'}, 120 | 121 | {name: 'Times New Roman', 122 | value: "Times New Roman", 123 | type: 'iOS'}, 124 | 125 | {name: 'Trebuchet MS', 126 | value: "Trebuchet MS", 127 | type: 'iOS'}, 128 | 129 | {name: 'Verdana', 130 | value: "Verdana", 131 | type: 'iOS'}, 132 | 133 | {name: 'Zapf Dingbats', 134 | value: "Zapf Dingbats", 135 | type: 'iOS'}, 136 | 137 | {name: 'Zapfino', 138 | value: "Zapfino", 139 | type: 'iOS'} 140 | -------------------------------------------------------------------------------- /icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/icon.png -------------------------------------------------------------------------------- /icons/mac/icon.icns: -------------------------------------------------------------------------------- 1 | How to use this icon: 2 | 3 | Step 1: Copy the icon to the clipboard 4 | a) Click on this file from the Finder 5 | b) Choose 'Get Info' from the 'File' menu. 6 | c) In the info window that pops up, click on the icon 7 | d) Choose 'Copy' from the 'Edit' menu. 8 | e) Close the info window 9 | 10 | Step 2: Paste the icon to the desired item 11 | a) Go to the item in the Finder that you want a custom icon 12 | b) Click the item (file, folder, disk, etc) 13 | b) Choose 'Get Info' from the 'File' menu. 14 | c) In the info window that pops up, click on the icon 15 | d) Choose 'Paste' from the 'Edit' menu. 16 | e) Close the info window 17 | 18 | Step 3: 19 | Enjoy your newly customized icon! 20 | 21 | For more thorough directions, see Apple's website at: 22 | http://www.apple.com/support/mac101/customize/6/ 23 | -------------------------------------------------------------------------------- /icons/png/1024x1024.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/1024x1024.png -------------------------------------------------------------------------------- /icons/png/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/128x128.png -------------------------------------------------------------------------------- /icons/png/16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/16x16.png -------------------------------------------------------------------------------- /icons/png/24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/24x24.png -------------------------------------------------------------------------------- /icons/png/256x256.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/256x256.png -------------------------------------------------------------------------------- /icons/png/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/32x32.png -------------------------------------------------------------------------------- /icons/png/48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/48x48.png -------------------------------------------------------------------------------- /icons/png/512x512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/512x512.png -------------------------------------------------------------------------------- /icons/png/64x64.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/64x64.png -------------------------------------------------------------------------------- /icons/png/96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/png/96x96.png -------------------------------------------------------------------------------- /icons/project_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/project_bg.png -------------------------------------------------------------------------------- /icons/project_bg_sm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/project_bg_sm.png -------------------------------------------------------------------------------- /icons/startup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/startup.png -------------------------------------------------------------------------------- /icons/win/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/icons/win/icon.ico -------------------------------------------------------------------------------- /images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/bg.png -------------------------------------------------------------------------------- /images/escheresque.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/escheresque.png -------------------------------------------------------------------------------- /images/fab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/fab.png -------------------------------------------------------------------------------- /images/honey_im_subtle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/honey_im_subtle.png -------------------------------------------------------------------------------- /images/squareLoader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/squareLoader.gif -------------------------------------------------------------------------------- /images/thumbnail-flows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-flows.png -------------------------------------------------------------------------------- /images/thumbnail-loading.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-loading.png -------------------------------------------------------------------------------- /images/thumbnail-paging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-paging.png -------------------------------------------------------------------------------- /images/thumbnail-scrolling.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-scrolling.png -------------------------------------------------------------------------------- /images/thumbnail-states.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-states.png -------------------------------------------------------------------------------- /images/thumbnail-tutorial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-tutorial.png -------------------------------------------------------------------------------- /images/thumbnail-tutorial2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/thumbnail-tutorial2.png -------------------------------------------------------------------------------- /images/woman.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/images/woman.png -------------------------------------------------------------------------------- /index 2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | 109 | 110 | 111 | 112 | 113 | 114 |
115 |
116 |

Untitled

117 |
118 |
119 | 120 |
121 |
122 | 123 | 124 | 125 |
126 | 127 |
128 | 129 | 130 |
131 | 132 |
133 | 134 |
135 |
136 | 137 |
138 |
139 |
140 | 141 | 146 | 147 | 148 |
149 |
150 | 163 |
164 | 165 | 166 | 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 87 | 88 | 89 | 90 | 109 | 110 | 111 | 112 | 113 | 114 |
115 |
116 |

Untitled

117 |
118 |
119 | 120 |
121 |
122 | 123 | 124 | 125 |
126 | 127 |
128 |
129 | 130 | 131 |
132 | 133 |
134 | 135 |
136 |
137 | 138 |
139 |
140 | 141 |
142 | 147 | 148 |
149 | 150 |
151 | 164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | -------------------------------------------------------------------------------- /js/additionJs/aligning_guidelines.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Should objects be aligned by a bounding box? 3 | * [Bug] Scaled objects sometimes can not be aligned by edges 4 | * 5 | */ 6 | function initAligningGuidelines(canvas) { 7 | 8 | var ctx = canvas.getSelectionContext(), 9 | aligningLineOffset = 10, 10 | aligningLineMargin = 4, 11 | aligningLineWidth = 1, 12 | aligningLineColor = 'hsl(205,100%,75%)', 13 | viewportTransform, 14 | zoom = 1; 15 | 16 | function drawVerticalLine(coords) { 17 | drawLine( 18 | coords.x + 0.5, 19 | coords.y1 > coords.y2 ? coords.y2 : coords.y1, 20 | coords.x + 0.5, 21 | coords.y2 > coords.y1 ? coords.y2 : coords.y1); 22 | } 23 | 24 | function drawHorizontalLine(coords) { 25 | drawLine( 26 | coords.x1 > coords.x2 ? coords.x2 : coords.x1, 27 | coords.y + 0.5, 28 | coords.x2 > coords.x1 ? coords.x2 : coords.x1, 29 | coords.y + 0.5); 30 | } 31 | 32 | function drawLine(x1, y1, x2, y2) { 33 | ctx.save(); 34 | ctx.lineWidth = aligningLineWidth; 35 | ctx.strokeStyle = aligningLineColor; 36 | ctx.beginPath(); 37 | ctx.moveTo(((x1+viewportTransform[4])*zoom), ((y1+viewportTransform[5])*zoom)); 38 | ctx.lineTo(((x2+viewportTransform[4])*zoom), ((y2+viewportTransform[5])*zoom)); 39 | ctx.stroke(); 40 | ctx.restore(); 41 | } 42 | 43 | function isInRange(value1, value2) { 44 | value1 = Math.round(value1); 45 | value2 = Math.round(value2); 46 | for (var i = value1 - aligningLineMargin, len = value1 + aligningLineMargin; i <= len; i++) { 47 | if (i === value2) { 48 | return true; 49 | } 50 | } 51 | return false; 52 | } 53 | 54 | var verticalLines = [], 55 | horizontalLines = []; 56 | 57 | canvas.on('mouse:down', function () { 58 | viewportTransform = canvas.viewportTransform; 59 | zoom = canvas.getZoom(); 60 | }); 61 | 62 | canvas.on('object:moving', function(e) { 63 | 64 | var activeObject = e.target, 65 | canvasObjects = canvas.getObjects(), 66 | activeObjectCenter = activeObject.getCenterPoint(), 67 | activeObjectLeft = activeObjectCenter.x, 68 | activeObjectTop = activeObjectCenter.y, 69 | activeObjectHeight = activeObject.getBoundingRectHeight() / viewportTransform[3], 70 | activeObjectWidth = activeObject.getBoundingRectWidth() / viewportTransform[0], 71 | horizontalInTheRange = false, 72 | verticalInTheRange = false, 73 | transform = canvas._currentTransform; 74 | 75 | if (!transform) return; 76 | 77 | // It should be trivial to DRY this up by encapsulating (repeating) creation of x1, x2, y1, and y2 into functions, 78 | // but we're not doing it here for perf. reasons -- as this a function that's invoked on every mouse move 79 | 80 | for (var i = canvasObjects.length; i--; ) { 81 | 82 | if (canvasObjects[i] === activeObject) continue; 83 | 84 | var objectCenter = canvasObjects[i].getCenterPoint(), 85 | objectLeft = objectCenter.x, 86 | objectTop = objectCenter.y, 87 | objectHeight = canvasObjects[i].getBoundingRectHeight() / viewportTransform[3], 88 | objectWidth = canvasObjects[i].getBoundingRectWidth() / viewportTransform[0]; 89 | 90 | // snap by the horizontal center line 91 | if (isInRange(objectLeft, activeObjectLeft)) { 92 | verticalInTheRange = true; 93 | verticalLines.push({ 94 | x: objectLeft, 95 | y1: (objectTop < activeObjectTop) 96 | ? (objectTop - objectHeight / 2 - aligningLineOffset) 97 | : (objectTop + objectHeight / 2 + aligningLineOffset), 98 | y2: (activeObjectTop > objectTop) 99 | ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) 100 | : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) 101 | }); 102 | activeObject.setPositionByOrigin(new fabric.Point(objectLeft, activeObjectTop), 'center', 'center'); 103 | } 104 | 105 | // snap by the left edge 106 | if (isInRange(objectLeft - objectWidth / 2, activeObjectLeft - activeObjectWidth / 2)) { 107 | verticalInTheRange = true; 108 | verticalLines.push({ 109 | x: objectLeft - objectWidth / 2, 110 | y1: (objectTop < activeObjectTop) 111 | ? (objectTop - objectHeight / 2 - aligningLineOffset) 112 | : (objectTop + objectHeight / 2 + aligningLineOffset), 113 | y2: (activeObjectTop > objectTop) 114 | ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) 115 | : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) 116 | }); 117 | activeObject.setPositionByOrigin(new fabric.Point(objectLeft - objectWidth / 2 + activeObjectWidth / 2, activeObjectTop), 'center', 'center'); 118 | } 119 | 120 | // snap by the right edge 121 | if (isInRange(objectLeft + objectWidth / 2, activeObjectLeft + activeObjectWidth / 2)) { 122 | verticalInTheRange = true; 123 | verticalLines.push({ 124 | x: objectLeft + objectWidth / 2, 125 | y1: (objectTop < activeObjectTop) 126 | ? (objectTop - objectHeight / 2 - aligningLineOffset) 127 | : (objectTop + objectHeight / 2 + aligningLineOffset), 128 | y2: (activeObjectTop > objectTop) 129 | ? (activeObjectTop + activeObjectHeight / 2 + aligningLineOffset) 130 | : (activeObjectTop - activeObjectHeight / 2 - aligningLineOffset) 131 | }); 132 | activeObject.setPositionByOrigin(new fabric.Point(objectLeft + objectWidth / 2 - activeObjectWidth / 2, activeObjectTop), 'center', 'center'); 133 | } 134 | 135 | // snap by the vertical center line 136 | if (isInRange(objectTop, activeObjectTop)) { 137 | horizontalInTheRange = true; 138 | horizontalLines.push({ 139 | y: objectTop, 140 | x1: (objectLeft < activeObjectLeft) 141 | ? (objectLeft - objectWidth / 2 - aligningLineOffset) 142 | : (objectLeft + objectWidth / 2 + aligningLineOffset), 143 | x2: (activeObjectLeft > objectLeft) 144 | ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) 145 | : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) 146 | }); 147 | activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop), 'center', 'center'); 148 | } 149 | 150 | // snap by the top edge 151 | if (isInRange(objectTop - objectHeight / 2, activeObjectTop - activeObjectHeight / 2)) { 152 | horizontalInTheRange = true; 153 | horizontalLines.push({ 154 | y: objectTop - objectHeight / 2, 155 | x1: (objectLeft < activeObjectLeft) 156 | ? (objectLeft - objectWidth / 2 - aligningLineOffset) 157 | : (objectLeft + objectWidth / 2 + aligningLineOffset), 158 | x2: (activeObjectLeft > objectLeft) 159 | ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) 160 | : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) 161 | }); 162 | activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop - objectHeight / 2 + activeObjectHeight / 2), 'center', 'center'); 163 | } 164 | 165 | // snap by the bottom edge 166 | if (isInRange(objectTop + objectHeight / 2, activeObjectTop + activeObjectHeight / 2)) { 167 | horizontalInTheRange = true; 168 | horizontalLines.push({ 169 | y: objectTop + objectHeight / 2, 170 | x1: (objectLeft < activeObjectLeft) 171 | ? (objectLeft - objectWidth / 2 - aligningLineOffset) 172 | : (objectLeft + objectWidth / 2 + aligningLineOffset), 173 | x2: (activeObjectLeft > objectLeft) 174 | ? (activeObjectLeft + activeObjectWidth / 2 + aligningLineOffset) 175 | : (activeObjectLeft - activeObjectWidth / 2 - aligningLineOffset) 176 | }); 177 | activeObject.setPositionByOrigin(new fabric.Point(activeObjectLeft, objectTop + objectHeight / 2 - activeObjectHeight / 2), 'center', 'center'); 178 | } 179 | } 180 | 181 | if (!horizontalInTheRange) { 182 | horizontalLines.length = 0; 183 | } 184 | 185 | if (!verticalInTheRange) { 186 | verticalLines.length = 0; 187 | } 188 | }); 189 | 190 | canvas.on('before:render', function() { 191 | canvas.clearContext(canvas.contextTop); 192 | }); 193 | 194 | canvas.on('after:render', function() { 195 | for (var i = verticalLines.length; i--; ) { 196 | drawVerticalLine(verticalLines[i]); 197 | } 198 | for (var i = horizontalLines.length; i--; ) { 199 | drawHorizontalLine(horizontalLines[i]); 200 | } 201 | 202 | verticalLines.length = horizontalLines.length = 0; 203 | }); 204 | 205 | canvas.on('mouse:up', function() { 206 | verticalLines.length = horizontalLines.length = 0; 207 | canvas.renderAll(); 208 | }); 209 | } 210 | -------------------------------------------------------------------------------- /js/additionJs/centering_guidelines.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Augments canvas by assigning to `onObjectMove` and `onAfterRender`. 3 | * This kind of sucks because other code using those methods will stop functioning. 4 | * Need to fix it by replacing callbacks with pub/sub kind of subscription model. 5 | * (or maybe use existing fabric.util.fire/observe (if it won't be too slow)) 6 | */ 7 | function initCenteringGuidelines(canvas) { 8 | 9 | var canvasWidth = canvas.getWidth(), 10 | canvasHeight = canvas.getHeight(), 11 | canvasWidthCenter = canvasWidth / 2, 12 | canvasHeightCenter = canvasHeight / 2, 13 | canvasWidthCenterMap = { }, 14 | canvasHeightCenterMap = { }, 15 | centerLineMargin = 4, 16 | centerLineColor = 'hsl(205,100%,75%)', 17 | centerLineWidth = 1, 18 | ctx = canvas.getSelectionContext(), 19 | viewportTransform; 20 | 21 | for (var i = canvasWidthCenter - centerLineMargin, len = canvasWidthCenter + centerLineMargin; i <= len; i++) { 22 | canvasWidthCenterMap[Math.round(i)] = true; 23 | } 24 | for (var i = canvasHeightCenter - centerLineMargin, len = canvasHeightCenter + centerLineMargin; i <= len; i++) { 25 | canvasHeightCenterMap[Math.round(i)] = true; 26 | } 27 | 28 | function showVerticalCenterLine() { 29 | showCenterLine(canvasWidthCenter + 0.5, 0, canvasWidthCenter + 0.5, canvasHeight); 30 | } 31 | 32 | function showHorizontalCenterLine() { 33 | showCenterLine(0, canvasHeightCenter + 0.5, canvasWidth, canvasHeightCenter + 0.5); 34 | } 35 | 36 | function showCenterLine(x1, y1, x2, y2) { 37 | ctx.save(); 38 | ctx.strokeStyle = centerLineColor; 39 | ctx.lineWidth = centerLineWidth; 40 | ctx.beginPath(); 41 | ctx.moveTo(x1 * viewportTransform[0], y1 * viewportTransform[3]); 42 | ctx.lineTo(x2 * viewportTransform[0], y2 * viewportTransform[3]); 43 | ctx.stroke(); 44 | ctx.restore(); 45 | } 46 | 47 | var afterRenderActions = [], 48 | isInVerticalCenter, 49 | isInHorizontalCenter; 50 | 51 | canvas.on('mouse:down', function () { 52 | viewportTransform = canvas.viewportTransform; 53 | }); 54 | 55 | canvas.on('object:moving', function(e) { 56 | var object = e.target, 57 | objectCenter = object.getCenterPoint(), 58 | transform = canvas._currentTransform; 59 | 60 | if (!transform) return; 61 | 62 | isInVerticalCenter = Math.round(objectCenter.x) in canvasWidthCenterMap, 63 | isInHorizontalCenter = Math.round(objectCenter.y) in canvasHeightCenterMap; 64 | 65 | if (isInHorizontalCenter || isInVerticalCenter) { 66 | object.setPositionByOrigin(new fabric.Point((isInVerticalCenter ? canvasWidthCenter : objectCenter.x), (isInHorizontalCenter ? canvasHeightCenter : objectCenter.y)), 'center', 'center'); 67 | } 68 | }); 69 | 70 | canvas.on('before:render', function() { 71 | canvas.clearContext(canvas.contextTop); 72 | }); 73 | 74 | canvas.on('after:render', function() { 75 | if (isInVerticalCenter) { 76 | showVerticalCenterLine(); 77 | } 78 | if (isInHorizontalCenter) { 79 | showHorizontalCenterLine(); 80 | } 81 | }); 82 | 83 | canvas.on('mouse:up', function() { 84 | // clear these values, to stop drawing guidelines once mouse is up 85 | isInVerticalCenter = isInHorizontalCenter = null; 86 | canvas.renderAll(); 87 | }); 88 | } 89 | -------------------------------------------------------------------------------- /js/additionJs/electAngular.js: -------------------------------------------------------------------------------- 1 | /* 2 | > electangular.js 3 | > AngularJS Module for Atom Electron 4 | > (c)2016 develephant @develephant 5 | > license MIT 6 | > version 0.0.2 7 | */ 8 | 'use strict'; 9 | 10 | var electangular = angular.module('electangular', []) 11 | 12 | electangular.run(['$rootScope', 'electron', function ($rootScope, ele) { 13 | ele.ipcRenderer.on('electron-msg', (event, arg) => { 14 | $rootScope.$emit('electron-msg', arg); 15 | }); 16 | }]) 17 | 18 | electangular.value("electron_core", require('electron')) -------------------------------------------------------------------------------- /js/additionJs/keymaster.js: -------------------------------------------------------------------------------- 1 | // keymaster.js 2 | // (c) 2011-2013 Thomas Fuchs 3 | // keymaster.js may be freely distributed under the MIT license. 4 | 5 | ;(function(global){ 6 | var k, 7 | _handlers = {}, 8 | _mods = { 16: false, 18: false, 17: false, 91: false }, 9 | _scope = 'all', 10 | // modifier keys 11 | _MODIFIERS = { 12 | '⇧': 16, shift: 16, 13 | '⌥': 18, alt: 18, option: 18, 14 | '⌃': 17, ctrl: 17, control: 17, 15 | '⌘': 91, command: 91 16 | }, 17 | // special keys 18 | _MAP = { 19 | backspace: 8, tab: 9, clear: 12, 20 | enter: 13, 'return': 13, 21 | enter: 13, 'return': 13, 22 | esc: 27, escape: 27, space: 32, 23 | left: 37, up: 38, 24 | right: 39, down: 40, 25 | del: 46, 'delete': 46, 26 | home: 36, end: 35, 27 | pageup: 33, pagedown: 34, 28 | ',': 188, '.': 190, '/': 191, 29 | '`': 192, '-': 189, '=': 187, 30 | ';': 186, '\'': 222, 31 | '[': 219, ']': 221, '\\': 220 32 | }, 33 | code = function(x){ 34 | return _MAP[x] || x.toUpperCase().charCodeAt(0); 35 | }, 36 | _downKeys = []; 37 | 38 | for(k=1;k<20;k++) _MAP['f'+k] = 111+k; 39 | 40 | // IE doesn't support Array#indexOf, so have a simple replacement 41 | function index(array, item){ 42 | var i = array.length; 43 | while(i--) if(array[i]===item) return i; 44 | return -1; 45 | } 46 | 47 | // for comparing mods before unassignment 48 | function compareArray(a1, a2) { 49 | if (a1.length != a2.length) return false; 50 | for (var i = 0; i < a1.length; i++) { 51 | if (a1[i] !== a2[i]) return false; 52 | } 53 | return true; 54 | } 55 | 56 | var modifierMap = { 57 | 16:'shiftKey', 58 | 18:'altKey', 59 | 17:'ctrlKey', 60 | 91:'metaKey' 61 | }; 62 | function updateModifierKey(event) { 63 | for(k in _mods) _mods[k] = event[modifierMap[k]]; 64 | }; 65 | 66 | // handle keydown event 67 | function dispatch(event) { 68 | var key, handler, k, i, modifiersMatch, scope; 69 | key = event.keyCode; 70 | 71 | if (index(_downKeys, key) == -1) { 72 | _downKeys.push(key); 73 | } 74 | 75 | // if a modifier key, set the key. property to true and return 76 | if(key == 93 || key == 224) key = 91; // right command on webkit, command on Gecko 77 | if(key in _mods) { 78 | _mods[key] = true; 79 | // 'assignKey' from inside this closure is exported to window.key 80 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = true; 81 | return; 82 | } 83 | updateModifierKey(event); 84 | 85 | // see if we need to ignore the keypress (filter() can can be overridden) 86 | // by default ignore key presses if a select, textarea, or input is focused 87 | if(!assignKey.filter.call(this, event)) return; 88 | 89 | // abort if no potentially matching shortcuts found 90 | if (!(key in _handlers)) return; 91 | 92 | scope = getScope(); 93 | 94 | // for each potential shortcut 95 | for (i = 0; i < _handlers[key].length; i++) { 96 | handler = _handlers[key][i]; 97 | 98 | // see if it's in the current scope 99 | if(handler.scope == scope || handler.scope == 'all'){ 100 | // check if modifiers match if any 101 | modifiersMatch = handler.mods.length > 0; 102 | for(k in _mods) 103 | if((!_mods[k] && index(handler.mods, +k) > -1) || 104 | (_mods[k] && index(handler.mods, +k) == -1)) modifiersMatch = false; 105 | // call the handler and stop the event if neccessary 106 | if((handler.mods.length == 0 && !_mods[16] && !_mods[18] && !_mods[17] && !_mods[91]) || modifiersMatch){ 107 | if(handler.method(event, handler)===false){ 108 | if(event.preventDefault) event.preventDefault(); 109 | else event.returnValue = false; 110 | if(event.stopPropagation) event.stopPropagation(); 111 | if(event.cancelBubble) event.cancelBubble = true; 112 | } 113 | } 114 | } 115 | } 116 | }; 117 | 118 | // unset modifier keys on keyup 119 | function clearModifier(event){ 120 | var key = event.keyCode, k, 121 | i = index(_downKeys, key); 122 | 123 | // remove key from _downKeys 124 | if (i >= 0) { 125 | _downKeys.splice(i, 1); 126 | } 127 | 128 | if(key == 93 || key == 224) key = 91; 129 | if(key in _mods) { 130 | _mods[key] = false; 131 | for(k in _MODIFIERS) if(_MODIFIERS[k] == key) assignKey[k] = false; 132 | } 133 | }; 134 | 135 | function resetModifiers() { 136 | for(k in _mods) _mods[k] = false; 137 | for(k in _MODIFIERS) assignKey[k] = false; 138 | }; 139 | 140 | // parse and assign shortcut 141 | function assignKey(key, scope, method){ 142 | var keys, mods; 143 | keys = getKeys(key); 144 | if (method === undefined) { 145 | method = scope; 146 | scope = 'all'; 147 | } 148 | 149 | // for each shortcut 150 | for (var i = 0; i < keys.length; i++) { 151 | // set modifier keys if any 152 | mods = []; 153 | key = keys[i].split('+'); 154 | if (key.length > 1){ 155 | mods = getMods(key); 156 | key = [key[key.length-1]]; 157 | } 158 | // convert to keycode and... 159 | key = key[0] 160 | key = code(key); 161 | // ...store handler 162 | if (!(key in _handlers)) _handlers[key] = []; 163 | _handlers[key].push({ shortcut: keys[i], scope: scope, method: method, key: keys[i], mods: mods }); 164 | } 165 | }; 166 | 167 | // unbind all handlers for given key in current scope 168 | function unbindKey(key, scope) { 169 | var multipleKeys, keys, 170 | mods = [], 171 | i, j, obj; 172 | 173 | multipleKeys = getKeys(key); 174 | 175 | for (j = 0; j < multipleKeys.length; j++) { 176 | keys = multipleKeys[j].split('+'); 177 | 178 | if (keys.length > 1) { 179 | mods = getMods(keys); 180 | } 181 | 182 | key = keys[keys.length - 1]; 183 | key = code(key); 184 | 185 | if (scope === undefined) { 186 | scope = getScope(); 187 | } 188 | if (!_handlers[key]) { 189 | return; 190 | } 191 | for (i = 0; i < _handlers[key].length; i++) { 192 | obj = _handlers[key][i]; 193 | // only clear handlers if correct scope and mods match 194 | if (obj.scope === scope && compareArray(obj.mods, mods)) { 195 | _handlers[key][i] = {}; 196 | } 197 | } 198 | } 199 | }; 200 | 201 | // Returns true if the key with code 'keyCode' is currently down 202 | // Converts strings into key codes. 203 | function isPressed(keyCode) { 204 | if (typeof(keyCode)=='string') { 205 | keyCode = code(keyCode); 206 | } 207 | return index(_downKeys, keyCode) != -1; 208 | } 209 | 210 | function getPressedKeyCodes() { 211 | return _downKeys.slice(0); 212 | } 213 | 214 | function filter(event){ 215 | var tagName = (event.target || event.srcElement).tagName; 216 | // ignore keypressed in any elements that support keyboard data input 217 | return !(tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA'); 218 | } 219 | 220 | // initialize key. to false 221 | for(k in _MODIFIERS) assignKey[k] = false; 222 | 223 | // set current scope (default 'all') 224 | function setScope(scope){ _scope = scope || 'all' }; 225 | function getScope(){ return _scope || 'all' }; 226 | 227 | // delete all handlers for a given scope 228 | function deleteScope(scope){ 229 | var key, handlers, i; 230 | 231 | for (key in _handlers) { 232 | handlers = _handlers[key]; 233 | for (i = 0; i < handlers.length; ) { 234 | if (handlers[i].scope === scope) handlers.splice(i, 1); 235 | else i++; 236 | } 237 | } 238 | }; 239 | 240 | // abstract key logic for assign and unassign 241 | function getKeys(key) { 242 | var keys; 243 | key = key.replace(/\s/g, ''); 244 | keys = key.split(','); 245 | if ((keys[keys.length - 1]) == '') { 246 | keys[keys.length - 2] += ','; 247 | } 248 | return keys; 249 | } 250 | 251 | // abstract mods logic for assign and unassign 252 | function getMods(key) { 253 | var mods = key.slice(0, key.length - 1); 254 | for (var mi = 0; mi < mods.length; mi++) 255 | mods[mi] = _MODIFIERS[mods[mi]]; 256 | return mods; 257 | } 258 | 259 | // cross-browser events 260 | function addEvent(object, event, method) { 261 | if (object.addEventListener) 262 | object.addEventListener(event, method, false); 263 | else if(object.attachEvent) 264 | object.attachEvent('on'+event, function(){ method(window.event) }); 265 | }; 266 | 267 | // set the handlers globally on document 268 | addEvent(document, 'keydown', function(event) { dispatch(event) }); // Passing _scope to a callback to ensure it remains the same by execution. Fixes #48 269 | addEvent(document, 'keyup', clearModifier); 270 | 271 | // reset modifiers to false whenever the window is (re)focused. 272 | addEvent(window, 'focus', resetModifiers); 273 | 274 | // store previously defined key 275 | var previousKey = global.key; 276 | 277 | // restore previously defined key and return reference to our key object 278 | function noConflict() { 279 | var k = global.key; 280 | global.key = previousKey; 281 | return k; 282 | } 283 | 284 | // set window.key and window.key.set/get/deleteScope, and the default filter 285 | global.key = assignKey; 286 | global.key.setScope = setScope; 287 | global.key.getScope = getScope; 288 | global.key.deleteScope = deleteScope; 289 | global.key.filter = filter; 290 | global.key.isPressed = isPressed; 291 | global.key.getPressedKeyCodes = getPressedKeyCodes; 292 | global.key.noConflict = noConflict; 293 | global.key.unbind = unbindKey; 294 | 295 | if(typeof module !== 'undefined') module.exports = assignKey; 296 | 297 | })(this); 298 | -------------------------------------------------------------------------------- /js/additionJs/paster.js: -------------------------------------------------------------------------------- 1 | var Paster = { 2 | 3 | init: function(callback) { 4 | 5 | this.callback = callback; 6 | 7 | // if no Clipboard object, create a contenteditable element that catches all pasted data 8 | if (!window.Clipboard) { 9 | this.createContentEditable(); 10 | } 11 | 12 | window.addEventListener("paste", this.pasteHandler.bind(this)); 13 | }, 14 | 15 | createContentEditable: function() { 16 | var pasteCatcher = document.createElement("div"); 17 |    18 | // Firefox allows images to be pasted into contenteditable elements 19 | pasteCatcher.setAttribute("contenteditable", ""); 20 | pasteCatcher.style.cssText = 'position: fixed; top: 0; left: -9999px;'; 21 | 22 | document.body.appendChild(pasteCatcher); 23 | 24 | // make sure it is always in focus 25 | pasteCatcher.focus(); 26 | document.addEventListener("click", function() { 27 | pasteCatcher.focus(); 28 | }); 29 | }, 30 | 31 | pasteHandler: function(e) { 32 | 33 | if (e.clipboardData) { 34 | console.log(e.clipboardData); 35 | 36 | var items = e.clipboardData.items; 37 | if (items) { 38 | this.checkItems(items); 39 | } 40 | } 41 | else { 42 | // read what was pasted from the contenteditable element; likely Firefox 43 | // make sure data read AFTER it has been inserted 44 | setTimeout(this.checkInput.bind(this), 1); 45 | } 46 | }, 47 | 48 | checkItems: function(items) { 49 | for (var i = 0; i < items.length; i++) { 50 | if (items[i].type.indexOf("image") > -1) { 51 | this.handleImageItem(items[i]); 52 | } 53 | if (items[i].type.indexOf("text/plain") > -1) { 54 | this.handleTextItem(items[i]); 55 | } 56 | } 57 | }, 58 | 59 | handleImageItem: function(item) { 60 | 61 | // represent the image as a file 62 | var blob = item.getAsFile(); 63 | 64 | // and use a URL or webkitURL (whichever is available to the browser) 65 | // to create a temporary URL to the object 66 | var URLObj = window.URL || window.webkitURL; 67 | if (!URLObj) return; 68 | 69 | var source = URLObj.createObjectURL(blob); 70 | 71 | // The URL can then be used as the source of an image 72 | this.createImage(source); 73 | }, 74 | 75 | handleTextItem: function(item) { 76 | console.log('handleTextItem'); 77 | 78 | var _this = this; 79 | item.getAsString(function(str) { 80 | _this.callback(str); 81 | }); 82 | }, 83 | 84 | /* Parse the input in the paste catcher element */ 85 | checkInput: function() { 86 | 87 | // store the pasted content in a variable 88 | var child = pasteCatcher.childNodes[0]; 89 | 90 | // make sure we're always getting the latest inserted content 91 | pasteCatcher.innerHTML = ""; 92 |   93 | if (!child) return; 94 |   95 | // if the user pastes an image, the src attribute 96 | // will represent the image as a base64 encoded string. 97 | if (child.tagName === "IMG") { 98 | this.createImage(child.src); 99 | } 100 | 101 | console.log('child', child); 102 | }, 103 |   104 | createImage: function(source) { 105 | var pastedImage = new Image(); 106 | var _this = this; 107 | pastedImage.onload = function() { 108 | _this.callback(pastedImage); 109 | }; 110 | pastedImage.src = source; 111 | } 112 | }; 113 | -------------------------------------------------------------------------------- /js/additionJs/utils.js: -------------------------------------------------------------------------------- 1 | (function(global) { 2 | 3 | function capitalize(string) { 4 | return string.charAt(0).toUpperCase() + string.slice(1); 5 | } 6 | 7 | function pad(str, length) { 8 | while (str.length < length) { 9 | str = '0' + str; 10 | } 11 | return str; 12 | } 13 | 14 | var getRandomInt = fabric.util.getRandomInt; 15 | function getRandomColor() { 16 | return ( 17 | pad(getRandomInt(0, 255).toString(16), 2) + 18 | pad(getRandomInt(0, 255).toString(16), 2) + 19 | pad(getRandomInt(0, 255).toString(16), 2) 20 | ); 21 | } 22 | 23 | function getRandomNum(min, max) { 24 | return Math.random() * (max - min) + min; 25 | } 26 | 27 | function getRandomLeftTop() { 28 | var offset = 50; 29 | return { 30 | left: fabric.util.getRandomInt(0 + offset, 700 - offset), 31 | top: fabric.util.getRandomInt(0 + offset, 500 - offset) 32 | }; 33 | } 34 | 35 | var supportsInputOfType = function(type) { 36 | return function() { 37 | var el = document.createElement('input'); 38 | try { 39 | el.type = type; 40 | } 41 | catch(err) { } 42 | return el.type === type; 43 | }; 44 | }; 45 | 46 | var supportsSlider = supportsInputOfType('range'), 47 | supportsColorpicker = supportsInputOfType('color'); 48 | 49 | global.getRandomNum = getRandomNum; 50 | global.getRandomInt = getRandomInt; 51 | global.getRandomColor = getRandomColor; 52 | global.getRandomLeftTop = getRandomLeftTop; 53 | global.supportsSlider = supportsSlider; 54 | global.supportsColorpicker = supportsColorpicker; 55 | global.capitalize = capitalize; 56 | 57 | })(this); 58 | -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/CanvasControlsController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('CanvasControlsController', function ($scope, leftPanelTabService, rightPanelTabService) { 2 | 3 | $scope.currentLeftTab = leftPanelTabService.tab.url; 4 | $scope.currentRightTab = rightPanelTabService.tab.url; 5 | $scope.canvas = canvas; 6 | $scope.getActiveStyle = getActiveStyle; 7 | $scope.zoom = 0;//default zoom 8 | 9 | $scope.insideRulerWidth = document.getElementsByClassName("rul_wrapper")[0].offsetWidth 10 | - document.getElementsByClassName("rul_ruler_Vertical")[0].offsetHeight - 70; 11 | $scope.insideRulerheight = document.getElementsByClassName("rul_wrapper")[0].offsetHeight - document.getElementsByClassName("toolbar-header")[0].offsetHeight 12 | - document.getElementsByClassName("toolbar-footer")[0].offsetHeight - 90; 13 | 14 | 15 | $scope.leftTab = leftPanelTabService.leftTab; 16 | $scope.rightTab = rightPanelTabService.rightTab; 17 | 18 | 19 | addAccessors($scope); 20 | watchCanvas($scope); 21 | 22 | //get canvas Angle and set it 23 | 24 | canvas.on('object:rotating', function (options) { 25 | 26 | console.log(options.target); 27 | if (document.getElementById("canvas-angle")) { 28 | document.getElementById("canvas-angle").value = 29 | parseFloat(options.target.angle) 30 | ? parseFloat(options.target.angle).toFixed(2) 31 | : document.getElementById("canvas-angle").value; 32 | 33 | document.getElementById("canvas-angle").value = parseFloat(options.target.angle.toFixed(2)); 34 | } 35 | 36 | 37 | //document.getElementById("position-y").value = Math.round(options.target.angle); 38 | }); 39 | canvas.on('object:modified', function (options) { 40 | if (document.getElementById("position-x")) { 41 | 42 | document.getElementById("transform-angle").value = 43 | parseFloat(options.target.angle) 44 | ? parseFloat(options.target.angle).toFixed(2) 45 | : document.getElementById("transform-angle").value; 46 | 47 | 48 | document.getElementById("position-x").value = parseFloat(options.target.left.toFixed(2)); 49 | document.getElementById("position-y").value = parseFloat(options.target.top.toFixed(2)); 50 | document.getElementById("size-propWidth").value = Math.round(options.target.width); 51 | document.getElementById("size-propHeight").value = Math.round(options.target.height); 52 | 53 | document.getElementById("scale-scaleX").value = 54 | parseFloat(options.target.scaleX) 55 | ? parseFloat(options.target.scaleX.toFixed(2)) 56 | : document.getElementById("scale-scaleX").value; 57 | 58 | document.getElementById("scale-scaleY").value = 59 | parseFloat(options.target.scaleY) 60 | ? parseFloat(options.target.scaleY.toFixed(2)) 61 | : document.getElementById("scale-scaleY").value; 62 | 63 | } 64 | if ((!canvas.getActiveObject() && document.getElementById('enableShadow')) 65 | || (canvas.getActiveObject() && !canvas.getActiveObject().shadow && document.getElementById('enableShadow'))) { 66 | document.getElementById('enableShadow').removeAttribute('toggled'); 67 | } 68 | 69 | if (document.getElementById('shadow-Offset-X') && document.getElementById('shadow-Offset-Y') && canvas.getActiveObject()) { 70 | 71 | document.getElementById('shadow-Offset-X').value = canvasObjectShadowOffsetX; 72 | document.getElementById('shadow-Offset-Y').value = canvasObjectShadowOffsetY; 73 | document.getElementById('shadow-blur').value = canvasObjectShadowBlur; 74 | 75 | } 76 | 77 | 78 | }); 79 | 80 | canvas.on('after:render', function (option) { 81 | 82 | getCanvasActiveObjectData(); 83 | setCanvasActiveObjectData(); 84 | enableDisableElement(); 85 | 86 | 87 | }); 88 | 89 | 90 | // $scope.canvasAngle = canvasAngle; 91 | // Editing manipulating the Canvas Size 92 | // ================================================================ 93 | 94 | 95 | $scope.setMySize = function () { 96 | //; 97 | var setWidth = document.getElementById('myWidth').value; 98 | var setHeight = document.getElementById('myHeight').value; 99 | canvas.setWidth(setWidth); 100 | canvas.setHeight(setHeight); 101 | console.info(setWidth, setHeight); 102 | canvas.calcOffset(); 103 | }; 104 | 105 | $scope.presetSizes = [{ 106 | name: 'iPad Landscape', 107 | height: 768, 108 | width: 1024 109 | }, 110 | { 111 | name: 'iPad Portrait', 112 | height: 1024, 113 | width: 766 114 | }, 115 | { 116 | name: 'iPad Pro Landscape', 117 | height: 1024, 118 | width: 1366 119 | }, 120 | { 121 | name: 'iPad Pro Portrait', 122 | height: 1366, 123 | width: 1024 124 | } 125 | ]; 126 | 127 | 128 | $scope.setCanvasSize = function (width, height) { 129 | canvas.setWidth(width); 130 | canvas.setHeight(height); 131 | canvas.calcOffset(); 132 | console.log("resising now..."); 133 | 134 | }; 135 | 136 | 137 | $scope.setZoom = function (param) { 138 | 139 | [].__proto__.forEach.call(canvas._objects, (canvasItem) => { 140 | 141 | console.log(canvasItem.name); 142 | if (canvas.getActiveObject().name != 'Image' && canvasItem.name == 'Image') { 143 | canvas.setActiveObject(canvasItem); 144 | 145 | } 146 | 147 | }); 148 | 149 | let scaleFactor = param.zoom / 100; 150 | if (canvas._objects && !canvas.getActiveObject()) { 151 | canvas.setActiveObject(canvas._objects[0]) 152 | 153 | } 154 | if (canvas._objects && canvas.getActiveObject()) { 155 | 156 | 157 | canvas.setZoom(scaleFactor); 158 | canvas.setWidth(canvas.getZoom() * canvas.getActiveObject().width); 159 | canvas.setHeight(canvas.getZoom() * canvas.getActiveObject().height); 160 | 161 | } 162 | 163 | else { 164 | 165 | console.log("there is now active objects"); 166 | } 167 | //; 168 | 169 | 170 | }; 171 | 172 | 173 | $scope.originalSize = function (param) { 174 | [].__proto__.forEach.call(canvas._objects, (canvasItem) => { 175 | console.log(canvasItem.name); 176 | if (canvas.getActiveObject().name != 'Image' && canvasItem.name == 'Image') { 177 | canvas.setActiveObject(canvasItem); 178 | 179 | } 180 | 181 | }); 182 | 183 | if (canvas._objects && !canvas.getActiveObject()) { 184 | //; 185 | canvas.setActiveObject(canvas._objects[0]) 186 | } 187 | if (canvas._objects && canvas.getActiveObject()) { 188 | canvas.getActiveObject().scaleX = 1; 189 | canvas.getActiveObject().scaley = 1; 190 | canvas.getActiveObject().left = 0; 191 | canvas.getActiveObject().top = 0; 192 | canvas.setZoom(1); 193 | canvas.setWidth(canvas.getZoom() * canvas.getActiveObject().width); 194 | canvas.setHeight(canvas.getZoom() * canvas.getActiveObject().height); 195 | $scope.zoom = (1) * 100; 196 | } 197 | else { 198 | alert("there is now active objects"); 199 | } 200 | 201 | 202 | }; 203 | 204 | $scope.fitToWin = function (param) { 205 | 206 | [].__proto__.forEach.call(canvas._objects, (canvasItem) => { 207 | 208 | console.log(canvasItem.name); 209 | if (canvas.getActiveObject().name != 'Image' && canvasItem.name == 'Image') { 210 | canvas.setActiveObject(canvasItem); 211 | 212 | } 213 | 214 | }); 215 | 216 | $scope.insideRulerWidth = document.getElementsByClassName("rul_wrapper")[0].offsetWidth 217 | - document.getElementsByClassName("rul_ruler_Vertical")[0].offsetHeight - 70; 218 | $scope.insideRulerheight = document.getElementsByClassName("rul_wrapper")[0].offsetHeight 219 | - document.getElementsByClassName("toolbar-header")[0].offsetHeight 220 | - document.getElementsByClassName("toolbar-footer")[0].offsetHeight - 90; 221 | 222 | 223 | if (canvas._objects && !canvas.getActiveObject()) { 224 | canvas.setActiveObject(canvas._objects[0]) 225 | } 226 | if (canvas._objects && canvas.getActiveObject()) { 227 | 228 | //; 229 | 230 | canvas.getActiveObject().left = 0; 231 | canvas.getActiveObject().top = 0; 232 | canvas.setWidth($scope.insideRulerWidth); 233 | canvas.setHeight($scope.insideRulerheight); 234 | 235 | canvas.getActiveObject().scaleY = 1; 236 | canvas.getActiveObject().scaleX = 1; 237 | 238 | if (canvas._activeObject && canvas._activeObject.width > canvas._activeObject.height) { 239 | 240 | 241 | // $scope.zoom = ((canvas.width ) / canvas._activeObject.width) * 100; 242 | $scope.zoom = ((canvas.width ) / canvas._activeObject.width) > ((canvas.height ) / canvas._activeObject.height) 243 | ? (((canvas.height ) / canvas._activeObject.height) * 100) : (((canvas.width ) / canvas._activeObject.width) * 100); 244 | 245 | 246 | let scaleFactorWidth = ((canvas.width / canvas._activeObject.width) * canvas._activeObject.width); 247 | let scaleFactorHeight = ((canvas.height / canvas._activeObject.height) * canvas._activeObject.height); 248 | 249 | } 250 | else { 251 | let tempScale = (window.innerHeight - 170) / canvas.getActiveObject().height; 252 | let tempZoom = ((canvas.width ) / canvas._activeObject.width) > ((canvas.height ) / canvas._activeObject.height) 253 | ? (tempScale * 100) : (tempScale * 100); 254 | $scope.zoom = tempZoom 255 | 256 | } 257 | 258 | 259 | } 260 | 261 | else { 262 | alert("there is now active objects"); 263 | } 264 | 265 | 266 | }; 267 | 268 | 269 | //$scope.rightPanelTab = 'templates/inspectorTab.html'; 270 | // $scope.rightPanelTab = $scope.rightTab[1].url; 271 | 272 | $scope.leftTab = leftPanelTabService.leftTab; 273 | $scope.rightTab = rightPanelTabService.rightTab; 274 | 275 | $scope.currentLeftTab = leftPanelTabService.tab.url; 276 | $scope.currentRightTab = rightPanelTabService.tab.url; 277 | 278 | $scope.onClickRightTab = function (tab) { 279 | 280 | 281 | rightPanelTabService.setTab(tab); 282 | 283 | //$scope.currentLeftTab = tab.url; 284 | $scope.currentRightTab = rightPanelTabService.getTab().url; 285 | 286 | } 287 | 288 | 289 | $scope.onClickLeftTab = function (tab) { 290 | 291 | 292 | leftPanelTabService.setTab(tab); 293 | 294 | //$scope.currentLeftTab = tab.url; 295 | $scope.currentLeftTab = leftPanelTabService.getTab().url; 296 | } 297 | 298 | $scope.isActiveTab = function (tabUrl, side) { 299 | 300 | 301 | if (side && side == 'l') { 302 | return (tabUrl == $scope.currentLeftTab); 303 | } 304 | if (side && side == 'r') { 305 | 306 | 307 | [].__proto__.forEach.call(document.getElementsByClassName('right-tab'), (rightTabItem) => { 308 | 309 | rightTabItem.removeAttribute('toggled'); 310 | 311 | }); 312 | 313 | return (tabUrl == $scope.currentRightTab); 314 | } 315 | return false; 316 | } 317 | 318 | }); 319 | -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/FontsController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('FontsCtrl', function ($scope) { 2 | $scope.fonts = [ 3 | { 4 | name: 'American Typewriter', 5 | value: "american typewriter", 6 | type: 'iOS' 7 | }, 8 | 9 | { 10 | name: 'Arial', 11 | value: "arial", 12 | type: 'iOS' 13 | }, 14 | 15 | { 16 | name: 'Arial Rounded MT Bold', 17 | value: "Arial Rounded MT Bold", 18 | type: 'iOS' 19 | }, 20 | 21 | { 22 | name: 'Avenir', 23 | value: "Avenir", 24 | type: 'iOS' 25 | }, 26 | 27 | { 28 | name: 'Avenir Next', 29 | value: "Avenir Next", 30 | type: 'iOS' 31 | }, 32 | 33 | { 34 | name: 'Avenir Next Condensed', 35 | value: "Avenir Next Condensed", 36 | type: 'iOS' 37 | }, 38 | 39 | { 40 | name: 'Baskerville', 41 | value: "Baskerville", 42 | type: 'iOS' 43 | }, 44 | 45 | { 46 | name: 'Bodoni 72', 47 | value: "Bodoni 72", 48 | type: 'iOS' 49 | }, 50 | 51 | { 52 | name: 'Bodoni 72 Oldstyle', 53 | value: "Bodoni 72 Oldstyle", 54 | type: 'iOS' 55 | }, 56 | 57 | { 58 | name: 'Bodoni 72 Smallcaps', 59 | value: "Bodoni 72 Smallcaps", 60 | type: 'iOS' 61 | }, 62 | 63 | { 64 | name: 'Bodoni Ornaments', 65 | value: "Bodoni Orvaluents", 66 | type: 'iOS' 67 | }, 68 | 69 | { 70 | name: 'Bradly Hand Bold', 71 | value: "Bradly Hand Bold", 72 | type: 'iOS' 73 | }, 74 | 75 | { 76 | name: 'Chalkboard SE', 77 | value: "Chalkboard SE", 78 | type: 'iOS' 79 | }, 80 | 81 | { 82 | name: 'Chalkduster', 83 | value: "Chalkduster", 84 | type: 'iOS' 85 | }, 86 | 87 | { 88 | name: 'Cochin', 89 | value: "Cochin", 90 | type: 'iOS' 91 | }, 92 | 93 | { 94 | name: 'Copperplate', 95 | value: "Copperplate", 96 | type: 'iOS' 97 | }, 98 | 99 | { 100 | name: 'Courier', 101 | value: "Courier", 102 | type: 'iOS' 103 | }, 104 | 105 | { 106 | name: 'Courier New', 107 | value: "Courier New", 108 | type: 'iOS' 109 | }, 110 | 111 | { 112 | name: 'Futura', 113 | value: "Futura", 114 | type: 'iOS' 115 | }, 116 | 117 | { 118 | name: 'Geeza Pro', 119 | value: "Geeza Pro", 120 | type: 'iOS' 121 | }, 122 | 123 | { 124 | name: 'Georgia', 125 | value: "Georgia", 126 | type: 'iOS' 127 | }, 128 | 129 | { 130 | name: 'Gill Sans', 131 | value: "Gill Sans", 132 | type: 'iOS' 133 | }, 134 | 135 | { 136 | name: 'Helvetica', 137 | value: "Helvetica", 138 | type: 'iOS' 139 | }, 140 | 141 | { 142 | name: 'Helvetica Neue', 143 | value: "Helvetica Neue", 144 | type: 'iOS' 145 | }, 146 | 147 | { 148 | name: 'Marker Felt', 149 | value: "Marker Felt", 150 | type: 'iOS' 151 | }, 152 | 153 | { 154 | name: 'Optima', 155 | value: "Optima", 156 | type: 'iOS' 157 | }, 158 | 159 | { 160 | name: 'Palatino', 161 | value: "Palatino", 162 | type: 'iOS' 163 | }, 164 | 165 | { 166 | name: 'Papyrus', 167 | value: "Papyrus", 168 | type: 'iOS' 169 | }, 170 | 171 | { 172 | name: 'Papyrus Condensed', 173 | value: "Papyrus Condensed", 174 | type: 'iOS' 175 | }, 176 | 177 | { 178 | name: 'Roboto', 179 | value: "Roboto", 180 | type: 'iOS' 181 | }, 182 | 183 | { 184 | name: 'Symbol', 185 | value: "Symbol", 186 | type: 'iOS' 187 | }, 188 | 189 | { 190 | name: 'Times New Roman', 191 | value: "Times New Roman", 192 | type: 'iOS' 193 | }, 194 | 195 | { 196 | name: 'Trebuchet MS', 197 | value: "Trebuchet MS", 198 | type: 'iOS' 199 | }, 200 | 201 | { 202 | name: 'Verdana', 203 | value: "Verdana", 204 | type: 'iOS' 205 | }, 206 | 207 | { 208 | name: 'Zapf Dingbats', 209 | value: "Zapf Dingbats", 210 | type: 'iOS' 211 | }, 212 | 213 | { 214 | name: 'Zapfino', 215 | value: "Zapfino", 216 | type: 'iOS' 217 | } 218 | 219 | ]; 220 | }); 221 | -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/LayersController.js: -------------------------------------------------------------------------------- 1 | // Layer panel test implementation 2 | // ================================================================ 3 | 4 | kitchensink.controller('LayersController', ['$scope', '$rootScope', '$timeout', function ($scope, $rootScope, $timeout) { 5 | 6 | $scope.objects = canvas._objects || []; 7 | 8 | $scope.sortableOptions = { 9 | items: '.object:visible', 10 | scroll: false, 11 | axis: 'y', 12 | containment: 'parent', 13 | start: function (e, ui) { 14 | ui.item.data('start', ui.item.index()); 15 | }, 16 | update: function (e, ui) { 17 | var start = ui.item.data('start'), 18 | end = ui.item.index(); 19 | 20 | 21 | obj = canvas.getObjects()[start]; 22 | 23 | if (!obj) return; 24 | 25 | if (end > start) { 26 | //send object forwards by the amount of objects it passed 27 | for (var i = 0; i < (end - start); i++) { 28 | canvas.bringForward(obj); 29 | } 30 | } else { 31 | //send object backwards by the amount of objects it passed 32 | for (var i = 0; i < (start - end); i++) { 33 | canvas.sendBackwards(obj); 34 | } 35 | } 36 | 37 | $timeout(function () { 38 | canvas.renderAll(); 39 | start = false; 40 | end = false; 41 | }); 42 | }, 43 | } 44 | 45 | $scope.setAsActive = function (object) { 46 | if (object) { 47 | canvas.setActiveObject(object); 48 | } 49 | }; 50 | 51 | $scope.setAsActiveLayer = function (item, list) { 52 | list.some(function (item) { 53 | if (item.active) { 54 | return item.active = false; 55 | } 56 | }); 57 | item.active = true; 58 | }; 59 | 60 | $scope.toggleVisibility = function (object) { 61 | if (!object) return; 62 | 63 | if (object.visible) { 64 | object.set({ 65 | visible: false, 66 | evented: false, 67 | selectable: false, 68 | hasBorders: false, 69 | hasCorners: false 70 | }); 71 | } else { 72 | object.set({ 73 | visible: true, 74 | evented: true, 75 | selectable: true, 76 | hasBorders: true, 77 | hasCorners: true 78 | }); 79 | canvas.setActiveObject(object); 80 | } 81 | 82 | canvas.renderAll(); 83 | }; 84 | 85 | $scope.deleteObject = function (object) { 86 | if (object) { 87 | canvas.remove(object); 88 | canvas.renderAll(); 89 | } 90 | }; 91 | 92 | $scope.toggleLock = function (object) { 93 | if (!object) return; 94 | 95 | if (object.locked) { 96 | object.set({ 97 | locked: false, 98 | selectable: true, 99 | evented: true, 100 | lockMovementX: false, 101 | lockMovementY: false, 102 | lockRotation: false, 103 | lockScalingX: false, 104 | lockScalingY: false, 105 | lockUniScaling: false, 106 | hasControls: true, 107 | hasBorders: true 108 | }); 109 | 110 | canvas.setActiveObject(object); 111 | } else { 112 | object.set({ 113 | locked: true, 114 | selectable: false, 115 | evented: false, 116 | lockMovementX: true, 117 | lockMovementY: true, 118 | lockRotation: true, 119 | lockScalingX: true, 120 | lockScalingY: true, 121 | lockUniScaling: true, 122 | hasControls: false, 123 | hasBorders: false 124 | }); 125 | } 126 | 127 | canvas.renderAll(); 128 | } 129 | }]) -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/LeftTabsController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('LeftTabsCtrl', function ($scope, leftPanelTabService) { 2 | // $scope.leftTab = [{ 3 | // title: 'Layers', 4 | // url: 'templates/layers.html', 5 | // micon: 'layers', 6 | // custom: 'images/icons.svg' 7 | // 8 | // }, 9 | // { 10 | // title: 'Pages', 11 | // url: 'templates/pages.html', 12 | // micon: 'pages', 13 | // custom: 'images/icons.svg' 14 | // 15 | // } 16 | // ]; 17 | 18 | 19 | 20 | ////////// 21 | // $scope.leftTab = leftPanelTabService.leftTab; 22 | // 23 | // 24 | // // $scope.currentLeftTab = 'templates/layers.html'; 25 | // debugger 26 | // $scope.currentLeftTab = leftPanelTabService.tab.url; 27 | // 28 | // $scope.onClickLeftTab = function (tab) { 29 | // leftPanelTabService.setTab(tab); 30 | // 31 | // //$scope.currentLeftTab = tab.url; 32 | // $scope.currentLeftTab = leftPanelTabService.getTab().url; 33 | // 34 | // } 35 | // 36 | // $scope.isActiveTab = function (tabUrl) { 37 | // return tabUrl == $scope.currentLeftTab; 38 | // } 39 | 40 | }) 41 | -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/PagesController.js: -------------------------------------------------------------------------------- 1 | // Layer panel test implementation 2 | // ================================================================ 3 | 4 | kitchensink.controller('PagesController', ['$scope', '$rootScope', '$timeout', function ($scope, $rootScope, $timeout) { 5 | 6 | $scope.objects = [{ 7 | name: 'Page 1', 8 | thumbnail: 'project/assets/thumbnails/page1.png', 9 | path: 'project/pages/' 10 | }, 11 | { 12 | name: 'Page 2', 13 | thumbnail: 'project/assets/thumbnails/page2.png', 14 | path: 'project/pages/' 15 | }, 16 | { 17 | name: 'Page 3', 18 | thumbnail: 'project/assets/thumbnails/page3.png', 19 | path: 'project/pages/' 20 | }, 21 | { 22 | name: 'Page 4', 23 | thumbnail: 'project/assets/thumbnails/page4.png', 24 | path: 'project/pages/' 25 | } 26 | ]; 27 | 28 | $scope.sortableOptions = { 29 | items: '.object:visible', 30 | scroll: false, 31 | axis: 'y', 32 | containment: 'parent', 33 | start: function (e, ui) { 34 | ui.item.data('start', ui.item.index()); 35 | }, 36 | update: function (e, ui) { 37 | var start = ui.item.data('start'), 38 | end = ui.item.index(); 39 | 40 | 41 | obj = canvas.getObjects()[start]; 42 | 43 | if (!obj) return; 44 | 45 | if (end > start) { 46 | for (var i = 0; i < (end - start); i++) { 47 | canvas.bringForward(obj); 48 | } 49 | } else { 50 | for (var i = 0; i < (start - end); i++) { 51 | canvas.sendBackwards(obj); 52 | } 53 | } 54 | 55 | $timeout(function () { 56 | canvas.renderAll(); 57 | start = false; 58 | end = false; 59 | }); 60 | }, 61 | } 62 | 63 | 64 | $scope.setAsActiveLayer = function (item, list) { 65 | list.some(function (item) { 66 | if (item.active) { 67 | return item.active = false; 68 | } 69 | }); 70 | item.active = true; 71 | }; 72 | 73 | $scope.toggleVisibility = function (object) { 74 | if (!object) return; 75 | 76 | if (object.visible) { 77 | object.set({ 78 | visible: false, 79 | evented: false, 80 | selectable: false, 81 | hasBorders: false, 82 | hasCorners: false 83 | }); 84 | } else { 85 | object.set({ 86 | visible: true, 87 | evented: true, 88 | selectable: true, 89 | hasBorders: true, 90 | hasCorners: true 91 | }); 92 | canvas.setActiveObject(object); 93 | } 94 | 95 | canvas.renderAll(); 96 | }; 97 | 98 | $scope.deleteObject = function (object) { 99 | 100 | if (object) { 101 | canvas.remove(object); 102 | canvas.renderAll(); 103 | } 104 | }; 105 | 106 | $scope.toggleLock = function (object) { 107 | if (!object) return; 108 | 109 | if (object.locked) { 110 | object.set({ 111 | locked: false, 112 | selectable: true, 113 | evented: true, 114 | lockMovementX: false, 115 | lockMovementY: false, 116 | lockRotation: false, 117 | lockScalingX: false, 118 | lockScalingY: false, 119 | lockUniScaling: false, 120 | hasControls: true, 121 | hasBorders: true 122 | }); 123 | 124 | canvas.setActiveObject(object); 125 | } else { 126 | object.set({ 127 | locked: true, 128 | selectable: false, 129 | evented: false, 130 | lockMovementX: true, 131 | lockMovementY: true, 132 | lockRotation: true, 133 | lockScalingX: true, 134 | lockScalingY: true, 135 | lockUniScaling: true, 136 | hasControls: false, 137 | hasBorders: false 138 | }); 139 | } 140 | 141 | canvas.renderAll(); 142 | } 143 | }]) -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/RightTabsController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('RightTabsCtrl', ['$scope', function ($scope) { 2 | 3 | const {dialog} = require('electron').remote; 4 | 5 | var fs = require('fs'); 6 | 7 | 8 | $scope.hasShadow; 9 | $scope.leftTab = [{ 10 | title: 'One', 11 | url: 'templates/project_menu.html', 12 | micon: 'phonelink-setup', 13 | custom: 'images/icons.svg' 14 | }, { 15 | title: 'insert-drive-file', 16 | url: 'templates/page_menu.html', 17 | micon: 'insert-drive-file', 18 | custom: 'images/icons.svg' 19 | }, { 20 | title: 'Three', 21 | url: 'templates/layout_menu.html', 22 | micon: 'perm-data-setting', 23 | custom: 'images/icons.svg' 24 | }, { 25 | title: 'Four', 26 | url: 'templates/style_menu.html', 27 | micon: 'style', 28 | custom: 'images/icons.svg' 29 | }, { 30 | title: 'Five', 31 | url: 'templates/text_menu.html', 32 | micon: 'format-size', 33 | custom: 'images/icons.svg' 34 | }, { 35 | title: 'Six', 36 | url: 'templates/actions_menu.html', 37 | micon: 'stars', 38 | custom: 'images/icons.svg' 39 | } 40 | 41 | ]; 42 | 43 | $scope.currentLeftTab = 'templates/page_menu.html'; 44 | 45 | $scope.onClickLeftTab = function (tab) { 46 | 47 | $scope.currentLeftTab = tab.url; 48 | //document.getElementById("objectIn-canvas-background-colorselect").value = canvasObjectBackColor; 49 | } 50 | 51 | $scope.isActiveTab = function (tabUrl) { 52 | return tabUrl == $scope.currentLeftTab; 53 | } 54 | 55 | $scope.getInputState = function () { 56 | return canvas._activeObject ? false : true; 57 | } 58 | 59 | function download(text, name, type) { 60 | var a = document.createElement("a"); 61 | var file = new Blob([text], {type: type}); 62 | a.href = URL.createObjectURL(file); 63 | a.download = name; 64 | a.click(); 65 | } 66 | 67 | var fileSavedPath = ""; 68 | 69 | 70 | 71 | 72 | ////////////// 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | }]) -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/bgContrlController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('bgContrl', ["$scope", function ($scope) { 2 | $scope.change = 'data'; 3 | $scope.getVal = function () { 4 | 5 | console.log($scope.changedVal); 6 | $scope.change = $scope.changedVal; 7 | } 8 | }]) 9 | -------------------------------------------------------------------------------- /js/controllers/kitchensinkController/projectListController.js: -------------------------------------------------------------------------------- 1 | kitchensink.controller('ProjectListCtrl', function ($scope) { 2 | $scope.projects = [ 3 | { 4 | title: 'My awesome Project', 5 | value: '22.11.2016', 6 | thumbnail: '../project/assets/proj_thumbnails/page1.png' 7 | }, 8 | 9 | { 10 | title: 'facebook project', 11 | value: '10.06.2016', 12 | thumbnail: '../project/assets/proj_thumbnails/page2.png' 13 | }, 14 | 15 | { 16 | title: 'IMA Italy awesomness', 17 | value: '22.05.2016', 18 | thumbnail: '../project/assets/proj_thumbnails/page3.png' 19 | }, 20 | 21 | { 22 | title: 'Just a blubb blubb project...', 23 | value: '24.04.2016', 24 | thumbnail: '../project/assets/proj_thumbnails/page4.png' 25 | }, 26 | 27 | { 28 | title: 'facebook project', 29 | value: '10.06.2016', 30 | thumbnail: '../project/assets/proj_thumbnails/page2.png' 31 | }, 32 | 33 | { 34 | title: 'IMA Italy awesomness', 35 | value: '22.05.2016', 36 | thumbnail: '../project/assets/proj_thumbnails/page3.png' 37 | }, 38 | 39 | { 40 | title: 'Just a blubb blubb project...', 41 | value: '24.04.2016', 42 | thumbnail: '../project/assets/proj_thumbnails/page4.png' 43 | } 44 | ]; 45 | }); 46 | -------------------------------------------------------------------------------- /js/direcives/kitchensinkDirectives/app_config_not_used.js: -------------------------------------------------------------------------------- 1 | // var kitchensink = angular.module('kitchensink', ['ui.sortable', 'electangular']); 2 | 3 | // /*kitchensink.config(function($interpolateProvider) { 4 | // $interpolateProvider 5 | // .startSymbol('{[') 6 | // .endSymbol(']}'); 7 | // });*/ 8 | 9 | // kitchensink.directive('bindValueTo', function () { 10 | // return { 11 | // restrict: 'A', 12 | 13 | // link: function ($scope, $element, $attrs) { 14 | 15 | // var prop = capitalize($attrs.bindValueTo), 16 | // getter = 'get' + prop, 17 | // setter = 'set' + prop; 18 | 19 | // $element.on('change keyup select', function () { 20 | // if ($element[0].type !== 'checkbox') { 21 | // $scope[setter] && $scope[setter](this.value); 22 | // } 23 | // }); 24 | 25 | // $element.on('click', function () { 26 | // if ($element[0].type === 'checkbox') { 27 | // if ($element[0].checked) { 28 | // $scope[setter] && $scope[setter](true); 29 | // } else { 30 | // $scope[setter] && $scope[setter](false); 31 | // } 32 | // } 33 | // }) 34 | 35 | // $scope.$watch($scope[getter], function (newVal) { 36 | // if ($element[0].type === 'radio') { 37 | // var radioGroup = document.getElementsByName($element[0].name); 38 | // for (var i = 0, len = radioGroup.length; i < len; i++) { 39 | // radioGroup[i].checked = radioGroup[i].value === newVal; 40 | // } 41 | // } else if ($element[0].type === 'checkbox') { 42 | // $element[0].checked = newVal; 43 | // } else { 44 | // $element.val(newVal); 45 | // } 46 | // }); 47 | // } 48 | // }; 49 | // }); 50 | 51 | // kitchensink.directive('objectButtonsEnabled', function () { 52 | // return { 53 | // restrict: 'A', 54 | 55 | // link: function ($scope, $element, $attrs) { 56 | // $scope.$watch($attrs.objectButtonsEnabled, function (newVal) { 57 | 58 | // $($element).find('.btn-object-action') 59 | // .prop('disabled', !newVal); 60 | // }); 61 | // } 62 | // }; 63 | // }); 64 | 65 | // kitchensink.directive('edObjectsPanelSortable', ['$rootScope', function ($rootScope) { 66 | // return { 67 | // link: function ($scope, el) { 68 | // var oldIndex, newIndex, obj; 69 | 70 | // el.sortable({ 71 | // items: '.object:visible', 72 | // scroll: false, 73 | // containment: 'parent', 74 | // start: function (e, ui) { 75 | // //oldIndex = $(ui.item).index(); 76 | // ui.item.data('start', ui.item.index()); 77 | // }, 78 | // update: function (e, ui) { 79 | // //newIndex = $(ui.item).index(); 80 | 81 | // var start = ui.item.data('start'), 82 | // end = ui.item.index(); 83 | 84 | // canvas.fabric._objects.splice(end, 0, 85 | // canvas.fabric._objects.splice(start, 1)[0]); 86 | // $scope.objects = canvas._objects; 87 | 88 | // $scope.$apply(); 89 | 90 | // console.log($scope.objects); 91 | 92 | // obj = canvas.getObjects()[start]; 93 | 94 | // if (!obj) return; 95 | 96 | // if (end > start) { 97 | // //send object forwards by the amount of objects it passed 98 | // for (var i = 0; i < (end - start); i++) { 99 | // canvas.bringForward(obj); 100 | // canvas.renderAll(); 101 | // } 102 | // } else { 103 | // //send object backwards by the amount of objects it passed 104 | // for (var i = 0; i < (start - end); i++) { 105 | // canvas.sendBackwards(obj); 106 | // canvas.renderAll(); 107 | // } 108 | // } 109 | 110 | // $rootScope.$apply(function () { 111 | // canvas.renderAll(); 112 | // start = false; 113 | // }); 114 | // } 115 | // }) 116 | // } 117 | // }; 118 | // }]); 119 | -------------------------------------------------------------------------------- /js/direcives/kitchensinkDirectives/bindValueToDirective.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var kitchensink = angular.module('kitchensink', ['ui.sortable']); 4 | 5 | /*kitchensink.config(function($interpolateProvider) { 6 | $interpolateProvider 7 | .startSymbol('{[') 8 | .endSymbol(']}'); 9 | });*/ 10 | 11 | 12 | 13 | kitchensink.directive('bindValueTo', function () { 14 | return { 15 | restrict: 'A', 16 | 17 | link: function ($scope, $element, $attrs) { 18 | 19 | var prop = capitalize($attrs.bindValueTo), 20 | getter = 'get' + prop, 21 | setter = 'set' + prop; 22 | 23 | $element.on('change keyup select', function () { 24 | if ($element[0].type !== 'checkbox') { 25 | $scope[setter] && $scope[setter](this.value); 26 | } 27 | }); 28 | 29 | $element.on('click', function () { 30 | if ($element[0].type === 'checkbox') { 31 | if ($element[0].checked) { 32 | $scope[setter] && $scope[setter](true); 33 | } else { 34 | $scope[setter] && $scope[setter](false); 35 | } 36 | } 37 | }) 38 | 39 | $scope.$watch($scope[getter], function (newVal) { 40 | if ($element[0].type === 'radio') { 41 | var radioGroup = document.getElementsByName($element[0].name); 42 | for (var i = 0, len = radioGroup.length; i < len; i++) { 43 | radioGroup[i].checked = radioGroup[i].value === newVal; 44 | } 45 | } else if ($element[0].type === 'checkbox') { 46 | $element[0].checked = newVal; 47 | } else { 48 | $element.val(newVal); 49 | } 50 | }); 51 | } 52 | }; 53 | }); 54 | -------------------------------------------------------------------------------- /js/direcives/kitchensinkDirectives/edObjectsPanelSortableDirective.js: -------------------------------------------------------------------------------- 1 | kitchensink.directive('edObjectsPanelSortable', ['$rootScope', function ($rootScope) { 2 | return { 3 | link: function ($scope, el) { 4 | var oldIndex, newIndex, obj; 5 | 6 | el.sortable({ 7 | items: '.object:visible', 8 | scroll: false, 9 | containment: 'parent', 10 | start: function (e, ui) { 11 | //oldIndex = $(ui.item).index(); 12 | ui.item.data('start', ui.item.index()); 13 | }, 14 | update: function (e, ui) { 15 | //newIndex = $(ui.item).index(); 16 | 17 | var start = ui.item.data('start'), 18 | end = ui.item.index(); 19 | 20 | canvas.fabric._objects.splice(end, 0, 21 | canvas.fabric._objects.splice(start, 1)[0]); 22 | $scope.objects = canvas._objects; 23 | 24 | $scope.$apply(); 25 | 26 | console.log($scope.objects); 27 | 28 | obj = canvas.getObjects()[start]; 29 | 30 | if (!obj) return; 31 | 32 | if (end > start) { 33 | //send object forwards by the amount of objects it passed 34 | for (var i = 0; i < (end - start); i++) { 35 | canvas.bringForward(obj); 36 | canvas.renderAll(); 37 | } 38 | } else { 39 | //send object backwards by the amount of objects it passed 40 | for (var i = 0; i < (start - end); i++) { 41 | canvas.sendBackwards(obj); 42 | canvas.renderAll(); 43 | } 44 | } 45 | 46 | $rootScope.$apply(function () { 47 | canvas.renderAll(); 48 | start = false; 49 | }); 50 | } 51 | }) 52 | } 53 | }; 54 | }]); -------------------------------------------------------------------------------- /js/direcives/kitchensinkDirectives/objectButtonsEnabledDirective.js: -------------------------------------------------------------------------------- 1 | kitchensink.directive('objectButtonsEnabled', function () { 2 | return { 3 | restrict: 'A', 4 | 5 | link: function ($scope, $element, $attrs) { 6 | $scope.$watch($attrs.objectButtonsEnabled, function (newVal) { 7 | 8 | $($element).find('.btn-object-action') 9 | .prop('disabled', !newVal); 10 | }); 11 | } 12 | }; 13 | }); -------------------------------------------------------------------------------- /js/objects/ObjectsPanelController.js: -------------------------------------------------------------------------------- 1 | angular.module('ImageEditor') 2 | 3 | .controller('ObjectsPanelController', ['$scope', '$rootScope', '$timeout', 'canvas', function($scope, $rootScope, $timeout, canvas) { 4 | $scope.objects = canvas.fabric._objects || []; 5 | 6 | $scope.sortableOptions = { 7 | items: '.object:visible', 8 | scroll: false, 9 | containment: 'parent', 10 | start: function(e, ui) { 11 | ui.item.data('start', ui.item.index()); 12 | }, 13 | update: function(e, ui) { 14 | var start = ui.item.data('start'), 15 | end = ui.item.index(); 16 | 17 | 18 | obj = canvas.fabric.getObjects()[start]; 19 | 20 | if ( ! obj) return; 21 | 22 | if (end > start) { 23 | //send object forwards by the amount of objects it passed 24 | for (var i = 0; i < (end - start); i++) { 25 | canvas.fabric.bringForward(obj); 26 | canvas.renderAll(); 27 | } 28 | } else { 29 | //send object backwards by the amount of objects it passed 30 | for (var i = 0; i < (start - end); i++) { 31 | canvas.fabric.sendBackwards(obj); 32 | canvas.renderAll(); 33 | } 34 | } 35 | 36 | $timeout(function() { 37 | canvas.fabric.renderAll(); 38 | start = false; end = false; 39 | }); 40 | }, 41 | } 42 | 43 | $scope.setAsActive = function(object) { 44 | if (object) { 45 | canvas.fabric.setActiveObject(object); 46 | canvas.renderAll(); 47 | } 48 | }; 49 | 50 | $scope.toggleVisibility = function(object) { 51 | if ( ! object) return; 52 | 53 | if (object.visible) { 54 | object.set({ visible: false, evented: false, selectable: false, hasBorders: false, hasCorners: false }); 55 | } else { 56 | object.set({ visible: true, evented: true, selectable: true, hasBorders: true, hasCorners: true }); 57 | canvas.fabric.setActiveObject(object); 58 | } 59 | 60 | canvas.fabric.renderAll(); 61 | }; 62 | 63 | $scope.deleteObject = function(object) { 64 | if (object) { 65 | canvas.fabric.remove(object); 66 | canvas.fabric.renderAll(); 67 | } 68 | }; 69 | 70 | $scope.toggleLock = function(object) { 71 | if ( ! object) return; 72 | 73 | if (object.locked) { 74 | object.set({ 75 | locked: false, 76 | selectable: true, 77 | evented: true, 78 | lockMovementX: false, 79 | lockMovementY: false, 80 | lockRotation: false, 81 | lockScalingX: false, 82 | lockScalingY: false, 83 | lockUniScaling: false, 84 | hasControls: true, 85 | hasBorders: true 86 | }); 87 | 88 | canvas.fabric.setActiveObject(object); 89 | } else { 90 | object.set({ 91 | locked: true, 92 | selectable: false, 93 | evented: false, 94 | lockMovementX: true, 95 | lockMovementY: true, 96 | lockRotation: true, 97 | lockScalingX: true, 98 | lockScalingY: true, 99 | lockUniScaling: true, 100 | hasControls: false, 101 | hasBorders: false 102 | }); 103 | } 104 | 105 | canvas.fabric.renderAll(); 106 | } 107 | }]); -------------------------------------------------------------------------------- /js/objects/ObjectsPanelSortableDirective.js: -------------------------------------------------------------------------------- 1 | angular.module('ImageEditor') 2 | 3 | .directive('edObjectsPanelSortable', ['$rootScope', 'canvas', function ($rootScope, canvas) { 4 | return { 5 | link: function ($scope, el) { 6 | var oldIndex, newIndex, obj; 7 | 8 | el.sortable({ 9 | items: '.object:visible', 10 | scroll: false, 11 | containment: 'parent', 12 | start: function(e, ui) { 13 | //oldIndex = $(ui.item).index(); 14 | ui.item.data('start', ui.item.index()); 15 | }, 16 | update: function(e, ui) { 17 | //newIndex = $(ui.item).index(); 18 | 19 | var start = ui.item.data('start'), 20 | end = ui.item.index(); 21 | 22 | canvas.fabric._objects.splice(end, 0, 23 | canvas.fabric._objects.splice(start, 1)[0]); 24 | $scope.objects = canvas.fabric._objects; 25 | 26 | $scope.$apply(); 27 | 28 | console.log($scope.objects); 29 | 30 | obj = canvas.fabric.getObjects()[start]; 31 | 32 | if ( ! obj) return; 33 | 34 | if (end > start) { 35 | //send object forwards by the amount of objects it passed 36 | for (var i = 0; i < (end - start); i++) { 37 | canvas.fabric.bringForward(obj); 38 | } 39 | } else { 40 | //send object backwards by the amount of objects it passed 41 | for (var i = 0; i < (start - end); i++) { 42 | canvas.fabric.sendBackwards(obj); 43 | } 44 | } 45 | 46 | $rootScope.$apply(function() { 47 | canvas.fabric.renderAll(); 48 | start = false; 49 | }); 50 | } 51 | }) 52 | } 53 | }; 54 | }]); 55 | -------------------------------------------------------------------------------- /js/ruler/ruler.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var ruler = function (options) { 3 | this.api = this.builder(); 4 | this.api.constructRulers.call(this, options); 5 | }; 6 | 7 | ruler.prototype.builder = function(){ 8 | var VERTICAL = 1, 9 | HORIZONTAL = 2, 10 | CUR_DELTA_X = 0, 11 | CUR_DELTA_Y = 0, 12 | CUR_SCALE = 1; 13 | 14 | var options, 15 | rulerz = {}, 16 | guides = [], 17 | theRulerDOM = document.createElement('div'), 18 | corners = [], 19 | defaultOptions = { 20 | rulerHeight: 15, 21 | fontFamily: 'arial', 22 | fontSize: '8px', 23 | strokeStyle: 'gray', 24 | sides: ['top', 'left'], 25 | cornerSides: ['TL'], 26 | lineWidth: 1, 27 | enableMouseTracking: true, 28 | enableToolTip: true 29 | }; 30 | 31 | var rotateRuler = function (curRuler, angle) { 32 | var rotation = 'rotate(' + angle + 'deg)'; 33 | var origin = ruler.prototype.utils.pixelize(Math.abs(parseInt(curRuler.canvas.style.left))) + ' 100%'; 34 | curRuler.canvas.style.webkitTransform = rotation; 35 | curRuler.canvas.style.MozTransform = rotation; 36 | curRuler.canvas.style.OTransform = rotation; 37 | curRuler.canvas.style.msTransform = rotation; 38 | curRuler.canvas.style.transform = rotation; 39 | curRuler.canvas.style.webkitTransformOrigin = origin; 40 | curRuler.canvas.style.MozTransformOrigin = origin; 41 | curRuler.canvas.style.OTransformOrigin = origin; 42 | curRuler.canvas.style.msTransformOrigin = origin; 43 | curRuler.canvas.style.transformOrigin = origin; 44 | 45 | }; 46 | 47 | var positionRuler = function (curRuler, alignment) { 48 | curRuler.canvas.style.left = ruler.prototype.utils.pixelize(-((curRuler.canvas.width / 2) - curRuler.canvas.height)); 49 | switch (alignment) { 50 | case 'top': 51 | curRuler.orgPos = parseInt(curRuler.canvas.style.left); 52 | break; 53 | case 'left': 54 | curRuler.canvas.style.top = ruler.prototype.utils.pixelize(-curRuler.canvas.height - 1); 55 | curRuler.orgPos = parseInt(curRuler.canvas.style.top); 56 | rotateRuler(curRuler, 90); 57 | break; 58 | } 59 | }; 60 | 61 | var attachListeners = function (container, curRul) { 62 | var mousedown = function (e) { 63 | constructGuide(curRul.dimension, e.clientX, e.clientY, e); 64 | 65 | }; 66 | 67 | curRul.canvas.addEventListener('mousedown', mousedown); 68 | curRul.clearListeners = function () { 69 | curRul.canvas.removeEventListener('mousedown', mousedown); 70 | } 71 | }; 72 | 73 | var constructGuide = function (dimension, x, y, e) { 74 | var guideIndex; 75 | var moveCB = function (line, x, y) { 76 | var coor = line.dimension === VERTICAL ? x : y; 77 | if (!line.assigned()) { 78 | if (coor > options.rulerHeight) { 79 | line.assigned(true); 80 | } 81 | return; 82 | } 83 | 84 | if (coor < options.rulerHeight) { 85 | guides.some(function (guideLine, index) { 86 | if (guideLine.line === line) { 87 | guideIndex = index; 88 | return true; 89 | } 90 | }); 91 | line.destroy(); 92 | guides.splice(guideIndex, 1); 93 | 94 | } 95 | }; 96 | 97 | var guide = document.createElement('div'), 98 | guideStyle = dimension === VERTICAL ? 'rul_lineVer' : 'rul_lineHor', 99 | curDelta = dimension === VERTICAL ? CUR_DELTA_X : CUR_DELTA_Y; 100 | guide.title = 'Double click to delete'; 101 | ruler.prototype.utils.addClasss(guide, ['rul_line', guideStyle]); 102 | guide = theRulerDOM.appendChild(guide); 103 | if (dimension === VERTICAL) { 104 | guide.style.left = ruler.prototype.utils.pixelize(x - options.container.getBoundingClientRect().left); 105 | } 106 | else { 107 | guide.style.top = ruler.prototype.utils.pixelize(y - options.container.getBoundingClientRect().top); 108 | } 109 | guides.push({ 110 | dimension: dimension, 111 | line: ruler.prototype.guideLine(guide, options.container.querySelector('.rul_wrapper'), dimension, options, curDelta, moveCB, e) 112 | }); 113 | }; 114 | 115 | 116 | var constructRuler = function (container, alignment) { 117 | var canvas, 118 | dimension = alignment === 'left' || alignment === 'right' ? VERTICAL : HORIZONTAL, 119 | rulerStyle = dimension === VERTICAL ? 'rul_ruler_Vertical' : 'rul_ruler_Horizontal', 120 | element = document.createElement('canvas'); 121 | 122 | 123 | ruler.prototype.utils.addClasss(element, ['rul_ruler', rulerStyle, 'rul_align_' + alignment]); 124 | canvas = container.appendChild(element); 125 | rulerz[alignment] = ruler.prototype.rulerConstructor(canvas, options, dimension); 126 | rulerz[alignment].drawRuler(container.offsetWidth, options.rulerHeight); 127 | positionRuler(rulerz[alignment], alignment); 128 | attachListeners(container, rulerz[alignment]); 129 | }; 130 | 131 | var constructCorner = (function () { 132 | function cornerDraw(container, side) { 133 | var corner = document.createElement('div'), 134 | cornerStyle = 'rul_corner' + side.toUpperCase(); 135 | 136 | corner.title = 'Clear Guide lines'; 137 | ruler.prototype.utils.addClasss(corner, ['rul_corner', cornerStyle]); 138 | corner.style.width = ruler.prototype.utils.pixelize(options.rulerHeight + 1); 139 | corner.style.height = ruler.prototype.utils.pixelize(options.rulerHeight); 140 | return container.appendChild(corner); 141 | 142 | } 143 | 144 | function mousedown(e) { 145 | e.stopPropagation(); 146 | clearGuides(); 147 | } 148 | 149 | return function (container, cornerSides) { 150 | cornerSides.forEach(function (side) { 151 | var corner = cornerDraw(container, side); 152 | corner.addEventListener('mousedown', mousedown); 153 | corner.destroy = function () { 154 | corner.removeEventListener('mousedown', mousedown); 155 | corner.parentNode.removeChild(corner); 156 | }; 157 | 158 | corners.push(corner); 159 | }) 160 | } 161 | 162 | })(); 163 | 164 | var mouseup = function (e) { 165 | guides.forEach(function (guide) { 166 | guide.line.stopDrag(); 167 | }) 168 | }; 169 | 170 | var constructRulers = function (curOptions) { 171 | theRulerDOM = ruler.prototype.utils.addClasss(theRulerDOM, 'rul_wrapper'); 172 | options = ruler.prototype.utils.extend(defaultOptions, curOptions); 173 | theRulerDOM = options.container.appendChild(theRulerDOM); 174 | options.sides.forEach(function (side) { 175 | constructRuler(theRulerDOM, side); 176 | }); 177 | constructCorner(theRulerDOM, options.cornerSides); 178 | options.container.addEventListener('mouseup', mouseup); 179 | 180 | 181 | }; 182 | 183 | var forEachRuler = function (cb) { 184 | var index = 0; 185 | for (var rul in rulerz) { 186 | if (rulerz.hasOwnProperty(rul)) { 187 | cb(rulerz[rul], index++); 188 | } 189 | } 190 | }; 191 | 192 | 193 | var setPos = function (values) { 194 | var orgX = 0, 195 | orgY, 196 | deltaX = 0, 197 | deltaY = 0; 198 | forEachRuler(function (curRul) { 199 | if (curRul.dimension === VERTICAL) { 200 | orgY = curRul.canvas.style.top; 201 | curRul.canvas.style.top = ruler.prototype.utils.pixelize(curRul.orgPos + (parseInt(values.y))); 202 | deltaY = parseInt(orgY) - parseInt(curRul.canvas.style.top); 203 | } 204 | else { 205 | orgX = curRul.canvas.style.left; 206 | curRul.canvas.style.left = ruler.prototype.utils.pixelize(curRul.orgPos + (parseInt(values.x))); 207 | deltaX = parseInt(orgX) - parseInt(curRul.canvas.style.left); 208 | } 209 | }); 210 | guides.forEach(function (guide) { 211 | if (guide.dimension === HORIZONTAL) { 212 | guide.line.guideLine.style.top = ruler.prototype.utils.pixelize(parseInt(guide.line.guideLine.style.top) - deltaY); 213 | guide.line.curPosDelta(parseInt(values.y)); 214 | } 215 | else { 216 | guide.line.guideLine.style.left = ruler.prototype.utils.pixelize(parseInt(guide.line.guideLine.style.left) - deltaX); 217 | guide.line.curPosDelta(parseInt(values.x)); 218 | } 219 | }); 220 | CUR_DELTA_X = parseInt(values.x); 221 | CUR_DELTA_Y = parseInt(values.y); 222 | 223 | }; 224 | 225 | var setScale = function (newScale) { 226 | var curPos, orgDelta, curScaleFac; 227 | forEachRuler(function (rul) { 228 | rul.context.clearRect(0, 0, rul.canvas.width, rul.canvas.height); 229 | rul.context.beginPath(); 230 | rul.setScale(newScale); 231 | rul.context.stroke(); 232 | CUR_SCALE = newScale; 233 | }); 234 | 235 | guides.forEach(function (guide) { 236 | if (guide.dimension === HORIZONTAL) { 237 | curPos = parseInt(guide.line.guideLine.style.top); 238 | orgDelta = options.rulerHeight + 1; 239 | curScaleFac = (parseFloat(newScale) / guide.line.curScale()); 240 | guide.line.guideLine.style.top = ruler.prototype.utils.pixelize(((curPos - orgDelta - CUR_DELTA_Y ) / curScaleFac) + orgDelta + CUR_DELTA_Y); 241 | guide.line.curScale(newScale); 242 | } 243 | else { 244 | curPos = parseInt(guide.line.guideLine.style.left); 245 | orgDelta = options.rulerHeight + 1; 246 | curScaleFac = (parseFloat(newScale) / guide.line.curScale()); 247 | guide.line.guideLine.style.left = ruler.prototype.utils.pixelize(((curPos - orgDelta - CUR_DELTA_X) / curScaleFac) + orgDelta + CUR_DELTA_X); 248 | guide.line.curScale(newScale); 249 | } 250 | }); 251 | }; 252 | 253 | 254 | var clearGuides = function () { 255 | guides.forEach(function (guide) { 256 | guide.line.destroy(); 257 | }); 258 | guides = []; 259 | }; 260 | 261 | var toggleGuideVisibility = function (val) { 262 | var func = val ? 'show' : 'hide'; 263 | guides.forEach(function (guide) { 264 | guide.line[func](); 265 | }); 266 | }; 267 | 268 | var toggleRulerVisibility = function (val) { 269 | var state = val ? 'block' : 'none'; 270 | theRulerDOM.style.display = state; 271 | var trackers = options.container.querySelectorAll('.rul_tracker'); 272 | if (trackers.length > 0) { 273 | trackers[0].style.display = state; 274 | trackers[1].style.display = state; 275 | } 276 | 277 | }; 278 | 279 | var getGuides = function () { 280 | return guides.map(function (guide) { 281 | return { 282 | posX: Math.round((parseInt(guide.line.guideLine.style.left) - CUR_DELTA_X - options.rulerHeight) * CUR_SCALE), 283 | posY: Math.round((parseInt(guide.line.guideLine.style.top) - CUR_DELTA_Y - options.rulerHeight) * CUR_SCALE), 284 | dimension: guide.dimension 285 | } 286 | }); 287 | }; 288 | 289 | var setGuides = function (_guides) { 290 | if(!_guides){return} 291 | _guides.forEach(function (guide) { 292 | constructGuide(guide.dimension, guide.posX, guide.posY) 293 | }) 294 | 295 | }; 296 | 297 | var destroy = function () { 298 | clearGuides(); 299 | forEachRuler(function (ruler) { 300 | ruler.destroy(); 301 | }); 302 | corners.forEach(function (corner) { 303 | corner.destroy(); 304 | }); 305 | options.container.removeEventListener('mouseup', mouseup); 306 | theRulerDOM.parentNode.removeChild(theRulerDOM); 307 | }; 308 | 309 | return { 310 | VERTICAL: VERTICAL, 311 | HORIZONTAL: HORIZONTAL, 312 | setPos: setPos, 313 | setScale: setScale, 314 | clearGuides: clearGuides, 315 | getGuides: getGuides, 316 | setGuides: setGuides, 317 | constructRulers: constructRulers, 318 | toggleRulerVisibility: toggleRulerVisibility, 319 | toggleGuideVisibility: toggleGuideVisibility, 320 | destroy: destroy 321 | } 322 | }; 323 | 324 | 325 | -------------------------------------------------------------------------------- /js/ruler/rulerConstructor.js: -------------------------------------------------------------------------------- 1 | 2 | ruler.prototype.rulerConstructor = function(_canvas, options, rulDimension) 3 | { 4 | 5 | var canvas = _canvas, 6 | context = canvas.getContext('2d'), 7 | rulThickness = 0, 8 | rulLength = 0, 9 | rulScale = 1, 10 | dimension = rulDimension || 2, 11 | orgPos = 0, 12 | tracker = document.createElement('div'); 13 | 14 | var getLength = function (){ 15 | return rulLength; 16 | }; 17 | 18 | var getThickness = function(){ 19 | return rulThickness; 20 | }; 21 | 22 | var getScale = function(){ 23 | return rulScale; 24 | }; 25 | 26 | var setScale = function(newScale){ 27 | rulScale = parseFloat(newScale); 28 | drawPoints(); 29 | return rulScale; 30 | }; 31 | 32 | var drawRuler = function (_rulerLength, _rulerThickness, _rulerScale){ 33 | rulLength = canvas.width = _rulerLength * 4; 34 | rulThickness = canvas.height = _rulerThickness; 35 | rulScale = _rulerScale || rulScale; 36 | context.strokeStyle = options.strokeStyle; 37 | context.font = options.fontSize + ' ' + options.fontFamily; 38 | context.lineWidth = options.lineWidth; 39 | context.beginPath(); 40 | drawPoints(); 41 | context.stroke(); 42 | }; 43 | 44 | 45 | 46 | var drawPoints = function () { 47 | var pointLength = 0, 48 | label = '', 49 | delta = 0, 50 | draw = false, 51 | lineLengthMax = 0, 52 | lineLengthMed = rulThickness / 2, 53 | lineLengthMin = rulThickness / 2; 54 | 55 | for (var pos = 0; pos <= rulLength; pos += 1) { 56 | delta = ((rulLength / 2) - pos); 57 | draw = false; 58 | label = ''; 59 | 60 | if (delta % 50 === 0) { 61 | pointLength = lineLengthMax; 62 | label = Math.round(Math.abs(delta)*rulScale); 63 | draw = true; 64 | } 65 | else if (delta % 25 === 0) { 66 | pointLength = lineLengthMed; 67 | draw = true; 68 | } 69 | else if (delta % 5 === 0) { 70 | pointLength = lineLengthMin; 71 | draw = true; 72 | } 73 | if (draw) { 74 | context.moveTo(pos + 0.5, rulThickness + 0.5); 75 | context.lineTo(pos + 0.5, pointLength + 0.5); 76 | context.fillText(label, pos + 1.5, (rulThickness / 2) + 1); 77 | } 78 | } 79 | }; 80 | 81 | var mousemove = function(e) { 82 | var posX = e.clientX; 83 | var posY = e.clientY; 84 | if(dimension === 2){ 85 | tracker.style.left = ruler.prototype.utils.pixelize(posX - parseInt(options.container.getBoundingClientRect().left)); 86 | } 87 | else{ 88 | tracker.style.top = ruler.prototype.utils.pixelize(posY - parseInt(options.container.getBoundingClientRect().top)) ; 89 | } 90 | }; 91 | 92 | var destroy = function(){ 93 | options.container.removeEventListener('mousemove', mousemove); 94 | tracker.parentNode.removeChild(tracker); 95 | this.clearListeners && this.clearListeners(); 96 | 97 | }; 98 | 99 | var initTracker = function(){ 100 | tracker = options.container.appendChild(tracker); 101 | ruler.prototype.utils.addClasss(tracker, 'rul_tracker'); 102 | var height = ruler.prototype.utils.pixelize(options.rulerHeight); 103 | if(dimension === 2){ 104 | tracker.style.height = height; 105 | } 106 | else{ 107 | tracker.style.width = height; 108 | } 109 | 110 | options.container.addEventListener('mousemove', mousemove); 111 | }; 112 | 113 | if(options.enableMouseTracking){ 114 | initTracker(); 115 | } 116 | 117 | 118 | return{ 119 | getLength: getLength, 120 | getThickness: getThickness, 121 | getScale: getScale, 122 | setScale: setScale, 123 | dimension: dimension, 124 | orgPos: orgPos, 125 | canvas: canvas, 126 | context: context, 127 | drawRuler: drawRuler, 128 | drawPoints: drawPoints, 129 | destroy: destroy 130 | } 131 | }; 132 | 133 | -------------------------------------------------------------------------------- /js/ruler/rulerGuideLine.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by maor.frankel on 5/23/15. 3 | */ 4 | ruler.prototype.guideLine = function (line, _dragContainer, lineDimension, options, curDelta, moveCB, event) { 5 | 6 | var self, 7 | guideLine = line, 8 | _curScale = 1, 9 | _assigned = false, 10 | _curPosDelta = curDelta || 0, 11 | dragContainer = _dragContainer, 12 | dimension = lineDimension || 2, 13 | moveCB = moveCB || function () { 14 | }; 15 | 16 | 17 | var curPosDelta = function (val) { 18 | if (typeof val === 'undefined') { 19 | return _curPosDelta; 20 | } 21 | return (_curPosDelta = val); 22 | }; 23 | 24 | var assigned = function (val) { 25 | if (typeof val === 'undefined') { 26 | return _assigned; 27 | } 28 | return (_assigned = val); 29 | }; 30 | 31 | var curScale = function (val) { 32 | if (typeof val === 'undefined') { 33 | return _curScale; 34 | } 35 | return (_curScale = val); 36 | }; 37 | 38 | 39 | var draggable = (function () { 40 | return { 41 | move: function (xpos, ypos) { 42 | guideLine.style.left = ruler.prototype.utils.pixelize(xpos); 43 | guideLine.style.top = ruler.prototype.utils.pixelize(ypos); 44 | updateToolTip(xpos, ypos); 45 | moveCB(self, xpos, ypos); 46 | }, 47 | startMoving: function (evt) { 48 | ruler.prototype.utils.addClasss(guideLine, ['rul_line_dragged']); 49 | evt = evt || window.event; 50 | var posX = evt ? evt.clientX : 0, 51 | posY = evt ? evt.clientY : 0, 52 | divTop = parseInt(guideLine.style.top || 0), 53 | divLeft = parseInt(guideLine.style.left || 0), 54 | eWi = parseInt(guideLine.offsetWidth), 55 | eHe = parseInt(guideLine.offsetHeight), 56 | cWi = parseInt(dragContainer.offsetWidth), 57 | cHe = parseInt(dragContainer.offsetHeight), 58 | cursor = dimension === 2 ? 'ns-resize' : 'ew-resize'; 59 | 60 | options.container.style.cursor = cursor; 61 | guideLine.style.cursor = cursor; 62 | var diffX = posX - divLeft, 63 | diffY = posY - divTop; 64 | document.onmousemove = function moving(evt) { 65 | evt = evt || window.event; 66 | var posX = evt.clientX, 67 | posY = evt.clientY, 68 | aX = posX - diffX, 69 | aY = posY - diffY; 70 | 71 | if (aX < 0) { 72 | aX = 0; 73 | } 74 | if (aY < 0) { 75 | aY = 0; 76 | } 77 | 78 | if (aX + eWi > cWi) { 79 | aX = cWi - eWi; 80 | } 81 | if (aY + eHe > cHe) { 82 | aY = cHe - eHe; 83 | } 84 | 85 | draggable.move(aX, aY); 86 | }; 87 | showToolTip(); 88 | }, 89 | stopMoving: function () { 90 | options.container.style.cursor = null; 91 | guideLine.style.cursor = null; 92 | document.onmousemove = function () { 93 | }; 94 | hideToolTip(); 95 | ruler.prototype.utils.removeClasss(guideLine, ['rul_line_dragged']); 96 | } 97 | } 98 | })(); 99 | 100 | var showToolTip = function (e) { 101 | if (!options.enableToolTip) { 102 | return; 103 | } 104 | ruler.prototype.utils.addClasss(guideLine, 'rul_tooltip'); 105 | }; 106 | 107 | var updateToolTip = function (x, y) { 108 | if (y) { 109 | guideLine.dataset.tip = 'Y: ' + Math.round((y - options.rulerHeight - 1 - _curPosDelta) * _curScale) + ' px'; 110 | } 111 | else { 112 | guideLine.dataset.tip = 'X: ' + Math.round((x - options.rulerHeight - 1 - _curPosDelta) * _curScale) + ' px'; 113 | } 114 | }; 115 | 116 | var hideToolTip = function (e) { 117 | ruler.prototype.utils.removeClasss(guideLine, 'rul_tooltip'); 118 | }; 119 | 120 | var destroy = function () { 121 | draggable.stopMoving(); 122 | moveCB = null; 123 | guideLine.removeEventListener('mousedown', mousedown); 124 | guideLine.removeEventListener('mouseup', mouseup); 125 | guideLine.removeEventListener('dblclick', dblclick); 126 | guideLine.parentNode && guideLine.parentNode.removeChild(guideLine); 127 | }; 128 | 129 | var hide = function () { 130 | guideLine.style.display = 'none'; 131 | }; 132 | 133 | var show = function () { 134 | guideLine.style.display = 'block'; 135 | }; 136 | 137 | var mousedown = function (e) { 138 | e.stopPropagation(); 139 | draggable.startMoving(); 140 | }; 141 | 142 | var mouseup = function (e) { 143 | draggable.stopMoving(); 144 | }; 145 | 146 | var dblclick = function (e) { 147 | e.stopPropagation(); 148 | destroy(); 149 | }; 150 | 151 | guideLine.addEventListener('mousedown', mousedown); 152 | 153 | guideLine.addEventListener('mouseup', mouseup); 154 | 155 | guideLine.addEventListener('dblclick', dblclick); 156 | if(event) draggable.startMoving(event); 157 | 158 | self = { 159 | setAsDraggable: draggable, 160 | startDrag: draggable.startMoving, 161 | stopDrag: draggable.stopMoving, 162 | destroy: destroy, 163 | curScale: curScale, 164 | assigned: assigned, 165 | curPosDelta: curPosDelta, 166 | guideLine: guideLine, 167 | dimension: dimension, 168 | hide: hide, 169 | show: show 170 | }; 171 | return self; 172 | 173 | }; -------------------------------------------------------------------------------- /js/ruler/ruler_demo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by maor.frankel on 5/19/15. 3 | */ 4 | 5 | 6 | 7 | 8 | setTimeout(function () { 9 | var ruler1 = new ruler({ 10 | container: document.querySelector('.image-builder'),// reference to DOM element to apply rulers on 11 | rulerHeight: 25, // thickness of ruler 12 | fontFamily: 'arial',// font for points 13 | fontSize: '9px', 14 | strokeStyle: 'grey', 15 | lineWidth: 1, 16 | enableMouseTracking: true, 17 | enableToolTip: true 18 | }) 19 | 20 | }, 0) 21 | 22 | 23 | function setPosX1(val){ 24 | ruler1.api.setPos({x:300, y:100}) 25 | } 26 | 27 | function setScale1(val){ 28 | rul1.api.setScale(val); 29 | } 30 | 31 | function hideRuler1(){ 32 | rul1.api.toggleRulerVisibility(visibleGuides1 = !visibleGuides1); 33 | } 34 | 35 | function clearGuides1(){ 36 | rul1.api.clearGuides(); 37 | } 38 | 39 | function storeGuides1(){ 40 | guides1 = rul1.api.getGuides(); 41 | } 42 | 43 | function setGuides1(){ 44 | rul1.api.setGuides(guides1); 45 | } 46 | 47 | function hideGuides1(){ 48 | rul1.api.toggleGuideVisibility(visible1 = !visible1); 49 | } 50 | 51 | function destory1(){ 52 | rul1.api.destroy(); 53 | } 54 | 55 | 56 | function setPosX2(val){ 57 | rul2.api.setPos({x:val}); 58 | } 59 | 60 | function setPosY2(val){ 61 | rul2.api.setPos({y:val}); 62 | } 63 | 64 | function setScale2(val){ 65 | rul2.api.setScale(val); 66 | } 67 | 68 | function hideRuler2(){ 69 | rul2.api.toggleRulerVisibility(visibleGuides2 = !visibleGuides2); 70 | } 71 | 72 | function clearGuides2(){ 73 | rul2.api.clearGuides(); 74 | } 75 | 76 | function storeGuides2(){ 77 | guides2 = rul2.api.getGuides(); 78 | } 79 | 80 | function setGuides2(){ 81 | rul2.api.setGuides(guides2); 82 | } 83 | 84 | function hideGuides2(){ 85 | rul2.api.toggleGuideVisibility(visible2 = !visible2); 86 | } 87 | 88 | function destory2(){ 89 | rul2.api.destroy(); 90 | } -------------------------------------------------------------------------------- /js/ruler/utils.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by maor.frankel on 5/25/15. 3 | */ 4 | ruler.prototype.utils = { 5 | extend: function extend(){ 6 | for(var i=1; i< arguments.length; i++) 7 | for(var key in arguments[i]) 8 | if(arguments[i].hasOwnProperty(key)) 9 | arguments[0][key] = arguments[i][key]; 10 | return arguments[0]; 11 | }, 12 | pixelize: function (val){ 13 | return val + 'px'; 14 | }, 15 | prependChild: function (container, element){ 16 | return container.insertBefore(element,container.firstChild); 17 | }, 18 | addClasss: function (element, classNames){ 19 | if(!(classNames instanceof Array)) 20 | { 21 | classNames = [classNames]; 22 | } 23 | 24 | classNames.forEach(function (name){ 25 | element.className += ' ' + name; 26 | }); 27 | 28 | return element; 29 | 30 | }, 31 | removeClasss: function (element, classNames){ 32 | var curCalsss = element.className; 33 | if(!(classNames instanceof Array)) 34 | { 35 | classNames = [classNames]; 36 | } 37 | 38 | classNames.forEach(function (name){ 39 | curCalsss = curCalsss.replace(name, ''); 40 | }); 41 | element.className = curCalsss; 42 | return element; 43 | 44 | } 45 | } ; 46 | -------------------------------------------------------------------------------- /js/service/electangularServiceIpc.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | electangular.service("ipc", ['electron_core', function (ele) { 4 | var ipcRenderer = ele.ipcRenderer; 5 | return { 6 | send: function (msg) { 7 | ipcRenderer.send('electron-msg', msg); 8 | }, 9 | sendToHost: function (msg) { 10 | ipcRenderer.sendToHost('electron-msg', msg); 11 | } 12 | } 13 | }]) 14 | 15 | 16 | -------------------------------------------------------------------------------- /js/service/electronService.js: -------------------------------------------------------------------------------- 1 | electangular.service("electron", ['$q', 'electron_core', function($q, core) { 2 | var remote = core.remote; 3 | return { 4 | Accelerator: remote.Accelerator, 5 | app: remote.app, 6 | autoUpdater: remote.autoUpdater, 7 | BrowserWindow: remote.BrowserWindow, 8 | contentTracing: remote.contentTracing, //TODO Promise 9 | dialog: { 10 | showErrorBox: remote.dialog.showErrorBox, 11 | showOpenDialog: function(bw, options) { 12 | if (!options) { 13 | options = bw; 14 | bw = remote.BrowserWindow.getFocusedWindow(); 15 | } 16 | var deferred = $q.defer(); 17 | remote.dialog.showOpenDialog(bw, options, (result) => { 18 | if (!result) { 19 | deferred.reject(); 20 | } else { 21 | deferred.resolve(result); 22 | } 23 | }); 24 | return deferred.promise; 25 | }, 26 | showSaveDialog: function(bw, options) { 27 | if (!options) { 28 | options = bw; 29 | bw = remote.BrowserWindow.getFocusedWindow(); 30 | } 31 | var deferred = $q.defer(); 32 | remote.dialog.showSaveDialog(bw, options, (result) => { 33 | if (!result) { 34 | deferred.reject(); 35 | } else { 36 | deferred.resolve(result); 37 | } 38 | }); 39 | return deferred.promise; 40 | }, 41 | showMessageBox: function(bw, options) { 42 | if (!options) { 43 | options = bw; 44 | bw = remote.BrowserWindow.getFocusedWindow(); 45 | } 46 | var deferred = $q.defer(); 47 | remote.dialog.showMessageBox(bw, options, (result) => { 48 | if (!result) { 49 | deferred.reject(); 50 | } else { 51 | deferred.resolve(result); 52 | } 53 | }); 54 | return deferred.promise; 55 | } 56 | }, 57 | globalShortcut: remote.globalShortcut, 58 | Menu: remote.Menu, 59 | MenuItem: remote.MenuItem, 60 | powerMonitor: remote.powerMonitor, 61 | powerSaveBlocker: remote.powerSaveBlocker, 62 | protocol: remote.protocol, 63 | session: remote.session, 64 | systemPreferences: remote.systemPreferences, 65 | Tray: remote.Tray, 66 | desktopCapturer: core.desktopCapturer, 67 | webFrame: core.webFrame, 68 | clipboard: core.clipboard, 69 | crashReporter: core.crashReporter, 70 | nativeImage: core.nativeImage, 71 | process: core.process, 72 | screen: core.screen, 73 | shell: core.shell, 74 | ipcRenderer: core.ipcRenderer 75 | } 76 | }]); -------------------------------------------------------------------------------- /js/service/leftPanelTabService.js: -------------------------------------------------------------------------------- 1 | kitchensink.service('leftPanelTabService', function () { 2 | var selfTabService = this; 3 | selfTabService.leftTab = [{ 4 | title: 'Layers', 5 | url: 'templates/layers.html', 6 | micon: 'layers', 7 | custom: 'images/icons.svg' 8 | 9 | }, 10 | { 11 | title: 'Pages', 12 | url: 'templates/pages.html', 13 | micon: 'pages', 14 | custom: 'images/icons.svg' 15 | 16 | } 17 | ]; 18 | 19 | 20 | selfTabService.tab = selfTabService.leftTab[0]; 21 | 22 | selfTabService.getTab = function () { 23 | 24 | 25 | return selfTabService.tab; 26 | 27 | } 28 | 29 | selfTabService.setTab = function (tab) { 30 | selfTabService.leftTab.forEach(function (tabItem) { 31 | 32 | if ((tab.url) && (tabItem.url == tab.url)) { 33 | selfTabService.tab = tab; 34 | 35 | } 36 | 37 | }) 38 | 39 | 40 | } 41 | 42 | }); -------------------------------------------------------------------------------- /js/service/rightPanelTabService.js: -------------------------------------------------------------------------------- 1 | kitchensink.service('rightPanelTabService', function () { 2 | var selfTabService = this; 3 | selfTabService.rightTab = [ 4 | { 5 | title: 'Inspector', 6 | url: 'templates/inspectorTab.html', 7 | micon: 'settings', 8 | custom: 'images/icons.svg' 9 | 10 | }, 11 | { 12 | title: 'Assets Library', 13 | url: 'templates/assests.html', 14 | micon: 'image', 15 | custom: 'images/icons.svg' 16 | 17 | } 18 | , 19 | { 20 | title: 'export', 21 | url: 'templates/export.html', 22 | micon: 'get-app', 23 | custom: 'images/icons.svg' 24 | 25 | } 26 | ]; 27 | 28 | 29 | selfTabService.tab = selfTabService.rightTab[0]; 30 | 31 | 32 | 33 | selfTabService.getTab = function () { 34 | 35 | return selfTabService.tab; 36 | 37 | } 38 | 39 | selfTabService.setTab = function (tab) { 40 | selfTabService.rightTab.forEach(function (tabItem) { 41 | 42 | if ((tab.url) && (tabItem.url == tab.url)) { 43 | selfTabService.tab = tab; 44 | 45 | } 46 | 47 | }) 48 | 49 | 50 | } 51 | 52 | }); -------------------------------------------------------------------------------- /lib/font_definitions.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | if (typeof Cufon == 'undefined') return; 3 | 4 | var fontDefinitions = { 5 | 'Modernist_One_400': 85, 6 | 'Quake_Cyr': 100, 7 | 'Terminator_Cyr': 10, 8 | 'Vampire95': 85, 9 | 'Encient_German_Gothic_400': 110, 10 | 'OdessaScript_500': 180, 11 | 'Globus_500': 100, 12 | 'CrashCTT_400': 60, 13 | 'CA_BND_Web_Bold_700': 60, 14 | 'Delicious_500': 80, 15 | 'Tallys_400': 70, 16 | 'DejaVu Serif': 130 17 | }; 18 | for (var prop in fontDefinitions) { 19 | if (Cufon.fonts[prop.toLowerCase()]) { 20 | Cufon.fonts[prop.toLowerCase()].offsetLeft = fontDefinitions[prop]; 21 | } 22 | } 23 | })(); -------------------------------------------------------------------------------- /main.js: -------------------------------------------------------------------------------- 1 | /* 2 | "use strict"; 3 | 4 | let {app, BrowserWindow} = require("electron"); 5 | require('electron-reload')(__dirname); 6 | 7 | app.on("ready", () => { 8 | let appWindow = new BrowserWindow({width: 1366, height: 768, titleBarStyle: 'hidden'}); 9 | appWindow.name = "app"; 10 | appWindow.loadURL(`file://${__dirname}/index.html`); 11 | 12 | });*/ 13 | 14 | 15 | const electron = require('electron') 16 | // Module to control application life. 17 | const app = electron.app 18 | // Module to create native browser window. 19 | const BrowserWindow = electron.BrowserWindow 20 | 21 | const path = require('path') 22 | const url = require('url') 23 | const { 24 | ipcMain 25 | } = require('electron') 26 | 27 | const reload = require('electron-reload')(__dirname) 28 | 29 | 30 | 31 | 32 | 33 | // Keep a global reference of the window object, if you don't, the window will 34 | // be closed automatically when the JavaScript object is garbage collected. 35 | 36 | 37 | let mainWindow 38 | let projectWindow 39 | //let secondWindow 40 | 41 | function createWindow() { 42 | 43 | 44 | 45 | // Create the browser window. 46 | mainWindow = new BrowserWindow({ 47 | width: 1680, 48 | height: 1050, 49 | titleBarStyle: 'hidden', 50 | vibrancy: 'medium-light', 51 | show: true, 52 | icon: path.join(__dirname, 'icons/png/64x64.png'), 53 | }) 54 | 55 | 56 | // and load the index.html of the app. 57 | mainWindow.loadURL(url.format({ 58 | pathname: path.join(__dirname, 'index.html'), 59 | protocol: 'file:', 60 | slashes: true 61 | })) 62 | 63 | mainWindow.once('ready-to-show', () => { 64 | mainWindow.show() 65 | }) 66 | 67 | mainWindow.webContents.on('did-finish-load', function () { 68 | mainWindow.webContents.send('ping', 'whoooooooh!'); 69 | }) 70 | 71 | // projectWindow = new BrowserWindow({ 72 | // frame: false, 73 | // width: 800, 74 | // height: 600, 75 | // minWidth: 800, 76 | // minHeight: 600, 77 | // backgroundColor: '#312450', 78 | // show: false, 79 | // icon: path.join(__dirname, 'icons/png/64x64.png'), 80 | // parent: mainWindow 81 | // }) 82 | // 83 | // projectWindow.loadURL(url.format({ 84 | // pathname: path.join(__dirname, 'windows/project.html'), 85 | // protocol: 'file:', 86 | // slashes: true 87 | // )) 88 | 89 | 90 | // Open the DevTools. 91 | // mainWindow.webContents.openDevTools() 92 | 93 | // Emitted when the window is closed. 94 | mainWindow.on('closed', function () { 95 | // Dereference the window object, usually you would store windows 96 | // in an array if your app supports multi windows, this is the time 97 | // when you should delete the corresponding element. 98 | mainWindow = null 99 | }) 100 | 101 | require('./menu/mainmenu') 102 | 103 | 104 | 105 | } 106 | 107 | ipcMain.on('openFile', (event, path) => { 108 | const { 109 | dialog 110 | } = require('electron') 111 | const fs = require('fs') 112 | dialog.showOpenDialog(function (fileNames) { 113 | // fileNames is an array that contains all the selected 114 | if (fileNames === undefined) { 115 | console.log("No file selected"); 116 | } else { 117 | readFile(fileNames[0]); 118 | } 119 | }); 120 | 121 | function readFile(filepath) { 122 | fs.readFile(filepath, 'utf-8', (err, data) => { 123 | if (err) { 124 | alert("An error ocurred reading the file :" + err.message) 125 | return 126 | } 127 | // handle the file content 128 | event.sender.send('fileData', filepath) 129 | }) 130 | } 131 | }) 132 | 133 | ipcMain.on('open-second-window', (event, arg)=> { 134 | mainWindow.show() 135 | }) 136 | 137 | ipcMain.on('close-second-window', (event, arg)=> { 138 | projectWindow.hide() 139 | }) 140 | 141 | // This method will be called when Electron has finished 142 | // initialization and is ready to create browser windows. 143 | // Some APIs can only be used after this event occurs. 144 | app.on('ready', createWindow) 145 | 146 | // Quit when all windows are closed. 147 | app.on('window-all-closed', function () { 148 | // On OS X it is common for applications and their menu bar 149 | // to stay active until the user quits explicitly with Cmd + Q 150 | if (process.platform !== 'darwin') { 151 | app.quit() 152 | } 153 | }) 154 | 155 | app.on('activate', function () { 156 | // On OS X it's common to re-create a window in the app when the 157 | // dock icon is clicked and there are no other windows open. 158 | if (mainWindow === null) { 159 | createWindow() 160 | } 161 | }) 162 | 163 | // In this file you can include the rest of your app's specific main process 164 | // code. You can also put them in separate files and require them here. 165 | -------------------------------------------------------------------------------- /main_ok.js: -------------------------------------------------------------------------------- 1 | /* 2 | "use strict"; 3 | 4 | let {app, BrowserWindow} = require("electron"); 5 | require('electron-reload')(__dirname); 6 | 7 | app.on("ready", () => { 8 | let appWindow = new BrowserWindow({width: 1366, height: 768, titleBarStyle: 'hidden'}); 9 | appWindow.name = "app"; 10 | appWindow.loadURL(`file://${__dirname}/index.html`); 11 | 12 | });*/ 13 | 14 | 15 | const electron = require('electron') 16 | // Module to control application life. 17 | const app = electron.app 18 | // Module to create native browser window. 19 | const BrowserWindow = electron.BrowserWindow 20 | 21 | const path = require('path') 22 | const url = require('url') 23 | const { 24 | ipcMain 25 | } = require('electron') 26 | 27 | const reload = require('electron-reload')(__dirname) 28 | 29 | 30 | //app.on('ready', () => { 31 | // let main = null 32 | // let loading = new BrowserWindow({ 33 | // show: false, 34 | // frame: false 35 | // }) 36 | // 37 | // loading.once('show', () => { 38 | // main = new BrowserWindow({ 39 | // show: false 40 | // }) 41 | // main.webContents.once('dom-ready', () => { 42 | // console.log('main loaded') 43 | // main.show() 44 | // loading.hide() 45 | // loading.close() 46 | // }) 47 | // // long loading html 48 | // main.loadURL('http://spacecrafts3d.org') 49 | // }) 50 | // loading.loadURL('loding.html') 51 | // loading.show() 52 | //}) 53 | 54 | 55 | // Keep a global reference of the window object, if you don't, the window will 56 | // be closed automatically when the JavaScript object is garbage collected. 57 | let mainWindow 58 | 59 | 60 | 61 | function createWindow() { 62 | // Create the browser window. 63 | mainWindow = new BrowserWindow({ 64 | width: 1680, 65 | height: 1050, 66 | titleBarStyle: 'hidden', 67 | vibrancy: 'medium-light', 68 | webPreferences: { 69 | experimentalFeatures: true 70 | } 71 | }) 72 | 73 | 74 | // and load the index.html of the app. 75 | mainWindow.loadURL(url.format({ 76 | pathname: path.join(__dirname, 'index.html'), 77 | protocol: 'file:', 78 | slashes: true 79 | })) 80 | 81 | mainWindow.webContents.on('did-finish-load', function () { 82 | mainWindow.webContents.send('ping', 'whoooooooh!'); 83 | }) 84 | 85 | // Open the DevTools. 86 | // mainWindow.webContents.openDevTools() 87 | 88 | // Emitted when the window is closed. 89 | mainWindow.on('closed', function () { 90 | // Dereference the window object, usually you would store windows 91 | // in an array if your app supports multi windows, this is the time 92 | // when you should delete the corresponding element. 93 | mainWindow = null 94 | }) 95 | 96 | require('./menu/mainmenu') 97 | 98 | 99 | 100 | } 101 | 102 | ipcMain.on('openFile', (event, path) => { 103 | const { 104 | dialog 105 | } = require('electron') 106 | const fs = require('fs') 107 | dialog.showOpenDialog(function (fileNames) { 108 | // fileNames is an array that contains all the selected 109 | if (fileNames === undefined) { 110 | console.log("No file selected"); 111 | } else { 112 | readFile(fileNames[0]); 113 | } 114 | }); 115 | 116 | function readFile(filepath) { 117 | fs.readFile(filepath, 'utf-8', (err, data) => { 118 | if (err) { 119 | alert("An error ocurred reading the file :" + err.message) 120 | return 121 | } 122 | // handle the file content 123 | event.sender.send('fileData', filepath) 124 | }) 125 | } 126 | }) 127 | 128 | 129 | 130 | // This method will be called when Electron has finished 131 | // initialization and is ready to create browser windows. 132 | // Some APIs can only be used after this event occurs. 133 | app.on('ready', createWindow) 134 | 135 | // Quit when all windows are closed. 136 | app.on('window-all-closed', function () { 137 | // On OS X it is common for applications and their menu bar 138 | // to stay active until the user quits explicitly with Cmd + Q 139 | if (process.platform !== 'darwin') { 140 | app.quit() 141 | } 142 | }) 143 | 144 | app.on('activate', function () { 145 | // On OS X it's common to re-create a window in the app when the 146 | // dock icon is clicked and there are no other windows open. 147 | if (mainWindow === null) { 148 | createWindow() 149 | } 150 | }) 151 | 152 | // In this file you can include the rest of your app's specific main process 153 | // code. You can also put them in separate files and require them here. 154 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Floido Designer", 3 | "version": "0.0.1", 4 | "lockfileVersion": 1 5 | } 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "xel-electron-demo", 3 | "productName": "Floido Designer", 4 | "version": "0.0.1", 5 | "description": "Democratizing Tablet Publishing...", 6 | "main": "main.js", 7 | "repository": "https://github.com/sandor/floido-designer", 8 | "keywords": [ 9 | "Electron", 10 | "AngularJS", 11 | "FarbricJS", 12 | "floido", 13 | "designer", 14 | "FramerJS", 15 | "Tablet", 16 | "Publishing" 17 | ], 18 | "author": "Sandor Rozsa | sharksinn gmbh", 19 | "license": "MIT", 20 | "dependencies": { 21 | "angular-custom-elements": "^2.1.0", 22 | "angular-ui-sortable": "^0.17.2", 23 | "electron-context-menu": "^0.9.1", 24 | "electron-reload": "^1.2.1", 25 | "electron-version": "^1.1.1", 26 | "ruler.js": "^1.0.1", 27 | "xel": "0.0.15" 28 | }, 29 | "devDependencies": { 30 | "electron": "^1.7.6" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /project/assets/proj_thumbnails/page1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/proj_thumbnails/page1.png -------------------------------------------------------------------------------- /project/assets/proj_thumbnails/page2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/proj_thumbnails/page2.png -------------------------------------------------------------------------------- /project/assets/proj_thumbnails/page3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/proj_thumbnails/page3.png -------------------------------------------------------------------------------- /project/assets/proj_thumbnails/page4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/proj_thumbnails/page4.png -------------------------------------------------------------------------------- /project/assets/thumbnails/page1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/thumbnails/page1.png -------------------------------------------------------------------------------- /project/assets/thumbnails/page2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/thumbnails/page2.png -------------------------------------------------------------------------------- /project/assets/thumbnails/page3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/thumbnails/page3.png -------------------------------------------------------------------------------- /project/assets/thumbnails/page4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandor/floido-designer/73b9bb48576640050bd23367dae034fa4f658318/project/assets/thumbnails/page4.png -------------------------------------------------------------------------------- /templates/actions_menu 2.html: -------------------------------------------------------------------------------- 1 |

Filters

2 |
3 | 4 |
5 | 6 | 7 |
8 |

Filters:

9 | 10 |
11 |

12 |
13 | 14 | 15 | 16 |

17 |

18 | 19 |

20 |

21 | 22 |

23 |

24 | 25 |

26 |

27 | 28 |

29 |

30 | 34 |

35 |

36 | 37 |

38 |

39 | 40 |

41 |

42 | 43 |

44 |

45 |
46 |
47 |
48 | 49 |

50 |

51 | 52 |
53 | 54 |

55 |

56 | 57 |
58 | 59 |
60 | 61 |
62 | 63 | 64 |

65 |

66 | 67 |
68 | 69 |

70 |

71 | 72 |
73 | 74 |

75 |

76 | 77 |
78 | 79 |

80 |

81 | 82 |
83 | 84 |

85 |

86 | 87 |
88 | 89 |

90 |

91 | 92 |
93 | 94 |

95 |

96 | 97 |

98 |

99 | 100 |

101 |

102 | 103 |
104 | 105 | 117 |
118 |
119 |
120 |

121 | 122 |
123 | 124 | 128 |
129 |
130 |

131 |
132 | 133 | 134 |
135 |
136 | 137 | -------------------------------------------------------------------------------- /templates/assests.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/export.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/inspectorTab.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /templates/layers.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

Layers

5 | 6 |
7 |
8 | 9 |
    10 | 11 |
  • 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
    24 |

    {{ object.name || object.type }}

    25 |
    26 |
  • 27 | 28 |
  • 29 |

    No layers yet.

    30 |
  • 31 |
32 |
33 | -------------------------------------------------------------------------------- /templates/layout_menu.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Element Layout

5 |
6 |
7 | 8 | Align 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |   21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 |
47 |
48 | 49 |
50 | 51 |
52 | 53 | 54 | 55 | 56 |
57 | Object Placement 58 |
59 | 60 |
61 | 62 | Position 63 | 64 | 66 | 67 | 68 | 69 |
70 |
71 | 72 | 74 | 75 | 76 | 77 |
78 | 79 | 80 | X 81 | 82 | Y 83 | 84 | 85 | 86 | 87 | Size 88 | 89 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | Width 107 | 108 | Height 109 | 110 | 111 | 112 | 113 | Transform 114 | 115 | 117 | 118 | 119 | 120 |
121 |
122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
135 | 136 | 137 | Rotate 138 | 139 | Flip 140 | 141 | 142 | 143 | 144 | 145 | Reset Object 146 | 147 | 148 | 149 | 150 |
151 |
152 |
153 | 154 | 155 | 156 |
157 | Object Scale 158 |
159 | 160 |
161 | 162 | Scale 163 | 164 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | Scale X 182 | 183 | Scale Y 184 | 185 |
186 |
187 |
188 | 189 | 190 |
191 | Object Origin 192 |
193 | 194 |
195 | 196 | Origin 197 | 198 | 199 | 200 | 201 | Left 202 | 203 | 204 | 205 | Center 206 | 207 | 208 | 209 | Right 210 | 211 | 212 | 213 | 214 | 215 |
216 |
217 | 218 | 219 | 220 | 221 | Top 222 | 223 | 224 | 225 | Middle 226 | 227 | 228 | 229 | Bottom 230 | 231 | 232 | 233 | 234 |
235 | 236 | 237 | Origin X 238 | 239 | Origin Y 240 | 241 |
242 |
243 |
244 | 245 |
246 | -------------------------------------------------------------------------------- /templates/page_menu.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

Page Settings

4 |
5 |
6 | 7 | 8 | 9 |
10 | Set page Size 11 |
12 | 13 |
14 | 15 | 16 | Presets 17 | 18 | 19 | 20 | 21 | {{ size.name }} 22 | 23 | 24 | 25 | 26 | 27 | 28 | Edit Size 29 | 30 | 31 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | Page Width 45 | 46 | Page Height 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | Apply Setting 55 | 56 | 57 | 58 | 59 |
60 |
61 |
62 | 63 | 64 | 65 |
66 | Background 67 |
68 | 69 |
70 | 71 | Fill Color 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 |
87 | 88 |
89 | 90 | 91 |
92 | Background Gradient 93 |
94 | 95 |
96 | 97 | Colors 98 | 99 | 100 | 101 | 102 | 103 | 104 |
105 |
106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 |
114 | 115 | 116 | Left Color 117 | 118 | Right Color 119 | 120 | 121 | 122 | 123 | Direction 124 | 125 | 126 | 127 | 128 | 129 |
130 |
131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 |
144 | 145 | 146 | Gradient Angle 147 | 148 | Direction 149 | 150 | 151 | 152 | 153 | 154 | Apply Background 155 | 156 | 157 | 158 | 159 |
160 |
161 |
162 | 163 | 164 | 165 |
166 | Background Image 167 |
168 | 169 |
170 | 171 | Image 172 | 173 | 174 | 175 | 176 | 177 |
178 |
179 | 180 | 181 | 182 | 183 | 184 | No Repeat 185 | 186 | 187 | 188 | Repeat X/Y 189 | 190 | 191 | 192 | Repeat X 193 | 194 | 195 | 196 | Repeat Y 197 | 198 | 199 | 200 | 201 | 202 | 203 | Reset Background 204 | 205 | 206 | 207 |
208 | 209 | 210 | Image Size 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 |
221 |
222 |
-------------------------------------------------------------------------------- /templates/pages.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |

Pages

5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 |
20 | 21 | 30 | 31 |
    32 | 33 |
  • 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 |
    42 |

    {{ object.name}}

    43 |
    44 | 45 | 46 |
    47 |
  • 48 |
49 |
-------------------------------------------------------------------------------- /templates/project_menu.html: -------------------------------------------------------------------------------- 1 |

Project Settings

2 |
3 | 4 |
5 | 6 |
7 | Sample content 8 |

Here we will define some project specific settings. This will be done later on...

9 |
10 |
11 |
-------------------------------------------------------------------------------- /templates/templates.html: -------------------------------------------------------------------------------- 1 |

Templates

2 |
3 | 4 |
5 | 6 |
7 | Sample content 8 |

Here we will define some project specific settings. This will be done later on...

9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /templates/toolbar.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | 7 | 8 | 9 | {{tab.title}} 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | Add Text 20 | 21 | 22 | 23 | 24 | 25 | 26 | Add Image 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | Insert Element 36 | 37 | 38 | 39 | 40 | Add Textfield 41 | 42 | 43 | 44 | 45 | Add Image... 46 | 47 | 48 | 49 | 50 | 51 | 52 | Add Video... 53 | 54 | 55 |
56 | 57 | 58 | 59 | Add Rectangle 60 | 61 | 62 | 63 | 64 | Add Rounded Rectangle 65 | 66 | 67 | 68 | 69 | Add Circle 70 | 71 | 72 | 73 | 74 | Add Triangle 75 | 76 | 77 | 78 | 79 | Add Line 80 | 81 |
82 |
83 |
84 | 85 |
86 | 87 | 88 | 89 | 90 | 91 | Page Editor 92 | 93 | 94 | 95 | 96 | 97 | 98 | Actions Editor 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | Page Flow 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | Project Preview 117 | 118 | 119 | 120 | 121 | 122 | 123 | Code View 124 | 125 | 126 | 127 | 128 | 129 | 130 | 133 | 134 | 135 | {{tab.title}} 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 |
165 |
166 | -------------------------------------------------------------------------------- /windows/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /windows/project.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 68 | 69 | 70 | 71 | 198 | 199 |
200 |
201 |

floido designer | Project Window

202 |
203 |
204 |
205 | 234 | 235 | 236 |
237 | 238 | 239 | 240 | Current Projects 241 | 242 | 243 | 244 | Active Templates 245 | 246 | 247 | 248 | 249 | 250 | 251 |
    252 | 253 |
  • 254 | 255 | 256 |
    257 | {{project.title}} 258 |
    259 |

    {{project.value}}

    260 |
    261 |
  • 262 |
263 | 264 |
265 | 266 |
267 | 268 | 269 |
270 |
271 |
272 | 273 | 274 | 275 | Show this Window on startup 276 | 277 | 278 | 279 | 283 | 284 | New Project... 285 | 286 | 287 | 288 | 289 | 290 | Open Project... 291 | 292 | 293 | 294 | 295 | 296 | Cancel 297 | 298 | 299 | 300 | 301 | 302 |
303 |
-------------------------------------------------------------------------------- /windows/settings.html: -------------------------------------------------------------------------------- 1 |
2 |

Vibrancy Type

3 | None 4 |
5 | Light 6 |
7 | Medium Light 8 |
9 | Dark 10 |
11 | Ultra Dark 12 |
13 |
14 | -------------------------------------------------------------------------------- /windows/simulator.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Our Code World 5 | 6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 |
14 |

15 |

16 | 17 | 18 |
19 |
20 |
21 |

22 | The file content will be the same as the editor. 23 |

24 | 25 |
26 | 129 | 130 | --------------------------------------------------------------------------------