/* * Created on Feb 7, 2007 * * Copyright (c) 2007 Jens Gulden * * http://www.frinika.com * * This file is part of Frinika. * * Frinika 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. * Frinika 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 Frinika; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package com.frinika.sequencer.gui.menu.midi; import com.frinika.project.ProjectContainer; import com.frinika.project.gui.ProjectFrame; import com.frinika.sequencer.gui.partview.PartView; import com.frinika.sequencer.gui.pianoroll.PianoRoll; import com.frinika.sequencer.gui.selection.MidiSelection; import com.frinika.sequencer.model.MultiEvent; import com.frinika.sequencer.model.NoteEvent; import com.frinika.sequencer.model.MidiLane; import com.frinika.sequencer.model.MidiPart; import com.frinika.gui.AbstractDialogAction; import javax.swing.JMenuItem; import java.awt.KeyboardFocusManager; import java.awt.event.ActionEvent; import java.util.*; /** * Abstract superclass for menu-actions that modify currently selected MIDI * data. * * @author Jens Gulden */ abstract public class AbstractMidiAction extends AbstractDialogAction { protected Collection<MultiEvent> events; protected long startTick; protected long lastTick; protected long endTick; public AbstractMidiAction(ProjectFrame frame, String actionId) { super(frame, actionId); } public void performPrepare() { ProjectContainer project = frame.getProjectContainer(); MidiSelection m = project.getMidiSelection(); events = m.getSelected(); if ((events == null) || (events.isEmpty())) { cancel(); } } @Override public void actionPerformed(ActionEvent e) { if( ! (java.awt.EventQueue.getCurrentEvent().getSource() instanceof JMenuItem) ) { // event does not originate from JMenuItem, but from KeyStroke Object focusOwner = KeyboardFocusManager.getCurrentKeyboardFocusManager().getPermanentFocusOwner(); if( ! ((focusOwner instanceof PartView) || (focusOwner instanceof PianoRoll)) ) { // otherwise any gui-element catching single-key strokes would invoke menu return; } } super.actionPerformed(e); } protected void performAction() { // to modify the model, events must first be removed, later be re-added to the sequencer track Collection<MultiEvent> clones = new ArrayList<MultiEvent>(); try { startTick = 0; lastTick = 0; endTick = 0; for (MultiEvent ev : events) { MultiEvent clone = (MultiEvent) (ev.clone()); clones.add(clone); if ((startTick == 0) || (clone.getStartTick() < startTick)) { startTick = clone.getStartTick(); } if (clone.getStartTick() > lastTick) { lastTick = clone.getStartTick(); } if (clone.getEndTick() > endTick) { endTick = clone.getEndTick(); } } } catch (CloneNotSupportedException cnse) { cnse.printStackTrace(); } modifyEvents(clones); Iterator<MultiEvent> clonesIterator = clones.iterator(); for (MultiEvent ev : events) { //if (ev instanceof NoteEvent) { ev.getPart().remove(ev); ev.restoreFromClone(clonesIterator.next()); ev.getPart().add(ev); //me.commitAdd(); //} } } /** * May be overwritten by subclasses for more complex modifying operations, * otherwise by default this calls midifyNoteEvents with all selected NoteEvents. */ public void modifyEvents(Collection<MultiEvent> events) { Collection<NoteEvent> notes = new ArrayList<NoteEvent>(); for (MultiEvent me : events) { if (me instanceof NoteEvent) { notes.add((NoteEvent)me); } } modifyNoteEvents(notes); } public void modifyNoteEvents(Collection<NoteEvent> events) { for (NoteEvent note : events) { modifyNoteEvent(note); } } public abstract void modifyNoteEvent(NoteEvent note); public MidiPart getMidiPart() { if ((events != null) && (!events.isEmpty())) { return events.iterator().next().getMidiPart(); } else { return null; } } public MidiLane getMidiLane() { MidiPart part = getMidiPart(); if (part != null) { return (MidiLane)part.getLane(); } else { return null; } } }