/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Nomad is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.sf.nmedit.jtheme.clavia.nordmodular;
import java.awt.event.ActionEvent;
import java.awt.event.MouseEvent;
import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JPopupMenu;
import net.sf.nmedit.jnmprotocol2.MorphKeyboardAssignmentMessage;
import net.sf.nmedit.jpatch.PParameter;
import net.sf.nmedit.jpatch.clavia.nordmodular.Knob;
import net.sf.nmedit.jpatch.clavia.nordmodular.MidiController;
import net.sf.nmedit.jpatch.clavia.nordmodular.NMPatch;
import net.sf.nmedit.jpatch.clavia.nordmodular.PNMMorphSection;
import net.sf.nmedit.jpatch.clavia.nordmodular.PNMMorphSection.Assignments;
import net.sf.nmedit.jtheme.JTPopupHandler;
import net.sf.nmedit.jtheme.component.JTComponent;
import net.sf.nmedit.jtheme.component.JTControl;
import net.sf.nmedit.jtheme.component.JTControlAdapter;
public class ControlPopupHandler implements JTPopupHandler
{
public void showPopup(MouseEvent e, JTComponent component)
{
if (component instanceof JTControl)
{
JTControl control = (JTControl) component;
JTControlAdapter adapter = control.getControlAdapter();
PParameter parameter = adapter == null ? null : adapter.getParameter();
if (parameter != null)
{
ControlPopup popup = new ControlPopup(control,parameter);
popup.show(e, component);
}
}
}
// used for multiparameters components e.g. seq editor
public void showPopup(MouseEvent e, JTComponent component, int parameterIndex)
{
if (component instanceof JTControl)
{
JTControl control = (JTControl) component;
JTControlAdapter adapter = control.getControlAdapter(parameterIndex);
PParameter parameter = adapter == null ? null : adapter.getParameter();
if (parameter != null)
{
ControlPopup popup = new ControlPopup(control,parameter);
popup.show(e, component);
}
}
}
private static class ControlPopup
{
private JPopupMenu popup;
private JMenu submenuKnob;
private JMenu submenuMorph;
private JMenu submenuMIDI;
private JMenu submenuKeyboard;
private PParameter parameter;
private NMPatch patch;
private JTControl control;
NMPatch getPatch()
{
if (patch == null)
patch = (NMPatch) parameter.getParentComponent()
.getParentComponent().getPatch();
return patch;
}
public PParameter getParameter()
{
return parameter;
}
public void show(MouseEvent e, JTComponent component)
{
popup.show(component, e.getX(), e.getY());
}
public PParameter getMorphParameter()
{
return (parameter == null) ? null : parameter.getExtensionParameter();
}
public ControlPopup(JTControl control, PParameter parameter)
{
this.parameter = parameter;
this.control = control;
AbstractAction tmpa;
int tmp;
popup = new JPopupMenu();
popup.add(new ParameterAction(this, ParameterAction.DEFAULTVALUE));
if (!(control.getParent() instanceof JTMorphModule)) {
popup.add(new ParameterAction(this, ParameterAction.ZEROMORPH));
}
// Knob
submenuKnob = new JMenu("Knob");
tmp = getPatch().getKnobs().getKnobIndex(parameter);
if (tmp >= 0) {
popup.add(new ParameterAction(this, ParameterAction.DISABLE_KNOB, tmp));
}
int tmpM = getPatch().getMorphSection().getAssignedMorph(getParameter());
if (tmpM >= 0) {
popup.add(new ParameterAction(this, ParameterAction.DISABLE_MORPH, tmpM));
}
for (int i = 0; i < 120; i++) {
if (getPatch().getMidiControllers().get(i).getParameter() == getParameter()) {
popup.add(new ParameterAction(this, ParameterAction.DISABLE_MIDI, i));
}
}
popup.addSeparator();
for (int i=0;i<=20;i++)
{
tmpa = new ParameterAction(this, ParameterAction.KNOB, i);
if (tmp==i)
{
tmpa.setEnabled(false);
//tmpa.putValue(mleAbstractAction.SELECTED_KEY, Boolean.TRUE);
}
submenuKnob.add(tmpa);
if (i==5||i==11||i==14||i==17)
submenuKnob.addSeparator();
}
submenuKnob.addSeparator();
tmpa = new ParameterAction(this, ParameterAction.KNOB);
if (tmp<0)
tmpa.setEnabled(false);
submenuKnob.add(tmpa);
popup.add(submenuKnob);
if (!(control.getParent() instanceof JTMorphModule)) {
// Morph
submenuMorph = new JMenu("Morph");
tmp = getPatch().getMorphSection().getAssignedMorph(getParameter());
for (int i=0;i<4;i++)
{
tmpa = new ParameterAction(this, ParameterAction.MORPH, i);
if (i==tmp)
tmpa.setEnabled(false);
submenuMorph.add(tmpa);
}
submenuMorph.addSeparator();
tmpa = new ParameterAction(this, ParameterAction.MORPH);
if (tmp<0)
tmpa.setEnabled(false);
submenuMorph.add(tmpa);
popup.add(submenuMorph);
} else {
JTMorphModule morphModule = (JTMorphModule)control.getParent();
int idx = morphModule.getMorphIndex(control);
if (idx >= 0) {
Assignments assignments = getPatch().getMorphSection().getAssignments(idx);
if (assignments.size() > 0) {
popup.addSeparator();
for (PParameter p : assignments) {
popup.add(new ParameterAction(this, ParameterAction.DISABLE_FROM_MORPH, p));
}
popup.addSeparator();
}
}
}
// MIDI Controller
submenuMIDI = new JMenu("MIDI Controller");
submenuMIDI.add(new ParameterAction(this, ParameterAction.MIDI, MidiController.MODULATION_WHEEL));
submenuMIDI.add(new ParameterAction(this, ParameterAction.MIDI, MidiController.FootPedal));
submenuMIDI.add(new ParameterAction(this, ParameterAction.MIDI, MidiController.VOLUME));
submenuMIDI.addSeparator();
for (int i = 0; i < 120; i+=10) {
JMenu subMenu = new JMenu("CC " + i + " to " + (i + 9 ));
for (int j = i ; j < (i + 10) && j <= 120; j++) {
if (MidiController.isValidCC(j))
subMenu.add(new ParameterAction(this, ParameterAction.MIDI, j));
}
submenuMIDI.add(subMenu);
}
submenuMIDI.addSeparator();
submenuMIDI.add(new ParameterAction(this, ParameterAction.MIDI, -2));
submenuMIDI.addSeparator();
submenuMIDI.add(new ParameterAction(this, ParameterAction.MIDI, -1));
popup.add(submenuMIDI);
if (parameter.getParentComponent().getParentComponent() == getPatch().getMorphSection())
{
popup.addSeparator();
submenuKeyboard = new JMenu("Keyboard");
submenuKeyboard.add(new ParameterAction(this, ParameterAction.KB, MorphKeyboardAssignmentMessage.KEYBOARD_VELOCITY));
submenuKeyboard.add(new ParameterAction(this, ParameterAction.KB, MorphKeyboardAssignmentMessage.KEYBOARD_NOTE));
submenuKeyboard.addSeparator();
submenuKeyboard.add(new ParameterAction(this, ParameterAction.KB, MorphKeyboardAssignmentMessage.KEYBOARD_DISABLE));
popup.add(submenuKeyboard);
}
/*
popup.add(new AbstractAction(){
{
putValue(NAME, "TEST");
}
public void actionPerformed(ActionEvent arg0)
{
testSettingsMessage();
}});
*/
// Default value
// Zero morph
// ----
// Knob >
// Knob [1-6]
// ----
// Knob [7-12]
// ----
// Knob [13-15]
// ----
// Knob [16-18]
// ----
// Pedal
// After touch
// On/Off switch
// ----
// Disable
// Morph >
// Group [1-4]
// ----
// Disable
// MIDI Controller >
// Modulation Wheel
// Expression Pedal
// Main Volume
// ----
// Other ...
// ----
// Disable
// ----
// Keyboard > (only in morph section!)
// Velocity
// Note
// ----
// Disable
}
/*
void testSettingsMessage()
{
NMPatch patch = getPatch();
NmSlot slot = (NmSlot) patch.getSlot();
NordModular nm = (NordModular) slot.getSynthesizer();
PatchSettingsMessage msg = new PatchSettingsMessage();
msg.setDefaults(slot.getSlotIndex(), slot.getPatchId(), 0x0);
Header h = patch.getHeader();
msg.set("kbrangeMin1", 0);
msg.set("kbrangeMin2", 0);
msg.set("kbrangeMax1", 1);
msg.set("kbrangeMax2", 0);
msg.set("velocityRangeMin1", 0);
msg.set("velocityRangeMin2", 0);
msg.set("velocityRangeMax1", 1);
msg.set("velocityRangeMax2", 0);
msg.set("bendRange", h.getBendRange());
msg.set("portamentoTime1", 0);
msg.set("portamentoTime2", 1);
msg.set("portamentoType", 0);
msg.set("pedalMode", 0);
msg.set("voiceCount", 1);
msg.set("dividerBar1", 0);
msg.set("dividerBar2", 0);
msg.set("octaveShift1", 0);
msg.set("octaveShift2", 0);
msg.set("red", 0);
msg.set("blue", 0);
msg.set("yellow", 0);
msg.set("gray", 0);
msg.set("green", 0);
msg.set("purple", 0);
msg.set("white", 0);
msg.set("voiceRetriggerCommon", 0);
msg.set("voiceRetriggerPoly", 0);
System.out.println(msg);
try
{
nm.getProtocol().send(msg);
}
catch (Exception e)
{
e.printStackTrace();
}
}*/
}
private static class ParameterAction extends AbstractAction
{
/**
*
*/
private static final long serialVersionUID = -6529948398460343031L;
public static final String DEFAULTVALUE = "Default value";
public static final String ZEROMORPH = "Zero morph";
public static final String KNOB = "Knob";
public static final String MORPH = "Morph";
public static final String DISABLE_KNOB = "Disable Knob";
public static final String DISABLE_MORPH = "Disable Morph";
public static final String DISABLE_FROM_MORPH = "Disable From Morph";
public static final String DISABLE_MIDI = "Disable Midi";
public static final String MIDI = "MIDI";
public static final String KB = "KB";
private ControlPopup parent;
private int index;
private PParameter parameter = null;
public PParameter getMorphParameter()
{
return (getParameter() == null) ? null : getParameter().getExtensionParameter();
}
public ParameterAction(ControlPopup parent, String actionCommand)
{
this(parent, actionCommand, -1);
}
public ParameterAction(ControlPopup parent, String actionCommand, PParameter parameter)
{
this(parent, actionCommand, -1, parameter);
}
public ParameterAction(ControlPopup parent, String actionCommand, int index) {
this(parent, actionCommand, index, null);
}
public ParameterAction(ControlPopup parent, String actionCommand, int index, PParameter parameter)
{
this.parameter = parameter;
putValue(ACTION_COMMAND_KEY, actionCommand);
this.parent = parent;
setEnabled(false);
this.index = index;
String name;
if (actionCommand == DEFAULTVALUE)
{
name = DEFAULTVALUE;
PParameter p = getParameter();
setEnabled(p.getValue()!=p.getDefaultValue());
}
else if (actionCommand == ZEROMORPH)
{
// TODO check if morph is enabled
setEnabled(getMorphParameter() != null /*&& morph enabled*/);
name = ZEROMORPH;
}
else if (actionCommand == DISABLE_MORPH) {
name = "Disable Morph " + (index + 1);
setEnabled(true);
}
else if (actionCommand == DISABLE_FROM_MORPH) {
name = "Remove Morph from " + getParameter().getParentComponent().getTitle() + extraInfo(getParameter());
setEnabled(getMorphParameter() != null);
}
else if (actionCommand == MORPH)
{
if (index>4) throw new IllegalArgumentException("invalid morph group:"+index);
boolean MorphAssignmentSupported = getMorphParameter() != null;
if (index>=0)
{
name = "Group "+(index+1);
if (MorphAssignmentSupported && index>=0)
{
PNMMorphSection ms = getPatch().getMorphSection();
int assignedToMorph = ms.getAssignedMorph(getParameter());
if (index == assignedToMorph)
{
name += extraInfo(getParameter());
}
else if (!ms.getAssignments(index).isFull())
{
setEnabled(true);
}
}
}
else // disable case
{
name = "Disable";
boolean assignedToMorph = getPatch().getMorphSection().getAssignedMorph(getParameter())>=0;
setEnabled(assignedToMorph);
}
}
else if (actionCommand == DISABLE_KNOB) {
name = "Disable ";
Knob k = getPatch().getKnobs().get(index);
name += k.getName();
setEnabled(true);
} else if (actionCommand == KNOB)
{
setEnabled(true);
if (index<0)
{
name = "Disable";
}
else
{
Knob k = getPatch().getKnobs().get(index);
name = k.getName();
if (k.getParameter() != null)
{
name += extraInfo(k.getParameter());
}
}
}
else if (actionCommand == DISABLE_MIDI) {
name = "Disable ";
name += MidiController.getDefaultName(index);
setEnabled(true);
}
else if (actionCommand == MIDI)
{
boolean assigned = false;
if (index>=0)
{
assigned = getPatch().getMidiControllers().get(index)
.getParameter() == getParameter();
}
if (MidiController.isValidCC(index))
{
setEnabled(!assigned);
MidiController mc = getPatch().getMidiControllers().get(index);
name = MidiController.getDefaultName(index)+extraInfo(mc.getParameter());
}
else
{
if (index==-1)
{
setEnabled(getPatch().getMidiControllers().getMidiControllerIndex(getParameter())>=0);
name = "Disable";
}
else if (index==-2)
{
setEnabled(true);
name = "Other...";
}
else
throw new IllegalArgumentException("invalid midi controller ID: "+index);
}
}
else if (actionCommand == KB && getParameter().getParentComponent().getParentComponent()==getPatch().getMorphSection())
{
PNMMorphSection ms =
(PNMMorphSection)getParameter().getParentComponent().getParentComponent();
setEnabled(ms.getKeyboardAssignment(getParameter().getComponentIndex()).getValue()!=index);
if (index == MorphKeyboardAssignmentMessage.KEYBOARD_VELOCITY)
name = "Velocity";
else if (index == MorphKeyboardAssignmentMessage.KEYBOARD_NOTE)
name = "Note";
else
name = "Disable";
}
else
{
throw new IllegalArgumentException("invalid action command:"+actionCommand);
}
putValue(NAME, name);
}
private String extraInfo(PParameter p)
{
if (p == null) return "";
String moduleName = p.getParentComponent().getName();
String paramName = p.getName();
return " ("+moduleName+"/"+paramName+")";
}
public void actionPerformed(ActionEvent e)
{
if (!isEnabled()) return;
final String command = e.getActionCommand();
if (command == KNOB)
{
if (index<0)
deassignKnob();
else assignKnob();
}
else if (command == DISABLE_KNOB){
deassignKnob();
} else if (command == DISABLE_MORPH) {
deassignMorph();
} else if (command == DISABLE_FROM_MORPH) {
deassignMorph();
} else if (command == DISABLE_MIDI) {
deassignMidiCtrl();
}
else if (command == MORPH)
{
if (index<0)
deassignMorph();
else assignMorph();
}
else if (command == ZEROMORPH)
{
getMorphParameter().setValue(0);
}
else if (command == DEFAULTVALUE)
{
PParameter p = getParameter();
p.setValue(p.getDefaultValue());
}
else if (command == MIDI)
{
if (index>=0) assignMidiCtrl();
else if (index==-1) deassignMidiCtrl();
else if (index==-2) MidiCtrlAssignmentDialog();
}
}
private void MidiCtrlAssignmentDialog()
{
MidiCtrlFrm.showDialog(parent.control, getPatch().getMidiControllers());
}
PParameter getParameter()
{
if (parameter == null)
return parent.getParameter();
else
return parameter;
}
NMPatch getPatch()
{
return parent.getPatch();
}
private void deassignMidiCtrl()
{
getPatch().getMidiControllers().deassign(getParameter());
}
public void assignMidiCtrl()
{
MidiController cc = getPatch().getMidiControllers().get(index);
cc.setParameter(getParameter());
}
private void deassignKnob()
{
getPatch().getKnobs().deassign(getParameter());
}
public void assignKnob()
{
Knob k = getPatch().getKnobs().get(index);
k.setParameter(getParameter());
}
public void deassignMorph()
{
getMorphParameter().setValue(0);
PNMMorphSection m = getPatch().getMorphSection();
int group = m.getAssignedMorph(getParameter());
if (group>=0)
m.getAssignments(group).remove(getParameter());
}
public void assignMorph()
{
PParameter parameter = getParameter();
PNMMorphSection m = getPatch().getMorphSection();
int group = m.getAssignedMorph(parameter);
if (group>=0)
m.getAssignments(group).remove(parameter);
m.getAssignments(index).add(parameter);
}
}
}