ModGUI Sidechain select
This commit is contained in:
+147
-123
@@ -24,17 +24,40 @@ import { withStyles } from "tss-react/mui";
|
||||
import { createStyles } from './WithStyles';
|
||||
import FullscreenIcon from '@mui/icons-material/Fullscreen';
|
||||
import IconButtonEx from './IconButtonEx';
|
||||
import { isDarkMode } from './DarkMode';
|
||||
import Backdrop from '@mui/material/Backdrop';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
|
||||
import Rect from './Rect';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
|
||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||
|
||||
const styles = (theme: Theme) => createStyles({
|
||||
pgraph: {
|
||||
pgraph: css({
|
||||
paddingBottom: 16
|
||||
}
|
||||
}),
|
||||
backdrop: css({
|
||||
zIndex: 1101,
|
||||
overflow: "clip",
|
||||
background: theme.palette.background.default,
|
||||
|
||||
}),
|
||||
noToolbar: css({
|
||||
display: "none"
|
||||
}),
|
||||
topToolBar: css({
|
||||
position: "absolute",
|
||||
zIndex: 1101,
|
||||
top: 0,
|
||||
display: "flex", flexFlow: "row nowrap", justifyContent: "start", columnGap: 8,
|
||||
}),
|
||||
rightToolbar: css({
|
||||
position: "absolute",
|
||||
zIndex: 1101,
|
||||
top: 24,
|
||||
display: "flex", flexFlow: "column nowrap", rowGap: 8
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
@@ -42,6 +65,7 @@ export interface AutoZoomProps extends WithStyles<typeof styles> {
|
||||
leftPad: number,
|
||||
rightPad: number,
|
||||
children?: React.ReactNode,
|
||||
toolbarChildren?: React.ReactNode[],
|
||||
contentReady: boolean,
|
||||
showZoomed: boolean,
|
||||
setShowZoomed: (value: boolean) => void;
|
||||
@@ -53,6 +77,15 @@ export interface AutoZoomState {
|
||||
}
|
||||
|
||||
|
||||
// non-react zoom state.
|
||||
class UnzoomedLayout {
|
||||
horizontalToolbar = false;
|
||||
effectiveClientRect: Rect = new Rect();
|
||||
showToolbar = false;
|
||||
zoom: number = 1;
|
||||
showZoomButton = false;
|
||||
contentRect: Rect = new Rect();
|
||||
}
|
||||
|
||||
const AutoZoom = withStyles(
|
||||
class extends ResizeResponsiveComponent<AutoZoomProps, AutoZoomState> {
|
||||
@@ -97,38 +130,43 @@ const AutoZoom = withStyles(
|
||||
if (this.normalRef) {
|
||||
this.updateZoom(this.normalRef);
|
||||
}
|
||||
if (this.maximizedRef) {
|
||||
this.updateMaximizedZoom();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resizeObserver: ResizeObserver | null = null;
|
||||
|
||||
|
||||
calculateZoomedClientRect(
|
||||
calculateUnzoomedLayout(
|
||||
clientRect: Rect,
|
||||
contentWidth: number,
|
||||
contentHeight: number,
|
||||
buttonPadding: number
|
||||
): Rect {
|
||||
): UnzoomedLayout {
|
||||
|
||||
let result = new UnzoomedLayout();
|
||||
|
||||
console.log("Zoom: " + clientRect.toString() + " content: " + contentWidth + "x" + contentHeight + " buttonPadding: " + buttonPadding);
|
||||
let rightButtonZoom = Math.min((clientRect.width - buttonPadding) / contentWidth, clientRect.height / contentHeight);
|
||||
let topButtonZoom = Math.min((clientRect.width - buttonPadding) / contentWidth, (clientRect.height - buttonPadding) / contentHeight);
|
||||
|
||||
let effectiveClientRect = clientRect.copy();
|
||||
if (rightButtonZoom > topButtonZoom) {
|
||||
result.horizontalToolbar = false;
|
||||
effectiveClientRect.width -= buttonPadding;
|
||||
} else {
|
||||
result.horizontalToolbar = true;
|
||||
effectiveClientRect.y += buttonPadding;
|
||||
effectiveClientRect.height -= buttonPadding;
|
||||
}
|
||||
result.effectiveClientRect = effectiveClientRect;
|
||||
|
||||
let zoom = Math.min(effectiveClientRect.width / contentWidth, effectiveClientRect.height / contentHeight);
|
||||
if (zoom > 1) {
|
||||
zoom = 1;
|
||||
}
|
||||
result.zoom = zoom;
|
||||
result.showZoomButton = zoom !== 1;
|
||||
result.showToolbar = result.showZoomButton || !!this.props.toolbarChildren;
|
||||
|
||||
let leftPad = (effectiveClientRect.width - contentWidth * zoom) / 2;
|
||||
if (leftPad < 0) {
|
||||
leftPad = 0;
|
||||
@@ -137,7 +175,8 @@ const AutoZoom = withStyles(
|
||||
if (topPad < 0) {
|
||||
topPad = 0;
|
||||
}
|
||||
return new Rect(effectiveClientRect.x + leftPad, effectiveClientRect.y + topPad, contentWidth * zoom, contentHeight * zoom);
|
||||
result.contentRect = new Rect(effectiveClientRect.x + leftPad, effectiveClientRect.y + topPad, contentWidth * zoom, contentHeight * zoom);
|
||||
return result;
|
||||
}
|
||||
|
||||
updateZoom(ref: HTMLDivElement) {
|
||||
@@ -145,59 +184,58 @@ const AutoZoom = withStyles(
|
||||
return;
|
||||
}
|
||||
let content = ref.firstElementChild as HTMLElement | null;
|
||||
const classes = withStyles.getClasses(this.props);
|
||||
|
||||
if (content) {
|
||||
const { leftPad, rightPad } = this.props;
|
||||
let bounds = new Rect(leftPad, 0, ref.clientWidth - leftPad - rightPad, ref.clientHeight - 8);
|
||||
let zoomedClientRect = this.calculateZoomedClientRect(
|
||||
let layout = this.calculateUnzoomedLayout(
|
||||
bounds, content.clientWidth, content.clientHeight, 48);
|
||||
|
||||
let contentRect = layout.contentRect;
|
||||
|
||||
content.style.left = "0px";
|
||||
content.style.top = "0px";
|
||||
content.style.transformOrigin = "0 0"; // top-left corner
|
||||
content.style.transform =
|
||||
`translate(${zoomedClientRect.x}px, ${zoomedClientRect.y}px) scale(${zoomedClientRect.width / content.clientWidth}, ${zoomedClientRect.height / content.clientHeight})`;
|
||||
`translate(${contentRect.x}px, ${contentRect.y}px) scale(${layout.zoom}, ${layout.zoom})`;
|
||||
|
||||
if (this.zoomButton) {
|
||||
this.zoomButton.style.display = zoomedClientRect.width < content.clientWidth ? "block" : "none";
|
||||
let rightSizeSpace = ref.clientWidth - zoomedClientRect.right;
|
||||
if (rightSizeSpace - rightPad >= 48) {
|
||||
this.zoomButton.style.top = `${zoomedClientRect.y + 24}px`;
|
||||
this.zoomButton.style.left = `${zoomedClientRect.right + 4}px`;
|
||||
if (this.zoomToolbar) {
|
||||
if (!layout.showToolbar) {
|
||||
|
||||
this.zoomToolbar.className = classes.noToolbar;
|
||||
} else if (layout.horizontalToolbar) {
|
||||
this.zoomToolbar.className = classes.topToolBar;
|
||||
this.zoomToolbar.style.left = `${contentRect.x +16}px`
|
||||
this.zoomToolbar.style.top = `${contentRect.y - 48}px`;
|
||||
this.zoomToolbar.style.width = `${contentRect.width}px`;
|
||||
} else {
|
||||
this.zoomButton.style.top = `${zoomedClientRect.y - 48}px`;
|
||||
this.zoomButton.style.left = `${zoomedClientRect.right - 64 - 12}px`;
|
||||
this.zoomToolbar.className = classes.rightToolbar;
|
||||
this.zoomToolbar.style.left = "";
|
||||
this.zoomToolbar.style.top = `${contentRect.y}px`;
|
||||
this.zoomToolbar.style.left = `${contentRect.right + 4}px`;
|
||||
this.zoomToolbar.style.width = "";
|
||||
}
|
||||
}
|
||||
if (this.zoomButton) {
|
||||
this.zoomButton.style.display = layout.showZoomButton ? "block" : "none";
|
||||
}
|
||||
|
||||
// save the position of the Mod UI in page coordinates for later zooming.
|
||||
this.zoomStartRect = zoomedClientRect.copy();
|
||||
this.zoomStartRect = layout.contentRect.copy();
|
||||
let refBounds = ref.getBoundingClientRect();
|
||||
this.zoomStartRect.x += refBounds.left;
|
||||
this.zoomStartRect.y += refBounds.top;
|
||||
} else {
|
||||
if (this.zoomToolbar) {
|
||||
this.zoomToolbar.className = classes.noToolbar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateMaximizedZoom() {
|
||||
let ref = this.maximizedRef;
|
||||
if (!this.mounted || !ref) {
|
||||
return;
|
||||
}
|
||||
let content = ref.firstElementChild as HTMLElement | null;
|
||||
|
||||
if (content) {
|
||||
let leftPad = 16; let rightPad = 16;
|
||||
let topPad = 16, bottomPad = 16;
|
||||
let bounds: Rect;
|
||||
bounds = new Rect(leftPad, topPad, ref.clientWidth - leftPad - rightPad, ref.clientHeight - topPad - bottomPad);
|
||||
|
||||
let zoomedClientRect = this.calculateZoomedClientRect(
|
||||
bounds, content.clientWidth, content.clientHeight, 48);
|
||||
content.style.left = "0px";
|
||||
content.style.top = "0px";
|
||||
content.style.transformOrigin = "0 0"; // top-left corner
|
||||
content.style.transform = `translate(${zoomedClientRect.x}px, ${zoomedClientRect.y}px) scale(${zoomedClientRect.width / content.clientWidth}, ${zoomedClientRect.height / content.clientHeight})`;
|
||||
//console.log("Zoomed to: ", zoomedClientRect.toString());
|
||||
|
||||
if (this.normalRef) {
|
||||
this.updateZoom(this.normalRef);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -234,20 +272,20 @@ const AutoZoom = withStyles(
|
||||
}
|
||||
this.maximizedAnimateFrameHandle = window.requestAnimationFrame(() => {
|
||||
this.maximizedAnimateFrameHandle = null;
|
||||
if (this.maximizedRef) {
|
||||
this.updateMaximizedZoom();
|
||||
}
|
||||
this.updateMaximizedZoom();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
private zoomToolbar: HTMLElement | null = null;
|
||||
private zoomButton: HTMLElement | null = null;
|
||||
private normalRef: HTMLDivElement | null = null;
|
||||
|
||||
setNormalRef(ref: HTMLDivElement | null) {
|
||||
setContentRef(ref: HTMLDivElement | null) {
|
||||
this.normalRef = ref;
|
||||
if (ref) {
|
||||
this.zoomButton = ref.querySelector("#maximize-button") as HTMLDivElement | null;
|
||||
this.zoomToolbar = ref.querySelector("#zoom-toolbar") as HTMLDivElement | null;
|
||||
this.zoomButton = ref.querySelector("#zoom-button") as HTMLDivElement | null;
|
||||
this.resizeObserver = new ResizeObserver(() => {
|
||||
this.requestZoomUpdate();
|
||||
});
|
||||
@@ -261,36 +299,15 @@ const AutoZoom = withStyles(
|
||||
if (this.resizeObserver) {
|
||||
this.resizeObserver.disconnect();
|
||||
this.resizeObserver = null;
|
||||
this.zoomButton = null;
|
||||
this.zoomToolbar = null;
|
||||
}
|
||||
this.zoomStartRect = null;
|
||||
this.zoomToolbar = null;
|
||||
this.zoomButton = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private maximizedRef: HTMLDivElement | null = null;
|
||||
private maximedResizeObserver: ResizeObserver | null = null;
|
||||
|
||||
setMaximizedRef(ref: HTMLDivElement | null) {
|
||||
this.maximizedRef = ref;
|
||||
if (ref) {
|
||||
this.maximedResizeObserver = new ResizeObserver(() => {
|
||||
this.requestMaximizedZoomUpdate();
|
||||
});
|
||||
this.maximedResizeObserver.observe(ref);
|
||||
let child = ref.firstElementChild as HTMLElement | null;
|
||||
if (child) {
|
||||
this.maximedResizeObserver.observe(child);
|
||||
}
|
||||
this.requestMaximizedZoomUpdate();
|
||||
} else {
|
||||
if (this.maximedResizeObserver) {
|
||||
this.maximedResizeObserver.disconnect();
|
||||
this.maximedResizeObserver = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private zoomStartRect: Rect | null = null;
|
||||
|
||||
startZoom() {
|
||||
@@ -300,70 +317,77 @@ const AutoZoom = withStyles(
|
||||
this.props.setShowZoomed(true);
|
||||
}
|
||||
|
||||
render() {
|
||||
content() {
|
||||
const classes = withStyles.getClasses(this.props);
|
||||
void classes; // suppress unused variable warning
|
||||
const landscape = this.state.screenWidth > this.state.screenHeight;
|
||||
return (<div style={{ overflow: "hidden", height: "100%", width: "100%" }} ref={(ref) => { this.setNormalRef(ref); }}>
|
||||
<div style={{
|
||||
display: "inline-block",
|
||||
position: "absolute",
|
||||
visibility: this.props.contentReady ? "visible" : "hidden",
|
||||
|
||||
}}>
|
||||
{!this.props.showZoomed && this.props.children}
|
||||
</div>
|
||||
<div id="maximize-button" style={{
|
||||
display: "none", position: "absolute", left: 0, top: 0, width: 52, height: 64, zIndex: 1101,
|
||||
borderRadius: "0px 26px 26px 0px",
|
||||
|
||||
}}
|
||||
return (
|
||||
<div ref={(ref) => { this.setContentRef(ref); }}
|
||||
style={{ width: "100%", height: "100%" }}
|
||||
>
|
||||
<IconButtonEx tooltip="Fullscreen view"
|
||||
style={{ margin: 2, background: isDarkMode() ? "#444" : "#eee" }}
|
||||
onClick={() => {
|
||||
this.startZoom();
|
||||
<div style={{
|
||||
display: "inline-block",
|
||||
position: "absolute",
|
||||
visibility: this.props.contentReady ? "visible" : "hidden"
|
||||
|
||||
}}>
|
||||
{this.props.children}
|
||||
</div>
|
||||
<div id="zoom-toolbar" className={classes.noToolbar}
|
||||
style={{
|
||||
visibility: this.props.contentReady ? "visible" : "hidden"
|
||||
}}
|
||||
>
|
||||
<FullscreenIcon style={{ color: "white" }} />
|
||||
</IconButtonEx>
|
||||
</div>
|
||||
{this.props.showZoomed && (
|
||||
<Backdrop id="modGuiZoomBackdrop"
|
||||
sx={(theme) => ({
|
||||
zIndex: this.props.showZoomed ? 1101 : -1,
|
||||
overflow: "clip",
|
||||
background: theme.palette.mode === 'dark' ? 'rgba(0, 0, 0, 0.9)' : 'rgba(255, 255, 255, 0.9)'
|
||||
})}
|
||||
open={this.props.showZoomed}
|
||||
>
|
||||
<div ref={(ref) => { this.setMaximizedRef(ref); }}
|
||||
style={{
|
||||
position: "absolute", left: 0, top: 0, right: 0, bottom: 0, overflow: "hidden",
|
||||
visibility: this.props.contentReady ? "visible" : "hidden"
|
||||
}}>
|
||||
|
||||
<div style={{ display: "inline-block", position: "relative" }}>
|
||||
{
|
||||
this.props.showZoomed && this.props.children
|
||||
}
|
||||
</div>
|
||||
|
||||
<IconButtonEx tooltip="Exit fullscreen"
|
||||
style={{
|
||||
position: "absolute",
|
||||
right: landscape? 80: 16, // avoid potential cutout in landscape mode
|
||||
top: 16, zIndex: 1104,
|
||||
|
||||
{!this.props.showZoomed ? (
|
||||
<IconButtonEx id="zoom-button" tooltip="Fullscreen view"
|
||||
onClick={() => {
|
||||
this.startZoom();
|
||||
}}
|
||||
>
|
||||
<FullscreenIcon style={{ opacity: 0.6 }}
|
||||
/>
|
||||
</IconButtonEx>
|
||||
|
||||
) : (
|
||||
<IconButtonEx tooltip="Exit fullscreen"
|
||||
style={{}}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
this.props.setShowZoomed(false);
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
<ArrowBackIcon style={{
|
||||
opacity: 0.6,
|
||||
}} />
|
||||
</IconButtonEx>
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
{this.props.toolbarChildren && this.props.toolbarChildren.map((child, index) => (
|
||||
<div key={index} style={{ display: "inline-block" }}>
|
||||
{child}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const classes = withStyles.getClasses(this.props);
|
||||
void classes; // suppress unused variable warning
|
||||
|
||||
return (<div style={{ overflow: "hidden", height: "100%", width: "100%" }} >
|
||||
{!this.props.showZoomed && this.content()}
|
||||
|
||||
{this.props.showZoomed && (
|
||||
<Backdrop id="modGuiZoomBackdrop"
|
||||
className={classes.backdrop}
|
||||
open={this.props.showZoomed}
|
||||
>
|
||||
{this.content()}
|
||||
|
||||
</Backdrop>
|
||||
)}
|
||||
</div>);
|
||||
|
||||
@@ -22,6 +22,9 @@ import { Theme } from '@mui/material/styles';
|
||||
import WithStyles, { withTheme } from './WithStyles';
|
||||
import { createStyles } from './WithStyles';
|
||||
import { css } from '@emotion/react';
|
||||
import IconButtonEx from './IconButtonEx';
|
||||
|
||||
import SidechainConnectIcon from './svg/ic_sidechain_open_48.svg?react';
|
||||
|
||||
import AutoZoom from './AutoZoom';
|
||||
|
||||
@@ -37,7 +40,7 @@ import {
|
||||
} from './Pedalboard';
|
||||
import PluginControl from './PluginControl';
|
||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||
import SideChainSelectControl from './SideChainSelectControl';
|
||||
import SideChainSelectControl, {SideChainSelectDialog} from './SideChainSelectControl';
|
||||
import VuMeter from './VuMeter';
|
||||
import { nullCast } from './Utility'
|
||||
import { PiPedalStateError } from './PiPedalError';
|
||||
@@ -373,11 +376,12 @@ type PluginControlViewState = {
|
||||
dialogFileValue: string,
|
||||
modGuiContentReady: boolean,
|
||||
showModGuiZoomed: boolean,
|
||||
sidechainDialogOpen: boolean
|
||||
};
|
||||
|
||||
const PluginControlView =
|
||||
withTheme(withStyles(
|
||||
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> {
|
||||
class extends ResizeResponsiveComponent<PluginControlViewProps, PluginControlViewState> {
|
||||
model: PiPedalModel;
|
||||
|
||||
constructor(props: PluginControlViewProps) {
|
||||
@@ -393,7 +397,8 @@ const PluginControlView =
|
||||
dialogFileProperty: new UiFileProperty(),
|
||||
dialogFileValue: "",
|
||||
modGuiContentReady: false,
|
||||
showModGuiZoomed: false
|
||||
showModGuiZoomed: false,
|
||||
sidechainDialogOpen: false
|
||||
|
||||
}
|
||||
this.onPedalboardChanged = this.onPedalboardChanged.bind(this);
|
||||
@@ -608,15 +613,15 @@ const PluginControlView =
|
||||
let title = uiPlugin.audio_side_chain_title ? uiPlugin.audio_side_chain_title : "Side chain";
|
||||
|
||||
return (
|
||||
<SideChainSelectControl
|
||||
<SideChainSelectControl
|
||||
title={title}
|
||||
selectItems={items}
|
||||
selectedInstanceId={selectedInstanceId}
|
||||
onChanged={(instanceId: number) => {
|
||||
this.model.setPedalboardSideChainInput(this.props.item.instanceId, instanceId);
|
||||
|
||||
|
||||
}}
|
||||
/>
|
||||
/>
|
||||
);
|
||||
|
||||
}
|
||||
@@ -876,6 +881,9 @@ const PluginControlView =
|
||||
return false;
|
||||
}
|
||||
|
||||
handleSelectSidechainInput() {
|
||||
this.setState({sidechainDialogOpen: true});
|
||||
}
|
||||
|
||||
handleModGuiFileProperty(instanceId: number, filePropertyUri: string, selectedFile: string) {
|
||||
let plugin = this.model.getUiPlugin(this.props.item.uri);
|
||||
@@ -900,10 +908,30 @@ const PluginControlView =
|
||||
if (!uiPlugin) {
|
||||
return (<div />);
|
||||
}
|
||||
let toolBarChildren: ReactNode[] = [];
|
||||
if (uiPlugin.audio_side_chain_inputs > 0) {
|
||||
toolBarChildren.push(
|
||||
<IconButtonEx tooltip="Select sidechain input"
|
||||
onClick={() => {
|
||||
this.handleSelectSidechainInput();
|
||||
}}
|
||||
>
|
||||
<SidechainConnectIcon
|
||||
style={{
|
||||
opacity: 0.6,
|
||||
width: 24,
|
||||
height: 24,
|
||||
fill: this.props.theme.palette.text.primary
|
||||
}}
|
||||
/>
|
||||
</IconButtonEx>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div style={{ width: "100%", height: "100%", }}>
|
||||
<AutoZoom leftPad={36} rightPad={52} contentReady={this.state.modGuiContentReady}
|
||||
showZoomed={this.state.showModGuiZoomed}
|
||||
toolbarChildren={toolBarChildren}
|
||||
setShowZoomed={
|
||||
(value) => { this.setState({ showModGuiZoomed: value }); }
|
||||
}
|
||||
@@ -1085,6 +1113,16 @@ const PluginControlView =
|
||||
}
|
||||
/>
|
||||
)}
|
||||
{this.state.sidechainDialogOpen && (
|
||||
<SideChainSelectDialog open={this.state.sidechainDialogOpen}
|
||||
onClose={()=>{ this.setState({sidechainDialogOpen: false});}}
|
||||
selectItems={this.getSidechainSelectItems()}
|
||||
selectedInstanceId={this.props.item.sideChainInputId}
|
||||
onChanged={(instanceId: number) => {
|
||||
this.model.setPedalboardSideChainInput(this.props.item.instanceId, instanceId);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{/* xxx: I don't think we need this anyore. */}
|
||||
<FullScreenIME uiControl={this.state.imeUiControl} value={this.state.imeValue}
|
||||
|
||||
|
||||
@@ -26,6 +26,12 @@ import { Component } from 'react';
|
||||
import { Theme } from '@mui/material/styles';
|
||||
import { css } from '@emotion/react';
|
||||
|
||||
import DialogEx from './DialogEx';
|
||||
import DialogTitle from '@mui/material/DialogTitle';
|
||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||
import Toolbar from '@mui/material/Toolbar';
|
||||
import DialogContent from '@mui/material/DialogContent';
|
||||
import IconButtonEx from './IconButtonEx';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import { PiPedalModel, PiPedalModelFactory, State } from './PiPedalModel';
|
||||
import Select from '@mui/material/Select';
|
||||
@@ -163,4 +169,55 @@ const SideChainSelectControl =
|
||||
, styles)
|
||||
)
|
||||
;
|
||||
export default SideChainSelectControl;
|
||||
export default SideChainSelectControl;
|
||||
|
||||
export interface SideChainSelectDialogProps {
|
||||
open: boolean,
|
||||
onClose: () => void,
|
||||
|
||||
selectItems: { instanceId: number, title: string }[];
|
||||
selectedInstanceId: number;
|
||||
onChanged(instanceId: number): void;
|
||||
|
||||
}
|
||||
export function SideChainSelectDialog(props: SideChainSelectDialogProps) {
|
||||
let { open, onClose, selectItems, selectedInstanceId, onChanged } = props;
|
||||
return (
|
||||
<DialogEx tag="nameDialog" open={open} fullWidth maxWidth="xs" onClose={onClose} aria-labelledby="Rename-dialog-title"
|
||||
style={{ userSelect: "none" }}
|
||||
onEnterKey={() => { }}
|
||||
>
|
||||
<DialogTitle id="alert-dialog-title" style={{ userSelect: "none", padding: 0, margin: 0 }}>
|
||||
<Toolbar style={{ paddingLeft: 24, paddingRight: 24, margin: 0 }} >
|
||||
<IconButtonEx
|
||||
tooltip="Back" edge="start" color="inherit" onClick={() => { onClose(); }} aria-label="back"
|
||||
>
|
||||
<ArrowBackIcon style={{opacity: 0.6}} />
|
||||
</IconButtonEx>
|
||||
|
||||
<Typography noWrap variant="body1" style={{ flex: "1 1 auto" }}>Sidechain Input</Typography>
|
||||
</Toolbar>
|
||||
</DialogTitle>
|
||||
|
||||
<DialogContent >
|
||||
<Select
|
||||
variant="standard"
|
||||
onChange={(event) => {
|
||||
onChanged(event.target.value as number);
|
||||
}}
|
||||
value={selectedInstanceId}
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
{selectItems.map((item) => {
|
||||
return (
|
||||
<MenuItem key={item.instanceId} value={item.instanceId}
|
||||
selected={item.instanceId === selectedInstanceId}>
|
||||
{item.title}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Select>
|
||||
</DialogContent>
|
||||
</DialogEx>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 6.35 6.35"
|
||||
version="1.1"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
id="path4452"
|
||||
d="M 3.1501953 1.1797729 C 2.3438819 1.1900494 1.6500313 1.6826477 1.3451375 2.38125 L 1.786971 2.38125 C 2.0624356 1.9000342 2.5807156 1.5761312 3.1760335 1.5761312 C 4.0608593 1.5761312 4.7733521 2.2912075 4.7733521 3.1760335 C 4.7733521 4.0608594 4.0608593 4.7733521 3.1760335 4.7733521 C 2.580068 4.7733521 2.0611725 4.450254 1.7859375 3.96875 L 1.3446208 3.96875 C 1.6524938 4.6748172 2.3583381 5.1697103 3.1760335 5.1697103 C 4.2753461 5.1697103 5.1697103 4.2753461 5.1697103 3.1760335 C 5.1697103 2.0767208 4.2753461 1.1797729 3.1760335 1.1797729 C 3.1674451 1.1797729 3.1587586 1.1796638 3.1501953 1.1797729 z " />
|
||||
<path
|
||||
id="ellipse4674"
|
||||
d="M 3.1760335 2.3300903 C 2.7944551 2.3300903 2.4622893 2.5720679 2.3455933 2.9098999 L 0.64078776 2.9098999 L 0.64078776 3.4395833 L 2.3450765 3.4395833 C 2.4612025 3.7778767 2.7937654 4.019393 3.1760335 4.0193929 C 3.651938 4.0193929 4.0488484 3.6453545 4.0488485 3.1760335 C 4.0488485 2.7067124 3.6519381 2.3300904 3.1760335 2.3300903 z M 3.1760335 2.7264486 C 3.4466224 2.7264486 3.6524902 2.9307799 3.6524902 3.1760335 C 3.6524901 3.4212871 3.4466224 3.6230347 3.1760335 3.6230347 C 2.9054446 3.6230347 2.6975099 3.4212871 2.6975098 3.1760335 C 2.6975098 2.9307799 2.9054446 2.7264486 3.1760335 2.7264486 z " />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
Reference in New Issue
Block a user