13
0
livetrax/share/web_surfaces/builtin/mixer/toolkit/widgets/knob.js
2020-07-21 06:49:27 +02:00

213 lines
6.8 KiB
JavaScript

/*
* This file is part of Toolkit.
*
* Toolkit is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Toolkit is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU General
* Public License along with this program; if not, write to the
* Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
/**
* The <code>useraction</code> event is emitted when a widget gets modified by user interaction.
* The event is emitted for the option <code>value</code>.
*
* @event TK.Knob#useraction
*
* @param {string} name - The name of the option which was changed due to the users action
* @param {mixed} value - The new value of the option
*/
"use strict";
(function(w, TK){
var format_viewbox = TK.FORMAT("0 0 %d %d");
function dblclick() {
this.userset("value", this.options.reset);
/**
* Is fired when the knob receives a double click in order to reset to initial value.
*
* @event TK.Knob#doubleclick
*
* @param {number} value - The value of the widget.
*/
this.fire_event("doubleclick", this.options.value);
}
function module_range() {
return this.parent.circular;
}
/**
* TK.Knob is a {@link TK.Circular} inside of an SVG which can be
* modified both by dragging and scrolling utilizing {@link TK.DragValue}
* and {@link TK.ScrollValue}.
* It inherits all options of {@link TK.Circular} and {@link TK.DragValue}.
* The options listed below consist of options from the contained widgets,
* only showing the default values.
*
* @class TK.Knob
*
* @extends TK.Widget
*
* @param {Object} [options={ }] - An object containing initial options.
*
* @property {Object} [options.hand={width: 1, length: 12, margin: 24}]
* @property {Number} [options.margin=13]
* @property {Number} [options.thickness=6]
* @property {Number} [options.step=1]
* @property {Number} [options.shift_up=4]
* @property {Number} [options.shift_down=0.25]
* @property {Object} [options.dot={length: 6, margin: 13, width: 2}]
* @property {Object} [options.marker={thickness: 6, margin: 13}]
* @property {Object} [options.label={margin: 10, align: "outer", format: function(val){return val;}}]
* @property {Number} [options.basis=300] - Distance to drag between <code>min</code> and <code>max</code>.
*/
TK.Knob = TK.class({
_class: "Knob",
Extends: TK.Widget,
_options: Object.assign(Object.create(TK.Widget.prototype._options), TK.Circular.prototype._options,
TK.DragValue.prototype._options, {
size: "number",
reset: "number",
}),
options: Object.assign({}, TK.Circular.prototype.options, {
size: 100,
hand: {width: 1, length: 12, margin: 24},
margin: 13,
thickness: 6,
step: 1,
shift_up: 4,
shift_down: 0.25,
dot: {length: 6, margin: 13, width: 2},
marker: {thickness: 6, margin: 13},
label: {margin: 12, align: "outer", format: function(val){return val;}},
direction: "polar",
rotation: 45,
blind_angle: 20,
basis: 300,
}),
static_events: {
dblclick: dblclick,
},
initialize: function (options) {
TK.Widget.prototype.initialize.call(this, options);
options = this.options;
var E, S;
/**
* @member {HTMLDivElement} TK.Knob#element - The main DIV container.
* Has class <code>toolkit-knob</code>.
*/
if (!(E = this.element)) this.element = E = TK.element("div")
TK.add_class(E, "toolkit-knob");
/**
* @member {SVGImage} TK.Knob#svg - The main SVG image.
*/
this.svg = S = TK.make_svg("svg");
var co = TK.object_and(options, TK.Circular.prototype._options);
co = TK.object_sub(co, TK.Widget.prototype._options);
co.container = S;
/**
* @member {TK.Circular} TK.Knob#circular - The {@link TK.Circular} module.
*/
this.circular = new TK.Circular(co);
this.widgetize(E, true, true, true);
/**
* @member {TK.DragValue} TK.Knob#drag - Instance of {@link TK.DragValue} used for the
* interaction.
*/
this.drag = new TK.DragValue(this, {
node: S,
range: module_range,
direction: options.direction,
rotation: options.rotation,
blind_angle: options.blind_angle,
limit: true,
});
/**
* @member {TK.ScrollValue} TK.Knob#scroll - Instance of {@link TK.ScrollValue} used for the
* interaction.
*/
this.scroll = new TK.ScrollValue(this, {
node: S,
range: module_range,
limit: true,
});
E.appendChild(S);
this.set("base", options.base);
if (options.reset === void(0))
options.reset = options.value;
this.add_child(this.circular);
},
get_range: function() {
return this.circular;
},
destroy: function () {
this.drag.destroy();
this.scroll.destroy();
this.circular.destroy();
TK.Widget.prototype.destroy.call(this);
},
redraw: function() {
var I = this.invalid;
var O = this.options;
if (I.size) {
I.size = false;
this.svg.setAttribute("viewBox", format_viewbox(O.size, O.size));
}
TK.Widget.prototype.redraw.call(this);
},
/**
* This is an alias for {@link TK.Circular#add_label} of the internal
* circular instance.
*
* @method TK.Knob#add_label
*/
add_label: function(x) {
return this.circular.add_label(x);
},
/**
* This is an alias for {@link TK.Circular#remove_label} of the internal
* circular instance.
*
* @method TK.Knob#remove_label
*/
remove_label: function(x) {
this.circular.remove_label(x);
},
set: function(key, value) {
if (key === "base") {
if (value === false) value = this.options.min;
}
// TK.Circular does the snapping
if (!TK.Widget.prototype._options[key]) {
if (TK.Circular.prototype._options[key])
value = this.circular.set(key, value);
if (TK.DragValue.prototype._options[key])
this.drag.set(key, value);
}
return TK.Widget.prototype.set.call(this, key, value);
},
});
})(this, this.TK);