/* * Created on Mar 21, 2006 * * Copyright (c) 2006 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.pianoroll; import static com.frinika.localization.CurrentLocale.getMessage; import java.awt.Color; import java.awt.Cursor; import java.awt.Graphics2D; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.font.TextLayout; import java.awt.geom.Point2D; import java.awt.geom.Rectangle2D; import java.util.Collection; import java.util.Iterator; import java.util.Vector; import com.frinika.project.ProjectContainer; import com.frinika.project.gui.ProjectFrame; import com.frinika.sequencer.FrinikaSequence; import com.frinika.sequencer.SwingSongPositionListenerWrapper; import com.frinika.sequencer.gui.ColorScheme; import com.frinika.sequencer.gui.DragViewTool; import com.frinika.sequencer.gui.EraseTool; import com.frinika.sequencer.gui.Item; import com.frinika.sequencer.gui.ItemScrollPane; import com.frinika.sequencer.gui.Layout; import com.frinika.sequencer.gui.MyCursors; import com.frinika.sequencer.gui.RectZoomTool; import com.frinika.sequencer.gui.SelectTool; import com.frinika.sequencer.gui.WriteTool; import com.frinika.sequencer.gui.pianoroll.ControllerHandle; import com.frinika.sequencer.model.EditHistoryAction; import com.frinika.sequencer.model.EditHistoryContainer; import com.frinika.sequencer.model.MidiLane; import com.frinika.sequencer.model.MidiPart; import com.frinika.sequencer.model.MultiEvent; import com.frinika.sequencer.model.Part; import com.frinika.sequencer.model.util.EventsInPartsIterator; public class ControllerView extends PianoRollPanelAdapter implements AdjustmentListener { // Height of each NoteItem (multiple of ? to make piano nice ?) ; int defaultLength; // create notes 1 beat long int pitchTop = 127; // top of screen in pitch (actually value in this case) int noteItemHeight; int yScreenBot; int velocity = 100; int channel = 1; private static final long serialVersionUID = 1L; private static final Color selCol = new Color(127, 127, 127, 200); // private static final Color noteCol = Color.RED; // private static final Color dragCol = Color.BLACK; //Vector<MultiEvent> dragList; EditHistoryContainer editHistory; Vector<MultiEvent> notesUnder; private ItemPanelMultiEventListener multiEventListener; private ItemPanelPartListener partListener; private int panelHeight; private int xLast; private ControllerHandle cntrl; private boolean velocityMode; MultiEvent dragEvent; Iterable<MultiEvent> eventsOnScreen; Iterable<MultiEvent> eventsInFocus; private int dValLast; /** * Constructor. * * @param project * project to view * @param scroller * controls the view onto the virtualScreen. */ public ControllerView(final ProjectFrame frame, ItemScrollPane scroller) { super(frame.getProjectContainer(), scroller,false,false); final ProjectContainer project = frame.getProjectContainer(); this.sequencer = project.getSequencer(); multiEventListener = new ItemPanelMultiEventListener(this); partListener = new ItemPanelPartListener(this); eventsOnScreen = new Iterable<MultiEvent>() { public Iterator<MultiEvent> iterator() { return new EventsInPartsIterator(project.getPartSelection() .getSelected(), ControllerView.this); } }; eventsInFocus = new Iterable<MultiEvent>() { public Iterator<MultiEvent> iterator() { Part focus = project.getPartSelection().getFocus(); if (focus == null) return null; return new EventsInPartsIterator(project.getPartSelection() .getFocus(), ControllerView.this); } }; project.getMultiEventSelection().addSelectionListener( multiEventListener); project.getPartSelection().addSelectionListener(partListener); // focusLane = null; sequencer.addSongPositionListener(new SwingSongPositionListenerWrapper(this)); FrinikaSequence seq = (FrinikaSequence) sequencer.getSequence(); editHistory = project.getEditHistoryContainer(); editHistory.addEditHistoryListener(this); ticksPerBeat = seq.getResolution(); defaultLength = ticksPerBeat; // snaptoQuantization = ticksPerBeat; setLayout(null); setBackground(Color.WHITE); repaintItems(); addComponentListener(this); makeTools(); } public void dispose() { project.getMultiEventSelection().removeSelectionListener( multiEventListener); project.getPartSelection().removeSelectionListener(partListener); editHistory.removeEditHistoryListener(this); } public void dragTo(Point p) { if (dragArmed) dValLast = 0; int dyDragged = p.y - yAnchor; int dValToT = 0; dValToT = -(dyDragged * (cntrl.maxVal - cntrl.minVal)) / panelHeight; int dVal = dValToT - dValLast; if (dVal == 0) return; if (dragArmed) dragStart(); dragArmed = false; dValLast = dValToT; Collection<Item> dragList=project.getDragList(); if (dVal != 0) { int valLim; if (dVal > 0) valLim = cntrl.minVal; else valLim = cntrl.maxVal; for (Item ev1 : dragList) { MultiEvent ev=(MultiEvent)ev1; int pitch = ev.getValueUI() + dVal; if (dVal > 0) valLim = Math.max(pitch, valLim); else valLim = Math.min(pitch, valLim); } if (dVal > 0 && valLim > cntrl.maxVal) dVal = dVal - (valLim - cntrl.maxVal); else if (dVal < 0 && valLim < cntrl.minVal) dVal = dVal - (valLim - cntrl.minVal); } if (dVal == 0) return; // boolean first = true; // long dt = 0; // MultiEvent dev = null; // boolean velMode = cntrl.name.equals("velocity"); for (Item ev1 : dragList) { MultiEvent ev=(MultiEvent)ev1; switch (dragMode) { case OVER_ITEM_TOP: int val = ev.getValueUI() + dVal; ev.setValue(val); break; default: try { throw new Exception(" unknown dragmode " + dragMode); } catch (Exception e) { e.printStackTrace(); } } } project.getDragList().notifyDragEventListeners(); project.getDragList().notifyFeedbackItemListeners(); repaintItems(); } public void clientClearSelection() { project.getMultiEventSelection().clearSelection(); } /** * Call this to start dragging with the reference point. See dragTo A copy * is made of the valid selected events into dragList. * */ public void dragStart() { project.getDragList().startDrag(dragItem); // dragList = new Vector<MultiEvent>(); // for (MultiEvent it : eventsInFocus) { // // { // // if (it instanceof NoteEvent) { // assert (isValidEvent(it)); // if (!it.isSelected()) // continue; // try { // MultiEvent dragMe = (MultiEvent) (it.clone()); // dragList.add(dragMe); // if (it == dragItem) { // dragEvent = dragMe; // project.getDragList().notifyDragEventListeners(dragMe); // } // } catch (CloneNotSupportedException e) { // e.printStackTrace(); // } // } } /** * Select/deselect all the items in a rectange. * * @param yes * true to select. false to deselect * @param rect * rectangle in score screen space. */ public synchronized void selectInRect(Rectangle rect,boolean shift) { Collection<MultiEvent> addTmp = new Vector<MultiEvent>(); Collection<MultiEvent> delTmp = new Vector<MultiEvent>(); Iterable<MultiEvent> list; Part focusPart = project.getPartSelection().getFocus(); if (focusPart != null) list = eventsInFocus; else list = eventsOnScreen; for (MultiEvent note : list) { if (!isValidEvent(note)) continue; if (rect.intersects(getItemBounds(note))) { if (shift) { if (note.isSelected()) delTmp.add(note); else addTmp.add(note); } else { addTmp.add(note); } } } project.getMultiEventSelection().removeSelected(delTmp); project.getMultiEventSelection().addSelected(addTmp); project.getMultiEventSelection().notifyListeners(); } @Override public void writeDraggedAt(Point p) { Part focusPart = project.getPartSelection().getFocus(); if (focusPart == null || !(focusPart instanceof MidiPart)) { System.out.println(" Please slectect a part "); return; } int x1 = Math.min(xLast, p.x); int x2 = Math.max(xLast, p.x); long tick1 = 0; long tick2 = 0; if (velocityMode) { notesUnder = eventsUnderScreen(x1, x2); if (notesUnder.size() == 0) return; } else { tick1 = screenToTickAbs(x1, true); tick2 = screenToTickAbs(x2, true) + (long) project.getPianoRollSnapQuantization(); notesUnder = eventsUnderTime(tick1, tick2); // TODO fixme } int val = screenToValue(p.y); xLast = p.x; val = Math.max(val, cntrl.minVal); val = Math.min(val, cntrl.maxVal); if (velocityMode) { setValue(notesUnder, val); project.getDragList().notifyFeedbackItemListeners(notesUnder.firstElement()); } else { if (notesUnder.size() != 0) { for (MultiEvent ev : notesUnder) { ev.getPart().remove(ev); } } MultiEvent ev = null; for (long tick = tick1; tick < tick2; tick += project.getPianoRollSnapQuantization()) { ev = cntrl.createEvent((MidiPart) focusPart, tick, val); ((MidiPart) focusPart).add(ev); } if (ev != null) project.getDragList().notifyFeedbackItemListeners(ev); } repaintItems(); } protected synchronized void writePressedAt(Point p) { Part focusPart = project.getPartSelection().getFocus(); velocityMode = cntrl.isVelocity(); if (focusPart == null || !(focusPart instanceof MidiPart)) { System.out.println(" Please slectect a part "); return; } if (velocityMode) { notesUnder = eventsUnderScreen(p.x, p.x); } else { long tick = screenToTickAbs(p.x, true); long tick2 = tick + (long) project.getPianoRollSnapQuantization(); notesUnder = eventsUnderTime(tick, tick2); // TODO fixme } xLast = p.x; int val = screenToValue(p.y); val = Math.max(val, cntrl.minVal); val = Math.min(val, cntrl.maxVal); if (velocityMode) { project.getEditHistoryContainer().mark( getMessage("sequencer.controllerview.adjust_velocity")); if (notesUnder.size() != 0) { setValue(notesUnder, val); project.getDragList().notifyFeedbackItemListeners(notesUnder.firstElement()); } } else { project.getEditHistoryContainer().mark( getMessage("sequencer.controllerview.write_control")); if (notesUnder.size() != 0) { for (MultiEvent ev : notesUnder) { ev.getPart().remove(ev); } } long tick = screenToTickAbs(p.x, true); MultiEvent ev = cntrl.createEvent((MidiPart) focusPart, tick, val); // new ControllerEvent((MidiPart) focusPart, tick, // cntrl.contrl, val); ((MidiPart) focusPart).add(ev); project.getDragList().notifyFeedbackItemListeners(ev); } repaintItems(); } void setValue(Vector<MultiEvent> notes, int val) { for (MultiEvent note : notes) { if (note.getValueUI() == val) continue; // ---------- Example by PJS MidiPart p = note.getPart(); p.remove(note); note.setValue(val); p.add(note); // ----------------------------- // note.commitChanges(); } repaintItems(); } private int screenToValue(int y) { return cntrl.minVal + ((panelHeight - y) * (cntrl.maxVal - cntrl.minVal)) / panelHeight; // TODO Auto-generated method stub } private int valueToScreen(int val) { return panelHeight - ((val - cntrl.minVal) * panelHeight) / (cntrl.maxVal - cntrl.minVal); } private Vector<MultiEvent> eventsUnderScreen(int x1, int x2) { Vector<MultiEvent> noteEvents = new Vector<MultiEvent>(); for (MultiEvent note : ((MidiPart) project.getPartSelection() .getFocus()).getMultiEvents()) { if (!isValidEvent(note)) continue; Rectangle rect = getItemBounds(note); int x11 = rect.x; int x22 = rect.x + rect.width; if ((x1 <= x22 && x1 >= x11) || (x2 <= x22 && x2 >= x11) || (x1 <= x11 && x2 >= x22)) { noteEvents.add(note); } } return noteEvents; } private Vector<MultiEvent> eventsUnderTime(long tick1, long tick2) { Vector<MultiEvent> noteEvents = new Vector<MultiEvent>(); for (MultiEvent note : ((MidiPart) project.getPartSelection() .getFocus()).getMultiEvents()) { if (!isValidEvent(note)) continue; long tick = note.getStartTick(); if (tick1 <= tick && tick < tick2) { noteEvents.add(note); } } return noteEvents; } /** * convert screen y to a pitch * * @param y * @return pitch for the given screen y */ private int screenToPitch(int y) { return pitchTop - (y / noteItemHeight); } /** * Find component the contains point x,y and set. first component found is * set (is this what we want ?) TODO multitrack thinking. * * @param x * @param y * @return the NoteEvent at this point. */ public Item itemAt(Point p) { MultiEvent at = null; for (MultiEvent note : eventsOnScreen) { if (!isValidEvent(note)) continue; if (getItemBounds(note).contains(p)) { if (note.isSelected()) return note; else if (at == null) at = note; } } return at; } public void fireSequenceDataChanged(EditHistoryAction[] edithistoryActions) { repaintItems(); } public synchronized void paintImageImpl(final Rectangle visibleRect, Graphics2D g) { if (g == null) return; if (cntrl == null) return; noteItemHeight = Layout.getNoteItemHeight(); yScreenBot = pitchTop * noteItemHeight; velocityMode = cntrl.isVelocity(); if (velocityMode) paintImageImplVel(visibleRect, g); else paintImageImplCntrl(visibleRect, g); } public synchronized void paintImageImplLabel(Graphics2D g) { if (g == null) return; if (cntrl == null) return; String label = cntrl.getName(); TextLayout tl = new TextLayout(label, g.getFont(), g .getFontRenderContext()); Rectangle2D bounds = tl.getBounds(); int margin = 3; // bot right of BB Point2D.Float locBB = new Point2D.Float(0f, (float) tl.getBounds() .getHeight() + 2 * margin); Point2D locTEXT = new Point2D.Float(margin, locBB.y - margin); bounds.setRect(0, 0, bounds.getWidth() + margin * 2, bounds.getHeight() + margin * 2); g.setColor(Color.WHITE); g.fill(bounds); g.setColor(Color.BLACK); g.draw(bounds); tl.draw(g, (float) locTEXT.getX(), (float) locTEXT.getY()); } private synchronized void paintImageImplCntrl(final Rectangle visibleRect, Graphics2D g) { int w = visibleRect.width; int x = visibleRect.x; int y = visibleRect.y; panelHeight = visibleRect.height; int yBot = yScreenBot; g.setColor(Color.WHITE); g.fill(visibleRect); // Vertical lines double tick1 = screenToTickAbs(x, true); int x1 = (int) userToScreen((long) tick1); if (x1 < x) { tick1 += project.getPianoRollSnapQuantization(); x1 = (int) userToScreen((long) tick1); } assert (x1 >= x); while (x1 < x + w) { if (Math.abs((tick1 + 1.0) % ticksPerBeat) < 2.0) g.setColor(Color.BLACK); else g.setColor(Color.lightGray); g.drawLine(x1, y, x1, y + panelHeight); tick1 += project.getPianoRollSnapQuantization(); x1 = (int) userToScreen((long) tick1); } // Horizontal lines g.setColor(Color.lightGray); // maxVal = 127; int inc = 10; for (int i = 0; i < 127; i += inc) { if (i % 10 != 0) continue; int yy = panelHeight - (i * panelHeight) / (cntrl.maxVal - cntrl.minVal); g.drawLine(x, yy, x + w, yy); } // Now draw the notes.................... Part fc=project.getPartSelection().getFocus(); if (fc != null && !( fc instanceof MidiPart)) return; MidiPart focusPart = (MidiPart) fc; MultiEvent evPrev = null; MultiEvent evNext = null; int valPrev = 0; int valNext = 0; int xNext = 0; int xPrev = 0; if (focusPart == null) return; Iterator<MultiEvent> iter = eventsInFocus.iterator(); if (!iter.hasNext()) return; Iterator<Item> diter = null; Collection<Item> dragList=project.getDragList(); if (!dragList.isEmpty()) diter = dragList.iterator(); boolean doit = true; boolean highLightNext=false; Rectangle rect = new Rectangle(); do { valPrev = valNext; evPrev = evNext; xPrev = xNext; boolean hilight = highLightNext; if (iter.hasNext()) { MultiEvent ev = iter.next(); if (!isValidEvent(ev)) continue; if (ev.isSelected()) { highLightNext = true; if (diter != null) { ev = (MultiEvent)diter.next(); } } else { highLightNext = false; } evNext = ev; xNext = (int)userToScreen(evNext.getStartTick()); valNext = evNext.getValueUI(); if (xNext < visibleRect.x) continue; } else { xNext = visibleRect.x + visibleRect.width; doit = false; } if (valPrev == cntrl.minVal) continue; rect.y = valueToScreen(valPrev); rect.height = panelHeight - rect.y; if (xNext > (visibleRect.x + visibleRect.width)) { xNext = visibleRect.x + visibleRect.width; } rect.x = xPrev; rect.width = xNext - xPrev; if (evPrev != null) { if (hilight) { // if (dragList == null) { g.setColor(ColorScheme.selectedColor); g.fill(rect); // } evPrev = evNext; } else { MidiLane myLane = (MidiLane) focusPart.getLane(); if (myLane == null) { g.setColor(Color.BLACK); } else { g.setColor(focusPart.getColor()); } g.fill(rect); } } evPrev = evNext; } while (doit); } public synchronized void paintImageImplVel(final Rectangle visibleRect, Graphics2D g) { int w = visibleRect.width; int x = visibleRect.x; int y = visibleRect.y; panelHeight = visibleRect.height; int yBot = yScreenBot; // - itemViewRect.y + Layout.timePanelHeight; // Draw vertical lines g.setColor(Color.WHITE); g.fill(visibleRect); // Vertical lines double tick1 = screenToTickAbs(x, true); double snaptoQuantization=project.getPianoRollSnapQuantization(); int x1 = (int)userToScreen((long) tick1); if (snaptoQuantization <= 0) { snaptoQuantization = project.getTicksPerBeat(); } if (x1 < x) { tick1 += snaptoQuantization; x1 =(int) userToScreen((long) tick1); } assert (x1 >= x); while (x1 < x + w) { if (Math.abs((tick1 + 1.0) % ticksPerBeat) < 2.0) g.setColor(Color.BLACK); else g.setColor(Color.lightGray); g.drawLine(x1, y, x1, y + panelHeight); tick1 += snaptoQuantization; x1 = (int)userToScreen((long) tick1); } // Horizontal lines g.setColor(Color.lightGray); // maxVal = 127; int inc = 10; for (int i = 0; i < 127; i += inc) { if (i % 10 != 0) continue; int yy = valueToScreen(i); g.drawLine(x, yy, x + w, yy); } // Now draw the notes.................... Part focusPart = project.getPartSelection().getFocus(); Collection<Item> dragList=project.getDragList(); if (!(focusPart instanceof MidiPart)) return; for (MultiEvent note : eventsOnScreen) { if (!isValidEvent(note)) continue; if (focusPart != null && note.getPart() == focusPart) continue; Rectangle noteRect = getItemBounds(note); if (visibleRect != null && !visibleRect.intersects(noteRect)) continue; if (note.isSelected()) { if (!dragList.isEmpty()) { g.setColor(ColorScheme.selectedColor); g.fill(noteRect); } } else { MidiLane myLane = (MidiLane) note.getPart().getLane(); if (myLane == null) { g.setColor(Color.BLACK); } else { g.setColor(note.getPart().getColor()); } g.fill(noteRect); } } if (focusPart != null) { for (MultiEvent note : ((MidiPart) focusPart).getMultiEvents()) { if (!isValidEvent(note)) continue; Rectangle noteRect = getItemBounds(note); if (visibleRect != null && !visibleRect.intersects(noteRect)) continue; if (note.isSelected()) { if (dragList.isEmpty()) { g.setColor(selCol); g.fill(noteRect); } } else { MidiLane myLane = (MidiLane) note.getPart().getLane(); if (myLane == null) { g.setColor(Color.BLACK); } else { g.setColor(note.getPart().getColor()); } g.fill(noteRect); } g.setColor(Color.BLACK); g.draw(noteRect); } } for (Item it: dragList) { MultiEvent note=(MultiEvent)it; Rectangle noteRect = getItemBounds(note); if (visibleRect != null && !visibleRect.intersects(noteRect)) continue; g.setColor(selCol); g.fill(noteRect); g.setColor(Color.RED); g.draw(noteRect); } } /** * Find the screen rectangle for the event * * WOuld it be better to pass a reference save creating off the stack (doubt * it?) * * @param e * NoteEvent * @return rectangle on screen */ final Rectangle tmpRect=new Rectangle(); private Rectangle getItemBounds(Item it) { // final Rectangle rect=new Rectangle(); MultiEvent e = (MultiEvent) it; long tick = e.getStartTick(); // long dur = e.getDuration(); int h1 = 0; h1 = ((e.getValueUI() - cntrl.minVal) * panelHeight) / (cntrl.maxVal - cntrl.minVal); // Careful that origins must always conincide int x1 = (int)userToScreen(tick); int w = 5; //rect.x=x1; tmpRect.setBounds((int) x1, panelHeight - h1, w, h1); return tmpRect; //return new Rectangle(); } @Override public void endDrag() { if (dragArmed) { dragArmed = false; return; } project.getDragList().endDragController(); } public void erase(Item it) { MultiEvent note = (MultiEvent) it; velocityMode = cntrl.isVelocity(); if (velocityMode) editHistory.mark("erase note"); else editHistory.mark("erase event"); note.getPart().remove(note); editHistory.notifyEditHistoryListeners(); } /* @Override public void setQuantizeOn(boolean b) { quantize = b; if (b) MultiEventClipboard.getDefaultMultiEventClipboard() .setQuantization(snaptoQuantization); else MultiEventClipboard.getDefaultMultiEventClipboard() .setQuantization(1); }*/ @Override public void rightButtonPressedOnItem(int x,int y) { System.out.println(" Right button pressed (so what?) "); } @Override public void clientAddToSelection(Item item) { project.getMultiEventSelection().addSelected((MultiEvent) item); project.getMultiEventSelection().notifyListeners(); } @Override public void clientRemoveFromSelection(Item item) { project.getMultiEventSelection().removeSelected((MultiEvent) item); project.getMultiEventSelection().notifyListeners(); } /** * Only used for it's iterator * * @author pjl * */ class NoteOnScreenCollection implements Collection<MultiEvent> { public int size() { // TODO Auto-generated method stub return 0; } public boolean isEmpty() { // TODO Auto-generated method stub return false; } public boolean contains(Object o) { // TODO Auto-generated method stub return false; } public Iterator<MultiEvent> iterator() { return new NoteOnScreenIterator(); } public Object[] toArray() { // TODO Auto-generated method stub return null; } public <T> T[] toArray(T[] a) { // TODO Auto-generated method stub return null; } public boolean add(MultiEvent o) { // TODO Auto-generated method stub return false; } public boolean remove(Object o) { // TODO Auto-generated method stub return false; } public boolean containsAll(Collection<?> c) { // TODO Auto-generated method stub return false; } public boolean addAll(Collection<? extends MultiEvent> c) { // TODO Auto-generated method stub return false; } public boolean removeAll(Collection<?> c) { // TODO Auto-generated method stub return false; } public boolean retainAll(Collection<?> c) { // TODO Auto-generated method stub return false; } public void clear() { // TODO Auto-generated method stub } } /** * TODO Rough implmentation needs to be optimized * * @author pjl * */ class NoteOnScreenIterator implements Iterator<MultiEvent> { Iterator<Part> partIter = null; Iterator<MultiEvent> noteIter = null; NoteOnScreenIterator() { partIter = project.getPartSelection().getSelected().iterator(); advanceToNextMidiPart(); } private boolean advanceToNextMidiPart() { Part part = null; while (partIter.hasNext()) { part = partIter.next(); if (part instanceof MidiPart) { noteIter = ((MidiPart) part).getMultiEvents().iterator(); return true; } } noteIter = null; return false; } public boolean hasNext() { if (noteIter == null) return false; if (noteIter.hasNext()) return true; // TODO Auto-generated method stub return advanceToNextMidiPart(); } public MultiEvent next() { if (noteIter.hasNext()) { MultiEvent ev = noteIter.next(); return ev; } // He he sneak a bit of recursion in here (PJL) if (advanceToNextMidiPart()) return next(); return null; } public void remove() { assert (false); // TODO Auto-generated method stub } } @Override public int getHoverStateAt(Point p) { final int endTol = 20; // final int extraX = 20 ; // if (true) return OVER_ITEM_MIDDLE; int tol = endTol; Iterable<MultiEvent> list; Part focusPart = project.getPartSelection().getFocus(); if (! (focusPart instanceof MidiPart) ) return OVER_NOTHING; if (focusPart == null) list = eventsOnScreen; else list = eventsInFocus; for (MultiEvent e : list) { assert (isValidEvent(e)); Rectangle rect = getItemBounds(e); if (rect.contains(p)) { return OVER_ITEM_TOP; } } return OVER_NOTHING; } public void adjustmentValueChanged(AdjustmentEvent arg0) { setX(arg0.getValue()); } void makeTools() { Cursor c = new Cursor(Cursor.DEFAULT_CURSOR); selectTool = new SelectTool(c); rectZoomTool = new RectZoomTool(c); writeTool = new WriteTool(MyCursors.getCursor("pencil")); eraseTool = new EraseTool(MyCursors.getCursor("eraser")); dragViewTool = new DragViewTool(MyCursors.getCursor("move")); } public void setControllerType(ControllerHandle handle) { this.cntrl = handle; setDirty(); repaintItems(); } final public boolean isValidEvent(MultiEvent ev) { // are we in velocity mode then only use NoteEvents. if (cntrl == null) return false; return cntrl.isValid(ev); } @Override protected void writeReleasedAt(Point p) { Part focusPart = project.getPartSelection().getFocus(); if (focusPart == null || !(focusPart instanceof MidiPart)) return; project.getEditHistoryContainer().notifyEditHistoryListeners(); } public void selectAll() { Part focus=project.getPartSelection().getFocus(); if (focus == null ) return; Vector<MultiEvent> events=new Vector<MultiEvent> (); for (MultiEvent e:eventsInFocus) { events.add(e); } project.getMultiEventSelection().setSelected(events); project.getMultiEventSelection().notifyListeners(); } }