diff --git a/vite/src/pipedal/MainPage.tsx b/vite/src/pipedal/MainPage.tsx index 176b85d..613f451 100644 --- a/vite/src/pipedal/MainPage.tsx +++ b/vite/src/pipedal/MainPage.tsx @@ -427,7 +427,6 @@ export const MainPage = let title = ""; let author = ""; let infoPluginUri = ""; - let presetsUri = ""; let missing = false; let canEditTitle = false; let modGuiButtonVisible = false; @@ -439,7 +438,6 @@ export const MainPage = } else if (pedalboardItem.isSyntheticItem()) { title = pedalboardItem.pluginName ?? "#error"; author = ""; - presetsUri = ""; infoPluginUri = ""; } else { @@ -456,7 +454,6 @@ export const MainPage = title = uiPlugin.name; author = uiPlugin.author_name; } - presetsUri = uiPlugin.uri; // if (uiPlugin.description.length > 20) { // } infoPluginUri = uiPlugin.uri; @@ -544,10 +541,6 @@ export const MainPage =
-
- -
{modGuiButtonVisible && (
@@ -634,6 +627,7 @@ export const MainPage = canShowModUi = this.canShowModUi(pedalboardItem); canDelete = pedalboard.canDeleteItem(pedalboardItem.instanceId); instanceId = pedalboardItem.instanceId; + pluginUri = pedalboardItem.uri; if (pedalboardItem.isEmpty()) { canInsert = true; canAppend = true; @@ -699,7 +693,12 @@ export const MainPage =
{this.props.enableStructureEditing && (
-
+
+ +
+ +
{ this.onAddClick(e) }} size="large"> @@ -718,7 +717,7 @@ export const MainPage = {canAppend && ( this.onAppendSplit(instanceId)}>Append split)}
-
+
{ this.onDeletePedal(pedalboardItem?.instanceId ?? -1) }} size="large"> diff --git a/vite/src/pipedal/Pedalboard.tsx b/vite/src/pipedal/Pedalboard.tsx index 0667f1c..3ee1777 100644 --- a/vite/src/pipedal/Pedalboard.tsx +++ b/vite/src/pipedal/Pedalboard.tsx @@ -59,6 +59,9 @@ export class ControlValue implements Deserializable { } export class PedalboardItem implements Deserializable { + clone() { + return new PedalboardItem().deserialize(this); + } deserializePedalboardItem(input: any): PedalboardItem { this.instanceId = input.instanceId ?? -1; this.title = input.title ?? ""; @@ -753,11 +756,14 @@ export class Pedalboard implements Deserializable { replaceItem(instanceId: number, newItem: PedalboardItem) { + newItem.instanceId = ++this.nextInstanceId; + let result = this._replaceItem(this.items,instanceId,newItem); if (!result) { throw new PiPedalArgumentError("instanceId not found."); } + return newItem.instanceId; } private _addItem(items: PedalboardItem[], newItem: PedalboardItem, instanceId: number, append: boolean) { diff --git a/vite/src/pipedal/PluginPresetSelector.tsx b/vite/src/pipedal/PluginPresetSelector.tsx index 4773d07..00eb640 100644 --- a/vite/src/pipedal/PluginPresetSelector.tsx +++ b/vite/src/pipedal/PluginPresetSelector.tsx @@ -23,29 +23,30 @@ import { PiPedalModel, PiPedalModelFactory, PluginPresetsChangedHandle } from '. import { Theme } from '@mui/material/styles'; import WithStyles from './WithStyles'; import { withStyles } from "tss-react/mui"; -import {createStyles} from './WithStyles'; +import { createStyles } from './WithStyles'; import PluginPresetsDialog from './PluginPresetsDialog'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; import Fade from '@mui/material/Fade'; import RenameDialog from './RenameDialog' -import {PluginUiPresets} from './PluginPreset'; +import { PluginUiPresets } from './PluginPreset'; import Divider from "@mui/material/Divider"; import PluginPresetsIcon from "./svg/ic_pluginpreset.svg?react"; import PluginPresetIcon from "./svg/ic_pluginpreset2.svg?react"; +import { Pedalboard, PedalboardItem } from './Pedalboard'; interface PluginPresetSelectorProps extends WithStyles { - pluginUri?: string; + pedalboardItem: PedalboardItem | null; instanceId: number; } interface PluginPresetSelectorState { - presets : PluginUiPresets; - enabled: boolean; + presets: PluginUiPresets; + //enabled: boolean; presetChanged: boolean; showPresetsDialog: boolean; showEditPresetsDialog: boolean; @@ -57,6 +58,10 @@ interface PluginPresetSelectorState { renameDialogOnOk?: (name: string) => void; saveAsName: string; + + isVisible: boolean; + hasPresets: boolean; + isPastePluginEnabled: boolean; } @@ -65,15 +70,17 @@ const styles = (theme: Theme) => createStyles({ width: 24, height: 24, marginRight: "4px", opacity: 0.6 }, pluginIcon: { - width: 24, height: 24, opacity: 0.6,fill: theme.palette.text.primary + width: 24, height: 24, opacity: 0.6, fill: theme.palette.text.primary }, pluginMenuIcon: { - width: 24, height: 24, opacity: 0.6,fill: theme.palette.text.primary,marginRight: 4 + width: 24, height: 24, opacity: 0.6, fill: theme.palette.text.primary, marginRight: 4 } }); +let pluginClipboardContents: PedalboardItem | null = null; + const PluginPresetSelector = withStyles( class extends Component { @@ -85,7 +92,7 @@ const PluginPresetSelector = this.model = PiPedalModelFactory.getInstance(); this.state = { presets: new PluginUiPresets(), - enabled: false, + isVisible: this.isVisible(props.pedalboardItem), presetChanged: false, showPresetsDialog: false, showEditPresetsDialog: false, @@ -94,26 +101,44 @@ const PluginPresetSelector = renameDialogDefaultName: "", renameDialogActionName: "", renameDialogOnOk: undefined, - saveAsName: "" + saveAsName: "", + hasPresets: this.hasPresets(this.props.pedalboardItem), + isPastePluginEnabled: pluginClipboardContents !== null + }; this.handleDialogClose = this.handleDialogClose.bind(this); this.handlePresetsMenuClose = this.handlePresetsMenuClose.bind(this); } - handleLoadPluginPreset(instanceId: number) - { - this.handlePresetsMenuClose(); - this.model.loadPluginPreset(this.props.instanceId,instanceId); - let presetName = this.getPresetName(instanceId); - this.setState({saveAsName: presetName}); + hasPresets(pedalboardItem: PedalboardItem | null): boolean { + if (pedalboardItem === null) return false; + if (!pedalboardItem.uri) return false; + if (pedalboardItem.isStart() || pedalboardItem.isEnd() + || pedalboardItem.isEmpty() || pedalboardItem.isSplit()) { + return false; + } + return true; } - getPresetName(instanceId: number) - { - for (let preset of this.state.presets.presets) - { - if (preset.instanceId === instanceId) - { + isVisible(pedalboardItem: PedalboardItem | null): boolean { + if (pedalboardItem === null) return false; + if (!pedalboardItem.uri) return false; + if (pedalboardItem.isStart() || pedalboardItem.isEnd() + || pedalboardItem.isSplit()) { + return false; + } + return true; + } + + handleLoadPluginPreset(instanceId: number) { + this.handlePresetsMenuClose(); + this.model.loadPluginPreset(this.props.instanceId, instanceId); + let presetName = this.getPresetName(instanceId); + this.setState({ saveAsName: presetName }); + } + getPresetName(instanceId: number) { + for (let preset of this.state.presets.presets) { + if (preset.instanceId === instanceId) { return preset.label; } } @@ -135,8 +160,8 @@ const PluginPresetSelector = this.renameDialogOpen(name, "Save As") .then((newName) => { - this.setState({saveAsName: newName}); - return this.model.saveCurrentPluginPresetAs(this.props.instanceId,newName); + this.setState({ saveAsName: newName }); + return this.model.saveCurrentPluginPresetAs(this.props.instanceId, newName); }) .then((newInstanceId) => { // s'fine. dealt with by updates, but we do need error handling. @@ -170,60 +195,62 @@ const PluginPresetSelector = return result; } - loadPresets():void { - if (!this.currentUri) return; - let captureUri: string = this.currentUri; + loadPresets(): void { + if (this.props.pedalboardItem === null) return; + if (!this.hasPresets(this.props.pedalboardItem)) return; + let captureUri: string = this.props.pedalboardItem.uri; this.model.getPluginPresets(captureUri) - .then((presets: PluginUiPresets) => { - if (captureUri === this.currentUri) - { - this.setState({presets: presets}); - } - }) - .catch(error => { - if (captureUri === this.currentUri) - { - this.setState({presets: new PluginUiPresets()}); - } - }); + .then((presets: PluginUiPresets) => { + if (captureUri === this.props.pedalboardItem?.uri) { + this.setState({ presets: presets }); + } + }) + .catch(error => { + if (captureUri === this.props.pedalboardItem?.uri) { + this.setState({ presets: new PluginUiPresets() }); + } + }); } onPluginPresetsChanged(pluginUri: string): void { - if (pluginUri === this.props.pluginUri) - { + if (pluginUri === this.props.pedalboardItem?.uri) { this.loadPresets(); } } _pluginPresetsChangedHandle?: PluginPresetsChangedHandle; - componentDidMount() - { + componentDidMount() { this._pluginPresetsChangedHandle = this.model.addPluginPresetsChangedListener( (pluginUri: string) => { this.onPluginPresetsChanged(pluginUri); } ); } - componentWillUnmount() - { - if (this._pluginPresetsChangedHandle) - { + componentWillUnmount() { + if (this._pluginPresetsChangedHandle) { this.model.removePluginPresetsChangedListener(this._pluginPresetsChangedHandle); this._pluginPresetsChangedHandle = undefined; } } - currentUri?: string = ""; - componentDidUpdate() + currentPedalboard?: PedalboardItem; + componentDidUpdate( + prevProps: Readonly, + prevState: Readonly, + snapshot?: any): void { - if (this.currentUri !== this.props.pluginUri) - { - this.currentUri = this.props.pluginUri; - if (!this.props.pluginUri) - { - this.setState({presets: new PluginUiPresets()}); - } else { - this.loadPresets(); + if (this.props.pedalboardItem !== prevProps.pedalboardItem) { + this.setState({ + isVisible: this.isVisible(this.props.pedalboardItem), + hasPresets: this.hasPresets(this.props.pedalboardItem) }); + if (this.props.pedalboardItem) { + if (this.props.pedalboardItem.isEmpty()) + { + this.setState({ presets: new PluginUiPresets() }); + } else + { + this.loadPresets(); + } } } } @@ -244,8 +271,38 @@ const PluginPresetSelector = } + isMenuCopyPluginEnabled(): boolean { + return this.state.hasPresets; + } + handleMenuCopyPlugin(): void { + this.handlePresetsMenuClose(); + let pedalboard: Pedalboard = this.model.pedalboard.get();; - handleMenuEditPluginPresets(): void { + + let pedalboardItem: PedalboardItem | null = pedalboard.tryGetItem(this.props.instanceId); + if (pedalboardItem === null) { + pluginClipboardContents = null; + this.setState({ isPastePluginEnabled: false }); + return; + } + pluginClipboardContents = pedalboardItem.clone(); + this.setState({ isPastePluginEnabled: true }); + + } + + private isMenuPastePluginEnabled(): boolean { + return this.state.isPastePluginEnabled; + } + private handleMenuPastePlugin(): void { + this.handlePresetsMenuClose(); + + if (pluginClipboardContents) { + this.model.replacePedalboarditem(this.props.instanceId, pluginClipboardContents.clone()); + } + } + + + private handleMenuEditPluginPresets(): void { this.handlePresetsMenuClose(); this.showEditPluginPresetsDialog(true); } @@ -282,21 +339,50 @@ const PluginPresetSelector = //this.model.loadPreset(event.target.value as number); } + buildMenuItems() { + let result : React.ReactNode[] = []; + if (this.state.hasPresets) { + result.push(( this.handlePluginPresetsMenuSaveAs(e)}>Save plugin preset...)); + result.push(( this.handleMenuEditPluginPresets()}>Manage plugin presets...)); + result.push(()); + } + let hasPresets = false; + for (let preset of this.state.presets.presets) { + result.push(( + this.handleLoadPluginPreset(preset.instanceId)} + > + + + {preset.label} + )); + hasPresets = true; + } + if (hasPresets) { + result.push(()); + } + result.push( + this.handleMenuCopyPlugin()}>Copy plugin + ); + result.push( + this.handleMenuPastePlugin()}>Paste plugin + ); + return result; + } render() { const classes = withStyles.getClasses(this.props); //const classes = withStyles.getClasses(this.props); //const classes = withStyles.getClasses(this.props); - if ((!this.props.pluginUri)) - { - return (
); + if (!this.state.isVisible) { + return (
); } return (
- this.handlePresetMenuClick(e)} size="large"> - + onClick={(e) => this.handlePresetMenuClick(e)} size="large"> + - this.handlePluginPresetsMenuSaveAs(e)}>Save plugin preset... - this.handleMenuEditPluginPresets()}>Manage plugin presets... - - { this.state.presets.presets.length !== 0 && - () - } { - this.state.presets.presets.map((preset) => { - return ( this.handleLoadPluginPreset(preset.instanceId)} - > - - - {preset.label}); - }) + this.buildMenuItems() } - this.handleDialogClose()} /> + )}