/*
* Created on Apr 19, 2007
*
* Copyright (c) 2006-2007 P.J.Leonard
*
* 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.selection;
import static com.frinika.localization.CurrentLocale.getMessage;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import com.frinika.project.ProjectContainer;
import com.frinika.sequencer.gui.Item;
import com.frinika.sequencer.gui.pianoroll.DragEventListener;
import com.frinika.sequencer.gui.pianoroll.FeedbackEventListener;
import com.frinika.sequencer.model.MultiEvent;
import com.frinika.sequencer.model.NoteEvent;
/**
*
* The drag list is a copy of the multiEventSelection.
*
* The copy is created by calling startDrag
*
* The after calling startDrag the caller can
* modifying the items in the drag list (e.g. the pith start tick etc).
* use the notification methods in this class to inform the GUI of changes.
*
* There are two types of observer.
* DragEventListener is interested in changes to the drag list.
* FeedbackItemListener is interested in a single representive item.
* Tpically an element of the drag list (defined as a parameter to start drag)
*
* Calling endDrag(false) will cause the original selected events to be replaced by the dragList.
* endDrag(true) will leave the originals and add the dragList to the part.
*
* You can call directly invoke notifyFeedbackListeners(Item it) if you wish to update the single item view listening
* to the DragList. (Any cleaner way to do this ?)
*
* @author pjl
*
*
*/
@SuppressWarnings("serial")
public class DragList extends Vector<Item> {
private ProjectContainer project;
transient Vector<DragEventListener> dragEventListeners;
transient Vector<FeedbackEventListener> feedbackEventListeners;
private Item dragItem;
// MultiEvent referenceItem;
public DragList(ProjectContainer project) {
this.project=project;
dragEventListeners = new Vector<DragEventListener>();
feedbackEventListeners = new Vector<FeedbackEventListener>();
}
public void endDrag(boolean copy) {
if (project.getMultiEventSelection().getSelected().isEmpty()) {
System.out
.println(" Selected list empty in pianoroll endDrag (why did you bother dragging nothing ?) ");
project.getDragList().clear();
return;
}
if (!copy) {
project.getEditHistoryContainer().mark(getMessage("sequencer.pianoroll.drag_move_notes"));
Iterator<Item> iter = project.getDragList().iterator();
Vector<MultiEvent> list = new Vector<MultiEvent>(project
.getMultiEventSelection().getSelected());
for (MultiEvent ev : list) {
ev.getPart().remove(ev);
ev.restoreFromClone((MultiEvent)iter.next());
ev.getPart().add(ev);
}
assert (!iter.hasNext());
project.getMultiEventSelection().setSelected(list);
} else {
project.getEditHistoryContainer().mark(getMessage("sequencer.pianoroll.drag_copy_notes"));
Iterator<Item> iter = project.getDragList().iterator();
for (MultiEvent ev : project.getMultiEventSelection().getSelected()) {
ev.getPart().add((MultiEvent)iter.next());
}
project.getMultiEventSelection().setSelected(
(Collection) project.getDragList());
assert (!iter.hasNext());
}
project.getEditHistoryContainer().notifyEditHistoryListeners();
project.getMultiEventSelection().notifyListeners();
clear();
notifyFeedbackItemListeners(project.getMultiEventSelection()
.getFocus());
notifyDragEventListeners();
}
public void endDragController() {
// TODO localization
if (project.getMultiEventSelection().getSelected().isEmpty()) {
System.out
.println(" Selected list empty in controllerview endDrag (why did you bother dragging nothing ? ) ");
return;
}
project.getEditHistoryContainer().mark("drag velocity");
// TODO may not want to delete these ? CNTRL DRAG
Iterator<Item> iter = iterator();
Vector<MultiEvent> list =new Vector<MultiEvent>(project.getMultiEventSelection().getSelected());
for (MultiEvent ev : list) {
// if (!validEvent(ev)) continue;
ev.getPart().remove(ev);
ev.restoreFromClone((MultiEvent)iter.next());
ev.getPart().add(ev);
}
project.getEditHistoryContainer().notifyEditHistoryListeners();
clear();
}
/**
*
* Start a drag.
*
*
* @param dragItem reference item for displaying feedback (the copy of this item in the draglist can be observered as it is being draged)
* getDragReferenceItem();
*
*/
public void startDrag(Item dragItemRef) {
// project.clearDragList();
// this.dragItem=dragItem;
Vector<Item> dragList = project.getDragList();
dragList.clear();
// referenceItem = null;
for (MultiEvent it : project.getMultiEventSelection().getSelected()) {
if (it instanceof NoteEvent) {
try {
NoteEvent dragNote = (NoteEvent) (it.clone());
dragList.add(dragNote);
if (it == dragItemRef) {
dragItem=dragNote;
notifyFeedbackItemListeners(dragNote);
}
} catch (CloneNotSupportedException e) {
e.printStackTrace();
}
}
}
}
public void addDragEventListener(DragEventListener o) {
dragEventListeners.add(o);
}
public void removeDragEventListener(DragEventListener o) {
dragEventListeners.add(o);
}
public void notifyDragEventListeners() {
for (DragEventListener l : dragEventListeners) {
l.update();
}
}
public void addFeedbackItemListener(FeedbackEventListener o) {
feedbackEventListeners.add(o);
}
public void removeFeedbackItemListener(FeedbackEventListener o) {
feedbackEventListeners.add(o);
}
public void notifyFeedbackItemListeners(Item ev) {
for (FeedbackEventListener l : feedbackEventListeners) {
l.notifyFeedbackItemChanged(ev);
}
}
public void notifyFeedbackItemListeners() {
for (FeedbackEventListener l : feedbackEventListeners) {
l.notifyFeedbackItemChanged(dragItem);
}
}
}