jm.gui.cpn.StaveActionHandler Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jmusic Show documentation
Show all versions of jmusic Show documentation
JMusic - Java Music Library
The newest version!
/*
Copyright (C) 2000 Andrew Brown
This program 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 any
later version.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
// Some GPL changes for jMusic CPN Written by Al Christians
// ([email protected]).
package jm.gui.cpn;
import jm.JMC;
import jm.music.data.Note;
import jm.music.data.Phrase;
import java.awt.*;
import java.awt.event.*;
public class StaveActionHandler implements JMC, MouseListener, MouseMotionListener, ActionListener, KeyListener {
private Stave theApp;
private int selectedNote = -1;
private boolean topTimeSelected = false, keySelected = false;
private int clickedPosY, clickedPosX, storedPitch = 72;
private double[] rhythmValues = {104.0, 103.0, 102.0, 101.5, 101.0, 100.75,
100.5, 100.25, 0.0, 0.25, 0.5, 0.75, 1.0, 1.5, 2.0, 3.0, 4.0};
private boolean button1Down = false;
private PopupMenu noteContextMenu;
private MenuItem editNote,
repeatNote,
makeRest,
deleteNote;
// constructor
StaveActionHandler(Stave stave) {
theApp = stave;
noteContextMenu = new PopupMenu();
editNote = new MenuItem("Edit Note");
editNote.addActionListener(this);
noteContextMenu.add(editNote);
repeatNote = new MenuItem("Repeat Note");
repeatNote.addActionListener(this);
noteContextMenu.add(repeatNote);
makeRest = new MenuItem("Change to Rest");
makeRest.addActionListener(this);
noteContextMenu.add(makeRest);
deleteNote = new MenuItem("Delete Note");
deleteNote.addActionListener(this);
noteContextMenu.add(deleteNote);
theApp.add(noteContextMenu);
}
boolean inNoteArea(MouseEvent e) {
Integer lastX;
if (theApp.notePositions.size() < 2) {
lastX = new Integer(theApp.getTotalBeatWidth());
} else {
lastX = (Integer) theApp.notePositions.elementAt(theApp.notePositions.size() - 2);
}
return (e.getX() <= lastX.intValue() + 15) &&
(e.getX() < theApp.getTotalBeatWidth() + 50);
}
private void searchForSelectedNote(MouseEvent e) {
Integer tempX;
Integer tempY;
for (int i = 0; i < theApp.notePositions.size(); i += 2) {
tempX = (Integer) theApp.notePositions.elementAt(i);
tempY = (Integer) theApp.notePositions.elementAt(i + 1);
if ((e.getX() > tempX.intValue()) &&
(e.getX() < tempX.intValue() + 15) &&
(e.getY() + theApp.staveDelta >
tempY.intValue() + 22) &&
(e.getY() + theApp.staveDelta < tempY.intValue() + 35)) {
selectedNote = i / 2;
clickedPosY = e.getY() + theApp.staveDelta;
clickedPosX = e.getX();
// get out of loop ASAP
i = theApp.notePositions.size();
}
}
}
// Mouse Listener stubs
public void mouseClicked(MouseEvent e) {
if ((((e.getModifiers() & InputEvent.BUTTON2_MASK) != 0)) &&
inNoteArea(e)) {
searchForSelectedNote(e);
if ((selectedNote >= 0) &&
(selectedNote < theApp.getPhrase().size())) {
noteContextMenu.show(theApp, e.getX(), e.getY());
}
}
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
//mouseMotionListener stubs
public void mouseMoved(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
if (e.isPopupTrigger() ||
((e.getModifiers() & InputEvent.BUTTON2_MASK) != 0) ||
(!theApp.editable)) return;
button1Down = true;
// add a new note if necessary
// no notes yet?
if (!inNoteArea(e)) {
// new note close to mouse click pitch
int newPitch = 85 - (e.getY() + theApp.staveDelta - theApp.bPos) / 2;
// make sure it is not an accidental
int[] blackNotes = {1, 3, 6, 8, 10};
boolean white = true;
for (int k = 0; k < blackNotes.length; k++) {
if (newPitch % 12 == blackNotes[k]) newPitch--;
}
Note n = new Note(newPitch, 1.0);
Phrase phr = theApp.getPhrase();
phr.addNote(n);
theApp.repaint();
// set cursor
theApp.setCursor(new Cursor(Cursor.HAND_CURSOR));
// get ready to drag it
selectedNote = phr.size() - 1;
//theApp.playCurrentNote(selectedNote);
clickedPosY = e.getY() + theApp.staveDelta;
clickedPosX = e.getX();
} else {
searchForSelectedNote(e);
theApp.setCursor(new Cursor(Cursor.MOVE_CURSOR));
// check for a click on a note - head?
}
if (selectedNote < 0) { // no note clicked on or yet made
// check which note to insert
for (int j = 0; j < theApp.notePositions.size() - 2; j += 2) {
Integer tempX = (Integer) theApp.notePositions.elementAt(j);
Integer nextTempX = (Integer) theApp.notePositions.elementAt(j + 2);
if (e.getX() > tempX.intValue() + 15 && e.getX() < nextTempX.intValue()) {
// change cursor
theApp.setCursor(new Cursor(Cursor.HAND_CURSOR));
// add new note close to mouse clicked pitch
int newPitch = 85 - (e.getY() + theApp.staveDelta - theApp.bPos) / 2;
// make sure it is not an accidental
int[] blackNotes = {1, 3, 6, 8, 10};
boolean white = true;
for (int k = 0; k < blackNotes.length; k++) {
if (newPitch % 12 == blackNotes[k]) newPitch--;
}
Note n = new Note(newPitch, 1.0);
Phrase phr = theApp.getPhrase();
phr.getNoteList().insertElementAt(n, j / 2 + 1);
theApp.repaint();
// play and update variables for dragging it
selectedNote = j / 2 + 1;
clickedPosY = e.getY() + theApp.staveDelta;
clickedPosX = e.getX();
// get out of the loop
j = theApp.notePositions.size();
}
}
}
// check if the time signature is clicked
int theSpace = theApp.rightMargin + theApp.clefWidth + theApp.keySigWidth;
if (e.getX() > theSpace && e.getX() < theSpace + 10) {
theApp.setCursor(new Cursor(Cursor.MOVE_CURSOR));
topTimeSelected = true;
clickedPosY = e.getY() + theApp.staveDelta;
clickedPosX = e.getX();
}
// check if the key signature is clicked
int theClefSpace = theApp.rightMargin + theApp.clefWidth;
int minKeySpace = 10;
if (theApp.keySigWidth > minKeySpace) minKeySpace = theApp.keySigWidth;
if (e.getX() > theClefSpace - 10 && e.getX() < theClefSpace + minKeySpace) {
theApp.setCursor(new Cursor(Cursor.MOVE_CURSOR));
keySelected = true;
clickedPosY = e.getY() + theApp.staveDelta;
clickedPosX = e.getX();
}
}
public void mouseDragged(MouseEvent e) {
if ((!button1Down) || (!theApp.editable))
return;
//theApp.dragNote(e.getX(), e.getY());
if (selectedNote >= 0) {
Phrase phr = theApp.getPhrase();
Note n = phr.getNote(selectedNote);
// move note down
if (e.getY() + theApp.staveDelta > clickedPosY + 2 && theApp.getPhrase().getNote(selectedNote).getPitch() != REST) {
n.setPitch(n.getPitch() - 1);
if (n.getPitch() < theApp.getMinPitch()) n.setPitch(theApp.getMinPitch());
// update the current mouse location
clickedPosY += 2;
// update the visual display
theApp.repaint();
// keep pitch to reinstate it after displaying a rest
storedPitch = n.getPitch();
}
// move note up
if (e.getY() + theApp.staveDelta < clickedPosY - 2 && theApp.getPhrase().getNote(selectedNote).getPitch() != REST) {
n.setPitch(n.getPitch() + 1);
if (n.getPitch() > theApp.getMaxPitch()) n.setPitch(theApp.getMaxPitch());
//theApp.playCurrentNote(selectedNote);
clickedPosY -= 2;
theApp.repaint();
storedPitch = n.getPitch();
}
// move note right - increase RV
if (e.getX() > clickedPosX + 6) {
double tempRV = n.getRhythmValue();
int tempPitch = n.getPitch();
// use +100 numbers for rests
if (tempPitch == REST) tempRV = tempRV + 100;
int currRVindex = rhythmValues.length;
// find current rhythm value and update RV
for (int i = 0; i < rhythmValues.length - 1; i++) {
if (tempRV == rhythmValues[i]) {
n.setRhythmValue(rhythmValues[i + 1]);
// update duration value
n.setDuration(n.getRhythmValue() * 0.9);
}
}
clickedPosX = e.getX();
// update pitch
if (n.getRhythmValue() > 100.0) {
n.setPitch(REST);
n.setRhythmValue(n.getRhythmValue() - 100);
// update duration value
n.setDuration(n.getRhythmValue() * 0.9);
} else {
if (tempPitch == REST) n.setPitch(storedPitch);
}
theApp.repaint();
}
// move note left - decrease RV
if (e.getX() < clickedPosX - 6) {
double tempRV = n.getRhythmValue();
int tempPitch = n.getPitch();
// use +100 numbers for rests
if (tempPitch == REST) tempRV = tempRV + 100;
// find current rhythm value position in the array
int currRVindex = 0;
for (int i = 0; i < rhythmValues.length; i++) {
if (tempRV == rhythmValues[i]) currRVindex = i;
}
// update rv
if (currRVindex > 0) {
n.setRhythmValue(rhythmValues[currRVindex - 1]);
// update duration value
n.setDuration(n.getRhythmValue() * 0.9);
clickedPosX = e.getX();
// update pitch
if (n.getRhythmValue() > 100.0) {
n.setPitch(REST);
n.setRhythmValue(n.getRhythmValue() - 100);
// update duration value
n.setDuration(n.getRhythmValue() * 0.9);
} else {
if (tempPitch == REST) n.setPitch(storedPitch);
}
theApp.repaint();
}
}
}
// check for time signature change
if (topTimeSelected) {
//increase?
if (e.getY() + theApp.staveDelta < clickedPosY - 4) {
theApp.setMetre(theApp.getMetre() + 1.0);
if (theApp.getMetre() > 9.0) theApp.setMetre(9.0);
if (theApp.getMetre() < 1.0) theApp.setMetre(1.0);
theApp.getPhrase()
.setNumerator(
(new
Double(
Math.round(theApp.getMetre())
)
).intValue()
);
clickedPosY -= 4;
theApp.repaint();
theApp.updateChange();
}
//decrease
if (e.getY() + theApp.staveDelta > clickedPosY + 4) {
theApp.setMetre(theApp.getMetre() - 1.0);
if (theApp.getMetre() < 1.0) theApp.setMetre(1.0);
if (theApp.getMetre() > 9.0) theApp.setMetre(9.0);
theApp.getPhrase()
.setNumerator(
(new
Double(
Math.round(theApp.getMetre())
)
).intValue()
);
clickedPosY += 4;
theApp.repaint();
theApp.updateChange();
}
}
// check for key signature change
if (keySelected) {
//increase?
if (e.getY() + theApp.staveDelta < clickedPosY - 4) {
theApp.setKeySignature(theApp.getKeySignature() + 1);
if (theApp.getKeySignature() > 7) theApp.setKeySignature(7);
clickedPosY -= 4;
theApp.repaint();
theApp.updateChange();
}
//decrease
if (e.getY() + theApp.staveDelta > clickedPosY + 4) {
theApp.setKeySignature(theApp.getKeySignature() - 1);
if (theApp.getKeySignature() < -7) theApp.setKeySignature(-7);
clickedPosY += 4;
theApp.repaint();
theApp.updateChange();
}
}
}
public void mouseReleased(MouseEvent e) {
button1Down = false;
if (!theApp.editable) return;
// delete note if necessary
for (int i = 0; i < theApp.getPhrase().getNoteList().size(); i++) {
if (theApp.getPhrase().getNote(i).getRhythmValue() == 0.0) {
theApp.getPhrase().getNoteList().removeElementAt(i);
}
}
// unflag any note being selected
theApp.repaint();
theApp.updateChange();
selectedNote = -1;
topTimeSelected = false;
keySelected = false;
theApp.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
}
public void actionPerformed(ActionEvent e) {
Phrase phrase = theApp.getPhrase();
Note note = phrase.getNote(selectedNote);
if (e.getSource() == editNote) {
Frame editorFrame
= new Frame("Edit this Note");
editorFrame.setSize(400, 400);
editorFrame.setResizable(true);
NoteEditor noteEditor
= new NoteEditor(editorFrame);
noteEditor.editNote(note, 20, 20);
} else if (e.getSource() == repeatNote) {
Note newNote = note.copy();
phrase.getNoteList().insertElementAt(
newNote,
selectedNote
);
} else if (e.getSource() == makeRest) {
note.setFrequency(Note.REST);
} else if (e.getSource() == deleteNote) {
phrase.getNoteList().removeElementAt(selectedNote);
}
selectedNote = -1;
theApp.repaint();
}
// key listener stubs
public void keyPressed(KeyEvent e) {
}
public void keyReleased(KeyEvent e) {
}
public void keyTyped(KeyEvent e) {
// System.out.println(e.getKeyChar());
if (e.getKeyChar() == '\b') theApp.deleteLastNote();
}
}