/* 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.jsynth.nomad.forms;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import javax.swing.AbstractListModel;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.Icon;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import net.sf.nmedit.jsynth.Bank;
import net.sf.nmedit.jsynth.Slot;
import net.sf.nmedit.jsynth.Synthesizer;
import net.sf.nmedit.jsynth.event.BankUpdateEvent;
import net.sf.nmedit.jsynth.event.BankUpdateListener;
import net.sf.nmedit.jsynth.worker.PatchLocation;
public class SaveInSynthDialog extends JDialog
{
/**
*
*/
private static final long serialVersionUID = 4854099017201533301L;
private Collection<Synthesizer> synths;
private SaveInSynthFrm form;
private boolean saveInBankAllowed = true;
private boolean saveInSlotAllowed = true;
private boolean openPatchAllowed = false;
private BankComboBoxModel usedBankModel;
public SaveInSynthDialog(Collection<Synthesizer> synths)
{
this.synths = synths;
setTitle("Save In Synthesizer");
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
createComponents();
}
public void setSaveInBankAllowed(boolean a)
{
if (this.saveInBankAllowed != a)
{
this.saveInBankAllowed = a;
updateState();
updateCheckBoxes();
}
}
public void setSaveInSlotAllowed(boolean a)
{
if (this.saveInSlotAllowed != a)
{
this.saveInSlotAllowed = a;
updateState();
updateCheckBoxes();
}
}
public void setOpenPatchAllowed(boolean a)
{
if (this.openPatchAllowed != a)
{
this.openPatchAllowed = a;
updateCheckBoxes();
}
}
private void updateCheckBoxes()
{
if (form.cbSaveInSlot.isEnabled())
{
if (isSaveInSlotAllowed() && (!isSaveInBankAllowed()))
form.cbSaveInSlot.setSelected(true);
}
if (form.cbSaveInBank.isEnabled())
{
if (isSaveInBankAllowed() && (!isSaveInSlotAllowed()))
form.cbSaveInBank.setSelected(true);
}
form.cbOpenPatch.setEnabled(openPatchAllowed);
}
public boolean isSaveInBankAllowed()
{
return saveInBankAllowed;
}
public boolean isOpenPatchAllowed()
{
return openPatchAllowed;
}
public boolean isSaveInSlotAllowed()
{
return saveInSlotAllowed;
}
public boolean isOpenPatchSelected()
{
return form.cbOpenPatch.isSelected();
}
public void setOpenPatchSelected(boolean s)
{
form.cbOpenPatch.setSelected(s);
}
private void createComponents()
{
form = new SaveInSynthFrm();
form.cbSynth.setModel(new DefaultComboBoxModel(synths.toArray()));
form.lblIcon.setText("");
form.cbSaveInSlot.setSelected(true);
form.cbSaveInBank.setSelected(false);
form.cbSlot.setRenderer(new CustomRenderer());
form.cbSynth.setRenderer(new CustomRenderer());
form.cbBank.setRenderer(new CustomRenderer());
form.cbBank.setMaximumRowCount(20);
form.cbSynth.setMaximumRowCount(20);
getRootPane().setDefaultButton(form.btnSave);
ActionHandler actionHandler = new ActionHandler();
form.cbSynth.setActionCommand(ActionHandler.SELECT_SYNTH);
form.cbSlot.setActionCommand(ActionHandler.SELECT_BANK_SLOT);
form.cbBank.setActionCommand(ActionHandler.SELECT_BANK_SLOT);
form.btnSave.setActionCommand(ActionHandler.SAVE);
form.btnCancel.setActionCommand(ActionHandler.CANCEL);
form.cbSaveInSlot.setActionCommand(ActionHandler.TOGGLE_SLOT_SELECT);
form.cbSaveInBank.setActionCommand(ActionHandler.TOGGLE_BANK_SELECT);
form.cbSynth.addActionListener(actionHandler);
form.cbSlot.addActionListener(actionHandler);
form.cbBank.addActionListener(actionHandler);
form.btnSave.addActionListener(actionHandler);
form.btnCancel.addActionListener(actionHandler);
form.cbSaveInSlot.addActionListener(actionHandler);
form.cbSaveInBank.addActionListener(actionHandler);
JPanel cp = new JPanel();
setContentPane(cp);
form.setBorder(BorderFactory.createEmptyBorder(2, 2, 2, 2));
getContentPane().setLayout(new BorderLayout());
getContentPane().add(new JScrollPane(form));
updateData();
updateState();
updateSynthIcon();
pack();
}
public void invoke()
{
Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
setLocation((screen.width-getWidth())/2, (screen.height-getHeight())/2);
setModal(true);
setVisible(true);
}
private class ActionHandler implements ActionListener
{
public static final String SELECT_SYNTH = "select.synth";
public static final String SELECT_BANK_SLOT = "select.bankslot";
public static final String SAVE = "save";
public static final String CANCEL = "cancel";
public static final String TOGGLE_SLOT_SELECT = "toggle.slot.select";
public static final String TOGGLE_BANK_SELECT = "toggle.bank.select";
public void actionPerformed(ActionEvent e)
{
String cmd = e.getActionCommand();
if (cmd == SELECT_SYNTH)
synthSelected();
else if (cmd == SELECT_BANK_SLOT)
updateState();
else if (cmd == TOGGLE_BANK_SELECT)
updateState();
else if (cmd == TOGGLE_SLOT_SELECT)
updateState();
else if (cmd == SAVE)
save();
else if (cmd == CANCEL)
cancel();
}
}
private void synthSelected()
{
updateData();
updateState();
updateSynthIcon();
}
private void updateSynthIcon()
{
Synthesizer synth = (Synthesizer) form.cbSynth.getSelectedItem();
Object ic = null;
if (synth != null)
ic = synth.getClientProperty("icon");
Icon icon = null;
if (ic instanceof Icon)
icon = (Icon) ic;
form.lblIcon.setIcon(icon);
}
private void updateData()
{
form.cbSlot.removeAllItems();
form.cbBank.removeAllItems();
Synthesizer synth = (Synthesizer) form.cbSynth.getSelectedItem();
ComboBoxModel model = getSlotModel(synth);
if (model != null)
form.cbSlot.setModel(model);
if (usedBankModel != null)
{
usedBankModel.uninstallListeners();
}
model = createBankModel(synth);
if (model != null)
form.cbBank.setModel(model);
}
private void updateState()
{
boolean dataToSaveInSlot =
saveInSlotAllowed &&
form.cbSlot.getItemCount()>0;
boolean dataToSaveInBank =
saveInBankAllowed &&
form.cbBank.getItemCount()>0;
boolean canSaveInSlot =
dataToSaveInSlot &&
form.cbSaveInSlot.isSelected();
boolean canSaveInBank =
dataToSaveInBank &&
form.cbSaveInBank.isSelected();
form.cbSaveInSlot.setEnabled(dataToSaveInSlot);
form.cbSlot.setEnabled(canSaveInSlot);
form.cbSaveInBank.setEnabled(dataToSaveInBank);
form.cbBank.setEnabled(canSaveInBank);
form.btnSave.setEnabled(canSaveInSlot||canSaveInBank);
}
private ComboBoxModel getSlotModel(Synthesizer synth)
{
if (synth != null)
{
List<Slot> slots = new ArrayList<Slot>(synth.getSlotCount());
for (int i=0;i<synth.getSlotCount();i++)
{
slots.add(synth.getSlot(i));
}
return new DefaultComboBoxModel(slots.toArray());
}
return null;
}
private ComboBoxModel createBankModel(Synthesizer synth)
{
if (synth != null)
{
return new BankComboBoxModel(synth);
}
return null;
}
private class BankComboBoxModel extends AbstractListModel implements ComboBoxModel, BankUpdateListener
{
/**
*
*/
private static final long serialVersionUID = 1400245057461209914L;
Object selectedObject;
private Bank<?>[] banks;
private List<PatchLocation> data;
private Synthesizer synth;
public BankComboBoxModel(Synthesizer synth)
{
this.synth = synth;
this.banks = synth.getBanks();
List<PatchLocation> data = new ArrayList<PatchLocation>(banks.length*100);
for (int i=0;i<synth.getBankCount();i++)
{
Bank<?> b = banks[i];
for (int j=0;j<b.getPatchCount();j++)
{
data.add(new BankPatchLocation(b, j));
}
}
this.data = data;
if (!data.isEmpty())
selectedObject = data.get(0);
installListeners();
// now check if updates are necessary
for (Bank<?> b: banks)
{
for (int i=0;i<b.getPatchCount();i++)
if (!b.isPatchInfoAvailable(i))
{
b.update(i, b.getPatchCount()-1);
break;
}
}
}
public void installListeners()
{
for (Bank<?> b: banks)
b.addBankUpdateListener(this);
}
public void uninstallListeners()
{
for (Bank<?> b: banks)
b.removeBankUpdateListener(this);
}
public void bankUpdated(BankUpdateEvent e)
{
fireContentsChanged(this, 0, data.size());
}
public void setSelectedItem(Object anObject) {
if ((selectedObject != null && !selectedObject.equals( anObject )) ||
selectedObject == null && anObject != null) {
selectedObject = anObject;
fireContentsChanged(this, -1, -1);
}
}
public Object getSelectedItem() {
return selectedObject;
}
public Object getElementAt(int index)
{
return data.get(index);
}
public int getSize()
{
return data.size();
}
}
private static class BankPatchLocation extends PatchLocation
{
private Bank<?> bank;
public BankPatchLocation(Bank<?> bank, int position)
{
super(bank.getBankIndex(), position);
this.bank = bank;
}
public String toString()
{
int pos = getPosition();
String name = bank.getPatchLocationName(pos)+": ";
if (!bank.isPatchInfoAvailable(pos))
{
name+="?";
}
else if (!bank.containsPatch(pos))
{
name+="<empty>";
}
else
{
name+=bank.getPatchName(pos);
}
return name;
}
}
private Object action = ActionHandler.CANCEL;
private void cancel()
{
action = ActionHandler.CANCEL;
setVisible(false);
dispose();
}
private void save()
{
action = ActionHandler.SAVE;
setVisible(false);
dispose();
}
public Synthesizer getSelectedSynthesizer()
{
if (isSaveOption())
{
return (Synthesizer) form.cbSynth.getSelectedItem();
}
return null;
}
public Slot getSelectedSlot()
{
if (getSelectedSynthesizer() != null)
{
if (!form.cbSaveInSlot.isSelected())
return null;
if (!isSaveInSlotAllowed())
return null;
return (Slot) form.cbSlot.getSelectedItem();
}
return null;
}
public PatchLocation getSelectedBank()
{
if (getSelectedSynthesizer() != null)
{
if (!form.cbSaveInBank.isSelected())
return null;
if (!isSaveInBankAllowed())
return null;
return (PatchLocation) form.cbBank.getSelectedItem();
}
return null;
}
public boolean isSaveOption()
{
return action == ActionHandler.SAVE;
}
private static class CustomRenderer extends DefaultListCellRenderer
{
/**
*
*/
private static final long serialVersionUID = 5574547544934341852L;
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus)
{
String text = null;
if (value != null)
{
if (value instanceof Synthesizer)
{
Synthesizer synth = (Synthesizer) value;
String n = synth.getName();
String dv = synth.getDeviceName();
String v = synth.getVendor();
if (n == null)
text = dv+" ("+v+")";
else
text = n+" ("+v+" "+dv+")";
}
else if (value instanceof Slot)
{
Slot slot = (Slot) value;
text = slot.getName()+" (Slot "+(1+slot.getSlotIndex())+")";
}
else
{
text = String.valueOf(value);
}
}
return super.getListCellRendererComponent(list, text, index, isSelected, cellHasFocus);
}
}
}