├── .gitignore
├── .travis.yml
├── Makefile
├── README.md
├── daisy_spread_image
├── .gitignore
├── css
│ └── style.css
├── image.svg
├── image
│ ├── icon.ai
│ ├── icon.icns
│ ├── icon.ico
│ ├── icon.png
│ └── icon.xcf
├── index.html
├── index.js
├── js
│ ├── ad.js
│ ├── daisy-io.js
│ ├── diagram.js
│ ├── external_browser.js
│ ├── fileex.js
│ ├── index.js
│ ├── menu.js
│ ├── object-util.js
│ ├── preference.js
│ ├── renderer.js
│ └── version.js
├── main.js
├── package.json
├── resource
│ ├── circle
│ │ ├── MagicCircle_RuneAMN_20141111.svg
│ │ ├── MagicCircle_RuneAMN_20141112.svg
│ │ ├── MagicCircle_RuneAMN_20141113.svg
│ │ ├── MagicCircle_RuneAMN_20141114.svg
│ │ ├── MagicCircle_RuneAMN_20141116.svg
│ │ ├── MagicCircle_RuneAMN_20141117.svg
│ │ ├── MagicCircle_RuneAMN_20141118.svg
│ │ ├── MagicCircle_RuneAMN_20141119.svg
│ │ ├── MagicCircle_RuneAMN_20141120.svg
│ │ ├── MagicCircle_RuneAMN_20141121.svg
│ │ ├── MagicCircle_RuneAMN_20141122.svg
│ │ └── MagicCircle_RuneAMN_20141123.svg
│ ├── default-document.daisyspreadimage
│ └── default-preference.json
└── test
│ ├── mocha.js
│ └── spec.js
├── document
└── image
│ └── daisy_spread_image_0.0.1.png
└── release
├── installer_darwin.sh
├── installer_debian.sh
├── installer_debian_amd64_config.json
└── installer_win32_x64.sh
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .*
3 | !.gitkeep
4 | !.gitignore
5 | tags
6 |
7 | *~
8 | *.back
9 | # patch command backup file
10 | *.rej
11 | *.orig
12 |
13 | # cash
14 | *~
15 |
16 | # tmporary
17 | tmp/
18 | temp/
19 | gabage/
20 | work/
21 | log/
22 |
23 | # object files
24 | *.d
25 | *.o
26 | *.a
27 | *.exe
28 | *.app
29 |
30 | # Object files
31 | *.o
32 | *.ko
33 | *.obj
34 | *.elf
35 |
36 | # Libraries
37 | *.lib
38 | *.a
39 | *.la
40 | *.lo
41 |
42 | # Shared objects (inc. Windows DLLs)
43 | *.dll
44 | *.so
45 | *.so.*
46 | *.dylib
47 |
48 | # doxygen
49 | doxygen/
50 |
51 | *.txt
52 |
53 |
54 | #
55 | .DS_Store
56 | Thumbs.db*
57 |
58 |
59 | node_modules/
60 | release/
61 | package-lock.json
62 |
63 | !.travis.yml
64 |
65 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo: false
2 |
3 | language: node_js
4 | node_js:
5 | - "14"
6 | - "12"
7 |
8 | addons:
9 | apt:
10 | packages:
11 | - make
12 | - librsvg2-bin
13 | - plantuml
14 | #- wine
15 |
16 | # need spectron test
17 | services:
18 | - xvfb
19 | before_script:
20 | - "export DISPLAY=:99.0"
21 |
22 | script:
23 | - make ci-test
24 |
25 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 |
2 | .PHONY: all run clean
3 |
4 | all:
5 | # NOP
6 | exit 1
7 |
8 | run:
9 | cd daisy_spread_image && npm run running
10 |
11 | clean:
12 | cd daisy_spread_image && npm run clean
13 | rm -rf release/release
14 |
15 | .PHONY: test ci-test
16 | ci-test:
17 | cd daisy_spread_image && npm install
18 | make test
19 | #make package
20 |
21 | test:
22 | cd daisy_spread_image && npm run test test/$(ARG)
23 |
24 | .PHONY: package package_desktop
25 | package: package_desktop
26 |
27 | package_desktop:
28 | rm -rf daisy_spread_image/node_modules
29 | #cd daisy_spread_image && npm install # audit command depend npm version 6
30 | cd daisy_spread_image && npm install && npm audit fix
31 | make test
32 | bash ./release/installer_win32_x64.sh
33 | bash ./release/installer_darwin.sh
34 | bash ./release/installer_debian.sh
35 |
36 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | daisy spread image
2 | ====
3 |
4 | [](https://travis-ci.org/MichinariNukazawa/daisy_spread_image)
5 |
6 | daisy spread image is magickcircle free scale image generator.
7 |
8 | # 概要
9 | daisy spread imageは、魔法陣ばら撒き画像の生成アプリです。
10 | Win/Mac/Linux対応。
11 |
12 | 
13 |
14 | # Download
15 | [Download for latest release](https://github.com/MichinariNukazawa/daisy_spread_image/releases)
16 |
17 | # Contact
18 | mail: [michinari.nukazawa@gmail.com][mailto]
19 | twitter: [@MNukazawa][twitter]
20 |
21 | Develop by Michinari.Nukazawa, in project "daisy bell".
22 |
23 | [pixiv_booth_project_daisy_bell]: https://daisy-bell.booth.pm/
24 | [gumroad_runeamn_fonts_pro]: https://gumroad.com/l/UNWF
25 | [mailto]: mailto:michinari.nukazawa@gmail.com
26 | [twitter]: https://twitter.com/MNukazawa
27 |
28 |
--------------------------------------------------------------------------------
/daisy_spread_image/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | object/
3 |
4 |
--------------------------------------------------------------------------------
/daisy_spread_image/css/style.css:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | html, body{
4 | margin: 0px; /* 余白の削除 */
5 | padding: 0px; /* 余白の削除 */
6 | width:100%;
7 | height: 99%;
8 | }
9 |
10 | /*dark theme*/
11 | body, input, button, select{
12 | color: rgb(240, 240, 240);
13 | border-color: rgb(180, 180, 180);
14 | background-color: rgb(30, 30, 30);
15 | }
16 |
17 | input, button{
18 | background-color: rgb(70, 70, 70);
19 | }
20 |
21 | div{
22 | margin: 0px;
23 | padding: 0px;
24 | }
25 |
26 | input, select{
27 | font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
28 | vertical-align: bottom;
29 | font-size: 0.8em;
30 | }
31 |
32 | input[type="number"]{
33 | text-align: right;
34 | width: 70px;
35 | direction: rtl;
36 | }
37 |
38 | input[type="text"]{
39 | width: 70px;
40 | }
41 |
42 | input[type="checkbox"][disabled] + span{
43 | color: #707070;
44 | }
45 |
46 | input:disabled, button:disabled, select:disabled{
47 | background: rgba(128, 128, 128, 0.8);
48 | color: rgba(64, 64, 64, 0.5);
49 | }
50 |
51 | button{
52 | font-size: 0.8em;
53 | }
54 |
55 | #editor__background-transparent-view{
56 | font-size: 75%;
57 | }
58 |
59 | #edit-control{
60 | text-align: right;
61 | font-size: 120%;
62 | background-color: rgb(40, 40, 40);
63 | }
64 |
65 | .box-container{
66 | display: flex;
67 | height: calc(99% - 48px);
68 | }
69 |
70 | .frame{
71 | margin: 2px;
72 | padding: 2px;
73 | border: solid 1.5px rgba(220, 220, 220, 0.6);
74 | border-radius: 2px;
75 | }
76 |
77 | table th{
78 | vertical-align: middle;
79 | text-align: left;
80 | overflow: visible;
81 | position: relative;
82 | font-weight: normal;
83 | }
84 |
85 | #property-editor{
86 | width: 320px;
87 | font-size: 120%;
88 | background-color: rgb(40, 40, 40);
89 | overflow: visible auto;
90 | }
91 |
92 | #canvas-header{
93 | padding: 5px;
94 | font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
95 | font-size: 75%;
96 | }
97 |
98 | #editor__element-text{
99 | resize: vertical;
100 | }
101 |
102 | #thumbnail-container{
103 | border: solid 1px rgba(0, 0, 0, 0.3);
104 | background: white;
105 | }
106 |
107 | #magickcircle_source_num{
108 | font-family: Consolas, 'Courier New', Courier, Monaco, monospace;
109 | }
110 |
111 | #canvas-container{
112 | border: solid 1px rgba(0, 0, 0, 0.3);
113 | /* background: white; */
114 | position:absolute;
115 | top:58px; bottom:24px; left:325px; right:2px;
116 | overflow: auto;
117 | cursor: default;
118 | }
119 |
120 | #canvas{
121 | min-height: 90%;
122 | }
123 |
124 | #canvas svg{
125 | background: white;
126 | }
127 |
128 | #footer-control{
129 | text-align: right;
130 | background-color: rgb(100, 100, 100);
131 | position: absolute;
132 | bottom: 0;
133 | width: 100%;
134 | padding-bottom: 1px;
135 | }
136 |
137 | #editor-canvas_scale_par{
138 | width: 70px;
139 | }
140 |
141 | #nodocument-message{
142 | padding: 5px;
143 | }
144 |
145 | #editor-magickcircle_source_directory_path{
146 | width: 70%;
147 | }
148 |
149 | #link-get-more-magickcircle{
150 | width: 100%;
151 | color: rgba(80, 200, 256, 0.92);
152 | cursor: default;
153 | }
154 |
155 | #editor-randomseed_value{
156 | text-align: right;
157 | width: 110px;
158 | }
159 |
160 |
--------------------------------------------------------------------------------
/daisy_spread_image/image.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
155 |
--------------------------------------------------------------------------------
/daisy_spread_image/image/icon.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/daisy_spread_image/image/icon.ai
--------------------------------------------------------------------------------
/daisy_spread_image/image/icon.icns:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/daisy_spread_image/image/icon.icns
--------------------------------------------------------------------------------
/daisy_spread_image/image/icon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/daisy_spread_image/image/icon.ico
--------------------------------------------------------------------------------
/daisy_spread_image/image/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/daisy_spread_image/image/icon.png
--------------------------------------------------------------------------------
/daisy_spread_image/image/icon.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/daisy_spread_image/image/icon.xcf
--------------------------------------------------------------------------------
/daisy_spread_image/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | daisy spread image
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | document size
15 | width: px
16 | height: px
17 |
18 |
103 |
112 |
113 |
114 |
--------------------------------------------------------------------------------
/daisy_spread_image/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | //const DaisyIO = require('./js/daisy-io');
4 |
5 | //module.exports.DaisyIO = DaisyIO;
6 |
7 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/ad.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | class Ad{
4 | constructor()
5 | {
6 | this.INTERVAL_MSEC = 50;
7 |
8 | this.TIMEOUT_COUNT_MSEC = 2 *1000;
9 | this.timeout_count = this.TIMEOUT_COUNT_MSEC;
10 |
11 | this.HIDE_COUNT_MSEC = 1 *1000;
12 | this.hide_count = this.HIDE_COUNT_MSEC;
13 |
14 | this.ad_root_element = document.createElement('div');
15 |
16 | this.ad_root_element.style.cssText =
17 | ''
18 | + 'top:' + 0 + 'px;'
19 | + 'left:' + 0 + 'px;'
20 | + 'width:320px;'
21 | + 'position: fixed;'
22 | //+ 'background-color:rgba(255, 255, 255, 0.95);'
23 | + 'color: rgb(240, 240, 240);'
24 | + 'background-color: rgb(30, 30, 30);'
25 | + 'border: 1.5px solid black;'
26 | + 'border-radius: 3px;'
27 | + 'text-align:center;'
28 | ;
29 |
30 |
31 | this.ads = [
32 | {
33 | 'width': 320,
34 | 'height': 240,
35 | 'html':`
36 |
37 |
38 | daisy spread image
39 | magickcircles freescale image generator.
40 |
`
41 | },
42 | /*
43 | {
44 | 'width': 320,
45 | 'height': 240,
46 | 'html':``
47 | },
48 | */
49 | ];
50 | }
51 |
52 | get_position_(width, height)
53 | {
54 | const position = {
55 | 'top': (window.innerHeight - height) - 150,
56 | 'left': (window.innerWidth - width) / 2,
57 | };
58 |
59 | return position;
60 | }
61 |
62 | hide_()
63 | {
64 | let callback = function(){
65 | this.hide_count -= this.INTERVAL_MSEC;
66 | if(0 > this.hide_count){
67 | this.ad_root_element.style["display"] = "none";
68 | }else{
69 | this.ad_root_element.style["opacity"] = (this.hide_count / this.HIDE_COUNT_MSEC);
70 | setTimeout(callback, this.INTERVAL_MSEC);
71 | }
72 | }.bind(this);
73 | setTimeout(callback, this.INTERVAL_MSEC);
74 | }
75 |
76 | start()
77 | {
78 | let index = Math.floor(Math.random(0, this.ads.length));
79 | const position = this.get_position_(this.ads[index].width, this.ads[index].height);
80 | console.log(index, position);
81 |
82 | this.ad_root_element.style["top"] = position["top"] + 'px';
83 | this.ad_root_element.style["left"] = position["left"] + 'px';
84 | this.ad_root_element.innerHTML = this.ads[index].html;
85 |
86 | document.body.appendChild(this.ad_root_element);
87 | let callback = function(){
88 | this.timeout_count -= this.INTERVAL_MSEC;
89 | // console.log("ad count:%d", this.timeout_count);
90 | if(0 > this.timeout_count){
91 | this.hide_();
92 | }else{
93 | setTimeout(callback, this.INTERVAL_MSEC);
94 | }
95 | }.bind(this);
96 | setTimeout(callback, this.INTERVAL_MSEC);
97 | }
98 | };
99 |
100 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/daisy-io.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const sprintf = require('sprintf-js').sprintf;
4 | const fs = require("fs");
5 |
6 | module.exports = class DaisyIO{
7 | static set_err_(err_, level, label, message)
8 | {
9 | err_.level = level;
10 | err_.label = label;
11 | err_.message = message;
12 | }
13 |
14 | static add_errs_(errs_, level, label, message)
15 | {
16 | let err_ = {};
17 | DaisyIO.set_err_(err_, level, label, message);
18 |
19 | if(! Array.isArray(errs_)){
20 | console.error(errs_);
21 | errs_ = [];
22 | }
23 | errs_.push(err_);
24 | }
25 |
26 | static open_diagram_from_path(filepath, errs_)
27 | {
28 | // const Diagram = require('./diagram');
29 |
30 | if(typeof filepath !== 'string'){
31 | DaisyIO.add_errs_(errs_, 'bug', "Open", "not filepath.");
32 | return null;
33 | }
34 |
35 | let strdata = '';
36 | try{
37 | strdata = fs.readFileSync(filepath, 'utf-8');
38 | }catch(err){
39 | console.error(err.message);
40 | DaisyIO.add_errs_(errs_, 'warning', "Open", err.message);
41 | return null;
42 | }
43 |
44 | const diagram = Diagram.create_from_native_format_string(strdata, errs_);
45 | return diagram;
46 | }
47 |
48 | static get_ext_from_filepath(filepath)
49 | {
50 | const m = filepath.match(/\.[a-zA-Z0-9]*$/);
51 | if(null === m){
52 | return '';
53 | }
54 | return m[0];
55 | }
56 |
57 | static write_export_diagram(filepath, diagram, errs_)
58 | {
59 | // 周辺情報: 0x0pxのSVGを開くとeye of gnomeが読み込みエラーを起こす。
60 |
61 | if(typeof filepath !== 'string'){
62 | DaisyIO.add_errs_(errs_, 'bug', "Export", "not filepath.");
63 | return null;
64 | }
65 |
66 | const ext = DaisyIO.get_ext_from_filepath(filepath);
67 |
68 | let res;
69 | switch(ext){
70 | case '.png':
71 | res = DaisyIO.write_export_png_from_diagram_(filepath, diagram, errs_);
72 | break;
73 | case '.svg':
74 | res = DaisyIO.write_export_svg_from_diagram_(filepath, diagram, errs_);
75 | break;
76 | case '':
77 | DaisyIO.add_errs_(errs_, "warning", "Export", sprintf("file type (ext) not exist. :`%s`", filepath));
78 | return false;
79 | break;
80 | default:
81 | DaisyIO.add_errs_(errs_, "warning", "Export", sprintf("invalid file type. :`%s`", filepath));
82 | return false;
83 | }
84 |
85 | return res;
86 | }
87 |
88 | static write_export_png_from_diagram_(filepath, diagram, errs_)
89 | {
90 | let err_ = {};
91 |
92 | /**
93 | png export is not synced.
94 | https://github.com/domenic/svg2png/issues/113
95 | */
96 | let svgAsPngUri = require('save-svg-as-png').svgAsPngUri;
97 | let dataUriToBuffer = require('data-uri-to-buffer');
98 |
99 | const opt = {'scale':1};
100 | let draw = Renderer.generate_svgjsdraw_from_diagram(diagram, opt);
101 | if(null === draw){
102 | DaisyIO.add_errs_(errs_, err_.level, "Export", err_.message);
103 | return false;
104 | }
105 |
106 | let svg_elem = draw.node;
107 | // saveSvgAsPng(svg_elem, filepath, {scale: 3});
108 | // @todo 上限サイズ(4800x3600~どこかまでの間)があるようでその場合0byteファイルが書き出される。
109 | svgAsPngUri(svg_elem,
110 | {
111 | 'backgroundColor': "#fff",
112 | },
113 | function(uri) {
114 | const decoded = dataUriToBuffer(uri)
115 | try{
116 | fs.writeFileSync(filepath, decoded);
117 | }catch(err){
118 | let err_ = {};
119 | DaisyIO.set_err_(err_, "warning", "Export", err.message);
120 | console.error(err_);
121 | alart(err_);
122 | return;
123 | }
124 | });
125 |
126 | return true;
127 | }
128 |
129 | static write_export_svg_from_diagram_(filepath, diagram, errs_)
130 | {
131 | let err_ = {};
132 | const opt = {
133 | 'scale': 1,
134 | };
135 | const strdata = DaisyIO.get_svg_string_from_diagram_(diagram, opt, err_);
136 | if(null === strdata){
137 | console.error(err_);
138 | DaisyIO.add_errs_(errs_, err_.level, "Export", err_.message);
139 | return false;
140 | }
141 |
142 | try{
143 | fs.writeFileSync(filepath, strdata);
144 | }catch(err){
145 | DaisyIO.add_errs_(errs_, "warning", "Export", sprintf("writeFile error. :`%s`", filepath));
146 | return false;
147 | }
148 |
149 | return true;
150 | }
151 |
152 | static get_svg_string_from_diagram_(diagram, opt, err_)
153 | {
154 | const xml_formatter = require('xml-formatter');
155 | const Version = require('./version');
156 |
157 | let s = Renderer.generate_svgstr_from_diagram(diagram, opt);
158 |
159 | const h = sprintf("", Version.get_name(), Version.get_version());
160 | s = h + s;
161 |
162 | let options = {indentation: '\t',};
163 | return xml_formatter(s, options);
164 | }
165 | };
166 |
167 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/diagram.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const sprintf = require('sprintf-js').sprintf;
4 |
5 | const ObjectUtil = require('./object-util');
6 | const Version = require('./version');
7 |
8 | module.exports = class Diagram{
9 | static set_err_(err_, level, label, message)
10 | {
11 | err_.level = level;
12 | err_.label = label;
13 | err_.message = message;
14 | }
15 |
16 | static add_errs_(errs_, level, label, message)
17 | {
18 | let err_ = {};
19 | DaisyIO.set_err_(err_, level, label, message);
20 |
21 | if(! Array.isArray(errs_)){
22 | console.error(errs_);
23 | errs_ = [];
24 | }
25 | errs_.push(err_);
26 | }
27 |
28 | static create_from_native_format_string(strdata, errs_)
29 | {
30 | let native_doc = {};
31 | try{
32 | native_doc = JSON.parse(strdata);
33 | }catch(err){
34 | console.debug(err);
35 | DaisyIO.add_errs_(errs_, 'error', "Diagram", err.message);
36 | return null;
37 | }
38 |
39 | if(! native_doc.hasOwnProperty('diagram')){
40 | DaisyIO.add_errs_(errs_, 'error', "Diagram", 'nothing property "diagram"');
41 | return null;
42 | }
43 |
44 | const sanitized_diagram = Diagram.sanitize(native_doc.diagram, errs_);
45 | if(null === sanitized_diagram){
46 | return null;
47 | }
48 |
49 | return sanitized_diagram;
50 | }
51 |
52 | static sanitize(src_diagram, errs_)
53 | {
54 | //! @todo not implement
55 | return ObjectUtil.deepcopy(src_diagram);
56 | }
57 |
58 | static get_size(diagram)
59 | {
60 | return {
61 | 'width': diagram.property.document_width,
62 | 'height': diagram.property.document_height,
63 | };
64 | }
65 |
66 | static MAX_SIZE()
67 | {
68 | return 30000;
69 | }
70 |
71 | static MIN_SIZE()
72 | {
73 | return 150;
74 | }
75 |
76 | static set_size(diagram, size)
77 | {
78 | if(! Number.isFinite(size.width)
79 | || Diagram.MIN_SIZE() > size.width
80 | || Diagram.MAX_SIZE() < size.width){
81 | return false;
82 | }
83 | if(! Number.isFinite(size.height)
84 | || Diagram.MIN_SIZE() > size.height
85 | || Diagram.MAX_SIZE() < size.height){
86 | return false;
87 | }
88 | diagram.property.document_width = Math.round(size.width);
89 | diagram.property.document_height = Math.round(size.height);
90 |
91 | return true;
92 | }
93 | };
94 |
95 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/external_browser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = class ExternalBrowser{
4 | static open(link){
5 | require('electron').shell.openExternal(link)
6 | }
7 | };
8 |
9 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/fileex.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = class FileEx{
4 | static is_exist_file(filepath){
5 | const fs = require('fs');
6 | try{
7 | fs.accessSync(filepath);
8 | return true;
9 | }catch(err){
10 | console.debug(err);
11 | return false;
12 | }
13 | }
14 |
15 | static touch(filepath){
16 | const fs = require('fs');
17 | fs.writeFileSync(filepath, "");
18 | }
19 |
20 | static join(path1, path2){
21 | const path = require('path');
22 | return path.join(path1, path2);
23 | }
24 |
25 | static read_textfile(filepath){
26 | const fs = require('fs');
27 | try{
28 | const t = fs.readFileSync(filepath, 'utf8');
29 | return t;
30 | }catch(err){
31 | console.debug(err);
32 | return null;
33 | }
34 | }
35 |
36 | static read_json(filepath){
37 | const t = FileEx.read_textfile(filepath);
38 | if(null === t){
39 | return {};
40 | }
41 | return JSON.parse(t);
42 | }
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require("fs");
4 | const path = require('path');
5 | const sprintf = require('sprintf-js').sprintf;
6 | let SVG = require('svg.js');
7 | //const {app} = require('electron').remote;
8 | const Preference = require('./js/preference');
9 | const Renderer = require('./js/renderer').Renderer;
10 | const RenderingHandle = require('./js/renderer').RenderingHandle;
11 | const DaisyIO = require('./js/daisy-io');
12 | const ExternalBrowser = require('./js/external_browser');
13 | let ad = new Ad();
14 |
15 | let rendering_handle = null;
16 | let rendering_handle_thumbnail = null;
17 |
18 |
19 |
20 | // 再現可能擬似乱数
21 | //! @notice 再現さえできればよく、かつ機能追加などであっさり呼び出しが増減するのでバージョン間の再現は諦める。
22 | // https://sbfl.net/blog/2017/06/01/javascript-reproducible-random/
23 | class Random {
24 | constructor(seed = 88675123) {
25 | this.x = 123456789;
26 | this.y = 362436069;
27 | this.z = 521288629;
28 | this.w = seed;
29 | }
30 |
31 | // XorShift
32 | next() {
33 | let t;
34 |
35 | t = this.x ^ (this.x << 11);
36 | this.x = this.y; this.y = this.z; this.z = this.w;
37 | return this.w = (this.w ^ (this.w >>> 19)) ^ (t ^ (t >>> 8));
38 | }
39 |
40 | range(min, max){
41 | const v = Math.abs(this.next());
42 | const n = max - min;
43 | const r = (v % n) + min;
44 | return r;
45 | }
46 | }
47 |
48 | class Point{
49 | static between_s(p0, p1){
50 | return Math.abs(p0.x - p1.x) + Math.abs(p0.y - p1.y);
51 | }
52 | }
53 |
54 |
55 |
56 | function isExistDirSync(file)
57 | {
58 | try{
59 | const stat = fs.statSync(file);
60 | return stat.isDirectory();
61 | }catch(err){
62 | return false;
63 | }
64 | }
65 |
66 | function opendir_dialog(default_dirpath)
67 | {
68 | const {app} = require('electron').remote;
69 | const {dialog} = require('electron').remote;
70 | const fs = require('fs');
71 |
72 | let open_dirpath = app.getPath('home');
73 | if(isExistDirSync(default_dirpath)){
74 | open_dirpath = default_dirpath;
75 | }
76 | console.debug('open_dirpath', open_dirpath);
77 |
78 | let filepath = dialog.showOpenDialogSync(
79 | remote.getCurrentWindow(),
80 | {
81 | title: 'Open',
82 | defaultPath: open_dirpath,
83 | properties: ['openDirectory'],
84 | });
85 |
86 | if(typeof filepath === "undefined"){
87 | return '';
88 | }
89 |
90 | filepath = filepath[0];
91 | return filepath;
92 | }
93 |
94 |
95 |
96 | function add_event_listener_from_property(property, callback_){
97 | Object.keys(property).forEach(function (key) {
98 | console.debug(key, property[key]);
99 |
100 | const property_name = key;
101 | const value = property[key];
102 | let element = document.getElementById('editor-' + property_name);
103 | if(! element){
104 | console.warn("bug or not implement", property_name); // not implement 'magickcircle_dirpath'
105 | return; // == continue;
106 | }
107 | switch(element.type){
108 | case 'checkbox':
109 | element.addEventListener('click', callback_, false);
110 | break;
111 | default:
112 | element.addEventListener('change', callback_, false);
113 | }
114 | });
115 | }
116 |
117 | function set_ui_from_property(property){
118 | Object.keys(property).forEach(function (key) {
119 | console.debug(key, property[key]);
120 |
121 | const property_name = key;
122 | const value = property[key];
123 | let element = document.getElementById('editor-' + property_name);
124 | if(! element){
125 | console.error("bug");
126 | return; // == continue;
127 | }
128 | switch(element.type){
129 | case 'checkbox':
130 | element.checked = value;
131 | break;
132 | default:
133 | element.value = value;
134 | }
135 |
136 | let view = document.getElementById('editor-' + property_name + '-view');
137 | if(view){
138 | view.textContent = '(' + sprintf("%3d", value) + '%)';
139 | }
140 | });
141 | }
142 |
143 | function get_property_from_ui(){
144 | let property = {};
145 |
146 | property.magickcircle_dirpath = get_circle_dirpath();
147 |
148 | property.canvas_scale_par = document.getElementById('editor-canvas_scale_par').value;
149 | property.document_width = document.getElementById('editor-document_width').value;
150 | property.document_height = document.getElementById('editor-document_height').value;
151 | property.randomseed_value = document.getElementById('editor-randomseed_value').value;
152 | property.magickcircle_num = document.getElementById('editor-magickcircle_num').value;
153 | property.magickcircle_source_kind = document.getElementById('editor-magickcircle_source_kind').value;
154 | property.magickcircle_source_directory_path = document.getElementById('editor-magickcircle_source_directory_path').value;
155 | property.magickcircle_unique_picking = document.getElementById('editor-magickcircle_unique_picking').checked;
156 | property.magickcircle_not_collision = document.getElementById('editor-magickcircle_not_collision').checked;
157 | property.magickcircle_imagescale = document.getElementById('editor-magickcircle_imagescale').value;
158 | property.magickcircle_randomsize = document.getElementById('editor-magickcircle_randomsize').checked;
159 | property.magickcircle_randomrotate = document.getElementById('editor-magickcircle_randomrotate').checked;
160 | property.magickcircle_randomskew = document.getElementById('editor-magickcircle_randomskew').checked;
161 | property.magickcircle_skewdegree = document.getElementById('editor-magickcircle_skewdegree').value;
162 |
163 | return property;
164 | }
165 |
166 | function read_circle_filepaths_from_dirpath(dirpath){
167 | let a = fs.readdirSync(dirpath);
168 | console.debug(a);
169 | return a.filter(name => /.svg$/.test(name));
170 | }
171 |
172 | function get_circle_dirpath(){
173 | const fileex = require('./js/fileex');
174 | return fileex.join(__dirname, "resource/circle/");
175 | }
176 |
177 | function generate_position_not_collision(random, position_range, elem_scale, diagram_elements){
178 | for(let i = 0; i < 400; i++){
179 | let position = {
180 | "x": random.range(position_range.min.x, position_range.max.x),
181 | "y": random.range(position_range.min.y, position_range.max.y),
182 | };
183 |
184 | let is_collision = false;
185 | for(let eix = 0; eix < diagram_elements.length; eix++){
186 | // @todo magickcircle自体の元サイズに関わらず左上基準位置の距離だけ見ている
187 | const col = 1600;
188 | const bet = (col / 2 * diagram_elements[eix].scale) + (col / 2 * elem_scale);
189 | if(bet > Point.between_s(position, diagram_elements[eix])){
190 | is_collision = true;
191 | break;
192 | }
193 | }
194 | if(! is_collision){ // 衝突していなければそれを返す
195 | return position;
196 | }
197 | }
198 |
199 | return null;
200 | }
201 |
202 | function set_ui_generate_diagram(diagram){
203 | const fileex = require('./js/fileex');
204 | const property = diagram.property;
205 | console.log("prop:", property);
206 |
207 | let dirpath = get_circle_dirpath();
208 | if('BuiltIn' !== property.magickcircle_source_kind){
209 | if(! isExistDirSync(property.magickcircle_source_directory_path)){
210 | // use faullback to BuiltIn
211 | console.log('use faullback to BuiltIn', property.magickcircle_source_directory_path);
212 | if('' !== property.magickcircle_source_directory_path){
213 | alert(sprintf("directory not exist:¥n`%s`", property.magickcircle_source_directory_path));
214 | }
215 | }else{
216 | dirpath = property.magickcircle_source_directory_path;
217 | Preference.save_preference_of_keypath('magickcircle_source_directory_path', dirpath);
218 | }
219 | }
220 | property.magickcircle_dirpath = dirpath;
221 |
222 | let circle_filepaths = read_circle_filepaths_from_dirpath(dirpath);
223 | document.getElementById('magickcircle_source_num').textContent = sprintf("%3d", circle_filepaths.length);
224 |
225 | let random = new Random(parseInt(diagram.property.randomseed_value, 10));
226 |
227 | const position_range = {
228 | "min": {"x": 0, "y": 0},
229 | "max": {
230 | "x": diagram.property.document_width - (1000 * diagram.property.magickcircle_imagescale),
231 | "y": diagram.property.document_height - (1000 * diagram.property.magickcircle_imagescale)
232 | },
233 | };
234 |
235 | diagram.diagram_elements = [];
236 | for(let i = 0; i < property.magickcircle_num; i++){
237 | const ix = random.range(0, circle_filepaths.length);
238 |
239 | if(0 === circle_filepaths.length){
240 | alert("empty magickcircle (or full unique)");
241 | break;
242 | }
243 |
244 | // randomrotate無効にした場合に位置他が変わらないよう乱数を取ってから消す。
245 | let rotate_degree = random.range(0, 360);
246 | if(! diagram.property.magickcircle_randomrotate){
247 | rotate_degree = 0;
248 | }
249 | let scale = random.range(5, 15);
250 | if(! diagram.property.magickcircle_randomsize){
251 | scale = 10.0;
252 | }
253 | scale = scale / 10.0;
254 | scale *= diagram.property.magickcircle_imagescale;
255 |
256 | let circle_subfilepath = circle_filepaths[ix];
257 | if(diagram.property.magickcircle_unique_picking){
258 | circle_filepaths.splice(ix, 1);
259 | }
260 | console.debug(i, circle_subfilepath);
261 |
262 | let position;
263 | if(! diagram.property.magickcircle_not_collision){
264 | position = {
265 | "x": random.range(position_range.min.x, position_range.max.x),
266 | "y": random.range(position_range.min.y, position_range.max.y),
267 | };
268 | }else{
269 | position = generate_position_not_collision(random, position_range, scale, diagram.diagram_elements);
270 | if(null == position){
271 | alert("position collision. document full.");
272 | break;
273 | }
274 | }
275 |
276 | let elem = {
277 | "kind": "circle_svg",
278 | "x": position.x,
279 | "y": position.y,
280 | "scale": scale,
281 | "rotate_degree": rotate_degree,
282 | "skew": { 'x': 0, 'y': 0,},
283 | "subfilepath": circle_subfilepath
284 | };
285 | diagram.diagram_elements.push(elem);
286 | }
287 |
288 | for(let i = 0; i < diagram.diagram_elements.length; i++){
289 | let elem = diagram.diagram_elements[i];
290 |
291 | if(diagram.property.magickcircle_randomskew){
292 | const skew_v = diagram.property.magickcircle_skewdegree; //20;
293 | const skew = {
294 | 'x': random.range(-100, 100) / 100.0 * skew_v,
295 | 'y': random.range(-100, 100) / 100.0 * skew_v,
296 | };
297 |
298 | elem.skew = skew;
299 | }
300 | }
301 |
302 | Renderer.rerendering(rendering_handle, diagram, null, null, null);
303 | Renderer.rendering_thumbnail(rendering_handle_thumbnail, rendering_handle, {'x': 300,'y': 150});
304 | }
305 |
306 | function rerendering(){
307 | const property = get_property_from_ui();
308 |
309 | console.debug("get prop", property);
310 | get_doc().diagram.property = property;
311 |
312 | set_ui_generate_diagram(get_doc().diagram);
313 | }
314 |
315 | // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Math/random
316 | function getRandomInt(min, max){
317 | min = Math.ceil(min);
318 | max = Math.floor(max);
319 | return Math.floor(Math.random() * (max - min)) + min; //The maximum is exclusive and the minimum is inclusive
320 | }
321 |
322 | let global_doc = null;
323 | function get_doc(){
324 | return global_doc;
325 | }
326 |
327 | window.addEventListener("load", function(){
328 | console.debug("wakeup");
329 |
330 | // ** preference
331 | try{
332 | Preference.init();
333 | }catch(err){
334 | message_dialog('error', 'user preference error', "user preference load error:\n" + err.message);
335 | }
336 |
337 | // ** doc init
338 | const fileex = require('./js/fileex');
339 | const filepathDefaultDoc = fileex.join(__dirname, "resource/default-document.daisyspreadimage");
340 | global_doc = fileex.read_json(filepathDefaultDoc);
341 | console.debug(global_doc);
342 |
343 | set_ui_from_property(get_doc().diagram.property);
344 |
345 | rendering_handle = new RenderingHandle('canvas');
346 | rendering_handle_thumbnail = new RenderingHandle('thumbnail-canvas');
347 |
348 | set_ui_generate_diagram(get_doc().diagram);
349 |
350 | {
351 | // ** preference overwrite
352 | const pref = Preference.get_preference();
353 | //console.log("pref", pref);
354 |
355 | document.getElementById('editor-magickcircle_source_directory_path').value = pref.magickcircle_source_directory_path;
356 | }
357 |
358 | // ** eventListener
359 | document.getElementById('generate-randomseed').addEventListener('click', function(e){
360 | document.getElementById('editor-randomseed_value').value = getRandomInt(0, 4294967295);
361 |
362 | rerendering();
363 | }, false);
364 | document.getElementById('editor-magickcircle_source_kind').addEventListener('change', function(e){
365 | console.log("kind:", e.target.value);
366 | let elem_pathinput = document.getElementById('editor-magickcircle_source_directory_path');
367 | let elem_pathbutton = document.getElementById('opendir-magickcircle_source_directory_path');
368 | switch(e.target.value){
369 | case "BuiltIn":
370 | elem_pathinput.disabled = true;
371 | elem_pathbutton.disabled = true;
372 | break;
373 | default:
374 | elem_pathinput.disabled = false;
375 | elem_pathbutton.disabled = false;
376 | }
377 | }, false);
378 | document.getElementById('opendir-magickcircle_source_directory_path').addEventListener('click', function(e){
379 | let elem_dirpath = document.getElementById('editor-magickcircle_source_directory_path');
380 | let dirpath = elem_dirpath.value;
381 | dirpath = opendir_dialog(dirpath);
382 | console.log("dirpath", dirpath);
383 | elem_dirpath.value = dirpath;
384 |
385 | rerendering();
386 | }, false);
387 | document.getElementById('link-get-more-magickcircle').addEventListener('click', function(e){
388 | ExternalBrowser.open('https://daisy-bell.booth.pm/items/81865');
389 | }, false);
390 |
391 | // **
392 | let callback_editor_change_ = function(e){
393 | console.debug(e.target);
394 |
395 | rerendering();
396 | };
397 | add_event_listener_from_property(get_doc().diagram.property, callback_editor_change_);
398 |
399 | ad.start();
400 | });
401 |
402 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/menu.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const remote = require('electron').remote;
4 | const Menu = remote.Menu;
5 | const MenuItem = remote.MenuItem;
6 | const join = require('path').join;
7 | const openAboutWindow = require('about-window').default;
8 |
9 | function message_dialog(strtype, strtitle, strmessage) {
10 | const {dialog} = require('electron').remote;
11 | dialog.showMessageBoxSync(
12 | remote.getCurrentWindow(),
13 | {
14 | type: strtype,
15 | buttons: ['OK'],
16 | title: ((typeof strtitle === 'string')? strtitle:''),
17 | message: strmessage,
18 | });
19 | }
20 |
21 | function confirm_dialog(strtitle, strmessage) {
22 | const {dialog} = require('electron').remote;
23 | let choice = dialog.showMessageBoxSync(
24 | remote.getCurrentWindow(),
25 | {
26 | type: 'question',
27 | buttons: ['Yes', 'No'],
28 | defaultId: 1,
29 | title: strtitle,
30 | message: strmessage,
31 | });
32 |
33 | return choice === 0;
34 | };
35 |
36 | function open_dialog(default_filepath)
37 | {
38 | const {app} = require('electron').remote;
39 | const {dialog} = require('electron').remote;
40 | const fs = require('fs');
41 | const isExistSync = function(file)
42 | {
43 | try{
44 | fs.statSync(file);
45 | }catch(err){
46 | return false;
47 | }
48 | return true
49 | };
50 |
51 | let open_filepath = app.getPath('home');
52 | if('' != default_filepath){
53 | default_filepath = path.resolve(default_filepath);
54 | const dirpath = path.dirname(default_filepath);
55 | if(isExistSync(default_filepath)){
56 | open_filepath = default_filepath;
57 | }else if(isExistSync(dirpath) && fs.statSync(dirpath).isDirectory()){
58 | open_filepath = dirpath;
59 | }
60 | }
61 | console.debug('open_filepath', open_filepath);
62 |
63 | let filepath = dialog.showOpenDialogSync(
64 | remote.getCurrentWindow(),
65 | {
66 | title: 'Open',
67 | defaultPath: open_filepath,
68 | filters: [
69 | {name: 'Documents', extensions: ['daisysequence']},
70 | {name: 'All', extensions: ['*']},
71 | ],
72 | properties: ['openFile'],
73 | });
74 |
75 | if(typeof filepath === "undefined"){
76 | return '';
77 | }
78 |
79 | filepath = filepath[0];
80 | return filepath;
81 | }
82 |
83 | function save_dialog(title, default_filepath)
84 | {
85 | const {app} = require('electron').remote;
86 | const {dialog} = require('electron').remote;
87 |
88 | if('' == default_filepath){
89 | // 拡張子のみのファイルパスを作っておくとdialogが勝手にoverwrite確認をしてくれる
90 | default_filepath = path.join(app.getPath('home'), '.' + 'daisysequence');
91 | }
92 | let filepath = dialog.showSaveDialogSync(
93 | remote.getCurrentWindow(),
94 | {
95 | 'title': title,
96 | defaultPath: default_filepath,
97 | filters: [
98 | {name: 'Documents', extensions: ['daisysequence']},
99 | {name: 'All', extensions: ['*']},
100 | ],
101 | });
102 | if(typeof filepath === "undefined"){
103 | return '';
104 | }
105 |
106 | return filepath;
107 | }
108 |
109 | function export_dialog(default_filepath, format_name)
110 | {
111 | const {app} = require('electron').remote;
112 | const {dialog} = require('electron').remote;
113 |
114 | if('' == default_filepath){
115 | default_filepath = path.join(app.getPath('home'), '.' + format_name);
116 | }else{
117 | default_filepath = default_filepath.replace(/\.[a-zA-Z0-9]*$/, '.' + format_name);
118 | }
119 | let filepath = dialog.showSaveDialogSync(
120 | remote.getCurrentWindow(),
121 | {
122 | title: 'Export',
123 | defaultPath: default_filepath,
124 | filters: [
125 | {name: format_name, extensions: [format_name]},
126 | {name: 'All', extensions: ['*']},
127 | ],
128 | });
129 | if(typeof filepath === "undefined"){
130 | return '';
131 | }
132 |
133 | return filepath;
134 | }
135 |
136 | function menu_do_export_(format_name)
137 | {
138 | let filepath = '';
139 | filepath = export_dialog(filepath, format_name);
140 | if('' == filepath){
141 | return;
142 | }
143 |
144 | let errs_ = [];
145 | let res = DaisyIO.write_export_diagram(filepath, get_doc().diagram, errs_);
146 |
147 | let message_ = "";
148 | for(let i = 0; i < errs_.length; i++){
149 | message_ += sprintf("%s: %s\n", errs_[i].level, errs_[i].message);
150 | }
151 |
152 | if(! res){
153 | message_dialog('warning', "Export", "Export error.\n" + message_);
154 | return;
155 | }else{
156 | if(0 !== errs_.length){
157 | message_dialog('info', "Export", "Export info.\n" + message_);
158 | }
159 | }
160 |
161 | console.log("Export");
162 | }
163 |
164 | const debug_menu = {
165 | label: 'debug(develop)',
166 | submenu: [
167 | /*
168 | {
169 | label: 'Reload',
170 | accelerator: 'CmdOrCtrl+R',
171 | click: function (item, focusedWindow) {
172 | if (focusedWindow) focusedWindow.reload()
173 | }
174 | },
175 | {
176 | label: 'Toggle Full Screen',
177 | accelerator: (function () {
178 | if (process.platform === 'darwin') {
179 | return 'Ctrl+Command+F'
180 | } else {
181 | return 'F11'
182 | }
183 | })(),
184 | click: function (item, focusedWindow) {
185 | if (focusedWindow) {
186 | focusedWindow.setFullScreen(!focusedWindow.isFullScreen())
187 | }
188 | }
189 | },
190 | */
191 | {
192 | label: 'Toggle Developer Tools',
193 | accelerator: (function () {
194 | if (process.platform === 'darwin') {
195 | return 'Alt+Command+I'
196 | } else {
197 | return 'Ctrl+Shift+I'
198 | }
199 | })(),
200 | click: function (item, focusedWindow) {
201 | if (focusedWindow) focusedWindow.toggleDevTools()
202 | }
203 | }
204 | ]
205 | };
206 |
207 | var template = [
208 | {
209 | label: '&File',
210 | submenu: [
211 | {
212 | label: '&Export SVG',
213 | accelerator: 'CmdOrCtrl+Shift+E',
214 | click: function () {
215 | menu_do_export_('svg');
216 | }
217 | },
218 | {
219 | label: 'Export PNG',
220 | click: function () {
221 | menu_do_export_('png');
222 | }
223 | },
224 | {type: 'separator'},
225 | {
226 | label: '&Quit',
227 | accelerator: 'CmdOrCtrl+Q',
228 | click: function () {
229 | const {app} = require('electron').remote;
230 | app.quit();
231 | },
232 | },
233 | ]
234 | },
235 | {
236 | label: '&Edit',
237 | submenu: [
238 | // キーボード・ショートカット表示用のダミー(js/index.js onloadにて処理)
239 | {
240 | label: '&Cut',
241 | accelerator: 'CmdOrCtrl+X',
242 | selector: "cut:"
243 | },
244 | {
245 | label: '&Copy',
246 | accelerator: 'CmdOrCtrl+C',
247 | selector: "copy:"
248 | },
249 | {
250 | label: '&Paste',
251 | accelerator: 'CmdOrCtrl+V',
252 | selector: "paste:"
253 | },
254 | ]
255 | },
256 | {
257 | label: '&Help',
258 | role: 'help',
259 | submenu: [
260 | {
261 | label: 'daisy bell official site',
262 | click: function () { require('electron').shell.openExternal('https://daisy-bell.booth.pm/') }
263 | },
264 | {
265 | label: 'Donate',
266 | submenu: [
267 | {
268 | label: 'Donate(Amazon)',
269 | click: function () { require('electron').shell.openExternal('http://amzn.asia/gxaSPhE') }
270 | },
271 | ]
272 | },
273 | {
274 | label: 'Bug and Request',
275 | submenu: [
276 | {
277 | label: 'mailto:michinari.nukazawa@gmail.com',
278 | click: function () { require('electron').shell.openExternal('mailto:michinari.nukazawa@gmail.com') }
279 | },
280 | {
281 | label: 'twitter:@MNukazawa',
282 | click: function () { require('electron').shell.openExternal('https://twitter.com/MNukazawa') }
283 | },
284 | ]
285 | },
286 | {
287 | label: 'GitHub',
288 | click: function () { require('electron').shell.openExternal('https://github.com/MichinariNukazawa/daisy_spread_image') }
289 | },
290 | {type: 'separator'},
291 | debug_menu,
292 | {type: 'separator'},
293 | {
294 | label: '&About',
295 | click: function () {
296 | openAboutWindow({
297 | icon_path: join(__dirname, 'image/icon.png'),
298 | copyright: 'Copyright (c) 2018 project daisy bell',
299 | package_json_dir: __dirname,
300 | // open_devtools: process.env.NODE_ENV !== 'production',
301 | });
302 | }
303 | }
304 | ]
305 | }
306 | ]
307 |
308 | function insert_window_menu(){
309 | template.splice(2, 0,
310 | {
311 | label: 'Window',
312 | role: 'window',
313 | submenu: [
314 | {
315 | label: 'Minimize',
316 | accelerator: 'CmdOrCtrl+M',
317 | role: 'minimize'
318 | },
319 | {
320 | label: 'Close',
321 | accelerator: 'CmdOrCtrl+W',
322 | role: 'close'
323 | }
324 | ]
325 | });
326 | }
327 |
328 | if (process.platform === 'darwin') {
329 | insert_window_menu();
330 |
331 | var name = require('electron').remote.app.getName()
332 | template.unshift({
333 | label: name,
334 | submenu: [
335 | {
336 | label: 'About ' + name,
337 | role: 'about'
338 | },
339 | {
340 | type: 'separator'
341 | },
342 | {
343 | label: 'Services',
344 | role: 'services',
345 | submenu: []
346 | },
347 | {
348 | type: 'separator'
349 | },
350 | {
351 | label: 'Hide ' + name,
352 | accelerator: 'Command+H',
353 | role: 'hide'
354 | },
355 | {
356 | label: 'Hide Others',
357 | accelerator: 'Command+Alt+H',
358 | role: 'hideothers'
359 | },
360 | {
361 | label: 'Show All',
362 | role: 'unhide'
363 | },
364 | {
365 | type: 'separator'
366 | },
367 | {
368 | label: 'Quit',
369 | accelerator: 'Command+Q',
370 | click: function () {
371 | const {app} = require('electron').remote;
372 | app.quit()
373 | }
374 | }
375 | ]
376 | })
377 | // Window menu.
378 | template[3].submenu.push(
379 | {
380 | type: 'separator'
381 | },
382 | {
383 | label: 'Bring All to Front',
384 | role: 'front'
385 | }
386 | )
387 | }
388 |
389 | var menu = Menu.buildFromTemplate(template);
390 | Menu.setApplicationMenu(menu);
391 |
392 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/object-util.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = class ObjectUtil{
4 | static deepcopy(obj)
5 | {
6 | /*
7 | let r = {};
8 | for(let name in obj){
9 | if(typeof obj[name] === 'object'){
10 | r[name] = this.deep_clone_(obj[name]);
11 | }else{
12 | r[name] = obj[name];
13 | }
14 | }
15 | return r;
16 | */
17 |
18 | return JSON.parse(JSON.stringify(obj))
19 | }
20 |
21 | static remove_key(obj, keys)
22 | {
23 | ObjectUtil.removeKey(obj, keys);
24 | }
25 |
26 | static removeKey(obj, keys)
27 | {
28 | if(obj instanceof Array){
29 | obj.forEach(function(item){
30 | ObjectUtil.removeKey(item,keys)
31 | });
32 | }
33 | else if(typeof obj === 'object'){
34 | Object.getOwnPropertyNames(obj).forEach(function(key){
35 | if(keys.indexOf(key) !== -1)delete obj[key];
36 | else ObjectUtil.removeKey(obj[key],keys);
37 | });
38 | }
39 | }
40 |
41 | static make_member(obj, path, value)
42 | {
43 | return ObjectUtil.makeMember(obj, path, value);
44 | }
45 |
46 | static makeMember(obj, path, value)
47 | {
48 | const keys = path.split('.');
49 | let o = obj;
50 | for(let i = 0; i < keys.length; i++){
51 | if(undefined === o || null === o || typeof o !== 'object'){
52 | return false;
53 | }
54 |
55 | if(! o.hasOwnProperty(keys[i])){
56 | if(i !== (keys.length - 1)){
57 | o[keys[i]] = {};
58 | }else{
59 | o[keys[i]] = value;
60 | }
61 | }
62 |
63 | o = o[keys[i]];
64 | }
65 |
66 | return true;
67 | }
68 |
69 | static get_property_from_path(obj, path)
70 | {
71 | return ObjectUtil.getPropertyFromPath(obj, path);
72 | }
73 |
74 | static getPropertyFromPath(obj, path)
75 | {
76 | const keys = (typeof path === 'string')? path.split('.') : [path];
77 | let o = obj;
78 | for(let i = 0; i < keys.length; i++){
79 | if(undefined === o || null === o || typeof o !== 'object'){
80 | return null;
81 | }
82 | if(! o.hasOwnProperty(keys[i])){
83 | return null;
84 | }else{
85 | o = o[keys[i]];
86 | }
87 | }
88 |
89 | return o;
90 | }
91 | };
92 |
93 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/preference.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = class Preference{
4 | static get_filepath(){
5 | const {app} = require('electron').remote;
6 | const fileex = require('./fileex');
7 | return fileex.join(app.getPath('userData'), "preference.json");
8 | }
9 |
10 | static init(){
11 | const fs = require("fs");
12 | const fileex = require('./fileex');
13 |
14 | const filepathDefaultPreference = fileex.join(__dirname, '../resource/default-preference.json');
15 | console.log(filepathDefaultPreference);
16 | const filepathPreference = Preference.get_filepath();
17 | let defaultPreference = fileex.read_json(filepathDefaultPreference);
18 | let preference = fileex.read_json(filepathPreference);
19 | //console.log(defaultPreference, preference);
20 | preference = Object.assign(defaultPreference, preference);
21 |
22 | fs.writeFileSync(filepathPreference, JSON.stringify(preference, null, '\t'));
23 | }
24 |
25 | static get_preference(){
26 | const fileex = require('./fileex');
27 |
28 | const filepathPreference = Preference.get_filepath();
29 | return fileex.read_json(filepathPreference);
30 | }
31 |
32 | static delete_preference(){
33 | const filepath = Preference.get_filepath();
34 | try{
35 | fs.unlinkSync(filepath);
36 | } catch (err) {
37 | console.error(filepath);
38 | return "delete error:\n" + err.message;
39 | }
40 | return "success.";
41 | }
42 |
43 | static get_filepath_user_css(){
44 | const {app} = require('electron').remote;
45 | const fileex = require('./fileex');
46 | return fileex.join(app.getPath('userData'), "user.css");
47 | }
48 |
49 | static save_preference_of_keypath(keypath, value){
50 | const fs = require("fs");
51 |
52 | let preference = Preference.get_preference();
53 |
54 | //今回は深い階層は無視する
55 | if(! preference.hasOwnProperty(keypath)){
56 | console.error(keypath);
57 | }
58 | preference[keypath] = value;
59 | console.log("save keypath:", keypath, value);
60 |
61 | const filepathPreference = Preference.get_filepath();
62 | fs.writeFileSync(filepathPreference, JSON.stringify(preference, null, '\t'));
63 | }
64 | }
65 |
66 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/renderer.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports.RenderingHandle = class RenderingHandle{
4 | constructor(elemId)
5 | {
6 | this.draw = null;
7 | this.groups = [];
8 |
9 | this.draw = SVG(elemId).size(0, 0);
10 | this.clear();
11 |
12 | this.resource = RenderingHandle.generate_resource();
13 | }
14 |
15 | static generate_resource()
16 | {
17 | let resource = {};
18 | /*
19 | try{
20 | const fs = require("fs");
21 | const path = require('path');
22 | const filepath = path.join(__dirname, '../image/edge.svg');
23 | resource.edge_icon_svg = fs.readFileSync(filepath, 'utf8');
24 | }catch(err){
25 | console.error(err);
26 | }
27 | */
28 | return resource;
29 | }
30 |
31 | get_draw()
32 | {
33 | return this.draw;
34 | }
35 |
36 | get_other_group()
37 | {
38 | return this.groups.other_group;
39 | }
40 |
41 | get_root_group()
42 | {
43 | return this.groups.root_group;
44 | }
45 |
46 | get_background_group()
47 | {
48 | return this.groups.background_group;
49 | }
50 |
51 | get_diagram_group()
52 | {
53 | return this.groups.diagram_group;
54 | }
55 |
56 | get_editor_group()
57 | {
58 | return this.groups.editor_group;
59 | }
60 |
61 | get_focus_group()
62 | {
63 | return this.groups.focus_group;
64 | }
65 |
66 | clear()
67 | {
68 | this.groups = [];
69 | this.draw.clear();
70 |
71 | this.groups.root_group = this.draw.group().addClass('dd__root-group');
72 | this.groups.background_group = this.get_root_group().group().addClass('dd__background-group');
73 | this.groups.diagram_group = this.get_root_group().group().addClass('dd__diagram-group');
74 | this.groups.other_group = this.get_root_group().group().addClass('dd__other-group');
75 |
76 | this.groups.editor_group = this.get_root_group().group().addClass('dd__editor-group');
77 | this.groups.focus_group = this.get_editor_group().group().addClass('dd__focus-group');
78 | }
79 | };
80 |
81 | module.exports.Renderer = class Renderer{
82 | static rerendering(rendering_handle, src_diagram, focus, mouse_state, tool_kind)
83 | {
84 | rendering_handle.clear();
85 |
86 | const deepcopy = function(obj){
87 | return JSON.parse(JSON.stringify(obj))
88 | };
89 | let diagram = deepcopy(src_diagram);
90 | diagram.width = diagram.property.document_width;
91 | diagram.height = diagram.property.document_height;
92 |
93 | if(null === diagram){
94 | return null;
95 | }
96 |
97 | const diagram_size = {
98 | 'x': diagram.property.document_width ,
99 | 'y': diagram.property.document_height,
100 | };
101 |
102 | const opt = {};
103 | const svgstr_diagram = Renderer.generate_svgstr_from_diagram(diagram, opt);
104 | rendering_handle.thumbnail_info = {
105 | 'svgstr_diagram': svgstr_diagram,
106 | 'diagram_size': diagram_size,
107 | };
108 |
109 |
110 | const canvas_scale = diagram.property.canvas_scale_par / 100;
111 | const canvas_info = {
112 | 'canvas_size': {
113 | 'x': diagram.property.document_width * canvas_scale,
114 | 'y': diagram.property.document_height * canvas_scale,
115 | },
116 | 'diagram_size': diagram_size,
117 | 'scale': canvas_scale,
118 | 'margin': 2,
119 | };
120 | console.debug(canvas_info, diagram.property.canvas_scale_par);
121 |
122 | Renderer.rendering_canvas_(rendering_handle, svgstr_diagram, canvas_info, focus, mouse_state, tool_kind);
123 | }
124 |
125 | static rendering_thumbnail(rendering_handle, rendering_handle_src, thumbnail_size)
126 | {
127 | rendering_handle.clear();
128 |
129 | const scale_x = thumbnail_size.x / rendering_handle_src.thumbnail_info.diagram_size.x;
130 | const scale_y = thumbnail_size.y / rendering_handle_src.thumbnail_info.diagram_size.y;
131 | const scale = Math.min(scale_x, scale_y);
132 | const canvas_info = {
133 | 'canvas_size': {
134 | 'x': thumbnail_size.x,
135 | 'y': thumbnail_size.y,
136 | },
137 | 'diagram_size': rendering_handle_src.thumbnail_info.diagram_size,
138 | 'scale': scale,
139 | 'margin': 2,
140 | };
141 | console.debug('thumb info', canvas_info);
142 | const svgstr_diagram = rendering_handle_src.thumbnail_info.svgstr_diagram;
143 | Renderer.rendering_canvas_(rendering_handle, svgstr_diagram, canvas_info, null, null, null);
144 | }
145 |
146 | static rendering_canvas_(rendering_handle, svgstr_diagram, canvas_info, focus, mouse_state, tool_kind){
147 | rendering_handle.get_draw().size(
148 | canvas_info.canvas_size.x + (canvas_info.margin * 2),
149 | canvas_info.canvas_size.y + (canvas_info.margin * 2),
150 | );
151 |
152 | // diagramの描画サイズ
153 | const diagram_rendering_size = {
154 | 'x': canvas_info.diagram_size.x * canvas_info.scale,
155 | 'y': canvas_info.diagram_size.y * canvas_info.scale,
156 | };
157 |
158 | // canvas内でdiagramをセンタリング表示する際の位置(左上座標)
159 | const diagram_position = {
160 | 'x': canvas_info.margin + ((canvas_info.canvas_size.x - diagram_rendering_size.x) / 2),
161 | 'y': canvas_info.margin + ((canvas_info.canvas_size.y - diagram_rendering_size.y) / 2),
162 | };
163 |
164 | rendering_handle.get_diagram_group().svg(svgstr_diagram);
165 | rendering_handle.get_diagram_group().move(diagram_position.x, diagram_position.y);
166 | rendering_handle.get_diagram_group().scale(canvas_info.scale, canvas_info.scale, 0, 0);
167 | /*
168 | Renderer.draw_focus_(rendering_handle, focus);
169 |
170 | Renderer.draw_mouse_state_(rendering_handle, mouse_state);
171 |
172 | Renderer.draw_tool_(rendering_handle, diagram, mouse_state, tool_kind);
173 | */
174 | // ** frame
175 | {
176 | let background_group = rendering_handle.get_background_group();
177 | if(null === background_group){
178 | console.error('bug');
179 | return;
180 | }
181 |
182 | let rect = {
183 | 'x': diagram_position.x,
184 | 'y': diagram_position.y,
185 | 'width': diagram_rendering_size.x,
186 | 'height': diagram_rendering_size.y,
187 | };
188 | background_group.rect(rect.width, rect.height)
189 | .move(rect.x, rect.y)
190 | .attr({
191 | 'stroke': '#ddd',
192 | 'fill-opacity': '0',
193 | 'stroke-width': '2',
194 | });
195 | }
196 | }
197 |
198 | static groupdrawing_circle_svg_(circle_group, diagram, elem){
199 | console.debug(diagram.property.magickcircle_dirpath, elem.subfilepath);
200 |
201 | const filepath = path.join(diagram.property.magickcircle_dirpath, elem.subfilepath);
202 | let circleimage_svg = fs.readFileSync(filepath, 'utf8');
203 | let diagram_group_ = circle_group.group().addClass('dd__circle_group__AA');
204 | diagram_group_.move(elem.x, elem.y)
205 | diagram_group_.scale(elem.scale, elem.scale)
206 | diagram_group_.skew(elem.skew.x, elem.skew.y)
207 | ;
208 | diagram_group_.svg(circleimage_svg)
209 | .rotate(elem.rotate_degree, 1000 / 2, 1000 / 2)
210 | .attr({
211 | 'opacity': 1.0,
212 | });
213 | }
214 |
215 | static generate_svgjsdraw_from_diagram(diagram, opt){
216 | console.debug("diag", diagram.property.document_width, diagram.property.document_height);
217 |
218 | let dummy_elem = document.createElementNS('http://www.w3.org/2000/svg','svg');
219 | let draw = SVG(dummy_elem).size(0, 0);
220 |
221 | let root_group = draw.group().addClass('dd__root_group');
222 |
223 | if(opt.hasOwnProperty('scale')){
224 | draw.size(diagram.property.document_width * opt.scale, diagram.property.document_height * opt.scale);
225 | root_group.scale(opt.scale, opt.scale);
226 | }else{
227 | draw.size(diagram.property.document_width, diagram.property.document_height);
228 | }
229 |
230 | if(opt.hasOwnProperty('background_color')){
231 | let backgroud_group = root_group.group().addClass('dd__background');
232 | backgroud_group.rect('100%','100%')
233 | .attr({
234 | 'fill': opt.background_color,
235 | });
236 | }
237 |
238 | let circle_group = root_group.group().addClass('dd__circle_group');
239 |
240 | for(let i = 0; i < diagram.diagram_elements.length; i++){
241 | const diagram_element = diagram.diagram_elements[i];
242 | console.debug(i, diagram_element);
243 |
244 | switch(diagram_element.kind){
245 | case 'circle_svg':
246 | Renderer.groupdrawing_circle_svg_(circle_group, diagram, diagram_element);
247 | break;
248 | default:
249 | console.error("bug", i, diagram_element);
250 | alert(diagram_element);
251 | }
252 | }
253 |
254 | return draw;
255 | }
256 |
257 | static generate_svgstr_from_diagram(diagram, opt){
258 | const draw = Renderer.generate_svgjsdraw_from_diagram(diagram, opt);
259 | return draw.svg();
260 | }
261 | };
262 |
263 |
--------------------------------------------------------------------------------
/daisy_spread_image/js/version.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = class Version{
4 | static get_name()
5 | {
6 | const Package = require('../package.json');
7 | return Package.name;
8 | }
9 |
10 | static get_version()
11 | {
12 | const Package = require('../package.json');
13 | const v = {
14 | "version": Package.version,
15 | };
16 | return v.version;
17 | }
18 | }
19 |
20 |
--------------------------------------------------------------------------------
/daisy_spread_image/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const {app, BrowserWindow} = require('electron')
4 | const path = require('path')
5 | const url = require('url')
6 |
7 | // MacOSX
8 | global.sharedObject = {'osx_open_file': null};
9 | let openFileHandler = function(event, path) {
10 | event.preventDefault();
11 | global.sharedObject.osx_open_file = path;
12 | };
13 | app.on('open-file', openFileHandler);
14 |
15 | // Keep a global reference of the window object, if you don't, the window will
16 | // be closed automatically when the JavaScript object is garbage collected.
17 | let win
18 |
19 | function createWindow () {
20 |
21 | // Create the browser window.
22 | win = new BrowserWindow({
23 | width: 1200,
24 | height: 700,
25 | webPreferences: {
26 | enableRemoteModule: true,
27 | nodeIntegration: true
28 | },
29 | icon: path.join(__dirname, 'image/icon.png')
30 | })
31 |
32 | // and load the index.html of the app.
33 | win.loadURL(url.format({
34 | pathname: path.join(__dirname, 'index.html'),
35 | protocol: 'file:',
36 | slashes: true
37 | }))
38 |
39 | // Open the DevTools.
40 | // win.webContents.openDevTools()
41 |
42 | // Emitted when the window is closed.
43 | win.on('closed', () => {
44 | // Dereference the window object, usually you would store windows
45 | // in an array if your app supports multi windows, this is the time
46 | // when you should delete the corresponding element.
47 | win = null
48 | })
49 | }
50 |
51 | // This method will be called when Electron has finished
52 | // initialization and is ready to create browser windows.
53 | // Some APIs can only be used after this event occurs.
54 | app.on('ready', createWindow)
55 |
56 | // Quit when all windows are closed.
57 | app.on('window-all-closed', () => {
58 | // On macOS it is common for applications and their menu bar
59 | // to stay active until the user quits explicitly with Cmd + Q
60 | if (process.platform !== 'darwin') {
61 | app.quit()
62 | }
63 | })
64 |
65 | app.on('activate', () => {
66 | // On macOS it's common to re-create a window in the app when the
67 | // dock icon is clicked and there are no other windows open.
68 | if (win === null) {
69 | createWindow()
70 | }
71 | })
72 |
73 | // In this file you can include the rest of your app's specific main process
74 | // code. You can also put them in separate files and require them here.
75 |
--------------------------------------------------------------------------------
/daisy_spread_image/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "daisy_spread_image",
3 | "version": "0.0.4",
4 | "description": "spread image in image generator",
5 | "main": "main.js",
6 | "dependencies": {
7 | "about-window": "^1.13.4",
8 | "data-uri-to-buffer": "^3.0.1",
9 | "save-svg-as-png": "^1.4.17",
10 | "sprintf-js": "^1.1.2",
11 | "svg.js": "^2.7.1",
12 | "xml-formatter": "^2.4.0"
13 | },
14 | "devDependencies": {
15 | "electron": "^11.1.1",
16 | "electron-installer-debian": "^3.1.0",
17 | "electron-packager": "^15.2.0",
18 | "intelli-espower-loader": "^1.0.1",
19 | "mocha": "^8.2.1",
20 | "power-assert": "^1.6.1",
21 | "spectron": "^13.0.0"
22 | },
23 | "scripts": {
24 | "running": "electron .",
25 | "debian_installer_debian": "electron-installer-debian --config ../release/installer_debian_amd64_config.json",
26 | "test": "mocha --require intelli-espower-loader",
27 | "clean": "rm -rf ./release",
28 | "pack:win": "electron-packager . --out=./release/win --platform=win32 --arch=x64 --icon='./image/icon.ico' --ignore='release' --ignore='object/' --ignore='obj/' --ignore='work/' --ignore='test/'",
29 | "pack:osx": "rm -rf ./release/osx/ && electron-packager . --out=./release/osx --platform=darwin --arch=x64 --icon='./image/icon.icns' --ignore='release/' --ignore='object/' --ignore='obj/' --ignore='work/' --ignore='test/'",
30 | "pack:linux": "rm -rf ./release/linux/ && electron-packager . --out=./release/linux --platform=linux --arch=x64 --icon='./image/icon.png' --ignore='release/' --ignore='object/' --ignore='obj/' --ignore='work/' --ignore='test/'",
31 | "testtotest": "mocha test/mocha.js"
32 | },
33 | "author": "michinari.nukazawa@gmail.com",
34 | "license": "MIT"
35 | }
36 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/circle/MagicCircle_RuneAMN_20141111.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
155 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/circle/MagicCircle_RuneAMN_20141116.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
148 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/circle/MagicCircle_RuneAMN_20141120.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
218 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/circle/MagicCircle_RuneAMN_20141121.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
70 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/circle/MagicCircle_RuneAMN_20141122.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
260 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/default-document.daisyspreadimage:
--------------------------------------------------------------------------------
1 | {
2 | "editor_info": {
3 | "application_name": "daisy_spread_image",
4 | "version": "none"
5 | },
6 | "filetype": "daisy spread image",
7 | "diagram": {
8 | "property": {
9 | "canvas_scale_par": 25,
10 | "document_width": 2400,
11 | "document_height": 1800,
12 | "randomseed_value": 128,
13 | "magickcircle_num": 7,
14 | "magickcircle_source_kind": "BuiltIn",
15 | "magickcircle_source_directory_path": "",
16 | "magickcircle_unique_picking": true,
17 | "magickcircle_not_collision": true,
18 | "magickcircle_imagescale": 0.4,
19 | "magickcircle_randomsize": true,
20 | "magickcircle_randomrotate": true,
21 | "magickcircle_randomskew": false,
22 | "magickcircle_skewdegree": 20
23 | },
24 | "diagram_elements": [
25 | ]
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/daisy_spread_image/resource/default-preference.json:
--------------------------------------------------------------------------------
1 | {
2 | "magickcircle_source_directory_path": ""
3 | }
4 |
--------------------------------------------------------------------------------
/daisy_spread_image/test/mocha.js:
--------------------------------------------------------------------------------
1 | var assert = require('assert');
2 | describe('Array', function() {
3 | describe('#indexOf()', function() {
4 | it('should return -1 when the value is not present', function() {
5 | assert.equal(-1, [1,2,3].indexOf(4));
6 | });
7 | });
8 | });
9 |
--------------------------------------------------------------------------------
/daisy_spread_image/test/spec.js:
--------------------------------------------------------------------------------
1 | const Application = require('spectron').Application
2 | const assert = require('assert')
3 | const electronPath = require('electron') // Require Electron from the binaries included in node_modules.
4 | const path = require('path')
5 |
6 | describe('Application launch', function () {
7 | this.timeout(10000)
8 |
9 | beforeEach(function () {
10 | this.app = new Application({
11 | // Your electron path can be any binary
12 | // i.e for OSX an example path could be '/Applications/MyApp.app/Contents/MacOS/MyApp'
13 | // But for the sake of the example we fetch it from our node_modules.
14 | path: electronPath,
15 |
16 | // Assuming you have the following directory structure
17 |
18 | // |__ my project
19 | // |__ ...
20 | // |__ main.js
21 | // |__ package.json
22 | // |__ index.html
23 | // |__ ...
24 | // |__ test
25 | // |__ spec.js <- You are here! ~ Well you should be.
26 |
27 | // The following line tells spectron to look and use the main.js file
28 | // and the package.json located 1 level above.
29 | args: [path.join(__dirname, '..')]
30 | })
31 | return this.app.start()
32 | })
33 |
34 | afterEach(function () {
35 | if (this.app && this.app.isRunning()) {
36 | return this.app.stop()
37 | }
38 | })
39 |
40 | it('shows an initial window', function () {
41 | return this.app.client.getWindowCount().then(function (count) {
42 | assert.equal(count, 1)
43 | // Please note that getWindowCount() will return 2 if `dev tools` are opened.
44 | // assert.equal(count, 2)
45 | })
46 | })
47 | })
48 |
--------------------------------------------------------------------------------
/document/image/daisy_spread_image_0.0.1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MichinariNukazawa/daisy_spread_image/ca71a9869bece5b9477d40bce8dd085500d63477/document/image/daisy_spread_image_0.0.1.png
--------------------------------------------------------------------------------
/release/installer_darwin.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # cross build
4 | # host: Ubuntu (Ubutn16.04 LTS amd64)
5 | # target: Win64
6 | #
7 | # Author: michinari.nukazawa@gmail.com
8 | #
9 |
10 | set -eu
11 | set -o pipefail
12 |
13 | trap 'echo "error:$0($LINENO) \"$BASH_COMMAND\" \"$@\""' ERR
14 |
15 |
16 | SCRIPT_DIR=$(cd $(dirname $0); pwd)
17 | ROOT_DIR=${SCRIPT_DIR}/..
18 | SOURCE_DIR=${ROOT_DIR}/daisy_spread_image
19 |
20 | APP_NAME=$(cat ${SOURCE_DIR}/package.json | grep '"name"' | sed -e 's/.*:.*"\(.*\)".*/\1/g')
21 |
22 | BUILD_DIR=${SOURCE_DIR}/release/osx/${APP_NAME}-darwin-x64
23 | PACKAGE_DIR=${SOURCE_DIR}/release/osx/${APP_NAME}-darwin-x64
24 | RELEASE_DIR=${ROOT_DIR}/release/release
25 |
26 | PACKAGE_POSTFIX=
27 | if [ 1 -eq $# ] ; then
28 | PACKAGE_POSTFIX="-$1"
29 | fi
30 |
31 | SHOW_VERSION=$(cat ${SOURCE_DIR}/package.json | grep '"version"' | sed -e 's/.*:.*"\(.*\)".*/\1/g')
32 |
33 | GIT_HASH=$(git log --pretty=format:'%h' -n 1)
34 | GIT_STATUS_SHORT=$(git diff --stat | tail -1)
35 | EX=""
36 | if [ -n "${GIT_STATUS_SHORT}" ] ; then
37 | EX="develop"
38 | fi
39 | PACKAGE_NAME=${APP_NAME}-macosx-${SHOW_VERSION}${EX}-${GIT_HASH}${PACKAGE_POSTFIX}
40 |
41 | ## build
42 | rm -rf ${BUILD_DIR}
43 | pushd ${SOURCE_DIR}
44 | npm run pack:osx
45 | popd
46 |
47 |
48 | ## packaging
49 | #rm -rf ${PACKAGE_DIR}
50 | #mv ${BUILD_DIR} ${PACKAGE_DIR}
51 |
52 | cp ${ROOT_DIR}/README.md ${PACKAGE_DIR}/
53 |
54 | pushd ${PACKAGE_DIR}
55 |
56 | rm -f ${RELEASE_DIR}/${PACKAGE_NAME}.zip
57 | mkdir -p ${RELEASE_DIR}
58 | zip -r9 ${RELEASE_DIR}/${PACKAGE_NAME}.zip *
59 |
60 | popd
61 |
62 |
--------------------------------------------------------------------------------
/release/installer_debian.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # Author: michinari.nukazawa@gmail.com
4 | #
5 |
6 | set -eu
7 | set -o pipefail
8 |
9 | trap 'echo "error:$0($LINENO) \"$BASH_COMMAND\" \"$@\""' ERR
10 |
11 | # cd daisy_spread_image && npm run installer_debian_amd64
12 | # "installer_debian_amd64": "node ./build_linux_x64.js && electron-installer-debian --config ./installer_debian_amd64_config.json",
13 | pushd ../daisy_spread_image/daisy_spread_image
14 | npm run pack:linux
15 | npm run debian_installer_debian
16 | popd
17 |
18 |
--------------------------------------------------------------------------------
/release/installer_debian_amd64_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "daisy-spread-image",
3 | "src": "./release/linux/daisy_spread_image-linux-x64/",
4 | "dest": "../release/release/",
5 | "arch": "amd64",
6 | "icon": "image/icon.png",
7 | "categories": [
8 | "Utility"
9 | ],
10 | "lintianOverrides": [
11 | "changelog-file-missing-in-native-package"
12 | ]
13 | }
14 |
--------------------------------------------------------------------------------
/release/installer_win32_x64.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | #
3 | # cross build
4 | # host: Ubuntu (Ubutn16.04 LTS amd64)
5 | # target: Win64
6 | #
7 | # Author: michinari.nukazawa@gmail.com
8 | #
9 |
10 | set -eu
11 | set -o pipefail
12 |
13 | trap 'echo "error:$0($LINENO) \"$BASH_COMMAND\" \"$@\""' ERR
14 |
15 |
16 | SCRIPT_DIR=$(cd $(dirname $0); pwd)
17 | ROOT_DIR=${SCRIPT_DIR}/..
18 | SOURCE_DIR=${ROOT_DIR}/daisy_spread_image
19 |
20 | APP_NAME=$(cat ${SOURCE_DIR}/package.json | grep '"name"' | sed -e 's/.*:.*"\(.*\)".*/\1/g')
21 |
22 | BUILD_DIR=${SOURCE_DIR}/release/win/${APP_NAME}-win32-x64
23 | PACKAGE_DIR=${SOURCE_DIR}/release/win/${APP_NAME}-win32-x64
24 | RELEASE_DIR=${ROOT_DIR}/release/release
25 |
26 | PACKAGE_POSTFIX=
27 | if [ 1 -eq $# ] ; then
28 | PACKAGE_POSTFIX="-$1"
29 | fi
30 |
31 | SHOW_VERSION=$(cat ${SOURCE_DIR}/package.json | grep '"version"' | sed -e 's/.*:.*"\(.*\)".*/\1/g')
32 |
33 | GIT_HASH=$(git log --pretty=format:'%h' -n 1)
34 | GIT_STATUS_SHORT=$(git diff --stat | tail -1)
35 | EX=""
36 | if [ -n "${GIT_STATUS_SHORT}" ] ; then
37 | EX="develop"
38 | fi
39 | PACKAGE_NAME=${APP_NAME}-win64-${SHOW_VERSION}${EX}-${GIT_HASH}${PACKAGE_POSTFIX}
40 |
41 | ## build
42 | rm -rf ${BUILD_DIR}
43 | pushd ${SOURCE_DIR}
44 | npm run pack:win
45 | popd
46 |
47 |
48 | ## packaging
49 | #rm -rf ${PACKAGE_DIR}
50 | #mv ${BUILD_DIR} ${PACKAGE_DIR}
51 |
52 | cp ${ROOT_DIR}/README.md ${PACKAGE_DIR}/
53 |
54 | pushd ${PACKAGE_DIR}
55 |
56 | rm -f ${RELEASE_DIR}/${PACKAGE_NAME}.zip
57 | mkdir -p ${RELEASE_DIR}
58 | zip -r9 ${RELEASE_DIR}/${PACKAGE_NAME}.zip *
59 |
60 | popd
61 |
62 |
--------------------------------------------------------------------------------