Graphic EQ controls; focus/click bugs.
This commit is contained in:
@@ -324,6 +324,7 @@ void Lv2Pedalboard::PrepareMidiMap(const PedalboardItem &pedalboardItem)
|
|||||||
mapping.midiBinding = binding;
|
mapping.midiBinding = binding;
|
||||||
mapping.instanceId = pedalboardItem.instanceId();
|
mapping.instanceId = pedalboardItem.instanceId();
|
||||||
|
|
||||||
|
|
||||||
if (pPortInfo->mod_momentaryOffByDefault() || pPortInfo->mod_momentaryOnByDefault())
|
if (pPortInfo->mod_momentaryOffByDefault() || pPortInfo->mod_momentaryOnByDefault())
|
||||||
{
|
{
|
||||||
mapping.mappingType = MidiControlType::MomentarySwitch;
|
mapping.mappingType = MidiControlType::MomentarySwitch;
|
||||||
|
|||||||
@@ -67,6 +67,8 @@
|
|||||||
|
|
||||||
#define PIPEDAL_UI__ledColor PIPEDAL_UI_PREFIX "ledColor"
|
#define PIPEDAL_UI__ledColor PIPEDAL_UI_PREFIX "ledColor"
|
||||||
|
|
||||||
|
#define PIPEDAL_UI__graphicEq PIPEDAL_UI_PREFIX "graphicEq"
|
||||||
|
|
||||||
|
|
||||||
namespace pipedal {
|
namespace pipedal {
|
||||||
|
|
||||||
|
|||||||
@@ -159,6 +159,7 @@ void PluginHost::LilvUris::Initialize(LilvWorld *pWorld)
|
|||||||
pipedalUI__yBottom = lilv_new_uri(pWorld, PIPEDAL_UI__yBottom);
|
pipedalUI__yBottom = lilv_new_uri(pWorld, PIPEDAL_UI__yBottom);
|
||||||
pipedalUI__xLog = lilv_new_uri(pWorld, PIPEDAL_UI__xLog);
|
pipedalUI__xLog = lilv_new_uri(pWorld, PIPEDAL_UI__xLog);
|
||||||
pipedalUI__width = lilv_new_uri(pWorld, PIPEDAL_UI__width);
|
pipedalUI__width = lilv_new_uri(pWorld, PIPEDAL_UI__width);
|
||||||
|
pipedalUI__graphicEq = lilv_new_uri(pWorld,PIPEDAL_UI__graphicEq);
|
||||||
|
|
||||||
ui__portNotification = lilv_new_uri(pWorld, LV2_UI__portNotification);
|
ui__portNotification = lilv_new_uri(pWorld, LV2_UI__portNotification);
|
||||||
ui__plugin = lilv_new_uri(pWorld, LV2_UI__plugin);
|
ui__plugin = lilv_new_uri(pWorld, LV2_UI__plugin);
|
||||||
@@ -1005,8 +1006,12 @@ Lv2PortInfo::Lv2PortInfo(PluginHost *host, const LilvPlugin *plugin, const LilvP
|
|||||||
this->integer_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->integer_property_uri);
|
this->integer_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->integer_property_uri);
|
||||||
this->mod_momentaryOffByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOffByDefault);
|
this->mod_momentaryOffByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOffByDefault);
|
||||||
this->mod_momentaryOnByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOnByDefault);
|
this->mod_momentaryOnByDefault_ = lilv_port_has_property(plugin, pPort, host->lilvUris->mod__preferMomentaryOnByDefault);
|
||||||
|
this->pipedal_graphicEq_ = lilv_port_has_property(plugin, pPort, host->lilvUris->pipedalUI__graphicEq);
|
||||||
|
|
||||||
|
|
||||||
this->enumeration_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->enumeration_property_uri);
|
this->enumeration_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->enumeration_property_uri);
|
||||||
|
|
||||||
|
|
||||||
this->toggled_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__toggled);
|
this->toggled_property_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__toggled);
|
||||||
this->not_on_gui_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__not_on_gui_property_uri);
|
this->not_on_gui_ = lilv_port_has_property(plugin, pPort, host->lilvUris->portprops__not_on_gui_property_uri);
|
||||||
this->connection_optional_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__connectionOptional);
|
this->connection_optional_ = lilv_port_has_property(plugin, pPort, host->lilvUris->core__connectionOptional);
|
||||||
@@ -1729,6 +1734,7 @@ json_map::storage_type<Lv2PortInfo> Lv2PortInfo::jmap{
|
|||||||
MAP_REF(Lv2PortInfo, toggled_property),
|
MAP_REF(Lv2PortInfo, toggled_property),
|
||||||
MAP_REF(Lv2PortInfo, mod_momentaryOffByDefault),
|
MAP_REF(Lv2PortInfo, mod_momentaryOffByDefault),
|
||||||
MAP_REF(Lv2PortInfo, mod_momentaryOnByDefault),
|
MAP_REF(Lv2PortInfo, mod_momentaryOnByDefault),
|
||||||
|
MAP_REF(Lv2PortInfo, pipedal_graphicEq),
|
||||||
MAP_REF(Lv2PortInfo, not_on_gui),
|
MAP_REF(Lv2PortInfo, not_on_gui),
|
||||||
MAP_REF(Lv2PortInfo, buffer_type),
|
MAP_REF(Lv2PortInfo, buffer_type),
|
||||||
MAP_REF(Lv2PortInfo, port_group),
|
MAP_REF(Lv2PortInfo, port_group),
|
||||||
@@ -1796,6 +1802,7 @@ json_map::storage_type<Lv2PluginUiPort> Lv2PluginUiPort::jmap{{
|
|||||||
|
|
||||||
MAP_REF(Lv2PluginUiPort, mod_momentaryOffByDefault),
|
MAP_REF(Lv2PluginUiPort, mod_momentaryOffByDefault),
|
||||||
MAP_REF(Lv2PluginUiPort, mod_momentaryOnByDefault),
|
MAP_REF(Lv2PluginUiPort, mod_momentaryOnByDefault),
|
||||||
|
MAP_REF(Lv2PluginUiPort, pipedal_graphicEq),
|
||||||
MAP_REF(Lv2PluginUiPort, enumeration_property),
|
MAP_REF(Lv2PluginUiPort, enumeration_property),
|
||||||
MAP_REF(Lv2PluginUiPort, not_on_gui),
|
MAP_REF(Lv2PluginUiPort, not_on_gui),
|
||||||
MAP_REF(Lv2PluginUiPort, toggled_property),
|
MAP_REF(Lv2PluginUiPort, toggled_property),
|
||||||
|
|||||||
@@ -221,6 +221,7 @@ namespace pipedal
|
|||||||
|
|
||||||
bool mod_momentaryOffByDefault_ = false;
|
bool mod_momentaryOffByDefault_ = false;
|
||||||
bool mod_momentaryOnByDefault_ = false;
|
bool mod_momentaryOnByDefault_ = false;
|
||||||
|
bool pipedal_graphicEq_ = false;
|
||||||
|
|
||||||
bool not_on_gui_ = false;
|
bool not_on_gui_ = false;
|
||||||
std::string buffer_type_;
|
std::string buffer_type_;
|
||||||
@@ -294,6 +295,7 @@ namespace pipedal
|
|||||||
LV2_PROPERTY_GETSET_SCALAR(integer_property);
|
LV2_PROPERTY_GETSET_SCALAR(integer_property);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOffByDefault);
|
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOffByDefault);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOnByDefault);
|
LV2_PROPERTY_GETSET_SCALAR(mod_momentaryOnByDefault);
|
||||||
|
LV2_PROPERTY_GETSET_SCALAR(pipedal_graphicEq);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(enumeration_property);
|
LV2_PROPERTY_GETSET_SCALAR(enumeration_property);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(toggled_property);
|
LV2_PROPERTY_GETSET_SCALAR(toggled_property);
|
||||||
LV2_PROPERTY_GETSET_SCALAR(not_on_gui);
|
LV2_PROPERTY_GETSET_SCALAR(not_on_gui);
|
||||||
@@ -513,6 +515,7 @@ namespace pipedal
|
|||||||
integer_property_(pPort->integer_property()),
|
integer_property_(pPort->integer_property()),
|
||||||
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
|
mod_momentaryOffByDefault_(pPort->mod_momentaryOffByDefault()),
|
||||||
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
|
mod_momentaryOnByDefault_(pPort->mod_momentaryOnByDefault()),
|
||||||
|
pipedal_graphicEq_(pPort->pipedal_graphicEq()),
|
||||||
|
|
||||||
enumeration_property_(pPort->enumeration_property()),
|
enumeration_property_(pPort->enumeration_property()),
|
||||||
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
|
toggled_property_(pPort->toggled_property()), not_on_gui_(pPort->not_on_gui()), scale_points_(pPort->scale_points()),
|
||||||
@@ -558,6 +561,8 @@ namespace pipedal
|
|||||||
|
|
||||||
bool mod_momentaryOffByDefault_ = false;
|
bool mod_momentaryOffByDefault_ = false;
|
||||||
bool mod_momentaryOnByDefault_ = false;
|
bool mod_momentaryOnByDefault_ = false;
|
||||||
|
bool pipedal_graphicEq_ = false;
|
||||||
|
|
||||||
bool enumeration_property_ = false;
|
bool enumeration_property_ = false;
|
||||||
bool not_on_gui_ = false;
|
bool not_on_gui_ = false;
|
||||||
bool toggled_property_ = false;
|
bool toggled_property_ = false;
|
||||||
@@ -728,6 +733,7 @@ namespace pipedal
|
|||||||
AutoLilvNode pipedalUI__yTop;
|
AutoLilvNode pipedalUI__yTop;
|
||||||
AutoLilvNode pipedalUI__yBottom;
|
AutoLilvNode pipedalUI__yBottom;
|
||||||
AutoLilvNode pipedalUI__width;
|
AutoLilvNode pipedalUI__width;
|
||||||
|
AutoLilvNode pipedalUI__graphicEq;
|
||||||
|
|
||||||
|
|
||||||
AutoLilvNode pipedalUI__outputPorts;
|
AutoLilvNode pipedalUI__outputPorts;
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Robin E. R. Davies
|
||||||
|
* All rights reserved.
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import SvgPathBuilder from "./SvgPathBuilder";
|
||||||
|
|
||||||
|
export interface GraphicEqCtlProps {
|
||||||
|
position: number;
|
||||||
|
imgRef: React.Ref<SVGSVGElement> | undefined;
|
||||||
|
onTouchStart: React.TouchEventHandler<SVGSVGElement> | undefined;
|
||||||
|
onTouchMove: React.TouchEventHandler<SVGSVGElement> | undefined;
|
||||||
|
onPointerDown: React.PointerEventHandler<SVGSVGElement> | undefined;
|
||||||
|
onPointerUp: React.PointerEventHandler<SVGSVGElement> | undefined;
|
||||||
|
onPointerMoveCapture: React.PointerEventHandler<SVGSVGElement> | undefined;
|
||||||
|
onDrag: React.DragEventHandler<SVGSVGElement> | undefined;
|
||||||
|
dialColor: string;
|
||||||
|
opacity: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
const STROKE_HEIGHT=8.0;
|
||||||
|
|
||||||
|
function MakeGraphicEqPath(value: number)
|
||||||
|
{
|
||||||
|
|
||||||
|
let x0 = 6;
|
||||||
|
let xN = 64-x0;
|
||||||
|
let xC0 = (64-STROKE_HEIGHT)/2;
|
||||||
|
let xC1 = xC0+STROKE_HEIGHT;
|
||||||
|
|
||||||
|
let h = 64-STROKE_HEIGHT*2.5;
|
||||||
|
|
||||||
|
let y0 = 0;
|
||||||
|
let y1 = h-h*value;;
|
||||||
|
let y2 = y1 + STROKE_HEIGHT;
|
||||||
|
let y3 = y2 + STROKE_HEIGHT/2;
|
||||||
|
let y4 = y3 + STROKE_HEIGHT;
|
||||||
|
let y5 = 64;
|
||||||
|
|
||||||
|
|
||||||
|
let s = new SvgPathBuilder();
|
||||||
|
s.moveTo(x0,y1)
|
||||||
|
.lineTo(xC0,y1)
|
||||||
|
.lineTo(xC0,y0)
|
||||||
|
.lineTo(xC1,y0)
|
||||||
|
.lineTo(xC1,y1)
|
||||||
|
.lineTo(xN,y1)
|
||||||
|
.lineTo(xN,y2)
|
||||||
|
.lineTo(x0,y2)
|
||||||
|
.closePath()
|
||||||
|
|
||||||
|
.moveTo(x0,y3)
|
||||||
|
.lineTo(x0,y4)
|
||||||
|
.lineTo(xC0,y4)
|
||||||
|
.lineTo(xC0,y5)
|
||||||
|
.lineTo(xC1,y5)
|
||||||
|
.lineTo(xC1,y4)
|
||||||
|
.lineTo(xN,y4)
|
||||||
|
.lineTo(xN,y3)
|
||||||
|
.lineTo(x0,y3)
|
||||||
|
.closePath();
|
||||||
|
return s.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
export function UpdateGraphicEqPath(el: SVGSVGElement, value: number) {
|
||||||
|
if (!el) return;
|
||||||
|
let p = MakeGraphicEqPath(value);
|
||||||
|
let pathEl = el.getElementById("myPath");
|
||||||
|
pathEl?.setAttribute("d",p);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function GraphicEqCtl(props: GraphicEqCtlProps) {
|
||||||
|
return (
|
||||||
|
<svg width="64px" height="64px"
|
||||||
|
ref={props.imgRef}
|
||||||
|
viewBox="0 0 64 64"
|
||||||
|
style={{
|
||||||
|
overscrollBehavior: "none",
|
||||||
|
touchAction: "none",
|
||||||
|
width: 36, height: 42, opacity: props.opacity
|
||||||
|
}}
|
||||||
|
onTouchStart={props.onTouchStart}
|
||||||
|
onTouchMove={props.onTouchMove}
|
||||||
|
onPointerDown={props.onPointerDown}
|
||||||
|
onPointerUp={props.onPointerUp}
|
||||||
|
onPointerMoveCapture={props.onPointerMoveCapture}
|
||||||
|
onDrag={props.onDrag}
|
||||||
|
fill={props.dialColor}
|
||||||
|
>
|
||||||
|
<path id="myPath" d={MakeGraphicEqPath(props.position)} />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -453,6 +453,7 @@ export enum ControlType {
|
|||||||
Trigger,
|
Trigger,
|
||||||
Momentary,
|
Momentary,
|
||||||
MomentaryOnByDefault,
|
MomentaryOnByDefault,
|
||||||
|
GraphicEq,
|
||||||
|
|
||||||
Tuner,
|
Tuner,
|
||||||
Vu,
|
Vu,
|
||||||
@@ -497,6 +498,7 @@ deserialize(input: any): UiControl {
|
|||||||
this.integer_property = input.integer_property;
|
this.integer_property = input.integer_property;
|
||||||
this.mod_momentaryOffByDefault = input.mod_momentaryOffByDefault;
|
this.mod_momentaryOffByDefault = input.mod_momentaryOffByDefault;
|
||||||
this.mod_momentaryOnByDefault = input.mod_momentaryOnByDefault;
|
this.mod_momentaryOnByDefault = input.mod_momentaryOnByDefault;
|
||||||
|
this.pipedal_graphicEq = input.pipedal_graphicEq;
|
||||||
this.enumeration_property = input.enumeration_property;
|
this.enumeration_property = input.enumeration_property;
|
||||||
this.toggled_property = input.toggled_property;
|
this.toggled_property = input.toggled_property;
|
||||||
this.trigger_property = input.trigger_property;
|
this.trigger_property = input.trigger_property;
|
||||||
@@ -548,7 +550,11 @@ deserialize(input: any): UiControl {
|
|||||||
}
|
}
|
||||||
if (this.is_input)
|
if (this.is_input)
|
||||||
{
|
{
|
||||||
if (this.mod_momentaryOnByDefault) {
|
if (this.pipedal_graphicEq)
|
||||||
|
{
|
||||||
|
this.controlType = ControlType.GraphicEq;
|
||||||
|
}
|
||||||
|
else if (this.mod_momentaryOnByDefault) {
|
||||||
this.controlType = ControlType.MomentaryOnByDefault;
|
this.controlType = ControlType.MomentaryOnByDefault;
|
||||||
} else if (this.mod_momentaryOffByDefault) {
|
} else if (this.mod_momentaryOffByDefault) {
|
||||||
this.controlType = ControlType.Momentary;
|
this.controlType = ControlType.Momentary;
|
||||||
@@ -604,6 +610,7 @@ deserialize(input: any): UiControl {
|
|||||||
integer_property: boolean = false;
|
integer_property: boolean = false;
|
||||||
mod_momentaryOffByDefault: boolean = false;
|
mod_momentaryOffByDefault: boolean = false;
|
||||||
mod_momentaryOnByDefault: boolean = false;
|
mod_momentaryOnByDefault: boolean = false;
|
||||||
|
pipedal_graphicEq: boolean = false;
|
||||||
enumeration_property: boolean = false;
|
enumeration_property: boolean = false;
|
||||||
trigger_property: boolean = false;
|
trigger_property: boolean = false;
|
||||||
not_on_gui: boolean = false;
|
not_on_gui: boolean = false;
|
||||||
@@ -647,6 +654,9 @@ deserialize(input: any): UiControl {
|
|||||||
isAbToggle(): boolean {
|
isAbToggle(): boolean {
|
||||||
return this.controlType === ControlType.ABSwitch;
|
return this.controlType === ControlType.ABSwitch;
|
||||||
}
|
}
|
||||||
|
isGraphicEq() : boolean {
|
||||||
|
return this.controlType === ControlType.GraphicEq;
|
||||||
|
}
|
||||||
isSelect(): boolean {
|
isSelect(): boolean {
|
||||||
return this.controlType === ControlType.Select;
|
return this.controlType === ControlType.Select;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import ControlTooltip from './ControlTooltip';
|
|||||||
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
import PlayArrowIcon from '@mui/icons-material/PlayArrow';
|
||||||
import StopIcon from '@mui/icons-material/Stop';
|
import StopIcon from '@mui/icons-material/Stop';
|
||||||
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
|
import FiberManualRecordIcon from '@mui/icons-material/FiberManualRecord';
|
||||||
|
import GraphicEqCtl, { UpdateGraphicEqPath } from './GraphicEqCtl';
|
||||||
|
|
||||||
const MIN_ANGLE = -135;
|
const MIN_ANGLE = -135;
|
||||||
const MAX_ANGLE = 135;
|
const MAX_ANGLE = 135;
|
||||||
@@ -59,6 +60,21 @@ const ULTRA_FINE_RANGE_SCALE = RANGE_SCALE * 50; // 12000 pixels to move from 0
|
|||||||
export const StandardItemSize = { width: 80, height: 140 }
|
export const StandardItemSize = { width: 80, height: 140 }
|
||||||
|
|
||||||
|
|
||||||
|
function preventNextClickAfterDrag() {
|
||||||
|
// the broswer fires a click event when the pointer goes up
|
||||||
|
// on ANY element under the mouse. Prevent this click event
|
||||||
|
// (and any other click event) from happening for 100ms
|
||||||
|
// after the drag stops.
|
||||||
|
let clickHandler = (e: MouseEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
document.addEventListener('click',clickHandler,true);
|
||||||
|
window.setTimeout(() => {
|
||||||
|
document.removeEventListener('click',clickHandler,true);
|
||||||
|
},100);
|
||||||
|
}
|
||||||
|
|
||||||
function androidEmoji(text: string) {
|
function androidEmoji(text: string) {
|
||||||
// android chrome doesn't support these characters properly.
|
// android chrome doesn't support these characters properly.
|
||||||
if (text === "⏹") {
|
if (text === "⏹") {
|
||||||
@@ -67,9 +83,8 @@ function androidEmoji(text: string) {
|
|||||||
if (text === "⏺") {
|
if (text === "⏺") {
|
||||||
return (<FiberManualRecordIcon fontSize={"medium"} />)
|
return (<FiberManualRecordIcon fontSize={"medium"} />)
|
||||||
}
|
}
|
||||||
if (text === "⏵")
|
if (text === "⏵") {
|
||||||
{
|
return (<PlayArrowIcon fontSize={"medium"} />);
|
||||||
return (<PlayArrowIcon fontSize={"medium"}/>);
|
|
||||||
}
|
}
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
@@ -129,6 +144,7 @@ export interface PluginControlProps extends WithStyles<typeof pluginControlStyle
|
|||||||
}
|
}
|
||||||
type PluginControlState = {
|
type PluginControlState = {
|
||||||
error: boolean;
|
error: boolean;
|
||||||
|
editFocused: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const PluginControl =
|
const PluginControl =
|
||||||
@@ -137,6 +153,7 @@ const PluginControl =
|
|||||||
|
|
||||||
frameRef: React.RefObject<HTMLDivElement | null>;
|
frameRef: React.RefObject<HTMLDivElement | null>;
|
||||||
imgRef: React.RefObject<SVGSVGElement | null>;
|
imgRef: React.RefObject<SVGSVGElement | null>;
|
||||||
|
graphicEqControlRef: React.RefObject<SVGSVGElement | null>;
|
||||||
inputRef: React.RefObject<HTMLInputElement | null>;
|
inputRef: React.RefObject<HTMLInputElement | null>;
|
||||||
selectRef: React.RefObject<HTMLSelectElement | null>;
|
selectRef: React.RefObject<HTMLSelectElement | null>;
|
||||||
|
|
||||||
@@ -148,10 +165,12 @@ const PluginControl =
|
|||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
error: false
|
error: false,
|
||||||
|
editFocused: false
|
||||||
};
|
};
|
||||||
this.model = PiPedalModelFactory.getInstance();
|
this.model = PiPedalModelFactory.getInstance();
|
||||||
this.imgRef = React.createRef();
|
this.imgRef = React.createRef();
|
||||||
|
this.graphicEqControlRef = React.createRef();
|
||||||
this.inputRef = React.createRef();
|
this.inputRef = React.createRef();
|
||||||
this.selectRef = React.createRef();
|
this.selectRef = React.createRef();
|
||||||
this.displayValueRef = React.createRef();
|
this.displayValueRef = React.createRef();
|
||||||
@@ -195,16 +214,19 @@ const PluginControl =
|
|||||||
inputChanged: boolean = false;
|
inputChanged: boolean = false;
|
||||||
|
|
||||||
onInputLostFocus(event: any): void {
|
onInputLostFocus(event: any): void {
|
||||||
|
this.setState({editFocused: false});
|
||||||
if (this.inputChanged) // validation requried?
|
if (this.inputChanged) // validation requried?
|
||||||
{
|
{
|
||||||
this.inputChanged = false;
|
this.inputChanged = false;
|
||||||
this.validateInput(event, true);
|
this.validateInput(event, true);
|
||||||
|
|
||||||
}
|
}
|
||||||
this.displayValueRef.current!.style.display = "block";
|
|
||||||
|
//this.displayValueRef.current!.style.display = "block";
|
||||||
}
|
}
|
||||||
onInputFocus(event: SyntheticEvent): void {
|
onInputFocus(event: SyntheticEvent): void {
|
||||||
this.displayValueRef.current!.style.display = "none";
|
//this.displayValueRef.current!.style.display = "none";
|
||||||
|
this.setState({editFocused: true});
|
||||||
if (Utility.hasIMEKeyboard()) {
|
if (Utility.hasIMEKeyboard()) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
@@ -273,6 +295,7 @@ const PluginControl =
|
|||||||
|
|
||||||
onDrag(e: SyntheticEvent) {
|
onDrag(e: SyntheticEvent) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
isValidPointer(e: PointerEvent<SVGSVGElement>): boolean {
|
isValidPointer(e: PointerEvent<SVGSVGElement>): boolean {
|
||||||
@@ -333,9 +356,19 @@ const PluginControl =
|
|||||||
if (!this.mouseDown && this.isValidPointer(e)) {
|
if (!this.mouseDown && this.isValidPointer(e)) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
if (document.activeElement)
|
||||||
|
{
|
||||||
|
let e = document.activeElement as any;
|
||||||
|
if (e.blur)
|
||||||
|
{
|
||||||
|
e.blur();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (this.isTouchDevice()) {
|
if (this.isTouchDevice()) {
|
||||||
if (this.props.uiControl?.isDial() ?? false) {
|
if (this.props.uiControl
|
||||||
|
&& (this.props.uiControl.isDial() || this.props.uiControl.isGraphicEq())
|
||||||
|
) {
|
||||||
this.isTap = false;
|
this.isTap = false;
|
||||||
this.showZoomedControl();
|
this.showZoomedControl();
|
||||||
return;
|
return;
|
||||||
@@ -390,7 +423,9 @@ const PluginControl =
|
|||||||
|
|
||||||
onPointerLostCapture(e: PointerEvent<SVGSVGElement>) {
|
onPointerLostCapture(e: PointerEvent<SVGSVGElement>) {
|
||||||
if (this.isCapturedPointer(e)) {
|
if (this.isCapturedPointer(e)) {
|
||||||
|
if (this.pointersDown !== 0) {
|
||||||
--this.pointersDown;
|
--this.pointersDown;
|
||||||
|
}
|
||||||
this.isTap = false;
|
this.isTap = false;
|
||||||
|
|
||||||
|
|
||||||
@@ -438,7 +473,7 @@ const PluginControl =
|
|||||||
onPointerDoubleTap() {
|
onPointerDoubleTap() {
|
||||||
let uiControl = this.props.uiControl;
|
let uiControl = this.props.uiControl;
|
||||||
if (uiControl) {
|
if (uiControl) {
|
||||||
if (uiControl.isDial()) {
|
if (uiControl.isDial() || uiControl.isGraphicEq()) {
|
||||||
this.resetToDefaultValue(uiControl);
|
this.resetToDefaultValue(uiControl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -457,10 +492,14 @@ const PluginControl =
|
|||||||
onPointerUp(e: PointerEvent<SVGSVGElement>) {
|
onPointerUp(e: PointerEvent<SVGSVGElement>) {
|
||||||
|
|
||||||
if (this.isCapturedPointer(e)) {
|
if (this.isCapturedPointer(e)) {
|
||||||
|
if (this.pointersDown !== 0)
|
||||||
|
{
|
||||||
--this.pointersDown;
|
--this.pointersDown;
|
||||||
|
}
|
||||||
|
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
let dRange = this.updateRange(e)
|
let dRange = this.updateRange(e)
|
||||||
this.previewRange(dRange, true);
|
this.previewRange(dRange, true);
|
||||||
|
|
||||||
@@ -471,9 +510,15 @@ const PluginControl =
|
|||||||
this.onPointerTap();
|
this.onPointerTap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// prevent click from firing on other elements
|
||||||
|
// when the pointer goes up0.
|
||||||
|
preventNextClickAfterDrag();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
if (this.pointersDown !== 0)
|
||||||
|
{
|
||||||
--this.pointersDown;
|
--this.pointersDown;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -527,10 +572,10 @@ const PluginControl =
|
|||||||
if (uiControl) {
|
if (uiControl) {
|
||||||
switch (buttonStyle) {
|
switch (buttonStyle) {
|
||||||
case ButtonStyle.Momentary:
|
case ButtonStyle.Momentary:
|
||||||
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.max_value);
|
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol, uiControl.max_value);
|
||||||
break;
|
break;
|
||||||
case ButtonStyle.MomentaryOnByDefault:
|
case ButtonStyle.MomentaryOnByDefault:
|
||||||
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.min_value);
|
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol, uiControl.min_value);
|
||||||
break;
|
break;
|
||||||
case ButtonStyle.Trigger:
|
case ButtonStyle.Trigger:
|
||||||
{
|
{
|
||||||
@@ -550,10 +595,10 @@ const PluginControl =
|
|||||||
if (uiControl) {
|
if (uiControl) {
|
||||||
switch (buttonStyle) {
|
switch (buttonStyle) {
|
||||||
case ButtonStyle.Momentary:
|
case ButtonStyle.Momentary:
|
||||||
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.min_value);
|
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol, uiControl.min_value);
|
||||||
break;
|
break;
|
||||||
case ButtonStyle.MomentaryOnByDefault:
|
case ButtonStyle.MomentaryOnByDefault:
|
||||||
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol,uiControl.max_value);
|
this.model.setPedalboardControl(this.props.instanceId, uiControl.symbol, uiControl.max_value);
|
||||||
break;
|
break;
|
||||||
case ButtonStyle.Trigger:
|
case ButtonStyle.Trigger:
|
||||||
{
|
{
|
||||||
@@ -567,16 +612,24 @@ const PluginControl =
|
|||||||
let range = this.valueToRange(value);
|
let range = this.valueToRange(value);
|
||||||
value = this.rangeToValue(range);
|
value = this.rangeToValue(range);
|
||||||
|
|
||||||
|
let imgElement = this.imgRef.current
|
||||||
|
if (imgElement) {
|
||||||
|
if (this.props.uiControl?.isGraphicEq()) {
|
||||||
|
let imgElement = this.imgRef.current
|
||||||
|
if (imgElement) {
|
||||||
|
UpdateGraphicEqPath(imgElement, range);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
let transform = this.rangeToRotationTransform(range);
|
let transform = this.rangeToRotationTransform(range);
|
||||||
if (this.mouseDown && !commitValue) {
|
if (this.mouseDown && !commitValue) {
|
||||||
transform += " scale(1.5, 1.5)";
|
transform += " scale(1.5, 1.5)";
|
||||||
}
|
}
|
||||||
let imgElement = this.imgRef.current
|
|
||||||
if (imgElement) {
|
|
||||||
if (imgElement.style) {
|
if (imgElement.style) {
|
||||||
imgElement.style.transform = transform;
|
imgElement.style.transform = transform;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (commitValue) {
|
if (commitValue) {
|
||||||
this.props.onChange(value);
|
this.props.onChange(value);
|
||||||
}
|
}
|
||||||
@@ -594,12 +647,20 @@ const PluginControl =
|
|||||||
// apply value quantization and clipping.
|
// apply value quantization and clipping.
|
||||||
range = this.valueToRange(value);
|
range = this.valueToRange(value);
|
||||||
|
|
||||||
|
if (this.props.uiControl?.isGraphicEq()) {
|
||||||
|
let imgElement = this.imgRef.current
|
||||||
|
if (imgElement) {
|
||||||
|
UpdateGraphicEqPath(imgElement, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
let imgElement = this.imgRef.current
|
let imgElement = this.imgRef.current
|
||||||
if (imgElement) {
|
if (imgElement) {
|
||||||
if (imgElement.style) {
|
if (imgElement.style) {
|
||||||
imgElement.style.transform = this.rangeToRotationTransform(range);
|
imgElement.style.transform = this.rangeToRotationTransform(range);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let inputElement = this.inputRef.current;
|
let inputElement = this.inputRef.current;
|
||||||
if (inputElement) {
|
if (inputElement) {
|
||||||
let v = this.props.uiControl?.formatShortValue(value) ?? "";
|
let v = this.props.uiControl?.formatShortValue(value) ?? "";
|
||||||
@@ -779,6 +840,16 @@ const PluginControl =
|
|||||||
return "rotate(" + angle + "deg)";
|
return "rotate(" + angle + "deg)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEqPosition(): number {
|
||||||
|
let range = 0;
|
||||||
|
let uiControl = this.props.uiControl;
|
||||||
|
if (uiControl) {
|
||||||
|
let value = this.props.value;
|
||||||
|
range = this.valueToRange(value);
|
||||||
|
}
|
||||||
|
return range;
|
||||||
|
|
||||||
|
}
|
||||||
getRotationTransform(): string {
|
getRotationTransform(): string {
|
||||||
let range = 0;
|
let range = 0;
|
||||||
let uiControl = this.props.uiControl;
|
let uiControl = this.props.uiControl;
|
||||||
@@ -812,6 +883,8 @@ const PluginControl =
|
|||||||
|
|
||||||
let isButton = false;
|
let isButton = false;
|
||||||
let buttonStyle: ButtonStyle = ButtonStyle.None;
|
let buttonStyle: ButtonStyle = ButtonStyle.None;
|
||||||
|
let isGraphicEq = control.isGraphicEq();
|
||||||
|
|
||||||
if (control.isTrigger()) {
|
if (control.isTrigger()) {
|
||||||
isButton = true;
|
isButton = true;
|
||||||
buttonStyle = ButtonStyle.Trigger;
|
buttonStyle = ButtonStyle.Trigger;
|
||||||
@@ -833,6 +906,9 @@ const PluginControl =
|
|||||||
if (isButton) {
|
if (isButton) {
|
||||||
item_width = undefined;
|
item_width = undefined;
|
||||||
}
|
}
|
||||||
|
if (isGraphicEq) {
|
||||||
|
item_width = 58;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -869,8 +945,10 @@ const PluginControl =
|
|||||||
(evt) => { this.handleButtonMouseUp(buttonStyle); }
|
(evt) => { this.handleButtonMouseUp(buttonStyle); }
|
||||||
}
|
}
|
||||||
onTouchStart={
|
onTouchStart={
|
||||||
(evt) => { evt.preventDefault();
|
(evt) => {
|
||||||
this.handleButtonMouseDown(buttonStyle); }
|
evt.preventDefault();
|
||||||
|
this.handleButtonMouseDown(buttonStyle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onTouchEnd={
|
onTouchEnd={
|
||||||
(evt) => {
|
(evt) => {
|
||||||
@@ -903,8 +981,10 @@ const PluginControl =
|
|||||||
(evt) => { this.handleButtonMouseUp(buttonStyle); }
|
(evt) => { this.handleButtonMouseUp(buttonStyle); }
|
||||||
}
|
}
|
||||||
onTouchStart={
|
onTouchStart={
|
||||||
(evt) => { evt.preventDefault();
|
(evt) => {
|
||||||
this.handleButtonMouseDown(buttonStyle); }
|
evt.preventDefault();
|
||||||
|
this.handleButtonMouseDown(buttonStyle);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onTouchEnd={
|
onTouchEnd={
|
||||||
(evt) => {
|
(evt) => {
|
||||||
@@ -935,8 +1015,26 @@ const PluginControl =
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
: ((isSelect || isAbSwitch || isOnOffSwitch) ? (
|
: (isSelect || isAbSwitch || isOnOffSwitch) ? (
|
||||||
this.makeSelect(control, value)
|
this.makeSelect(control, value)
|
||||||
|
)
|
||||||
|
: (isGraphicEq) ? (
|
||||||
|
<div style={{ flex: "0 1 auto" }}>
|
||||||
|
<GraphicEqCtl
|
||||||
|
imgRef={this.imgRef}
|
||||||
|
position={this.getEqPosition()}
|
||||||
|
dialColor={dialColor}
|
||||||
|
opacity={DEFAULT_OPACITY}
|
||||||
|
|
||||||
|
onTouchStart={this.onTouchStart}
|
||||||
|
onTouchMove={this.onTouchMove}
|
||||||
|
onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp}
|
||||||
|
onPointerMoveCapture={this.onPointerMove}
|
||||||
|
onDrag={this.onDrag}
|
||||||
|
|
||||||
|
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ flex: "0 1 auto" }}>
|
<div style={{ flex: "0 1 auto" }}>
|
||||||
<DialIcon ref={this.imgRef}
|
<DialIcon ref={this.imgRef}
|
||||||
@@ -945,12 +1043,13 @@ const PluginControl =
|
|||||||
width: 36, height: 36, opacity: DEFAULT_OPACITY, transform: this.getRotationTransform()
|
width: 36, height: 36, opacity: DEFAULT_OPACITY, transform: this.getRotationTransform()
|
||||||
}}
|
}}
|
||||||
onTouchStart={this.onTouchStart} onTouchMove={this.onTouchMove}
|
onTouchStart={this.onTouchStart} onTouchMove={this.onTouchMove}
|
||||||
onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp} onPointerMoveCapture={this.onPointerMove} onDrag={this.onDrag}
|
onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp}
|
||||||
|
onPointerMoveCapture={this.onPointerMove}
|
||||||
|
onDrag={this.onDrag}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -969,6 +1068,8 @@ const PluginControl =
|
|||||||
defaultValue={control.formatShortValue(value)}
|
defaultValue={control.formatShortValue(value)}
|
||||||
error={this.state.error}
|
error={this.state.error}
|
||||||
inputProps={{
|
inputProps={{
|
||||||
|
min: this.props.uiControl?.min_value,
|
||||||
|
max: this.props.uiControl?.max_value,
|
||||||
'aria-label':
|
'aria-label':
|
||||||
control.symbol + " value",
|
control.symbol + " value",
|
||||||
style: { textAlign: "center", fontSize: FONT_SIZE },
|
style: { textAlign: "center", fontSize: FONT_SIZE },
|
||||||
@@ -978,7 +1079,10 @@ const PluginControl =
|
|||||||
onFocus={this.onInputFocus}
|
onFocus={this.onInputFocus}
|
||||||
|
|
||||||
onKeyPress={this.onInputKeyPress} />
|
onKeyPress={this.onInputKeyPress} />
|
||||||
<div className={classes.displayValue} ref={this.displayValueRef} onClick={(e) => { this.inputRef.current!.focus(); }} >
|
<div className={classes.displayValue}
|
||||||
|
ref={this.displayValueRef} onClick={(e) => { this.inputRef.current!.focus(); }}
|
||||||
|
style={{display: this.state.editFocused? "none": "block"}}
|
||||||
|
>
|
||||||
<Typography noWrap color="inherit" style={{ fontSize: "12.8px", paddingTop: 4, paddingBottom: 6 }}
|
<Typography noWrap color="inherit" style={{ fontSize: "12.8px", paddingTop: 4, paddingBottom: 6 }}
|
||||||
|
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user