Touch tooltips, more tooltips
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
|
|
||||||
|
channel bindings help dialog. <ChannelBindingHelpDialog
|
||||||
|
|
||||||
Tooltips on touch ui?
|
Tooltips on touch ui?
|
||||||
|
|
||||||
|
|||||||
@@ -46,3 +46,6 @@ input[type=number] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
img {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
@@ -29,7 +29,7 @@ import { withStyles } from "tss-react/mui";
|
|||||||
import WithStyles from './WithStyles';
|
import WithStyles from './WithStyles';
|
||||||
import { css } from '@emotion/react';
|
import { css } from '@emotion/react';
|
||||||
|
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism';
|
import VolunteerActivismIcon from '@mui/icons-material/VolunteerActivism';
|
||||||
import MenuButton from '@mui/icons-material/Menu';
|
import MenuButton from '@mui/icons-material/Menu';
|
||||||
import { TemporaryDrawer } from './TemporaryDrawer';
|
import { TemporaryDrawer } from './TemporaryDrawer';
|
||||||
@@ -802,21 +802,23 @@ export
|
|||||||
(
|
(
|
||||||
<AppBar position="absolute" >
|
<AppBar position="absolute" >
|
||||||
<Toolbar variant="dense" className={classes.toolBar} >
|
<Toolbar variant="dense" className={classes.toolBar} >
|
||||||
<IconButton
|
<IconButtonEx tooltip="Menu"
|
||||||
edge="start"
|
edge="start"
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={() => { this.showDrawer() }}
|
onClick={() => { this.showDrawer() }}
|
||||||
size="large">
|
size="large">
|
||||||
<MenuButton style={{ opacity: 0.75 }} />
|
<MenuButton style={{ opacity: 0.75 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<div style={{ flex: "0 1 400px", minWidth: 100 }}>
|
<div style={{ flex: "0 1 400px", minWidth: 100 }}>
|
||||||
<PresetSelector />
|
<PresetSelector />
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: "2 2 30px" }} />
|
<div style={{ flex: "2 2 30px" }} />
|
||||||
{this.state.canFullScreen &&
|
{this.state.canFullScreen &&
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
aria-label="menu"
|
aria-label="maximise/minimise"
|
||||||
|
tooltip={this.state.isFullScreen ? "Exit full screen" : "Full screen"}
|
||||||
|
style={{ marginRight: 8, marginLeft: 8 }}
|
||||||
onClick={() => { this.toggleFullScreen(); }}
|
onClick={() => { this.toggleFullScreen(); }}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="large">
|
size="large">
|
||||||
@@ -827,22 +829,24 @@ export
|
|||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
}
|
}
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.toolBarContent} >
|
<div className={classes.toolBarContent} >
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Menu"
|
||||||
style={{ position: "absolute", left: 12, top: 8, zIndex: 2 }}
|
style={{ position: "absolute", left: 12, top: 8, zIndex: 2 }}
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
onClick={() => { this.showDrawer() }}
|
onClick={() => { this.showDrawer() }}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="large">
|
size="large">
|
||||||
<MenuButton />
|
<MenuButton />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
{this.state.canFullScreen && (
|
{this.state.canFullScreen && (
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip={this.state.isFullScreen ? "Exit full screen" : "Full screen"}
|
||||||
style={{ position: "absolute", right: 8, top: 8, zIndex: 2 }}
|
style={{ position: "absolute", right: 8, top: 8, zIndex: 2 }}
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
@@ -855,7 +859,7 @@ export
|
|||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -9,30 +9,42 @@ import ToolTipEx from './ToolTipEx'
|
|||||||
interface ControlTooltipProps {
|
interface ControlTooltipProps {
|
||||||
children: ReactElement,
|
children: ReactElement,
|
||||||
uiControl: UiControl
|
uiControl: UiControl
|
||||||
|
valueTooltip?: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export default function ControlTooltip(props: ControlTooltipProps) {
|
export default function ControlTooltip(props: ControlTooltipProps) {
|
||||||
let { children, uiControl } = props;
|
let { children, uiControl, valueTooltip } = props;
|
||||||
if (uiControl.comment && (uiControl.comment !== uiControl.name)) {
|
if (uiControl.comment && (uiControl.comment !== uiControl.name)) {
|
||||||
return (
|
return (
|
||||||
<ToolTipEx title={(
|
<ToolTipEx
|
||||||
<React.Fragment>
|
valueTooltip={valueTooltip}
|
||||||
<Typography variant="caption">{uiControl.name}</Typography>
|
title={
|
||||||
<Divider />
|
(
|
||||||
<Typography variant="caption">{uiControl.comment}</Typography>
|
<React.Fragment>
|
||||||
|
<Typography variant="caption">{uiControl.name}</Typography>
|
||||||
|
<Divider />
|
||||||
|
<Typography variant="caption">{uiControl.comment}</Typography>
|
||||||
|
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
<div>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</ToolTipEx>
|
</ToolTipEx>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<ToolTipEx title={uiControl.name}
|
<ToolTipEx valueTooltip={valueTooltip}
|
||||||
|
title={
|
||||||
|
(
|
||||||
|
<Typography variant="caption">{uiControl.name}</Typography>
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{children}
|
<div >
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
</ToolTipEx>
|
</ToolTipEx>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,6 @@ import InsertDriveFileIcon from '@mui/icons-material/InsertDriveFile';
|
|||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import DialogTitle from '@mui/material/DialogTitle';
|
import DialogTitle from '@mui/material/DialogTitle';
|
||||||
import DialogContent from '@mui/material/DialogContent';
|
import DialogContent from '@mui/material/DialogContent';
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import IconButtonEx from './IconButtonEx';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import OldDeleteIcon from './OldDeleteIcon';
|
import OldDeleteIcon from './OldDeleteIcon';
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
@@ -995,7 +994,8 @@ export default withStyles(
|
|||||||
}} >
|
}} >
|
||||||
{this.state.reordering && (
|
{this.state.reordering && (
|
||||||
<Toolbar style={{ padding: 0 }}>
|
<Toolbar style={{ padding: 0 }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Close"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="cancel"
|
aria-label="cancel"
|
||||||
@@ -1004,7 +1004,7 @@ export default withStyles(
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<CloseIcon style={{ width: 24, height: 24 }} />
|
<CloseIcon style={{ width: 24, height: 24 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
Reorder files
|
Reorder files
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -1013,7 +1013,8 @@ export default withStyles(
|
|||||||
)}
|
)}
|
||||||
{this.state.multiSelect && (
|
{this.state.multiSelect && (
|
||||||
<Toolbar style={{ padding: 0 }}>
|
<Toolbar style={{ padding: 0 }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Close"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="cancel"
|
aria-label="cancel"
|
||||||
@@ -1023,7 +1024,7 @@ export default withStyles(
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<CloseIcon style={{ width: 24, height: 24 }} />
|
<CloseIcon style={{ width: 24, height: 24 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
{this.state.selectedFiles.length.toString() + " files selected."}
|
{this.state.selectedFiles.length.toString() + " files selected."}
|
||||||
</Typography>
|
</Typography>
|
||||||
@@ -1071,7 +1072,8 @@ export default withStyles(
|
|||||||
{!(this.state.reordering || this.state.multiSelect) && (
|
{!(this.state.reordering || this.state.multiSelect) && (
|
||||||
<>
|
<>
|
||||||
<Toolbar style={{ padding: 0 }}>
|
<Toolbar style={{ padding: 0 }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
@@ -1079,7 +1081,7 @@ export default withStyles(
|
|||||||
onClick={() => { this.props.onCancel(); }}
|
onClick={() => { this.props.onCancel(); }}
|
||||||
>
|
>
|
||||||
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
{this.props.fileProperty.label}
|
{this.props.fileProperty.label}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ import TextField, { StandardTextFieldProps } from "@mui/material/TextField";
|
|||||||
import DialogTitle from "@mui/material/DialogTitle";
|
import DialogTitle from "@mui/material/DialogTitle";
|
||||||
import DialogEx from "./DialogEx";
|
import DialogEx from "./DialogEx";
|
||||||
import Toolbar from "@mui/material/Toolbar";
|
import Toolbar from "@mui/material/Toolbar";
|
||||||
import IconButton from "@mui/material/IconButton";
|
import IconButtonEx from "./IconButtonEx";
|
||||||
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
import ArrowBackIcon from "@mui/icons-material/ArrowBack";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
import Slider, { SliderProps } from "@mui/material/Slider";
|
import Slider, { SliderProps } from "@mui/material/Slider";
|
||||||
@@ -456,7 +456,8 @@ export default function LoopDialog(props: LoopDialogProps) {
|
|||||||
>
|
>
|
||||||
<DialogTitle style={{ paddingTop: 0 }}>
|
<DialogTitle style={{ paddingTop: 0 }}>
|
||||||
<Toolbar style={{ padding: 0 }}>
|
<Toolbar style={{ padding: 0 }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
@@ -467,7 +468,7 @@ export default function LoopDialog(props: LoopDialogProps) {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
Loop
|
Loop
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -33,7 +33,8 @@ import Utility from './Utility';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import MicNoneOutlinedIcon from '@mui/icons-material/MicNoneOutlined';
|
import MicNoneOutlinedIcon from '@mui/icons-material/MicNoneOutlined';
|
||||||
import MicOutlinedIcon from '@mui/icons-material/MicOutlined';
|
import MicOutlinedIcon from '@mui/icons-material/MicOutlined';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
|
|
||||||
import NumericInput from './NumericInput';
|
import NumericInput from './NumericInput';
|
||||||
|
|
||||||
|
|
||||||
@@ -259,7 +260,8 @@ const MidiBindingView =
|
|||||||
this.generateMidiNoteSelects()
|
this.generateMidiNoteSelects()
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Listen for MIDI input"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (this.props.listen) {
|
if (this.props.listen) {
|
||||||
this.props.onListen(-2, "", false)
|
this.props.onListen(-2, "", false)
|
||||||
@@ -273,7 +275,7 @@ const MidiBindingView =
|
|||||||
) : (
|
) : (
|
||||||
<MicNoneOutlinedIcon />
|
<MicNoneOutlinedIcon />
|
||||||
)}
|
)}
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -292,7 +294,8 @@ const MidiBindingView =
|
|||||||
this.generateControlSelects()
|
this.generateControlSelects()
|
||||||
}
|
}
|
||||||
</Select>
|
</Select>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Listen for MIDI input"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (this.props.listen) {
|
if (this.props.listen) {
|
||||||
this.props.onListen(-2, "", false)
|
this.props.onListen(-2, "", false)
|
||||||
@@ -306,7 +309,7 @@ const MidiBindingView =
|
|||||||
) : (
|
) : (
|
||||||
<MicNoneOutlinedIcon />
|
<MicNoneOutlinedIcon />
|
||||||
)}
|
)}
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import { withStyles } from "tss-react/mui";
|
|||||||
import AppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import MidiBinding from './MidiBinding';
|
import MidiBinding from './MidiBinding';
|
||||||
import MidiBindingView from './MidiBindingView';
|
import MidiBindingView from './MidiBindingView';
|
||||||
import Snackbar from '@mui/material/Snackbar';
|
import Snackbar from '@mui/material/Snackbar';
|
||||||
@@ -350,14 +350,15 @@ export const MidiBindingDialog =
|
|||||||
<div style={{ flex: "0 0 auto" }}>
|
<div style={{ flex: "0 0 auto" }}>
|
||||||
<AppBar className={classes.dialogAppBar} >
|
<AppBar className={classes.dialogAppBar} >
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={this.handleClose}
|
onClick={this.handleClose}
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
size="large">
|
size="large">
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
<Typography noWrap variant="h6" className={classes.dialogTitle}>
|
||||||
Preset MIDI Bindings
|
Preset MIDI Bindings
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -27,8 +27,7 @@ import DialogActions from '@mui/material/DialogActions';
|
|||||||
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
import { PiPedalModel, PiPedalModelFactory } from './PiPedalModel';
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
import ChannelBindingHelpDialog from './ChannelBindingsHelpDialog';
|
import ChannelBindingHelpDialog from './ChannelBindingsHelpDialog';
|
||||||
|
import IconButtonEx from './IconButtonEx';
|
||||||
import IconButton from '@mui/material/IconButton';
|
|
||||||
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined';
|
||||||
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
import Checkbox from '@mui/material/Checkbox';
|
||||||
@@ -167,7 +166,9 @@ function MidiChannelBindingDialog(props: MidiChannelBindingDialogProps) {
|
|||||||
} label="Allow Program Changes"
|
} label="Allow Program Changes"
|
||||||
/>
|
/>
|
||||||
{false&&( // wait until the implementation stabilizes before exposing the help dialog.
|
{false&&( // wait until the implementation stabilizes before exposing the help dialog.
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Help"
|
||||||
|
aria-label="help"
|
||||||
onClick={() => { setHelpDialog(true); }}
|
onClick={() => { setHelpDialog(true); }}
|
||||||
size="large">
|
size="large">
|
||||||
<InfoOutlinedIcon color='inherit'
|
<InfoOutlinedIcon color='inherit'
|
||||||
@@ -176,7 +177,7 @@ function MidiChannelBindingDialog(props: MidiChannelBindingDialogProps) {
|
|||||||
opacity: 0.6
|
opacity: 0.6
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ export interface PluginControlProps extends WithStyles<typeof pluginControlStyle
|
|||||||
type PluginControlState = {
|
type PluginControlState = {
|
||||||
error: boolean;
|
error: boolean;
|
||||||
editFocused: boolean;
|
editFocused: boolean;
|
||||||
|
previewValue?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
const PluginControl =
|
const PluginControl =
|
||||||
@@ -167,7 +168,9 @@ const PluginControl =
|
|||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
error: false,
|
error: false,
|
||||||
editFocused: false
|
editFocused: false,
|
||||||
|
previewValue: undefined
|
||||||
|
|
||||||
};
|
};
|
||||||
this.model = PiPedalModelFactory.getInstance();
|
this.model = PiPedalModelFactory.getInstance();
|
||||||
this.imgRef = React.createRef();
|
this.imgRef = React.createRef();
|
||||||
@@ -406,6 +409,7 @@ const PluginControl =
|
|||||||
img.style.opacity = "" + SELECTED_OPACITY;
|
img.style.opacity = "" + SELECTED_OPACITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.setState({ previewValue: undefined });
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (this.isExtraTouch(e)) {
|
if (this.isExtraTouch(e)) {
|
||||||
@@ -494,7 +498,9 @@ const PluginControl =
|
|||||||
if (this.pointersDown !== 0) {
|
if (this.pointersDown !== 0) {
|
||||||
--this.pointersDown;
|
--this.pointersDown;
|
||||||
}
|
}
|
||||||
|
if (this.pointersDown === 0) {
|
||||||
|
this.setState({ previewValue: undefined });
|
||||||
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
|
|
||||||
@@ -543,7 +549,7 @@ const PluginControl =
|
|||||||
}
|
}
|
||||||
|
|
||||||
clickSlop() {
|
clickSlop() {
|
||||||
return 3.5; // maybe larger on touch devices.
|
return 5; // maybe larger on touch devices.
|
||||||
}
|
}
|
||||||
onPointerMove(e: PointerEvent<SVGSVGElement>): void {
|
onPointerMove(e: PointerEvent<SVGSVGElement>): void {
|
||||||
if (this.isCapturedPointer(e)) {
|
if (this.isCapturedPointer(e)) {
|
||||||
@@ -604,6 +610,7 @@ const PluginControl =
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.setState({ previewValue: undefined});
|
||||||
}
|
}
|
||||||
previewInputValue(value: number, commitValue: boolean) {
|
previewInputValue(value: number, commitValue: boolean) {
|
||||||
let range = this.valueToRange(value);
|
let range = this.valueToRange(value);
|
||||||
@@ -667,6 +674,12 @@ const PluginControl =
|
|||||||
if (displayValue) {
|
if (displayValue) {
|
||||||
let v = this.formatDisplayValue(this.props.uiControl, value);
|
let v = this.formatDisplayValue(this.props.uiControl, value);
|
||||||
displayValue.childNodes[0].textContent = v;
|
displayValue.childNodes[0].textContent = v;
|
||||||
|
|
||||||
|
if (commitValue) {
|
||||||
|
this.setState({ previewValue: undefined });
|
||||||
|
} else {
|
||||||
|
this.setState({ previewValue: v });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let selectElement = this.selectRef.current;
|
let selectElement = this.selectRef.current;
|
||||||
if (selectElement) {
|
if (selectElement) {
|
||||||
@@ -1026,7 +1039,8 @@ const PluginControl =
|
|||||||
)
|
)
|
||||||
: (isGraphicEq) ? (
|
: (isGraphicEq) ? (
|
||||||
<div style={{ flex: "0 1 auto" }}>
|
<div style={{ flex: "0 1 auto" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
|
||||||
|
<ControlTooltip uiControl={control} valueTooltip={this.state.previewValue}>
|
||||||
<GraphicEqCtl
|
<GraphicEqCtl
|
||||||
imgRef={this.imgRef}
|
imgRef={this.imgRef}
|
||||||
position={this.getEqPosition()}
|
position={this.getEqPosition()}
|
||||||
@@ -1045,7 +1059,8 @@ const PluginControl =
|
|||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ flex: "0 1 auto" }}>
|
<div style={{ flex: "0 1 auto" }}>
|
||||||
<ControlTooltip uiControl={control}>
|
<ControlTooltip uiControl={control}
|
||||||
|
valueTooltip={this.state.previewValue}>
|
||||||
<DialIcon ref={this.imgRef}
|
<DialIcon ref={this.imgRef}
|
||||||
style={{
|
style={{
|
||||||
overscrollBehavior: "none", touchAction: "none", fill: dialColor,
|
overscrollBehavior: "none", touchAction: "none", fill: dialColor,
|
||||||
@@ -1053,7 +1068,7 @@ const PluginControl =
|
|||||||
}}
|
}}
|
||||||
onTouchStart={this.onTouchStart} onTouchMove={this.onTouchMove}
|
onTouchStart={this.onTouchStart} onTouchMove={this.onTouchMove}
|
||||||
onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp}
|
onPointerDown={this.onPointerDown} onPointerUp={this.onPointerUp}
|
||||||
onPointerMoveCapture={this.onPointerMove}
|
onPointerMove={this.onPointerMove}
|
||||||
onDrag={this.onDrag}
|
onDrag={this.onDrag}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
import { SyntheticEvent, Component } from 'react';
|
import { SyntheticEvent, Component } from 'react';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import { PiPedalModel, PiPedalModelFactory, PresetIndex } from './PiPedalModel';
|
import { PiPedalModel, PiPedalModelFactory, PresetIndex } from './PiPedalModel';
|
||||||
import SaveIconOutline from '@mui/icons-material/Save';
|
import SaveIconOutline from '@mui/icons-material/Save';
|
||||||
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
import MoreVertIcon from '@mui/icons-material/MoreVert';
|
||||||
@@ -300,12 +300,12 @@ const PresetSelector =
|
|||||||
justifyContent: "left", flexWrap: "nowrap", alignItems: "center", height: "100%", position: "relative"
|
justifyContent: "left", flexWrap: "nowrap", alignItems: "center", height: "100%", position: "relative"
|
||||||
}}>
|
}}>
|
||||||
<div style={{ flex: "0 0 auto" }}>
|
<div style={{ flex: "0 0 auto" }}>
|
||||||
<IconButton
|
<IconButtonEx tooltip="Save current preset"
|
||||||
style={{ flex: "0 0 auto", opacity: this.state.presets.presetChanged ? 1.0 : 0.0, color: "#FFFFFF" }}
|
style={{ flex: "0 0 auto", opacity: this.state.presets.presetChanged ? 1.0 : 0.0, color: "#FFFFFF" }}
|
||||||
onClick={(e) => { this.handleSave(); }}
|
onClick={(e) => { this.handleSave(); }}
|
||||||
size="large">
|
size="large">
|
||||||
<SaveIconOutline style={{ opacity: 0.75 }} color="inherit" />
|
<SaveIconOutline style={{ opacity: 0.75 }} color="inherit" />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div style={{ flex: "1 1 auto", minWidth: 60, maxWidth: 300, position: "relative", paddingRight: 12 }} >
|
<div style={{ flex: "1 1 auto", minWidth: 60, maxWidth: 300, position: "relative", paddingRight: 12 }} >
|
||||||
@@ -337,13 +337,14 @@ const PresetSelector =
|
|||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ flex: "0 0 auto"}}>
|
<div style={{ flex: "0 0 auto"}}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="More..."
|
||||||
style={{ flex: "0 0 auto", color: "#FFFFFF" }}
|
style={{ flex: "0 0 auto", color: "#FFFFFF" }}
|
||||||
onClick={(e) => this.handlePresetMenuClick(e)}
|
onClick={(e) => this.handlePresetMenuClick(e)}
|
||||||
size="large"
|
size="large"
|
||||||
>
|
>
|
||||||
<MoreVertIcon style={{ opacity: 0.75 }} color="inherit" />
|
<MoreVertIcon style={{ opacity: 0.75 }} color="inherit" />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Menu
|
<Menu
|
||||||
id="edit-presets-menu"
|
id="edit-presets-menu"
|
||||||
anchorEl={this.state.presetsMenuAnchorRef}
|
anchorEl={this.state.presetsMenuAnchorRef}
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import ListItemButton from '@mui/material/ListItemButton';
|
|||||||
import DialogTitle from '@mui/material/DialogTitle';
|
import DialogTitle from '@mui/material/DialogTitle';
|
||||||
import DialogActions from '@mui/material/DialogActions';
|
import DialogActions from '@mui/material/DialogActions';
|
||||||
import FormControlLabel from '@mui/material/FormControlLabel';
|
import FormControlLabel from '@mui/material/FormControlLabel';
|
||||||
|
import Typography from '@mui/material/Typography';
|
||||||
|
|
||||||
import Checkbox from '@mui/material/Checkbox';
|
import Checkbox from '@mui/material/Checkbox';
|
||||||
import {AlsaMidiDeviceInfo} from './AlsaMidiDeviceInfo';
|
import {AlsaMidiDeviceInfo} from './AlsaMidiDeviceInfo';
|
||||||
@@ -110,6 +111,10 @@ function SelectMidiChannelsDialog(props: SelectMidiChannelsDialogProps) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
)}
|
)}
|
||||||
|
{availableChannels.length === 0 && (
|
||||||
|
<Typography variant="body2" style={{ marginLeft: 32, marginRight: 24,marginTop:8, marginBottom: 16}}>
|
||||||
|
No MIDI devices found.</Typography>
|
||||||
|
)}
|
||||||
</List>
|
</List>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button onClick={handleClose} variant="dialogSecondary" >
|
<Button onClick={handleClose} variant="dialogSecondary" >
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import CssBaseline from '@mui/material/CssBaseline';
|
|||||||
import {createStyles} from './WithStyles';
|
import {createStyles} from './WithStyles';
|
||||||
|
|
||||||
import { withStyles } from "tss-react/mui";
|
import { withStyles } from "tss-react/mui";
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import FullscreenIcon from '@mui/icons-material/Fullscreen';
|
import FullscreenIcon from '@mui/icons-material/Fullscreen';
|
||||||
import FullscreenExitIcon from '@mui/icons-material/FullscreenExit';
|
import FullscreenExitIcon from '@mui/icons-material/FullscreenExit';
|
||||||
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
import ResizeResponsiveComponent from './ResizeResponsiveComponent';
|
||||||
@@ -271,14 +271,15 @@ const SnapshotEditor = withStyles(
|
|||||||
<CssBaseline />
|
<CssBaseline />
|
||||||
<AppBar position="static" sx={{ bgcolor: isDarkMode() ? getBackgroundColor("purple") : "#200040" }} >
|
<AppBar position="static" sx={{ bgcolor: isDarkMode() ? getBackgroundColor("purple") : "#200040" }} >
|
||||||
<Toolbar variant="dense" >
|
<Toolbar variant="dense" >
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
aria-label="menu"
|
aria-label="menu"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={() => { this.handleOk(); }}
|
onClick={() => { this.handleOk(); }}
|
||||||
size="large">
|
size="large">
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
{!this.state.collapseLabel && (
|
{!this.state.collapseLabel && (
|
||||||
<Typography style={{ flex: "0 1 auto", opacity: 0.66 }}
|
<Typography style={{ flex: "0 1 auto", opacity: 0.66 }}
|
||||||
variant="body1" noWrap
|
variant="body1" noWrap
|
||||||
@@ -310,7 +311,8 @@ const SnapshotEditor = withStyles(
|
|||||||
this.setState({ color: newColor });
|
this.setState({ color: newColor });
|
||||||
}} />
|
}} />
|
||||||
{this.state.canFullScreen &&
|
{this.state.canFullScreen &&
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip={this.state.isFullScreen ? "Exit Full Screen" : "Full Screen"}
|
||||||
aria-label="full-screen"
|
aria-label="full-screen"
|
||||||
onClick={() => { this.toggleFullScreen(); }}
|
onClick={() => { this.toggleFullScreen(); }}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
@@ -322,15 +324,16 @@ const SnapshotEditor = withStyles(
|
|||||||
|
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
}
|
}
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Cancel"
|
||||||
aria-label="cancel"
|
aria-label="cancel"
|
||||||
onClick={() => { this.props.onClose(); }}
|
onClick={() => { this.props.onClose(); }}
|
||||||
color="inherit"
|
color="inherit"
|
||||||
size="medium">
|
size="medium">
|
||||||
<CloseIcon />
|
<CloseIcon />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
|
|
||||||
</Toolbar>
|
</Toolbar>
|
||||||
</AppBar>
|
</AppBar>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ import MidiBinding from './MidiBinding';
|
|||||||
import Utility from './Utility';
|
import Utility from './Utility';
|
||||||
import MicNoneOutlinedIcon from '@mui/icons-material/MicNoneOutlined';
|
import MicNoneOutlinedIcon from '@mui/icons-material/MicNoneOutlined';
|
||||||
import MicOutlinedIcon from '@mui/icons-material/MicOutlined';
|
import MicOutlinedIcon from '@mui/icons-material/MicOutlined';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -195,7 +195,8 @@ const SystemMidiBindingView =
|
|||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Listen for MIDI input"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (this.props.listen) {
|
if (this.props.listen) {
|
||||||
this.props.onListen(-2, "", false)
|
this.props.onListen(-2, "", false)
|
||||||
@@ -209,7 +210,7 @@ const SystemMidiBindingView =
|
|||||||
) : (
|
) : (
|
||||||
<MicNoneOutlinedIcon />
|
<MicNoneOutlinedIcon />
|
||||||
)}
|
)}
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -31,13 +31,13 @@ import { PiPedalModel, PiPedalModelFactory, ListenHandle } from './PiPedalModel'
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import { Theme } from '@mui/material/styles';
|
import { Theme } from '@mui/material/styles';
|
||||||
import WithStyles from './WithStyles';
|
import WithStyles from './WithStyles';
|
||||||
import {createStyles} from './WithStyles';
|
import { createStyles } from './WithStyles';
|
||||||
|
|
||||||
import { withStyles } from "tss-react/mui";
|
import { withStyles } from "tss-react/mui";
|
||||||
import AppBar from '@mui/material/AppBar';
|
import AppBar from '@mui/material/AppBar';
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import MidiBinding from './MidiBinding';
|
import MidiBinding from './MidiBinding';
|
||||||
import SystemMidiBindingView from './SystemMidiBindingView';
|
import SystemMidiBindingView from './SystemMidiBindingView';
|
||||||
import Snackbar from '@mui/material/Snackbar';
|
import Snackbar from '@mui/material/Snackbar';
|
||||||
@@ -69,11 +69,11 @@ const styles = (theme: Theme) => createStyles({
|
|||||||
paddingTop: 12
|
paddingTop: 12
|
||||||
}),
|
}),
|
||||||
plainRow: css({
|
plainRow: css({
|
||||||
borderWidth: "1px 0px 0px 0px", borderStyle: "solid", borderColor: "transparent"
|
borderWidth: "1px 0px 0px 0px", borderStyle: "solid", borderColor: "transparent"
|
||||||
}),
|
}),
|
||||||
dividerRow: css({
|
dividerRow: css({
|
||||||
borderWidth: "1px 0px 0px 0px", borderStyle: "solid", borderColor: theme.palette.divider
|
borderWidth: "1px 0px 0px 0px", borderStyle: "solid", borderColor: theme.palette.divider
|
||||||
})
|
})
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -139,7 +139,7 @@ export const SystemMidiBindingDialog =
|
|||||||
}
|
}
|
||||||
else if (item.symbol === "nextProgram") {
|
else if (item.symbol === "nextProgram") {
|
||||||
displayName = "Next Preset";
|
displayName = "Next Preset";
|
||||||
}else if (item.symbol === "prevProgram") {
|
} else if (item.symbol === "prevProgram") {
|
||||||
displayName = "Previous Preset";
|
displayName = "Previous Preset";
|
||||||
}
|
}
|
||||||
else if (item.symbol === "snapshot1") {
|
else if (item.symbol === "snapshot1") {
|
||||||
@@ -170,8 +170,7 @@ export const SystemMidiBindingDialog =
|
|||||||
} else {
|
} else {
|
||||||
found = false;
|
found = false;
|
||||||
}
|
}
|
||||||
if (found)
|
if (found) {
|
||||||
{
|
|
||||||
result.push(new BindingEntry(displayName, listenInstanceId, item));
|
result.push(new BindingEntry(displayName, listenInstanceId, item));
|
||||||
++listenInstanceId;
|
++listenInstanceId;
|
||||||
}
|
}
|
||||||
@@ -277,12 +276,11 @@ export const SystemMidiBindingDialog =
|
|||||||
|
|
||||||
for (var item of items) {
|
for (var item of items) {
|
||||||
let symbol = item.midiBinding.symbol;
|
let symbol = item.midiBinding.symbol;
|
||||||
let hasDivider = symbol === "snapshot1" || symbol === "stopHotspot" || symbol === "shotdown";
|
let hasDivider = symbol === "snapshot1" || symbol === "stopHotspot" || symbol === "shotdown";
|
||||||
if (hasDivider)
|
if (hasDivider) {
|
||||||
{
|
|
||||||
result.push(
|
result.push(
|
||||||
<tr>
|
<tr>
|
||||||
<td colSpan={2} className={classes.dividerRow}><div style={{height: 1}} /></td>
|
<td colSpan={2} className={classes.dividerRow}><div style={{ height: 1 }} /></td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -321,7 +319,7 @@ export const SystemMidiBindingDialog =
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
let props = this.props;
|
let props = this.props;
|
||||||
let { open} = props;
|
let { open } = props;
|
||||||
|
|
||||||
const classes = withStyles.getClasses(this.props);
|
const classes = withStyles.getClasses(this.props);
|
||||||
if (!open) {
|
if (!open) {
|
||||||
@@ -332,20 +330,21 @@ export const SystemMidiBindingDialog =
|
|||||||
<DialogEx tag="systemMidiBindings" open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
|
<DialogEx tag="systemMidiBindings" open={open} fullWidth onClose={this.handleClose} aria-labelledby="Rename-dialog-title"
|
||||||
fullScreen={true}
|
fullScreen={true}
|
||||||
style={{ userSelect: "none" }}
|
style={{ userSelect: "none" }}
|
||||||
onEnterKey={()=>{}}
|
onEnterKey={() => { }}
|
||||||
>
|
>
|
||||||
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
|
<div style={{ display: "flex", flexDirection: "column", flexWrap: "nowrap", width: "100%", height: "100%", overflow: "hidden" }}>
|
||||||
<div style={{ flex: "0 0 auto" }}>
|
<div style={{ flex: "0 0 auto" }}>
|
||||||
<AppBar className={classes.dialogAppBar} >
|
<AppBar className={classes.dialogAppBar} >
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={this.handleClose}
|
onClick={this.handleClose}
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
size="large">
|
size="large">
|
||||||
<ArrowBackIcon />
|
<ArrowBackIcon />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography variant="h6" className={classes.dialogTitle}>
|
<Typography variant="h6" className={classes.dialogTitle}>
|
||||||
System MIDI Bindings
|
System MIDI Bindings
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import { withStyles } from "tss-react/mui";
|
|||||||
import {createStyles} from './WithStyles';
|
import {createStyles} from './WithStyles';
|
||||||
|
|
||||||
|
|
||||||
import IconButton from '@mui/material/Toolbar';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import Drawer from '@mui/material/Drawer';
|
import Drawer from '@mui/material/Drawer';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import { Theme } from '@mui/material/styles';
|
import { Theme } from '@mui/material/styles';
|
||||||
@@ -100,9 +100,10 @@ export const TemporaryDrawer = withStyles(
|
|||||||
>
|
>
|
||||||
<div style={{ display: "flex", flexFlow: "row nowrap", justifyContent: "flex-start", alignItems: "center", width: "100%"}}>
|
<div style={{ display: "flex", flexFlow: "row nowrap", justifyContent: "flex-start", alignItems: "center", width: "100%"}}>
|
||||||
|
|
||||||
<IconButton style={{ flex: "0 0 auto" }} >
|
<IconButtonEx tooltip="Back"
|
||||||
|
style={{ flex: "0 0 auto" }} >
|
||||||
<ArrowBackIcon style={{ fill: '#666' }} />
|
<ArrowBackIcon style={{ fill: '#666' }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<img src="img/Pi-Logo-3.png" alt="" style={{height: 36}} />
|
<img src="img/Pi-Logo-3.png" alt="" style={{height: 36}} />
|
||||||
</div>
|
</div>
|
||||||
{this.props.children}
|
{this.props.children}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ import TextField, { StandardTextFieldProps } from '@mui/material/TextField';
|
|||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Toolbar from '@mui/material/Toolbar';
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
import Timebase, { TimebaseUnits } from './Timebase';
|
import Timebase, { TimebaseUnits } from './Timebase';
|
||||||
|
|
||||||
@@ -198,7 +198,8 @@ export default function TimebaseSelectorDialog(props: TimebaseSelectorDialogProp
|
|||||||
>
|
>
|
||||||
<DialogTitle style={{ paddingTop: 0 }}>
|
<DialogTitle style={{ paddingTop: 0 }}>
|
||||||
<Toolbar style={{ padding: 0 }}>
|
<Toolbar style={{ padding: 0 }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
@@ -206,7 +207,7 @@ export default function TimebaseSelectorDialog(props: TimebaseSelectorDialogProp
|
|||||||
onClick={() => { handleClose(); }}
|
onClick={() => { handleClose(); }}
|
||||||
>
|
>
|
||||||
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
<ArrowBackIcon style={{ width: 24, height: 24 }} />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
<Typography noWrap component="div" sx={{ flexGrow: 1 }}>
|
||||||
Timebase Settings
|
Timebase Settings
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|||||||
@@ -27,13 +27,12 @@ import LoopDialog from './LoopDialog';
|
|||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import ButtonEx from './ButtonEx';
|
import ButtonEx from './ButtonEx';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import Pause from '@mui/icons-material/Pause';
|
import Pause from '@mui/icons-material/Pause';
|
||||||
import PlayArrow from '@mui/icons-material/PlayArrow';
|
import PlayArrow from '@mui/icons-material/PlayArrow';
|
||||||
import FastForward from '@mui/icons-material/FastForward';
|
import FastForward from '@mui/icons-material/FastForward';
|
||||||
import FastRewind from '@mui/icons-material/FastRewind';
|
import FastRewind from '@mui/icons-material/FastRewind';
|
||||||
import { PiPedalModelFactory, State } from './PiPedalModel';
|
import { PiPedalModelFactory, State } from './PiPedalModel';
|
||||||
import ButtonTooltip from './ButtonTooltip';
|
|
||||||
import { pathFileNameOnly } from './FileUtils';
|
import { pathFileNameOnly } from './FileUtils';
|
||||||
import ButtonBase from '@mui/material/ButtonBase';
|
import ButtonBase from '@mui/material/ButtonBase';
|
||||||
import FilePropertyDialog from './FilePropertyDialog';
|
import FilePropertyDialog from './FilePropertyDialog';
|
||||||
@@ -351,61 +350,56 @@ export default function ToobPlayerControl(
|
|||||||
},
|
},
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<ButtonTooltip title="Previous track">
|
<IconButtonEx tooltip="Previous track"
|
||||||
<IconButton
|
style={{ opacity: (pluginState === PluginState.Idle ? 0.2 : 0.7) }}
|
||||||
style={{ opacity: (pluginState === PluginState.Idle ? 0.2 : 0.7) }}
|
onClick={() => {
|
||||||
onClick={() => {
|
if (position > start + 3.0) {
|
||||||
if (position > start + 3.0) {
|
model.sendPedalboardControlTrigger(
|
||||||
|
props.instanceId,
|
||||||
|
"stop",
|
||||||
|
1
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
onPreviousTrack();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<FastRewind fontSize="large" />
|
||||||
|
</IconButtonEx>
|
||||||
|
<IconButtonEx
|
||||||
|
tooltip={paused ? "Play" : "Pause"}
|
||||||
|
|
||||||
|
style={{ opacity: (pluginState === PluginState.Idle ? 0.2 : 0.7) }}
|
||||||
|
onClick={() => {
|
||||||
|
if (pluginState != PluginState.Idle) {
|
||||||
|
if (paused) {
|
||||||
model.sendPedalboardControlTrigger(
|
model.sendPedalboardControlTrigger(
|
||||||
props.instanceId,
|
props.instanceId,
|
||||||
"stop",
|
"play",
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
onPreviousTrack();
|
model.sendPedalboardControlTrigger(
|
||||||
|
props.instanceId,
|
||||||
|
"pause",
|
||||||
|
1
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}}
|
}
|
||||||
>
|
}}
|
||||||
<FastRewind fontSize="large" />
|
>
|
||||||
</IconButton>
|
{paused ? (
|
||||||
</ButtonTooltip>
|
<PlayArrow sx={{ fontSize: '3rem' }} />
|
||||||
<ButtonTooltip title="Play/Pause">
|
) : (
|
||||||
<IconButton
|
<Pause sx={{ fontSize: '3rem' }} />
|
||||||
|
)}
|
||||||
style={{ opacity: (pluginState === PluginState.Idle ? 0.2 : 0.7) }}
|
</IconButtonEx>
|
||||||
onClick={() => {
|
<IconButtonEx tooltip="Next track"
|
||||||
if (pluginState != PluginState.Idle) {
|
style={{ opacity: (pluginState == PluginState.Idle ? 0.2 : 0.7) }}
|
||||||
if (paused) {
|
onClick={() => { onNextTrack(); }}
|
||||||
model.sendPedalboardControlTrigger(
|
>
|
||||||
props.instanceId,
|
<FastForward fontSize="large" />
|
||||||
"play",
|
</IconButtonEx>
|
||||||
1
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
model.sendPedalboardControlTrigger(
|
|
||||||
props.instanceId,
|
|
||||||
"pause",
|
|
||||||
1
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{paused ? (
|
|
||||||
<PlayArrow sx={{ fontSize: '3rem' }} />
|
|
||||||
) : (
|
|
||||||
<Pause sx={{ fontSize: '3rem' }} />
|
|
||||||
)}
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
<ButtonTooltip title="Next track">
|
|
||||||
<IconButton
|
|
||||||
style={{ opacity: (pluginState == PluginState.Idle ? 0.2 : 0.7) }}
|
|
||||||
onClick={() => { onNextTrack(); }}
|
|
||||||
>
|
|
||||||
<FastForward fontSize="large" />
|
|
||||||
</IconButton>
|
|
||||||
</ButtonTooltip>
|
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|||||||
+189
-15
@@ -25,39 +25,213 @@ import React from 'react';
|
|||||||
import Tooltip from '@mui/material/Tooltip';
|
import Tooltip from '@mui/material/Tooltip';
|
||||||
|
|
||||||
export interface ToolTipExProps extends React.ComponentProps<typeof Tooltip> {
|
export interface ToolTipExProps extends React.ComponentProps<typeof Tooltip> {
|
||||||
|
valueTooltip?: React.ReactNode; // For use with value prop, to show a tooltip on the value.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ToolTipEx: a reimplementation of the MUI Tooltip that works with pointer events and long presses. */
|
||||||
|
|
||||||
function ToolTipEx(props: ToolTipExProps) {
|
function ToolTipEx(props: ToolTipExProps) {
|
||||||
let [disableToolTip, setDisableToolTip] = React.useState(false);
|
let {title, valueTooltip, ...extras} = props;
|
||||||
let {title, ...extras} = props;
|
let [open,setOpen]= React.useState(false);
|
||||||
function handleMouseDownCapture(event: React.PointerEvent<HTMLDivElement>) {
|
let [isLongPress, setIsLongPress] = React.useState(false);
|
||||||
if ((event as any).pointerType === "mouse") {
|
let [longPressLeaving, setLongPressLeaving] = React.useState(false);
|
||||||
setDisableToolTip(true);
|
let [timeout, setTimeout] = React.useState<number>(0);
|
||||||
|
let [timeoutInstance, setTimeoutInstance] = React.useState<number>(0);
|
||||||
|
let [pointerDownPoint, setPointerdownPoint] = React.useState<{x: number, y: number} | null>(null);
|
||||||
|
|
||||||
|
const hoverTimeout = 1250;
|
||||||
|
const longpressTimeout = 500;
|
||||||
|
const longpressLeaveTimeout = 1500;
|
||||||
|
|
||||||
|
function startTimeout(timeout: number) {
|
||||||
|
setTimeout(timeout);
|
||||||
|
setTimeoutInstance(timeoutInstance + 1); // make useeffect run.
|
||||||
|
}
|
||||||
|
function stopTimeout() {
|
||||||
|
if (timeout > 0) {
|
||||||
|
startTimeout(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleMouseEnter(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
|
setOpen(false);
|
||||||
|
startTimeout(hoverTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleMouseLeave(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
|
setOpen(false);
|
||||||
|
stopTimeout();
|
||||||
|
}
|
||||||
|
|
||||||
|
function handlePointerDownCapture(event: React.PointerEvent<HTMLDivElement>) {
|
||||||
|
let pointerType = (event as any).pointerType || "n/a";
|
||||||
|
setIsLongPress(false);
|
||||||
|
if (pointerType === "mouse") {
|
||||||
|
setOpen(false);
|
||||||
|
stopTimeout(); // Reset hover timeout for mouse
|
||||||
|
} else { // pen, or touch.
|
||||||
|
setTimeout(longpressTimeout);
|
||||||
|
setOpen(false);
|
||||||
|
setPointerdownPoint({x: event.clientX, y: event.clientY});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePointerMoveCapture(event: React.PointerEvent<HTMLDivElement>) {
|
React.useEffect(()=> {
|
||||||
if ((event as any).pointerType !== "mouse") {
|
let t = timeout;
|
||||||
setDisableToolTip(false);
|
let handle: number | null = null;
|
||||||
|
if (valueTooltip === undefined) // no timeout if there's a value tooltip
|
||||||
|
{
|
||||||
|
if (t > 0) {
|
||||||
|
console.log("ToolTipEx: starting timeout for ", t);
|
||||||
|
handle = window.setTimeout(() => {
|
||||||
|
setOpen(true);
|
||||||
|
},t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return () => {
|
||||||
|
if (handle !== null) {
|
||||||
|
console.log("ToolTipEx: clearing timeout for ", t);
|
||||||
|
window.clearTimeout(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},[timeoutInstance]);
|
||||||
|
|
||||||
|
React.useEffect(()=> {
|
||||||
|
if (longPressLeaving) {
|
||||||
|
let handle: number | null = null;
|
||||||
|
handle = window.setTimeout(() => {
|
||||||
|
setIsLongPress(false);
|
||||||
|
setLongPressLeaving(false);
|
||||||
|
}, longpressLeaveTimeout);
|
||||||
|
return () => {
|
||||||
|
if (handle !== null) {
|
||||||
|
window.clearTimeout(handle);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return () => { };
|
||||||
|
}
|
||||||
|
},[longPressLeaving]);
|
||||||
|
|
||||||
|
function handlePointerCancel(event: React.PointerEvent<HTMLDivElement>) {
|
||||||
|
setOpen(false);
|
||||||
|
setIsLongPress(false);
|
||||||
|
stopTimeout();
|
||||||
|
setPointerdownPoint(null); // Reset the mouse down point
|
||||||
|
}
|
||||||
|
function handlePointerMoveCapture(event: React.PointerEvent<HTMLDivElement>) {
|
||||||
|
let pointerType = (event as any).pointerType || "n/a";
|
||||||
|
if (pointerType === "mouse") {
|
||||||
|
setOpen(false);
|
||||||
|
startTimeout(hoverTimeout); // Reset hover timeout for mouse
|
||||||
|
} else { // pen, or touch.
|
||||||
|
if (pointerDownPoint) {
|
||||||
|
const dx = event.clientX - pointerDownPoint.x;
|
||||||
|
const dy = event.clientY - pointerDownPoint.y;
|
||||||
|
if (Math.abs(dx) > 5 || Math.abs(dy) > 5) {
|
||||||
|
// If the mouse has moved more than 5 pixels, re-enable the tooltip
|
||||||
|
setOpen(false);
|
||||||
|
setIsLongPress(false);
|
||||||
|
stopTimeout();
|
||||||
|
setPointerdownPoint(null); // Reset the mouse down point
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleConextMenu(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
|
event.preventDefault(); // Prevent the default context menu from appearing
|
||||||
|
event.stopPropagation(); // Prevent the default context menu from appearing
|
||||||
|
if (pointerDownPoint) // touch sequence. This is a long press.
|
||||||
|
{
|
||||||
|
setIsLongPress(true);
|
||||||
|
setOpen(true);
|
||||||
|
stopTimeout();
|
||||||
|
}
|
||||||
|
} // Reset hover timeout for context menu
|
||||||
|
function handlePointerUpCapture(event: React.PointerEvent<HTMLDivElement>) {
|
||||||
|
let pointerType = (event as any).pointerType || "n/a";
|
||||||
|
if (pointerType === "mouse") {
|
||||||
|
setOpen(false);
|
||||||
|
stopTimeout(); // Reset hover timeout for mouse
|
||||||
|
} else { // pen, or touch.
|
||||||
|
stopTimeout();
|
||||||
|
setOpen(false);
|
||||||
|
if (isLongPress) {
|
||||||
|
// If this is a long press, we want to leave the tooltip open for a while.
|
||||||
|
setLongPressLeaving(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let effectiveTitle: React.ReactNode | null = null;
|
||||||
|
let placement: "top-start" | "right" = "top-start";
|
||||||
|
if (valueTooltip !== undefined && !isLongPress) {
|
||||||
|
effectiveTitle = valueTooltip; // Show value tooltip if available
|
||||||
|
placement = "right";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (open || isLongPress) {
|
||||||
|
effectiveTitle = title; // Show regular title if no value tooltip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function handleClickCapture(event: React.MouseEvent<HTMLDivElement>) {
|
||||||
|
setLongPressLeaving(false);
|
||||||
|
setIsLongPress(false);
|
||||||
|
setOpen(false);
|
||||||
|
stopTimeout(); // Reset hover timeout on click
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
|
onClickCapture={(e) => {
|
||||||
|
console.log("ToolTipEx: onClickCapture");
|
||||||
|
handleClickCapture(e);
|
||||||
|
}}
|
||||||
|
|
||||||
|
onMouseEnter={(e)=> {
|
||||||
|
console.log("ToolTipEx: onMouseEnter");
|
||||||
|
|
||||||
|
handleMouseEnter(e);
|
||||||
|
}}
|
||||||
|
onMouseLeave={(e)=> {
|
||||||
|
console.log("ToolTipEx: onMouseLeave");
|
||||||
|
handleMouseLeave(e);
|
||||||
|
}}
|
||||||
|
|
||||||
|
onPointerCancelCapture={(e) => {
|
||||||
|
console.log("ToolTipEx: onPointerCancelCapture");
|
||||||
|
handlePointerCancel(e);
|
||||||
|
}}
|
||||||
|
onContextMenuCapture={(e) => {
|
||||||
|
console.log("ToolTipEx: onContextMenuCapture");
|
||||||
|
handleConextMenu(e);
|
||||||
|
return false;
|
||||||
|
}}
|
||||||
onPointerDownCapture={(e) => {
|
onPointerDownCapture={(e) => {
|
||||||
handleMouseDownCapture(e);
|
console.log("ToolTipEx: onPointerDownCapture");
|
||||||
|
handlePointerDownCapture(e);
|
||||||
}}
|
}}
|
||||||
onPointerMoveCapture={(e) => {
|
onPointerMoveCapture={(e) => {
|
||||||
|
console.log("ToolTipEx: onPointerMoveCapture");
|
||||||
handlePointerMoveCapture(e);
|
handlePointerMoveCapture(e);
|
||||||
}}
|
}}
|
||||||
onMouseLeave={() => {
|
onPointerUpCapture={(e) => {
|
||||||
setDisableToolTip(false);
|
console.log("ToolTipEx: onPointerUpCapture");
|
||||||
}
|
handlePointerUpCapture(e);
|
||||||
}
|
}}
|
||||||
>
|
>
|
||||||
<Tooltip {...extras}
|
<Tooltip {...extras}
|
||||||
title={disableToolTip? undefined: title}
|
open={open || isLongPress || valueTooltip !== undefined}
|
||||||
placement="top-start" arrow enterDelay={1500} enterNextDelay={1500}
|
disableInteractive={true}
|
||||||
|
disableTouchListener={true}
|
||||||
|
disableHoverListener={true}
|
||||||
|
disableFocusListener={true}
|
||||||
|
|
||||||
|
title={effectiveTitle}
|
||||||
|
placement={ placement}
|
||||||
|
arrow enterDelay={1500} enterNextDelay={1500}
|
||||||
|
slotProps={{
|
||||||
|
transition: {
|
||||||
|
timeout: 0 // Disable transition for the tooltip
|
||||||
|
}
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import IconButton from '@mui/material/IconButton';
|
import IconButtonEx from './IconButtonEx';
|
||||||
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
||||||
|
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
@@ -305,14 +305,15 @@ const WifiDirectConfigDialog =
|
|||||||
{this.state.landscapeLayout && (
|
{this.state.landscapeLayout && (
|
||||||
<DialogContent >
|
<DialogContent >
|
||||||
<div style={{ display: "flex", gap: 16, alignItems: "left" }}>
|
<div style={{ display: "flex", gap: 16, alignItems: "left" }}>
|
||||||
<IconButton
|
<IconButtonEx
|
||||||
|
tooltip="Back"
|
||||||
edge="start"
|
edge="start"
|
||||||
color="inherit"
|
color="inherit"
|
||||||
onClick={() => { this.props.onClose(); }}
|
onClick={() => { this.props.onClose(); }}
|
||||||
aria-label="back"
|
aria-label="back"
|
||||||
size="large">
|
size="large">
|
||||||
<ArrowBackIcon htmlColor="#888" />
|
<ArrowBackIcon htmlColor="#888" />
|
||||||
</IconButton>
|
</IconButtonEx>
|
||||||
<FormControlLabel
|
<FormControlLabel
|
||||||
control={(
|
control={(
|
||||||
<Switch
|
<Switch
|
||||||
|
|||||||
Reference in New Issue
Block a user