From 203185f0efc9b1bbb0f2362744b77743bc1b69bd Mon Sep 17 00:00:00 2001 From: viliusle Date: Wed, 27 Jan 2021 00:44:35 +0200 Subject: [PATCH] #223 - guides --- images/test-collection.json | 6 +- src/js/config-menu.js | 18 +++++ src/js/config.js | 2 + src/js/core/base-gui.js | 41 +++++++++++ src/js/core/base-layers.js | 12 +++ src/js/core/base-tools.js | 10 +++ src/js/modules/file/open.js | 3 + src/js/modules/file/save.js | 1 + src/js/modules/image/guides.js | 123 +++++++++++++++++++++++++++++++ src/js/modules/tools/settings.js | 20 +++++ 10 files changed, 235 insertions(+), 1 deletion(-) create mode 100644 src/js/modules/image/guides.js diff --git a/images/test-collection.json b/images/test-collection.json index 82ea942..367a207 100644 --- a/images/test-collection.json +++ b/images/test-collection.json @@ -5,7 +5,11 @@ "about": "Image data with multi-layers. Can be opened using miniPaint - https://github.com/viliusle/miniPaint", "date": "2021-01-02", "version": "4.5.0", - "layer_active": 1 + "layer_active": 1, + "guides": [ + { "x": null, "y": 400}, + { "x": null, "y": 600} + ] }, "layers": [ { diff --git a/src/js/config-menu.js b/src/js/config-menu.js index dbda39f..07ed54d 100644 --- a/src/js/config-menu.js +++ b/src/js/config-menu.js @@ -242,6 +242,24 @@ const menuDefinition = [ shortcut: 'G', target: 'image/grid.grid' }, + { + name: 'Guides', + children: [ + { + name: 'Insert', + ellipsis: true, + target: 'image/guides.insert' + }, + { + name: 'Update', + target: 'image/guides.update' + }, + { + name: 'Remove all', + target: 'image/guides.remove' + } + ] + }, { divider: true }, diff --git a/src/js/config.js b/src/js/config.js index 7b1d617..127d606 100644 --- a/src/js/config.js +++ b/src/js/config.js @@ -22,6 +22,8 @@ config.mouse = {}; config.swatches = { default: [] // Only default used right now, object format for swatch swapping in future. }; +config.guides_enabled = true; +config.guides = []; //requires styles in reset.css config.themes = [ diff --git a/src/js/core/base-gui.js b/src/js/core/base-gui.js index 71da635..584818a 100644 --- a/src/js/core/base-gui.js +++ b/src/js/core/base-gui.js @@ -110,6 +110,16 @@ class Base_gui_class { else{ config.SNAP = Boolean(snap_cookie); } + + //guides + var guides_cookie = this.Helper.getCookie('guides'); + if (guides_cookie === null) { + //default + config.guides_enabled = true; + } + else{ + config.guides_enabled = Boolean(guides_cookie); + } } render_main_gui() { @@ -360,6 +370,37 @@ class Base_gui_class { ctx.stroke(); } } + + draw_guides(ctx){ + if(config.guides_enabled == false){ + return; + } + + for(var i in config.guides) { + var guide = config.guides[i]; + + if (guide.x === 0 || guide.y === 0) { + continue; + } + + //set styles + ctx.strokeStyle = '#49ffff'; + ctx.lineWidth = 1; + + ctx.beginPath(); + if (guide.y === null) { + //vertical + ctx.moveTo(guide.x, 0); + ctx.lineTo(guide.x, config.HEIGHT); + } + if (guide.x === null) { + //horizontal + ctx.moveTo(0, guide.y); + ctx.lineTo(config.WIDTH, guide.y); + } + ctx.stroke(); + } + } /** * change draw area size diff --git a/src/js/core/base-layers.js b/src/js/core/base-layers.js index 98ca403..bc67e73 100644 --- a/src/js/core/base-layers.js +++ b/src/js/core/base-layers.js @@ -168,6 +168,9 @@ class Base_layers_class { //grid this.Base_gui.draw_grid(this.ctx); + //guides + this.Base_gui.draw_guides(this.ctx); + //render selected object controls this.Base_selection.draw_selection(); @@ -693,6 +696,15 @@ class Base_layers_class { }; } + /** + * returns all layers + * + * @returns {array} + */ + get_layers() { + return config.layers; + } + } export default Base_layers_class; diff --git a/src/js/core/base-tools.js b/src/js/core/base-tools.js index 84f2761..b808c60 100644 --- a/src/js/core/base-tools.js +++ b/src/js/core/base-tools.js @@ -585,6 +585,16 @@ class Base_tools_class { config.HEIGHT, ], }; + if(config.guides_enabled == true){ + //use guides + for(var i in config.guides){ + var guide = config.guides[i]; + if(guide.y === null) + snap_positions.x.push(guide.x); + else + snap_positions.y.push(guide.y); + } + } for(var i in config.layers){ if(exclude_id != null && exclude_id == config.layers[i].id){ continue; diff --git a/src/js/modules/file/open.js b/src/js/modules/file/open.js index dfe1bf7..d0b60fc 100644 --- a/src/js/modules/file/open.js +++ b/src/js/modules/file/open.js @@ -524,6 +524,9 @@ class File_open_class { new app.Actions.Select_layer_action(json.info.layer_active, true) ); } + if (json.info.guides != undefined) { + config.guides = json.info.guides; + } actions.push( new app.Actions.Set_object_property_action(this.Base_layers, 'auto_increment', max_id_order + 1) ); diff --git a/src/js/modules/file/save.js b/src/js/modules/file/save.js index afbbf85..de95f33 100644 --- a/src/js/modules/file/save.js +++ b/src/js/modules/file/save.js @@ -594,6 +594,7 @@ class File_save_class { date: today, version: VERSION, layer_active: config.layer.id, + guides: config.guides, }; //layers diff --git a/src/js/modules/image/guides.js b/src/js/modules/image/guides.js new file mode 100644 index 0000000..7e2b38b --- /dev/null +++ b/src/js/modules/image/guides.js @@ -0,0 +1,123 @@ +import config from './../../config.js'; +import Dialog_class from './../../libs/popup.js'; +import Helper_class from './../../libs/helpers.js'; +import Base_layers_class from './../../core/base-layers.js'; +import alertify from './../../../../node_modules/alertifyjs/build/alertify.min.js'; + +class Image_guides_class { + + + constructor() { + this.POP = new Dialog_class(); + this.Base_layers = new Base_layers_class(); + this.Helper = new Helper_class(); + } + + insert() { + var _this = this; + + var settings = { + title: 'Insert guides', + params: [ + {name: "type", title: "Type:", values: ["Vertical", "Horizontal"], value :"Vertical"}, + {name: "position", title: "Position:", value: 20}, + ], + on_finish: function (params) { + _this.insert_handler(params); + }, + }; + this.POP.show(settings); + } + + insert_handler(data){ + var type = data.type; + var position = parseInt(data.position); + + //check if we have guides layer + var layers = this.Base_layers.get_layers(); + var layer = null; + for(var i in layers){ + if(layers[i].type == 'guides'){ + layer = layers[i]; + break; + } + } + + var x = null; + var y = null; + if(type == 'Vertical') + x = position; + if(type == 'Horizontal') + y = position; + + //update + config.guides.push({x: x, y: y}); + + if(config.guides_enabled == false){ + //was disabled + config.guides_enabled = true; + this.Helper.setCookie('guides', 1); + alertify.warning('Guides enabled.'); + } + + config.need_render = true; + } + + update(){ + var _this = this; + + var params = []; + for(var i in config.guides){ + var guide = config.guides[i]; + + if(guide.y === null) + params.push({name: i, title: "Vertical:", value: guide.x}); + } + for(var i in config.guides){ + var guide = config.guides[i]; + + if(guide.x === null) + params.push({name: i, title: "Horizontal:", value: guide.y}); + } + + var settings = { + title: 'Update guides', + params: params, + on_finish: function (params) { + _this.update_handler(params); + }, + }; + this.POP.show(settings); + } + + update_handler(data){ + //update + for (var i in data) { + var key = parseInt(i); + var value = parseInt(data[i]); + + if (config.guides[key].x === null) + config.guides[key].y = value; + else + config.guides[key].x = value; + } + + //remove empty + for (var i = 0; i < config.guides.length; i++) { + if(config.guides[i].x === 0 || config.guides[i].y === 0){ + config.guides.splice(i, 1); + i--; + } + } + + config.need_render = true; + } + + remove(params) { + config.guides = []; + config.need_render = true; + } + +} + +export default Image_guides_class; \ No newline at end of file diff --git a/src/js/modules/tools/settings.js b/src/js/modules/tools/settings.js index 633a0cd..0a93454 100644 --- a/src/js/modules/tools/settings.js +++ b/src/js/modules/tools/settings.js @@ -56,6 +56,15 @@ class Tools_settings_class { var snap = Boolean(snap_cookie); } + //guides + var guides_cookie = this.Helper.getCookie('guides'); + if (guides_cookie === null) { + var guides = true; //default + } + else{ + var guides = Boolean(guides_cookie); + } + var settings = { title: 'Settings', params: [ @@ -65,6 +74,7 @@ class Tools_settings_class { {name: "theme", title: "Theme", values: config.themes, value: theme}, {name: "save_resolution", title: "Save resolution:", value: save_resolution}, {name: "snap", title: "Enable snap:", value: snap}, + {name: "guides", title: "Enable guides:", value: guides}, ], on_change: function (params) { this.Base_gui.change_theme(params.theme); @@ -120,6 +130,16 @@ class Tools_settings_class { config.SNAP = false; } + //guides + if (params.guides) { + this.Helper.setCookie('guides', 1); + config.guides_enabled = true; + } + else { + this.Helper.setCookie('guides', 0); + config.guides_enabled = false; + } + //finish this.Base_gui.prepare_canvas(); config.need_render = true;