Upgraded svg.js library to version 3

This commit is contained in:
Ziver Koc 2023-01-10 00:53:30 +01:00
parent d8a1b66738
commit fb7f43ed23
17 changed files with 7968 additions and 5917 deletions

View file

@ -30,6 +30,7 @@ subprojects {
java { java {
srcDirs 'src' srcDirs 'src'
} }
// We do not want the resource folder to be included in the jar file
//resources { //resources {
// srcDir 'resource' // srcDir 'resource'
//} //}

View file

@ -0,0 +1,64 @@
.selection_border {
fill: none;
stroke: black;
stroke-width:1;
}
.selection_handle_shear {
fill: white;
stroke: black;
stroke-width:1;
}
.selection_handle_rot {
fill: white;
stroke: black;
stroke-width:1;
}
/* .svg_select_points_lt{
cursor: nw-resize;
}
.svg_select_points_rt{
cursor: ne-resize;
}
.svg_select_points_rb{
cursor: se-resize;
}
.svg_select_points_lb{
cursor: sw-resize;
}
.svg_select_points_t{
cursor: n-resize;
}
.svg_select_points_r{
cursor: e-resize;
}
.svg_select_points_b{
cursor: s-resize;
}
.svg_select_points_l{
cursor: w-resize;
}
.svg_select_points_rot{
stroke-width:1;
stroke:black;
fill: #F9FFED;
}
.svg_select_points_point{
cursor: move;
}
.svg_select_boundingRect{
stroke-width:1;
fill:gray;
stroke-dasharray:10 10;
stroke:black;
stroke-opacity:0.8;
fill-opacity:0.1;
pointer-events:none; /* This ons is needed if you want to deselect or drag the shape*/
/*} */

View file

@ -0,0 +1 @@
.svg_select_points_lt{cursor:nw-resize}.svg_select_points_rt{cursor:ne-resize}.svg_select_points_rb{cursor:se-resize}.svg_select_points_lb{cursor:sw-resize}.svg_select_points_t{cursor:n-resize}.svg_select_points_r{cursor:e-resize}.svg_select_points_b{cursor:s-resize}.svg_select_points_l{cursor:w-resize}.svg_select_points_rot{stroke-width:1;stroke:#000;fill:#f9ffed}.svg_select_points_point{cursor:move}.svg_select_boundingRect{stroke-width:1;fill:gray;stroke-dasharray:10 10;stroke:#000;stroke-opacity:.8;fill-opacity:.1;pointer-events:none}

View file

@ -2,6 +2,8 @@
// Autostart // Autostart
// -------------------------------------------------------- // --------------------------------------------------------
"use strict";
$(function(){ $(function(){
$(".toggle-switch").bootstrapSwitch({inverse: true, size: "mini"}); $(".toggle-switch").bootstrapSwitch({inverse: true, size: "mini"});

View file

@ -1,221 +1,177 @@
/*! svg.draggable.js - v2.2.0 - 2016-05-21 /*!
* https://github.com/wout/svg.draggable.js * @svgdotjs/svg.draggable.js - An extension for svg.js which allows to drag elements with your mouse
* Copyright (c) 2016 Wout Fierens; Licensed MIT */ * @version 3.0.2
;(function() { * https://github.com/svgdotjs/svg.draggable.js
*
* @copyright Wout Fierens
* @license MIT
*
* BUILT: Tue Feb 19 2019 17:12:16 GMT+0100 (GMT+01:00)
*/;
(function (svg_js) {
'use strict';
// creates handler, saves it function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
var getCoordsFromEvent = function getCoordsFromEvent(ev) {
if (ev.changedTouches) {
ev = ev.changedTouches[0];
}
return {
x: ev.clientX,
y: ev.clientY
};
}; // Creates handler, saves it
var DragHandler =
/*#__PURE__*/
function () {
function DragHandler(el) { function DragHandler(el) {
el.remember('_draggable', this) _classCallCheck(this, DragHandler);
this.el = el
el.remember('_draggable', this);
this.el = el;
this.drag = this.drag.bind(this);
this.startDrag = this.startDrag.bind(this);
this.endDrag = this.endDrag.bind(this);
} // Enables or disabled drag based on input
_createClass(DragHandler, [{
key: "init",
value: function init(enabled) {
if (enabled) {
this.el.on('mousedown.drag', this.startDrag);
this.el.on('touchstart.drag', this.startDrag);
} else {
this.el.off('mousedown.drag');
this.el.off('touchstart.drag');
} }
} // Start dragging
}, {
key: "startDrag",
value: function startDrag(ev) {
var isMouse = !ev.type.indexOf('mouse'); // Check for left button
if (isMouse && (ev.which || ev.buttons) !== 1) {
return;
} // Fire beforedrag event
// Sets new parameter, starts dragging if (this.el.dispatch('beforedrag', {
DragHandler.prototype.init = function(constraint, val){ event: ev,
var _this = this handler: this
this.constraint = constraint }).defaultPrevented) {
this.value = val return;
this.el.on('mousedown.drag', function(e){ _this.start(e) }) } // Prevent browser drag behavior as soon as possible
this.el.on('touchstart.drag', function(e){ _this.start(e) })
ev.preventDefault(); // Prevent propagation to a parent that might also have dragging enabled
ev.stopPropagation(); // Make sure that start events are unbound so that one element
// is only dragged by one input only
this.init(false);
this.box = this.el.bbox();
this.lastClick = this.el.point(getCoordsFromEvent(ev)); // We consider the drag done, when a touch is canceled, too
var eventMove = (isMouse ? 'mousemove' : 'touchmove') + '.drag';
var eventEnd = (isMouse ? 'mouseup' : 'touchcancel.drag touchend') + '.drag'; // Bind drag and end events to window
svg_js.on(window, eventMove, this.drag);
svg_js.on(window, eventEnd, this.endDrag); // Fire dragstart event
this.el.fire('dragstart', {
event: ev,
handler: this,
box: this.box
});
} // While dragging
}, {
key: "drag",
value: function drag(ev) {
var box = this.box,
lastClick = this.lastClick;
var currentClick = this.el.point(getCoordsFromEvent(ev));
var x = box.x + (currentClick.x - lastClick.x);
var y = box.y + (currentClick.y - lastClick.y);
var newBox = new svg_js.Box(x, y, box.w, box.h);
if (this.el.dispatch('dragmove', {
event: ev,
handler: this,
box: newBox
}).defaultPrevented) return;
this.move(x, y);
return newBox;
} }
}, {
// transforms one point from screen to user coords key: "move",
DragHandler.prototype.transformPoint = function(event, offset){ value: function move(x, y) {
event = event || window.event // Svg elements bbox depends on their content even though they have
var touches = event.changedTouches && event.changedTouches[0] || event // x, y, width and height - strange!
this.p.x = touches.pageX - (offset || 0) // Thats why we handle them the same as groups
this.p.y = touches.pageY if (this.el.type === 'svg') {
return this.p.matrixTransform(this.m) svg_js.G.prototype.move.call(this.el, x, y);
} } else {
this.el.move(x, y);
// gets elements bounding box with special handling of groups, nested and use
DragHandler.prototype.getBBox = function(){
var box = this.el.bbox()
if(this.el instanceof SVG.Nested) box = this.el.rbox()
if (this.el instanceof SVG.G || this.el instanceof SVG.Use || this.el instanceof SVG.Nested) {
box.x = this.el.x()
box.y = this.el.y()
}
return box
}
// start dragging
DragHandler.prototype.start = function(e){
// check for left button
if(e.type == 'click'|| e.type == 'mousedown' || e.type == 'mousemove'){
if((e.which || e.buttons) != 1){
return
} }
} }
}, {
var _this = this key: "endDrag",
value: function endDrag(ev) {
// fire beforedrag event
this.el.fire('beforedrag', { event: e, handler: this })
// search for parent on the fly to make sure we can call
// draggable() even when element is not in the dom currently
this.parent = this.parent || this.el.parent(SVG.Nested) || this.el.parent(SVG.Doc)
this.p = this.parent.node.createSVGPoint()
// save current transformation matrix
this.m = this.el.node.getScreenCTM().inverse()
var box = this.getBBox()
var anchorOffset;
// fix text-anchor in text-element (#37)
if(this.el instanceof SVG.Text){
anchorOffset = this.el.node.getComputedTextLength();
switch(this.el.attr('text-anchor')){
case 'middle':
anchorOffset /= 2;
break
case 'start':
anchorOffset = 0;
break;
}
}
this.startPoints = {
// We take absolute coordinates since we are just using a delta here
point: this.transformPoint(e, anchorOffset),
box: box
}
// add drag and end events to window
SVG.on(window, 'mousemove.drag', function(e){ _this.drag(e) })
SVG.on(window, 'touchmove.drag', function(e){ _this.drag(e) })
SVG.on(window, 'mouseup.drag', function(e){ _this.end(e) })
SVG.on(window, 'touchend.drag', function(e){ _this.end(e) })
// fire dragstart event
this.el.fire('dragstart', {event: e, p: this.startPoints.point, m: this.m, handler: this})
// prevent browser drag behavior
e.preventDefault()
// prevent propagation to a parent that might also have dragging enabled
e.stopPropagation();
}
// while dragging
DragHandler.prototype.drag = function(e){
var box = this.getBBox()
, p = this.transformPoint(e)
, x = this.startPoints.box.x + p.x - this.startPoints.point.x
, y = this.startPoints.box.y + p.y - this.startPoints.point.y
, c = this.constraint
var event = new CustomEvent('dragmove', {
detail: {
event: e
, p: p
, m: this.m
, handler: this
}
, cancelable: true
})
this.el.fire(event)
if(event.defaultPrevented) return p
// move the element to its new position, if possible by constraint
if (typeof c == 'function') {
var coord = c.call(this.el, x, y, this.m)
// bool, just show us if movement is allowed or not
if (typeof coord == 'boolean') {
coord = {
x: coord,
y: coord
}
}
// if true, we just move. If !false its a number and we move it there
if (coord.x === true) {
this.el.x(x)
} else if (coord.x !== false) {
this.el.x(coord.x)
}
if (coord.y === true) {
this.el.y(y)
} else if (coord.y !== false) {
this.el.y(coord.y)
}
} else if (typeof c == 'object') {
// keep element within constrained box
if (c.minX != null && x < c.minX)
x = c.minX
else if (c.maxX != null && x > c.maxX - box.width){
x = c.maxX - box.width
}if (c.minY != null && y < c.minY)
y = c.minY
else if (c.maxY != null && y > c.maxY - box.height)
y = c.maxY - box.height
this.el.move(x, y)
}
// so we can use it in the end-method, too
return p
}
DragHandler.prototype.end = function(e){
// final drag // final drag
var p = this.drag(e); var box = this.drag(ev); // fire dragend event
// fire dragend event this.el.fire('dragend', {
this.el.fire('dragend', { event: e, p: p, m: this.m, handler: this }) event: ev,
handler: this,
box: box
}); // unbind events
// unbind events svg_js.off(window, 'mousemove.drag');
SVG.off(window, 'mousemove.drag') svg_js.off(window, 'touchmove.drag');
SVG.off(window, 'touchmove.drag') svg_js.off(window, 'mouseup.drag');
SVG.off(window, 'mouseup.drag') svg_js.off(window, 'touchend.drag'); // Rebind initial Events
SVG.off(window, 'touchend.drag')
this.init(true);
} }
}]);
SVG.extend(SVG.Element, { return DragHandler;
// Make element draggable }();
// Constraint might be an object (as described in readme.md) or a function in the form "function (x, y)" that gets called before every move.
// The function can return a boolean or an object of the form {x, y}, to which the element will be moved. "False" skips moving, true moves to raw x, y.
draggable: function(value, constraint) {
// Check the parameters and reassign if needed svg_js.extend(svg_js.Element, {
if (typeof value == 'function' || typeof value == 'object') { draggable: function draggable() {
constraint = value var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
value = true var dragHandler = this.remember('_draggable') || new DragHandler(this);
dragHandler.init(enable);
return this;
} }
});
var dragHandler = this.remember('_draggable') || new DragHandler(this) }(SVG));
//# sourceMappingURL=svg.draggable.js.map
// When no parameter is given, value is true
value = typeof value === 'undefined' ? true : value
if(value) dragHandler.init(constraint || {}, value)
else {
this.off('mousedown.drag')
this.off('touchstart.drag')
}
return this
}
})
}).call(this);

View file

@ -1,4 +1,3 @@
/*! svg.draggable.js - v2.2.0 - 2016-05-21 /*! @svgdotjs/svg.draggable.js v3.0.2 MIT*/;
* https://github.com/wout/svg.draggable.js !function(s){"use strict";function a(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}var h=function(t){return t.changedTouches&&(t=t.changedTouches[0]),{x:t.clientX,y:t.clientY}},e=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),t.remember("_draggable",this),this.el=t,this.drag=this.drag.bind(this),this.startDrag=this.startDrag.bind(this),this.endDrag=this.endDrag.bind(this)}var t,i,n;return t=e,(i=[{key:"init",value:function(t){t?(this.el.on("mousedown.drag",this.startDrag),this.el.on("touchstart.drag",this.startDrag)):(this.el.off("mousedown.drag"),this.el.off("touchstart.drag"))}},{key:"startDrag",value:function(t){var e=!t.type.indexOf("mouse");if(!(e&&1!==(t.which||t.buttons)||this.el.dispatch("beforedrag",{event:t,handler:this}).defaultPrevented)){t.preventDefault(),t.stopPropagation(),this.init(!1),this.box=this.el.bbox(),this.lastClick=this.el.point(h(t));var i=(e?"mousemove":"touchmove")+".drag",n=(e?"mouseup":"touchcancel.drag touchend")+".drag";s.on(window,i,this.drag),s.on(window,n,this.endDrag),this.el.fire("dragstart",{event:t,handler:this,box:this.box})}}},{key:"drag",value:function(t){var e=this.box,i=this.lastClick,n=this.el.point(h(t)),a=e.x+(n.x-i.x),r=e.y+(n.y-i.y),o=new s.Box(a,r,e.w,e.h);if(!this.el.dispatch("dragmove",{event:t,handler:this,box:o}).defaultPrevented)return this.move(a,r),o}},{key:"move",value:function(t,e){"svg"===this.el.type?s.G.prototype.move.call(this.el,t,e):this.el.move(t,e)}},{key:"endDrag",value:function(t){var e=this.drag(t);this.el.fire("dragend",{event:t,handler:this,box:e}),s.off(window,"mousemove.drag"),s.off(window,"touchmove.drag"),s.off(window,"mouseup.drag"),s.off(window,"touchend.drag"),this.init(!0)}}])&&a(t.prototype,i),n&&a(t,n),e}();s.extend(s.Element,{draggable:function(){var t=!(0<arguments.length&&void 0!==arguments[0])||arguments[0];return(this.remember("_draggable")||new e(this)).init(t),this}})}(SVG);
* Copyright (c) 2016 Wout Fierens; Licensed MIT */ //# sourceMappingURL=svg.draggable.min.js.map
(function(){function a(a){a.remember("_draggable",this),this.el=a}a.prototype.init=function(a,b){var c=this;this.constraint=a,this.value=b,this.el.on("mousedown.drag",function(a){c.start(a)}),this.el.on("touchstart.drag",function(a){c.start(a)})},a.prototype.transformPoint=function(a,b){a=a||window.event;var c=a.changedTouches&&a.changedTouches[0]||a;return this.p.x=c.pageX-(b||0),this.p.y=c.pageY,this.p.matrixTransform(this.m)},a.prototype.getBBox=function(){var a=this.el.bbox();return this.el instanceof SVG.Nested&&(a=this.el.rbox()),(this.el instanceof SVG.G||this.el instanceof SVG.Use||this.el instanceof SVG.Nested)&&(a.x=this.el.x(),a.y=this.el.y()),a},a.prototype.start=function(a){if("click"!=a.type&&"mousedown"!=a.type&&"mousemove"!=a.type||1==(a.which||a.buttons)){var b=this;this.el.fire("beforedrag",{event:a,handler:this}),this.parent=this.parent||this.el.parent(SVG.Nested)||this.el.parent(SVG.Doc),this.p=this.parent.node.createSVGPoint(),this.m=this.el.node.getScreenCTM().inverse();var c,d=this.getBBox();if(this.el instanceof SVG.Text)switch(c=this.el.node.getComputedTextLength(),this.el.attr("text-anchor")){case"middle":c/=2;break;case"start":c=0}this.startPoints={point:this.transformPoint(a,c),box:d},SVG.on(window,"mousemove.drag",function(a){b.drag(a)}),SVG.on(window,"touchmove.drag",function(a){b.drag(a)}),SVG.on(window,"mouseup.drag",function(a){b.end(a)}),SVG.on(window,"touchend.drag",function(a){b.end(a)}),this.el.fire("dragstart",{event:a,p:this.startPoints.point,m:this.m,handler:this}),a.preventDefault(),a.stopPropagation()}},a.prototype.drag=function(a){var b=this.getBBox(),c=this.transformPoint(a),d=this.startPoints.box.x+c.x-this.startPoints.point.x,e=this.startPoints.box.y+c.y-this.startPoints.point.y,f=this.constraint,g=new CustomEvent("dragmove",{detail:{event:a,p:c,m:this.m,handler:this},cancelable:!0});if(this.el.fire(g),g.defaultPrevented)return c;if("function"==typeof f){var h=f.call(this.el,d,e,this.m);"boolean"==typeof h&&(h={x:h,y:h}),h.x===!0?this.el.x(d):h.x!==!1&&this.el.x(h.x),h.y===!0?this.el.y(e):h.y!==!1&&this.el.y(h.y)}else"object"==typeof f&&(null!=f.minX&&d<f.minX?d=f.minX:null!=f.maxX&&d>f.maxX-b.width&&(d=f.maxX-b.width),null!=f.minY&&e<f.minY?e=f.minY:null!=f.maxY&&e>f.maxY-b.height&&(e=f.maxY-b.height),this.el.move(d,e));return c},a.prototype.end=function(a){var b=this.drag(a);this.el.fire("dragend",{event:a,p:b,m:this.m,handler:this}),SVG.off(window,"mousemove.drag"),SVG.off(window,"touchmove.drag"),SVG.off(window,"mouseup.drag"),SVG.off(window,"touchend.drag")},SVG.extend(SVG.Element,{draggable:function(b,c){("function"==typeof b||"object"==typeof b)&&(c=b,b=!0);var d=this.remember("_draggable")||new a(this);return b="undefined"==typeof b?!0:b,b?d.init(c||{},b):(this.off("mousedown.drag"),this.off("touchstart.drag")),this}})}).call(this);

File diff suppressed because it is too large Load diff

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2014 Fuzzy
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,425 @@
/*!
* svg.select.js - An extension of svg.js which allows to select elements with mouse
* @version 3.0.1
* https://github.com/svgdotjs/svg.select.js
*
* @copyright Ulrich-Matthias Schäfer
* @license MIT
*/;
;(function() {
"use strict";
function SelectHandler(el) {
this.el = el;
el.remember('_selectHandler', this);
this.pointSelection = {isSelected: false};
this.rectSelection = {isSelected: false};
// helper list with position settings of each type of point
this.pointsList = {
lt: [ 0, 0 ],
rt: [ 'width', 0 ],
rb: [ 'width', 'height' ],
lb: [ 0, 'height' ],
t: [ 'width', 0 ],
r: [ 'width', 'height' ],
b: [ 'width', 'height' ],
l: [ 0, 'height' ]
};
// helper function to get point coordinates based on settings above and an object (bbox in our case)
this.pointCoord = function (setting, object, isPointCentered) {
var coord = typeof setting !== 'string' ? setting : object[setting];
// Top, bottom, right and left points are placed in the center of element width/height
return isPointCentered ? coord / 2 : coord
}
this.pointCoords = function (point, object) {
var settings = this.pointsList[point];
return {
x: this.pointCoord(settings[0], object, (point === 't' || point === 'b')),
y: this.pointCoord(settings[1], object, (point === 'r' || point === 'l'))
}
}
}
SelectHandler.prototype.init = function (value, options) {
var bbox = this.el.bbox();
this.options = {};
// store defaults list of points in order to verify users config
var points = this.el.selectize.defaults.points;
// Merging the defaults and the options-object together
for (var i in this.el.selectize.defaults) {
this.options[i] = this.el.selectize.defaults[i];
if (options[i] !== undefined) {
this.options[i] = options[i];
}
}
// prepare & validate list of points to be added (or excluded)
var pointsLists = ['points', 'pointsExclude'];
for (var i in pointsLists) {
var option = this.options[pointsLists[i]];
if (typeof option === 'string') {
if (option.length > 0) {
// if set as comma separated string list => convert it into an array
option = option.split(/\s*,\s*/i);
} else {
option = [];
}
} else if (typeof option === 'boolean' && pointsLists[i] === 'points') {
// this is not needed, but let's have it for legacy support
option = option ? points : [];
}
this.options[pointsLists[i]] = option;
}
// intersect correct all points options with users config (exclude unwanted points)
// ES5 -> NO arrow functions nor Array.includes()
this.options.points = [ points, this.options.points ].reduce(
function (a, b) {
return a.filter(
function (c) {
return b.indexOf(c) > -1;
}
)
}
);
// exclude pointsExclude, if wanted
this.options.points = [ this.options.points, this.options.pointsExclude ].reduce(
function (a, b) {
return a.filter(
function (c) {
return b.indexOf(c) < 0;
}
)
}
);
this.parent = this.el.parent();
this.nested = (this.nested || this.parent.group());
this.nested.matrix(new SVG.Matrix(this.el).translate(bbox.x, bbox.y));
// When deepSelect is enabled and the element is a line/polyline/polygon, draw only points for moving
if (this.options.deepSelect && ['line', 'polyline', 'polygon'].indexOf(this.el.type) !== -1) {
this.selectPoints(value);
} else {
this.selectRect(value);
}
this.observe();
this.cleanup();
};
SelectHandler.prototype.selectPoints = function (value) {
this.pointSelection.isSelected = value;
// When set is already there we dont have to create one
if (this.pointSelection.set) {
return this;
}
// Create our set of elements
this.pointSelection.set = this.parent.set();
// draw the points and mark the element as selected
this.drawPoints();
return this;
};
// create the point-array which contains the 2 points of a line or simply the points-array of polyline/polygon
SelectHandler.prototype.getPointArray = function () {
var bbox = this.el.bbox();
return this.el.array().valueOf().map(function (el) {
return [el[0] - bbox.x, el[1] - bbox.y];
});
};
// Draws a points
SelectHandler.prototype.drawPoints = function () {
var _this = this, array = this.getPointArray();
// go through the array of points
for (var i = 0, len = array.length; i < len; ++i) {
var curriedEvent = (function (k) {
return function (ev) {
ev = ev || window.event;
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
ev.stopPropagation();
var x = ev.pageX || ev.touches[0].pageX;
var y = ev.pageY || ev.touches[0].pageY;
_this.el.fire('point', {x: x, y: y, i: k, event: ev});
};
})(i);
// add every point to the set
// add css-classes and a touchstart-event which fires our event for moving points
var point = this.drawPoint(array[i][0], array[i][1])
.addClass(this.options.classPoints)
.addClass(this.options.classPoints + '_point')
.on('touchstart', curriedEvent)
.on('mousedown', curriedEvent)
this.pointSelection.set.add(point);
}
};
// The function to draw single point
SelectHandler.prototype.drawPoint = function (cx, cy) {
var pointType = this.options.pointType;
switch (pointType) {
case 'circle':
return this.drawCircle(cx, cy);
case 'rect':
return this.drawRect(cx, cy);
default:
if (typeof pointType === 'function') {
return pointType.call(this, cx, cy);
}
throw new Error('Unknown ' + pointType + ' point type!');
}
};
// The function to draw the circle point
SelectHandler.prototype.drawCircle = function (cx, cy) {
return this.nested.circle(this.options.pointSize)
.stroke(this.options.pointStroke)
.fill(this.options.pointFill)
.center(cx, cy);
};
// The function to draw the rect point
SelectHandler.prototype.drawRect = function (cx, cy) {
return this.nested.rect(this.options.pointSize, this.options.pointSize)
.stroke(this.options.pointStroke)
.fill(this.options.pointFill)
.center(cx, cy);
};
// every time a point is moved, we have to update the positions of our point
SelectHandler.prototype.updatePointSelection = function () {
var array = this.getPointArray();
this.pointSelection.set.each(function (i) {
if (this.cx() === array[i][0] && this.cy() === array[i][1]) {
return;
}
this.center(array[i][0], array[i][1]);
});
};
SelectHandler.prototype.updateRectSelection = function () {
var _this = this, bbox = this.el.bbox();
this.rectSelection.set.get(0).attr({
width: bbox.width,
height: bbox.height
});
// set.get(1) is always in the upper left corner. no need to move it
if (this.options.points.length) {
this.options.points.map(function (point, index) {
var coords = _this.pointCoords(point, bbox);
_this.rectSelection.set.get(index + 1).center(coords.x, coords.y);
});
}
if (this.options.rotationPoint) {
var length = this.rectSelection.set.length();
this.rectSelection.set.get(length - 1).center(bbox.width / 2, 20);
}
};
SelectHandler.prototype.selectRect = function (value) {
var _this = this, bbox = this.el.bbox();
this.rectSelection.isSelected = value;
// when set is already p
this.rectSelection.set = this.rectSelection.set || this.parent.set();
// helperFunction to create a mouse-down function which triggers the event specified in `eventName`
function getMoseDownFunc(eventName) {
return function (ev) {
ev = ev || window.event;
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
ev.stopPropagation();
var x = ev.pageX || ev.touches[0].pageX;
var y = ev.pageY || ev.touches[0].pageY;
_this.el.fire(eventName, {x: x, y: y, event: ev});
};
}
// create the selection-rectangle and add the css-class
if (!this.rectSelection.set.get(0)) {
this.rectSelection.set.add(this.nested.rect(bbox.width, bbox.height).addClass(this.options.classRect));
}
// Draw Points at the edges, if enabled
if (this.options.points.length && this.rectSelection.set.length() < 2) {
var ename ="touchstart", mname = "mousedown";
this.options.points.map(function (point, index) {
var coords = _this.pointCoords(point, bbox);
var pointElement = _this.drawPoint(coords.x, coords.y)
.attr('class', _this.options.classPoints + '_' + point)
.on(mname, getMoseDownFunc(point))
.on(ename, getMoseDownFunc(point));
_this.rectSelection.set.add(pointElement);
});
this.rectSelection.set.each(function () {
this.addClass(_this.options.classPoints);
});
}
// draw rotationPint, if enabled
if (this.options.rotationPoint && ((this.options.points && !this.rectSelection.set.get(9)) || (!this.options.points && !this.rectSelection.set.get(1)))) {
var curriedEvent = function (ev) {
ev = ev || window.event;
ev.preventDefault ? ev.preventDefault() : ev.returnValue = false;
ev.stopPropagation();
var x = ev.pageX || ev.touches[0].pageX;
var y = ev.pageY || ev.touches[0].pageY;
_this.el.fire('rot', {x: x, y: y, event: ev});
};
var pointElement = this.drawPoint(bbox.width / 2, 20)
.attr('class', this.options.classPoints + '_rot')
.on("touchstart", curriedEvent)
.on("mousedown", curriedEvent);
this.rectSelection.set.add(pointElement);
}
};
SelectHandler.prototype.handler = function () {
var bbox = this.el.bbox();
this.nested.matrix(new SVG.Matrix(this.el).translate(bbox.x, bbox.y));
if (this.rectSelection.isSelected) {
this.updateRectSelection();
}
if (this.pointSelection.isSelected) {
this.updatePointSelection();
}
};
SelectHandler.prototype.observe = function () {
var _this = this;
if (MutationObserver) {
if (this.rectSelection.isSelected || this.pointSelection.isSelected) {
this.observerInst = this.observerInst || new MutationObserver(function () {
_this.handler();
});
this.observerInst.observe(this.el.node, {attributes: true});
} else {
try {
this.observerInst.disconnect();
delete this.observerInst;
} catch (e) {
}
}
} else {
this.el.off('DOMAttrModified.select');
if (this.rectSelection.isSelected || this.pointSelection.isSelected) {
this.el.on('DOMAttrModified.select', function () {
_this.handler();
});
}
}
};
SelectHandler.prototype.cleanup = function () {
//var _this = this;
if (!this.rectSelection.isSelected && this.rectSelection.set) {
// stop watching the element, remove the selection
this.rectSelection.set.each(function () {
this.remove();
});
this.rectSelection.set.clear();
delete this.rectSelection.set;
}
if (!this.pointSelection.isSelected && this.pointSelection.set) {
// Remove all points, clear the set, stop watching the element
this.pointSelection.set.each(function () {
this.remove();
});
this.pointSelection.set.clear();
delete this.pointSelection.set;
}
if (!this.pointSelection.isSelected && !this.rectSelection.isSelected) {
this.nested.remove();
delete this.nested;
}
};
SVG.extend(SVG.Element, {
// Select element with mouse
selectize: function (value, options) {
// Check the parameters and reassign if needed
if (typeof value === 'object') {
options = value;
value = true;
}
var selectHandler = this.remember('_selectHandler') || new SelectHandler(this);
selectHandler.init(value === undefined ? true : value, options || {});
return this;
}
});
SVG.Element.prototype.selectize.defaults = {
points: ['lt', 'rt', 'rb', 'lb', 't', 'r', 'b', 'l'], // which points to draw, default all
pointsExclude: [], // easier option if to exclude few than rewrite all
classRect: 'svg_select_boundingRect', // Css-class added to the rect
classPoints: 'svg_select_points', // Css-class added to the points
pointSize: 7, // size of point
rotationPoint: true, // If true, rotation point is drawn. Needed for rotation!
deepSelect: false, // If true, moving of single points is possible (only line, polyline, polyon)
pointType: 'circle', // Point type: circle or rect, default circle
pointFill: "#000", // Point fill color
pointStroke: { width: 1, color: "#000" } // Point stroke properties
};
}());

File diff suppressed because one or more lines are too long

View file

@ -1,26 +0,0 @@
// Title Plugin
// Source: https://github.com/wout/svg.js/issues/147
//
// // example usage
// var draw = SVG('drawing')
// var group = draw.group()
// group.title('This is a pink square.')
// group.rect(100,100).fill('#f06')
SVG.Title = SVG.invent({
create: 'title',
inherit: SVG.Element,
extend: {
text: function(text) {
while (this.node.firstChild)
this.node.removeChild(this.node.firstChild)
this.node.appendChild(document.createTextNode(text))
return this
}
},
construct: {
title: function(text) {
return this.put(new SVG.Title).text(text)
}
}
})

View file

@ -1,17 +1,19 @@
"use strict";
var svg; var svg;
var data = {
rooms: [],
sensors: [],
events: []
};
var editModeEnabled = false; var editModeEnabled = false;
$(function(){ $(function(){
if (!SVG.supported) {
alert("Image format(SVG) not supported by your browser.");
return;
}
// ------------------------------------------ // ------------------------------------------
// Setup map // Setup map
// ------------------------------------------ // ------------------------------------------
svg = SVG("map"); svg = SVG("#map").size("100%", "700").viewbox(0, 0, 1000, 700);
// Initialize events // Initialize events
@ -67,46 +69,64 @@ $(function(){
// Start draw loop // Start draw loop
// ------------------------------------------ // ------------------------------------------
fetchData(drawMap);
setInterval(function() { setInterval(function() {
if (editModeEnabled == false) if (editModeEnabled == false) {
drawMap(); fetchData(drawMap);
}
}, 3000); // 3 sec }, 3000); // 3 sec
//}, 10000); // 10 sec
}); });
// ----------------------------------------------
// Events
// ----------------------------------------------
function editMode(enable){ function editMode(enable){
if (editModeEnabled == enable) if (editModeEnabled == enable) {
return; return;
}
editModeEnabled = enable; editModeEnabled = enable;
if (editModeEnabled) { if (editModeEnabled) {
$(".edit-mode").show(); $(".edit-mode").show();
$(".view-mode").hide(); $(".view-mode").hide();
$("#map").css("border-color", "#6eb16e"); $("#map").css("border-color", "#6eb16e");
svg.select(".draggable").draggable(true); } else {
} $(".room").selectize(false)
else {
$(".edit-mode").hide(); $(".edit-mode").hide();
$(".view-mode").show(); $(".view-mode").show();
$("#map").css("border-color", ""); $("#map").css("border-color", "");
svg.select(".draggable").draggable(false);
} }
} }
function drawMap(){ function beforeDragEvent(e) {
// Get map data if (editModeEnabled == false) {
$.getJSON("/api/map?action=getdata", function(json){ e.preventDefault(); // Prevent drag
// Reset map }
svg.clear(); }
function selectEntity(e) {
if (editModeEnabled == false) {
e.target.selectize();
}
}
// -------------------------------------- // --------------------------------------
// Draw // Draw
// -------------------------------------- // --------------------------------------
function drawMap() {
// Reset map
//svg.clear();
// Background // Background
if (SVG.find("svg .bg-image").length > 0) { if (svg.find(".bg-image").length <= 0) {
var bg_image = svg.image("?bgimage").addClass("bg-image") var bgImage = svg.image("?bgimage").addClass("bg-image")
.x(0) .x(0)
.y(0) .y(0)
.width("100%") .width("100%")
@ -115,66 +135,105 @@ function drawMap(){
// Rooms // Rooms
if (json.rooms != null) { if (data.rooms != null) {
$.each(json.rooms, function(i, room) { $.each(data.rooms, function(i, room) {
svg.find("#room-" + room.id).remove();
var group = svg.group(); var group = svg.group();
group.rect(room.width, room.height); group.text(room.name).move(5, 5).fill('#999');
group.text(room.name).move(10, 10).fill('#999'); group.rect(room.map.width, room.map.height).selectize();
group.addClass("draggable").addClass("room") group.addClass("room")
.x(room.x) .attr("id", "room-" + room.id)
.y(room.y) .attr("room-id", room.id)
.attr("room-id", room.id); .x(room.map.x)
.y(room.map.y);
group.draggable().on('beforedrag', beforeDragEvent);
//group.on('mousedown', selectEntity, false);
}); });
} }
// Sensors // Sensors
if (json.sensors != null) { if (data.sensors != null) {
$.each(json.sensors, function(i, sensor) { $.each(data.sensors, function(i, sensor) {
svg.find("#sensor-" + sensor.id).remove();
var group = svg.group(); var group = svg.group();
group.element('title').words(sensor.name);
group.image("/img/temperature.svg"); group.text(sensor.data.valueStr).move(45, 15).fill('#999');
group.text(sensor.data).move(45, 15).fill('#999'); group.image("/img/temperature.svg").size(50, 50);
group.addClass("draggable").addClass("sensor") group.addClass("sensor")
.x(sensor.x) .attr("id", "sensor-" + sensor.id)
.y(sensor.y) .attr("sensor-id", sensor.id)
.attr("sensor-id", sensor.id); .x(sensor.map.x)
group.title(sensor.name); .y(sensor.map.y);
group.draggable().on('beforedrag', beforeDragEvent);
}); });
} }
// Events // Events
if (json.event != null) { if (data.events != null) {
$.each(json.events, function(i, event) { $.each(data.events, function(i, event) {
svg.find("#event-" + event.id).remove();
var group = svg.group(); var group = svg.group();
group.element('title').words(event.name);
var img = "/img/lightbulb_off.svg"; var img = "/img/lightbulb_off.svg";
if (event.data == "ON") if (event.data.valueStr == "ON")
img = "/img/lightbulb_on.svg"; img = "/img/lightbulb_on.svg";
group.image(img); group.image(img).size(50, 50);
group.addClass("draggable").addClass("event") group.addClass("event")
.x(event.x) .attr("id", "event-" + event.id)
.y(event.y) .attr("event-id", event.id)
.attr("event-id", event.id); .x(event.map.x)
group.title(event.name); .y(event.map.y);
group.draggable().on('beforedrag', beforeDragEvent);
}); });
} }
}); }
// ----------------------------------------------
// Load and Store data
// ----------------------------------------------
async function fetchData(callback) {
await fetch('/api/room')
.then(response => response.json())
.then(json => {
data.rooms = json;
})
await fetch('/api/sensor')
.then(response => response.json())
.then(json => {
data.sensors = json;
})
await fetch('/api/event')
.then(response => response.json())
.then(json => {
data.events = json;
})
callback();
} }
function saveMap(){ function saveMap(){
svg.select(".room").each(function(){ svg.find(".room").each(function(){
saveDevice(this, "room", "room-id"); saveDevice(this, "room", "room-id");
}); });
svg.select(".sensor").each(function(){ svg.find(".sensor").each(function(){
saveDevice(this, "sensor", "sensor-id"); saveDevice(this, "sensor", "sensor-id");
}); });
svg.select(".event").each(function(){ svg.find(".event").each(function(){
saveDevice(this, "event", "event-id"); saveDevice(this, "event", "event-id");
}); });
} }

View file

@ -13,8 +13,9 @@
</style> </style>
<div class="col-sm-9 col-sm-offset-1 col-md-10 col-md-offset-1"> <div class="col-sm-9 col-sm-offset-1 col-md-10 col-md-offset-1">
<svg id="map" width="100%" width="500" viewBox="0 0 1000 500"></svg> <svg id="map"></svg>
</div> </div>
<div class="col-sm-1 col-md-1"> <div class="col-sm-1 col-md-1">
<a id="button-edit" class="view-mode" href="#"> <a id="button-edit" class="view-mode" href="#">
<span class="view-mode glyphicon glyphicon-wrench" aria-hidden="true"></span> <span class="view-mode glyphicon glyphicon-wrench" aria-hidden="true"></span>
@ -41,16 +42,18 @@
</div> </div>
</div> </div>
<script src="js/lib/svg.min.js"></script>
<script src="js/lib/svg.title.js"></script>
<script src="js/lib/svg.draggable.min.js"></script>
<script src="js/lib/jquery.filer.min.js"></script>
<link href="css/jquery.filer.css" rel="stylesheet"> <link href="css/jquery.filer.css" rel="stylesheet">
<link href="css/svg.select.min.js" rel="stylesheet">
<script src="js/lib/jquery.filer.min.js"></script>
<script src="js/lib/svg.min.js"></script>
<script src="js/lib/svg.select.min.js"></script>
<script src="js/lib/svg.draggable.min.js"></script>
<script src="js/map.js"></script> <script src="js/map.js"></script>
<!------------------ MODALS ----------------------> <!------------------ MODALS ---------------------->
<div class="modal fade" id="bgUploadModal" tabindex="-1"> <div class="modal fade" id="bgUploadModal" tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">

View file

@ -30,9 +30,9 @@ public class HalContext {
public static final String RESOURCE_ROOT; public static final String RESOURCE_ROOT;
static { static {
if (FileUtil.find("build/resources/") != null) if (FileUtil.find("build/resources/") != null) // Development environment
RESOURCE_ROOT = "build/resources"; RESOURCE_ROOT = "build/resources";
else if (FileUtil.find("resources/") != null) else if (FileUtil.find("resources/") != null) // Release package environment
RESOURCE_ROOT = "resources"; RESOURCE_ROOT = "resources";
else else
RESOURCE_ROOT = "."; RESOURCE_ROOT = ".";

View file

@ -223,8 +223,8 @@ public abstract class HalAbstractDevice<V extends HalAbstractDevice, C extends H
return mapY; return mapY;
} }
public void setMapCoordinates(double x, double y) { public void setMapCoordinates(double x, double y) {
this.mapX = x; this.mapX = Math.max(0.0, x);
this.mapY = y; this.mapY = Math.max(0.0, y);
} }
public void addReportListener(HalDeviceReportListener listener) { public void addReportListener(HalDeviceReportListener listener) {

View file

@ -33,9 +33,7 @@ public class MapApiEndpoint extends HalApiEndpoint {
DBConnection db = HalContext.getDB(); DBConnection db = HalContext.getDB();
DataNode root = new DataNode(DataNode.DataType.Map); DataNode root = new DataNode(DataNode.DataType.Map);
if ("getdata".equals(request.get("action"))) { if ("save".equals(request.get("action"))) {
getDeviceNode(db, root);
} else if ("save".equals(request.get("action"))) {
int id = Integer.parseInt(request.get("id")); int id = Integer.parseInt(request.get("id"));
HalAbstractDevice device = null; HalAbstractDevice device = null;
@ -46,40 +44,11 @@ public class MapApiEndpoint extends HalApiEndpoint {
else if ("event".equals(request.get("type"))) else if ("event".equals(request.get("type")))
device = Event.getEvent(db, id); device = Event.getEvent(db, id);
device.setMapCoordinates(Float.parseFloat(request.get("x")), Float.parseFloat(request.get("y"))); device.setMapCoordinates(
Float.parseFloat(request.get("x")),
Float.parseFloat(request.get("y")));
device.save(db); device.save(db);
} }
return root; return root;
} }
private void getDeviceNode(DBConnection db, DataNode root) throws SQLException {
DataNode sensorsNode = new DataNode(DataNode.DataType.List);
for (Sensor sensor : Sensor.getLocalSensors(db)) {
DataNode sensorNode = getDeviceNode(sensor);
sensorNode.set("data", ""+sensor.getDeviceData());
sensorsNode.add(sensorNode);
}
root.set("sensors", sensorsNode);
DataNode eventsNode = new DataNode(DataNode.DataType.List);
for (Event event : Event.getLocalEvents(db)) {
DataNode eventNode = getDeviceNode(event);
eventNode.set("data", ""+event.getDeviceData());
eventsNode.add(eventNode);
}
root.set("events", eventsNode);
}
private DataNode getDeviceNode(HalAbstractDevice device) {
DataNode deviceNode = new DataNode(DataNode.DataType.Map);
deviceNode.set("id", device.getId());
deviceNode.set("name", device.getName());
deviceNode.set("x", device.getMapX());
deviceNode.set("y", device.getMapY());
return deviceNode;
}
} }