node-red/packages/node_modules/@node-red/editor-client/src/js/ui/touch/radialMenu.js

152 lines
4.8 KiB
JavaScript

/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.touch = RED.touch||{};
RED.touch.radialMenu = (function() {
var touchMenu = null;
var isActive = false;
var isOutside = false;
var activeOption = null;
function createRadial(obj,pos,options) {
isActive = true;
try {
touchMenu = d3.select("body").append("div").classed("red-ui-editor-radial-menu",true)
.on('touchstart',function() {
hide();
d3.event.preventDefault();
});
var menu = touchMenu.append("div")
.style({
top: (pos[1]-80)+"px",
left:(pos[0]-80)+"px",
});
var menuOpts = [];
var createMenuOpt = function(x,y,opt) {
opt.el = menu.append("div").classed("red-ui-editor-radial-menu-opt",true)
.style({
top: (y+80-25)+"px",
left:(x+80-25)+"px"
})
.classed("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled)
opt.el.html(opt.name);
opt.x = x;
opt.y = y;
menuOpts.push(opt);
opt.el.on('touchstart',function() {
opt.el.classed("red-ui-editor-radial-menu-opt-active",true)
d3.event.preventDefault();
d3.event.stopPropagation();
});
opt.el.on('touchend',function() {
hide();
opt.onselect();
d3.event.preventDefault();
d3.event.stopPropagation();
});
}
var n = options.length;
var dang = Math.max(Math.PI/(n-1),Math.PI/4);
var ang = Math.PI;
for (var i=0;i<n;i++) {
var x = Math.floor(Math.cos(ang)*80);
var y = Math.floor(Math.sin(ang)*80);
if (options[i].name) {
createMenuOpt(x,y,options[i]);
}
ang += dang;
}
var hide = function() {
isActive = false;
activeOption = null;
touchMenu.remove();
touchMenu = null;
}
obj.on('touchend.radial',function() {
obj.on('touchend.radial',null);
obj.on('touchmenu.radial',null);
if (activeOption) {
try {
activeOption.onselect();
} catch(err) {
RED._debug(err);
}
hide();
} else if (isOutside) {
hide();
}
});
obj.on('touchmove.radial',function() {
try {
var touch0 = d3.event.touches.item(0);
var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]];
for (var i=0;i<menuOpts.length;i++) {
var opt = menuOpts[i];
if (!opt.disabled) {
if (p[0]>opt.x-30 && p[0]<opt.x+30 && p[1]>opt.y-30 && p[1]<opt.y+30) {
if (opt !== activeOption) {
opt.el.classed("selected",true);
activeOption = opt;
}
} else {
if (opt === activeOption) {
activeOption = null;
}
opt.el.classed("selected",false);
}
}
}
if (!activeOption) {
var d = Math.abs((p[0]*p[0])+(p[1]*p[1]));
isOutside = (d > 80*80);
}
} catch(err) {
RED._debug(err);
}
});
} catch(err) {
RED._debug(err);
}
}
return {
show: createRadial,
active: function() {
return isActive;
}
}
})();