2018-08-28 00:34:17 -04:00
'use strict' ;
2018-03-06 22:08:34 -05:00
function Dotgrid ( width , height , grid _x , grid _y , block _x , block _y )
2016-12-31 10:00:57 -05:00
{
2018-08-17 15:58:01 -04:00
this . controller = null ;
2017-11-06 21:10:09 -05:00
this . theme = new Theme ( ) ;
2017-11-14 16:11:09 -05:00
this . interface = new Interface ( ) ;
2018-01-31 04:10:48 -05:00
this . history = new History ( ) ;
2018-02-05 18:39:25 -05:00
this . guide = new Guide ( ) ;
2018-05-10 18:06:03 -04:00
this . renderer = new Renderer ( ) ;
2018-02-05 18:39:25 -05:00
this . tool = new Tool ( ) ;
2018-03-06 19:50:41 -05:00
this . picker = new Picker ( ) ;
2018-08-02 18:57:35 -04:00
this . cursor = new Cursor ( ) ;
2017-11-06 21:10:09 -05:00
2016-12-31 12:18:01 -05:00
this . grid _x = grid _x ;
this . grid _y = grid _y ;
2016-12-31 15:37:13 -05:00
this . block _x = block _x ;
this . block _y = block _y ;
2016-12-31 16:35:14 -05:00
2016-12-31 10:00:57 -05:00
this . install = function ( )
2018-07-07 20:15:35 -04:00
{
2018-05-08 05:05:19 -04:00
document . getElementById ( "app" ) . appendChild ( this . guide . el ) ;
2017-11-04 20:52:05 -04:00
2018-09-11 21:20:31 -04:00
this . theme . install ( document . body , this . update ) ;
}
this . start = function ( )
{
2017-11-06 21:10:09 -05:00
this . theme . start ( ) ;
2018-03-06 17:57:52 -05:00
this . tool . start ( ) ;
2017-11-09 14:47:06 -05:00
this . guide . start ( ) ;
2017-11-14 16:11:09 -05:00
this . interface . start ( ) ;
2018-01-12 03:09:26 -05:00
2018-08-02 18:57:35 -04:00
document . addEventListener ( 'mousedown' , function ( e ) { dotgrid . cursor . down ( e ) ; } , false ) ;
document . addEventListener ( 'mousemove' , function ( e ) { dotgrid . cursor . move ( e ) ; } , false ) ;
document . addEventListener ( 'contextmenu' , function ( e ) { dotgrid . cursor . alt ( e ) ; } , false ) ;
document . addEventListener ( 'mouseup' , function ( e ) { dotgrid . cursor . up ( e ) ; } , false ) ;
2018-07-26 02:56:06 -04:00
document . addEventListener ( 'copy' , function ( e ) { dotgrid . copy ( e ) ; } , false ) ;
document . addEventListener ( 'cut' , function ( e ) { dotgrid . cut ( e ) ; } , false ) ;
document . addEventListener ( 'paste' , function ( e ) { dotgrid . paste ( e ) ; } , false ) ;
2018-01-11 22:22:50 -05:00
window . addEventListener ( 'drop' , dotgrid . drag ) ;
2018-07-26 02:56:06 -04:00
2018-01-31 04:10:48 -05:00
this . new ( ) ;
2016-12-31 12:18:01 -05:00
}
2018-05-07 01:03:35 -04:00
// File
2018-01-12 03:46:09 -05:00
2018-01-12 03:09:26 -05:00
this . new = function ( )
{
2018-07-17 20:52:23 -04:00
this . set _zoom ( 1.0 )
2018-05-07 00:51:58 -04:00
this . set _size ( { width : 300 , height : 300 } )
2018-02-05 22:27:48 -05:00
this . history . push ( this . tool . layers ) ;
2018-05-07 01:03:35 -04:00
this . clear ( ) ;
2018-01-12 03:09:26 -05:00
}
2018-05-10 17:57:14 -04:00
this . open = function ( )
{
2018-08-26 15:39:15 -04:00
if ( ! dialog ) { return ; }
let paths = dialog . showOpenDialog ( { properties : [ 'openFile' ] , filters : [ { name : "Dotgrid Image" , extensions : [ "dot" , "grid" ] } ] } ) ;
2018-05-10 17:57:14 -04:00
2018-08-28 17:41:41 -04:00
if ( ! paths ) { console . warn ( "Nothing to load" ) ; return ; }
2018-05-10 17:57:14 -04:00
fs . readFile ( paths [ 0 ] , 'utf-8' , ( err , data ) => {
if ( err ) { alert ( "An error ocurred reading the file :" + err . message ) ; return ; }
2018-05-10 18:06:03 -04:00
this . tool . replace ( JSON . parse ( data . toString ( ) . trim ( ) ) ) ;
2018-09-11 21:20:31 -04:00
this . guide . update ( ) ;
2018-05-10 17:57:14 -04:00
} ) ;
}
2018-05-10 18:37:10 -04:00
this . save = function ( content = this . tool . export ( ) )
2018-01-12 03:09:26 -05:00
{
2018-08-28 17:41:41 -04:00
if ( dotgrid . tool . length ( ) < 1 ) { console . warn ( "Nothing to save" ) ; return ; }
2018-08-03 23:55:08 -04:00
2018-08-17 17:34:24 -04:00
if ( ! dialog ) { this . save _web ( content ) ; return ; }
2018-08-25 22:21:10 -04:00
dialog . showSaveDialog ( { title : "Save to .grid" , filters : [ { name : "Dotgrid Format" , extensions : [ "grid" , "dot" ] } ] } , ( fileName ) => {
2018-01-12 03:09:26 -05:00
if ( fileName === undefined ) { return ; }
2018-05-16 16:58:31 -04:00
fileName = fileName . substr ( - 5 , 5 ) != ".grid" ? fileName + ".grid" : fileName ;
fs . writeFileSync ( fileName , content ) ;
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( )
2018-01-12 03:09:26 -05:00
} ) ;
}
2018-08-17 17:34:24 -04:00
this . save _web = function ( content )
{
console . info ( "Web Save" ) ;
2018-08-26 15:39:15 -04:00
let win = window . open ( "" , "Save" , ` toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top= ${ screen . height - 200 } ,left= ${ screen . width - 640 } ` ) ;
2018-08-17 17:56:22 -04:00
win . document . body . innerHTML = ` <style>body { background: ${ dotgrid . theme . active . background } ; color: ${ dotgrid . theme . active . f _med } } pre { color: ${ dotgrid . theme . active . f _high } }</style><p>To save: Copy this into a .grid file.<br />To load: Drag the .grid onto the browser window.</p><pre> ${ content } </pre> ` ;
2018-08-17 17:34:24 -04:00
}
2018-05-16 18:53:29 -04:00
this . render = function ( content = this . renderer . to _png ( { width : dotgrid . tool . settings . size . width * 2 , height : dotgrid . tool . settings . size . height * 2 } ) , ready = null , size = null )
2018-01-12 03:09:26 -05:00
{
2018-05-10 18:37:10 -04:00
if ( ! ready ) { return ; }
2018-08-28 17:41:41 -04:00
if ( dotgrid . tool . length ( ) < 1 ) { console . warn ( "Nothing to render" ) ; return ; }
2018-05-10 18:37:10 -04:00
2018-08-17 17:34:24 -04:00
if ( ! dialog ) { dotgrid . render _web ( content ) ; return ; }
2018-08-25 22:21:10 -04:00
dialog . showSaveDialog ( { title : "Save to .png" , filters : [ { name : "Image Format" , extensions : [ "png" ] } ] } , ( fileName ) => {
2018-05-10 17:57:14 -04:00
if ( fileName === undefined ) { return ; }
2018-05-16 16:58:31 -04:00
fileName = fileName . substr ( - 4 , 4 ) != ".png" ? fileName + ".png" : fileName ;
2018-05-10 19:08:51 -04:00
console . log ( ` Rendered ${ size . width } x ${ size . height } ` )
2018-05-16 16:58:31 -04:00
fs . writeFileSync ( fileName , ready ) ;
2018-05-10 17:57:14 -04:00
} ) ;
}
2018-01-12 03:09:26 -05:00
2018-08-17 17:34:24 -04:00
this . render _web = function ( content , window )
{
// Handled in Renderer
2018-08-17 17:56:22 -04:00
console . info ( "Web Render" ) ;
2018-08-17 17:34:24 -04:00
}
2018-05-10 18:37:10 -04:00
this . export = function ( content = this . renderer . to _svg ( ) )
2018-05-10 17:57:14 -04:00
{
2018-08-28 17:41:41 -04:00
if ( dotgrid . tool . length ( ) < 1 ) { console . warn ( "Nothing to export" ) ; return ; }
2018-08-03 23:55:08 -04:00
2018-08-17 17:34:24 -04:00
if ( ! dialog ) { this . export _web ( content ) ; return ; }
2018-08-25 22:21:10 -04:00
dialog . showSaveDialog ( { title : "Save to .svg" , filters : [ { name : "Vector Format" , extensions : [ "svg" ] } ] } , ( fileName ) => {
2018-05-10 17:57:14 -04:00
if ( fileName === undefined ) { return ; }
2018-05-16 16:58:31 -04:00
fileName = fileName . substr ( - 4 , 4 ) != ".svg" ? fileName + ".svg" : fileName ;
fs . writeFileSync ( fileName , content ) ;
2018-09-11 21:20:31 -04:00
this . guide . update ( )
2018-01-12 03:09:26 -05:00
} ) ;
}
2018-08-17 17:34:24 -04:00
this . export _web = function ( content )
{
console . info ( "Web Export" ) ;
2018-08-26 15:39:15 -04:00
let win = window . open ( "" , "Save" , ` toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=640,height=480,top= ${ screen . height - 200 } ,left= ${ screen . width - 640 } ` ) ;
2018-08-17 17:56:22 -04:00
win . document . body . innerHTML = ` <style>body { background: ${ dotgrid . theme . active . background } }</style> ${ dotgrid . renderer . to _svg ( ) } ` ;
2018-08-17 17:34:24 -04:00
}
2018-05-07 01:03:35 -04:00
// Basics
2018-07-07 20:15:35 -04:00
2018-08-28 00:34:17 -04:00
this . set _size = function ( size = { width : 300 , height : 300 } , ui = true , scale = 1 )
2017-11-21 17:58:07 -05:00
{
2018-08-02 21:48:16 -04:00
size = { width : clamp ( step ( size . width , 15 ) , 105 , 1080 ) , height : clamp ( step ( size . height , 15 ) , 120 , 1080 ) }
2018-05-06 19:15:23 -04:00
2018-05-07 18:47:09 -04:00
this . tool . settings . size . width = size . width
this . tool . settings . size . height = size . height
2018-05-10 04:01:31 -04:00
2018-08-17 15:58:01 -04:00
try {
2018-08-26 15:39:15 -04:00
let win = require ( 'electron' ) . remote . getCurrentWindow ( ) ;
2018-08-28 00:34:17 -04:00
win . setSize ( ( size . width + 100 ) * scale , ( size . height + 100 + ( ui ? 10 : 0 ) ) * scale , true ) ;
2018-08-17 15:58:01 -04:00
}
catch ( err ) {
console . log ( "No window" )
}
2017-11-21 17:58:07 -05:00
this . grid _x = size . width / 15
this . grid _y = size . height / 15
2018-05-07 00:24:01 -04:00
2018-05-07 18:47:09 -04:00
this . grid _width = this . tool . settings . size . width / this . grid _x ;
this . grid _height = this . tool . settings . size . height / this . grid _y ;
2018-05-07 00:51:58 -04:00
2017-11-21 17:58:07 -05:00
dotgrid . guide . resize ( size ) ;
2018-05-10 17:13:01 -04:00
2018-09-11 21:20:31 -04:00
this . interface . update ( ) ;
dotgrid . guide . update ( ) ;
2017-11-04 19:59:11 -04:00
}
2018-05-12 17:50:19 -04:00
this . set _zoom = function ( scale )
{
this . set _size ( { width : this . tool . settings . size . width , height : this . tool . settings . size . height } , true , scale )
2018-08-17 15:58:01 -04:00
try {
webFrame . setZoomFactor ( scale )
}
catch ( err ) {
console . log ( "Cannot zoom" )
}
2018-05-12 17:50:19 -04:00
}
2016-12-31 12:18:01 -05:00
// Draw
2018-07-07 20:15:35 -04:00
2016-12-31 12:37:10 -05:00
this . reset = function ( )
2016-12-31 12:18:01 -05:00
{
2018-02-06 14:16:01 -05:00
this . tool . clear ( ) ;
2018-09-11 21:20:31 -04:00
this . update ( ) ;
2016-12-31 12:18:01 -05:00
}
2017-11-07 16:40:13 -05:00
this . clear = function ( )
{
2018-02-04 16:09:46 -05:00
this . history . clear ( ) ;
2018-02-06 14:16:01 -05:00
this . tool . reset ( ) ;
2017-11-07 16:40:13 -05:00
this . reset ( ) ;
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
dotgrid . interface . update ( true ) ;
2017-11-07 16:40:13 -05:00
}
2018-09-11 21:20:31 -04:00
this . update = function ( )
2018-08-17 15:58:01 -04:00
{
2018-08-26 15:39:15 -04:00
let size = { width : step ( window . innerWidth - 90 , 15 ) , height : step ( window . innerHeight - 120 , 15 ) }
2018-08-17 15:58:01 -04:00
dotgrid . tool . settings . size . width = size . width
dotgrid . tool . settings . size . height = size . height
dotgrid . grid _x = size . width / 15
dotgrid . grid _y = size . height / 15
dotgrid . grid _width = dotgrid . tool . settings . size . width / dotgrid . grid _x ;
dotgrid . grid _height = dotgrid . tool . settings . size . height / dotgrid . grid _y ;
dotgrid . guide . resize ( size ) ;
2018-09-11 21:20:31 -04:00
dotgrid . interface . update ( ) ;
dotgrid . guide . update ( ) ;
2018-08-17 17:34:24 -04:00
document . title = ` Dotgrid — ${ size . width } x ${ size . height } `
2018-08-17 15:58:01 -04:00
}
2018-01-11 22:22:50 -05:00
this . drag = function ( e )
{
e . preventDefault ( ) ;
e . stopPropagation ( ) ;
2018-07-07 20:15:35 -04:00
2018-08-26 15:39:15 -04:00
let file = e . dataTransfer . files [ 0 ] ;
2018-01-11 22:22:50 -05:00
2018-04-09 00:50:52 -04:00
if ( ! file . path || file . path . indexOf ( ".dot" ) < 0 && file . path . indexOf ( ".grid" ) < 0 ) { console . log ( "Dotgrid" , "Not a dot file" ) ; return ; }
2018-01-11 22:22:50 -05:00
2018-08-26 15:39:15 -04:00
let reader = new FileReader ( ) ;
2018-01-11 22:22:50 -05:00
reader . onload = function ( e ) {
2018-02-07 15:34:17 -05:00
dotgrid . tool . replace ( JSON . parse ( e . target . result . toString ( ) . trim ( ) ) ) ;
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2018-01-11 22:22:50 -05:00
} ;
reader . readAsText ( file ) ;
}
2017-11-21 16:24:25 -05:00
this . copy = function ( e )
{
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2018-01-13 15:11:57 -05:00
2018-07-26 04:40:06 -04:00
if ( e . target !== this . picker . el ) {
2018-07-26 02:56:06 -04:00
e . clipboardData . setData ( 'text/source' , dotgrid . tool . export ( dotgrid . tool . layer ( ) ) ) ;
e . clipboardData . setData ( 'text/plain' , dotgrid . tool . path ( ) ) ;
e . clipboardData . setData ( 'text/html' , dotgrid . renderer . to _svg ( ) ) ;
e . clipboardData . setData ( 'text/svg+xml' , dotgrid . renderer . to _svg ( ) ) ;
e . preventDefault ( ) ;
}
2018-02-07 01:44:18 -05:00
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2018-02-07 01:44:18 -05:00
}
this . cut = function ( e )
{
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2018-02-07 01:44:18 -05:00
2018-07-26 04:40:06 -04:00
if ( e . target !== this . picker . el ) {
2018-07-26 02:56:06 -04:00
e . clipboardData . setData ( 'text/plain' , dotgrid . tool . export ( dotgrid . tool . layer ( ) ) ) ;
e . clipboardData . setData ( 'text/html' , dotgrid . renderer . to _svg ( ) ) ;
e . clipboardData . setData ( 'text/svg+xml' , dotgrid . renderer . to _svg ( ) ) ;
dotgrid . tool . layers [ dotgrid . tool . index ] = [ ] ;
e . preventDefault ( ) ;
}
2018-02-07 01:44:18 -05:00
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2017-11-21 16:24:25 -05:00
}
this . paste = function ( e )
{
2018-07-26 04:40:06 -04:00
if ( e . target !== this . picker . el ) {
2018-08-26 15:39:15 -04:00
let data = e . clipboardData . getData ( "text/source" ) ;
2018-07-26 02:56:06 -04:00
if ( is _json ( data ) ) {
data = JSON . parse ( data . trim ( ) ) ;
dotgrid . tool . import ( data ) ;
}
e . preventDefault ( ) ;
2018-05-07 21:32:06 -04:00
}
2018-07-07 20:15:35 -04:00
2018-09-11 21:20:31 -04:00
dotgrid . guide . update ( ) ;
2017-11-21 16:24:25 -05:00
}
2017-11-05 23:35:29 -05:00
}
2017-11-06 21:10:09 -05:00
2017-11-12 16:47:34 -05:00
window . addEventListener ( 'resize' , function ( e )
{
2018-09-11 21:20:31 -04:00
dotgrid . update ( ) ;
2017-11-12 16:47:34 -05:00
} , false ) ;
2018-01-11 22:22:50 -05:00
window . addEventListener ( 'dragover' , function ( e )
2017-11-06 21:10:09 -05:00
{
e . stopPropagation ( ) ;
2018-01-11 22:22:50 -05:00
e . preventDefault ( ) ;
e . dataTransfer . dropEffect = 'copy' ;
2018-01-13 15:11:57 -05:00
} ) ;
2018-03-21 03:10:09 -04:00
String . prototype . capitalize = function ( )
{
return this . charAt ( 0 ) . toUpperCase ( ) + this . slice ( 1 ) . toLowerCase ( ) ;
2018-05-09 03:22:00 -04:00
}
2018-07-17 20:52:23 -04:00
function is _json ( text ) { try { JSON . parse ( text ) ; return true ; } catch ( error ) { return false ; } }
function pos _is _equal ( a , b ) { return a && b && a . x == b . x && a . y == b . y }
function clamp ( v , min , max ) { return v < min ? min : v > max ? max : v ; }
2018-08-02 18:57:35 -04:00
function step ( v , s ) { return Math . round ( v / s ) * s ; }