]> ruin.nu Git - moosique.git/blob - MooNoteElement.java
*** empty log message ***
[moosique.git] / MooNoteElement.java
1 import javax.swing.*;
2 import java.awt.*;
3 import java.awt.event.*;
4
5 /**
6  * Graphical representation of a MIDI note.
7  * 
8  * @author  Andersson, Andreen, Lanneskog, Pehrson
9  * @version 1
10  */
11  
12 public class MooNoteElement extends JPanel implements Comparable{
13
14         private MooTrackView mtv;
15         private MooNote note;
16         private JPopupMenu popup;
17         private JMenuItem popupRemove, popupProp, popupTranspOctUp, popupTranspOctDown;
18         private Rectangle pitchRect, veloRect;
19         private String notePitch, noteVelocity;
20         private boolean selected = false, leftMouseButtonPressed = false, mouseIn = false;
21         public Color textColor;
22         public static final Color bgColor = new Color(160, 218, 255);
23         public static final Color invBgColor = new Color(96, 38, 0);
24
25         /** 
26          * Creates a new note element.
27          * @param parent        The MooTrackView that this element will be painted on.
28          * @param mn            the note that will be graphically represented
29          */
30         public MooNoteElement (MooTrackView parent, MooNote mn) {
31                 mtv = parent;
32                 note = mn;
33                 calculateString();
34                 addMouseListener(new MAdapter());
35                 setBorder(BorderFactory.createLineBorder(Color.black));
36                 setBackground(bgColor);
37                 textColor = Color.black;
38
39                 // Defines coordinates.
40                 pitchRect = new Rectangle(0, 0, 15, 10);
41                 veloRect = new Rectangle(20, 0, 40, 10);
42
43                 // Creates pop-up menu.
44                 popup = new JPopupMenu();
45                 PopupListener pList = new PopupListener();
46                 popupProp = new JMenuItem("Preferences...");
47                 popupProp.addActionListener(pList);
48                 popup.add(popupProp);
49                 popupRemove = new JMenuItem("Remove");
50                 popupRemove.addActionListener(pList);
51                 popup.add(popupRemove);
52                 popupTranspOctUp = new JMenuItem("Transpose one octave up");
53                 popupTranspOctUp.addActionListener(pList);
54                 popup.add(popupTranspOctUp);
55                 popupTranspOctDown = new JMenuItem("Transpose one octave down");
56                 popupTranspOctDown.addActionListener(pList);
57                 popup.add(popupTranspOctDown);
58         }
59
60         /** 
61          * Returns the note of this element.
62          * @return the note
63          */
64         public MooNote getNote() {
65                 return note;
66         }
67
68         /** 
69          * Compares the note of this element to that of another note.
70          * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object
71          */
72         public int compareTo(Object o) {
73                 return note.compareTo(((MooNoteElement)o).getNote());
74         }
75
76         /** 
77          * Selects the current NoteElement.
78          */
79         public void select() {
80                 selected = true;
81                 mtv.selectNote(this);
82                 setBackground(invBgColor);
83                 textColor = Color.white;
84                 repaint();
85         }
86
87         /** 
88          * Deselects the current NoteElement.
89          */
90         public void deselect() {
91                 selected = false;
92                 // mtv.deselectNote(this);
93                 setBackground(bgColor);
94                 textColor = Color.black;
95                 repaint();
96         }
97
98         /** 
99          * Transposes the current note element the given number of halftones.
100          * @param halftones     the number of halftones to transpose - positive for up, negative for down
101          */
102         public void transpose(int halftones) {
103                 note.transpose(halftones);
104                 update();
105         }
106
107         /**
108          * Draws the string that shows the note's properties.
109          * @param g     The Graphics object used to draw the strings.
110          */
111         public void paintComponent(Graphics g)
112         {
113                 super.paintComponent(g);
114                 if (!(g instanceof Graphics2D)) return;
115                 Graphics2D g2 = (Graphics2D)g;
116                 g2.setColor(textColor);
117                 g2.setFont(new Font("Helvetica", Font.PLAIN, 8));
118         /*
119                 switch(columns) {
120                         case 0:
121                         case 1:
122                         ...
123                 }
124         */
125                 
126                 g2.drawString(notePitch, 1, 8);
127                 g2.drawString("" + noteVelocity, 21, 8);
128         }
129
130         /**
131          * Calculate what the string that shows the note properties should look like.
132          */
133         protected void calculateString(){
134
135                 noteVelocity = ""; 
136                 notePitch = "";
137                 if(note == null) return;
138
139                 int pitch = note.getPitch();
140                 switch (pitch % 12) {
141                         case  0: notePitch = "C";  break;
142                         case  1: notePitch = "C#"; break;
143                         case  2: notePitch = "D";  break;
144                         case  3: notePitch = "D#"; break;
145                         case  4: notePitch = "E";  break;
146                         case  5: notePitch = "F";  break;
147                         case  6: notePitch = "F#"; break;
148                         case  7: notePitch = "G";  break;
149                         case  8: notePitch = "G#"; break;
150                         case  9: notePitch = "A";  break;
151                         case 10: notePitch = "A#"; break;
152                         case 11: notePitch = "B";  break;
153                 }
154                 notePitch += pitch / 12 - 1;
155                 noteVelocity = ""+note.getVelocity();
156         }
157
158
159         /**
160          * Asks the MooTrackView that the note element is painted on to remove this element and the note.
161          */
162         protected void remove(){
163                 mtv.removeNote(this);
164         }
165
166         /**
167          * Updates the graphical content of the element and repaints it.
168          */
169         public void update() {
170                 calculateString();
171                 repaint();
172         }
173
174         /**
175          * Layout this changed elemnt.
176          */
177         protected void newLayout(){
178                 mtv.layoutElement(this,true);
179         }
180
181         /**
182          * Listener that checks the mouse actions on this element.
183          */
184         class MAdapter extends MouseAdapter {
185         
186                 /**
187                  * Selects the note if mouse entered with the left mouse button pressed.
188                  */
189                 public void mouseEntered(MouseEvent e) {
190                         mouseIn = true;
191                         if (mtv.isLeftMouseButtonPressed()) {
192                                 select();
193                         }
194                 }
195
196                 /**
197                  * Registers mouse exited.
198                  */
199                 public void mouseExited(MouseEvent e) {
200                         mouseIn = false;
201                 }
202
203                 /**
204                  * Checks if the mouse is pressed.
205                  * Increases the pitch or velocity if the right mouse button is pressed while holding CTRL.
206                  * Decreases the pitch or velocity if the left mouse button is pressed while holding CTRL.
207                  * @param e the event recieved.
208                  */
209                 public void mousePressed(MouseEvent e) {
210                         if (e.isControlDown()) {
211                                 if (pitchRect.contains(e.getPoint())) {
212                                         if (SwingUtilities.isRightMouseButton(e)) {
213                                                 note.transpose(1);
214                                         } else if (SwingUtilities.isLeftMouseButton(e)) {
215                                                 note.transpose(-1);
216                                         }
217                                         Moosique.setEdited();
218                                         calculateString();
219                                         repaint();
220                                 } else if (veloRect.contains(e.getPoint())) {
221                                         if (SwingUtilities.isRightMouseButton(e)) {
222                                                 note.setVelocity(note.getVelocity() + 1);
223                                         } else if (SwingUtilities.isLeftMouseButton(e)) {
224                                                 note.setVelocity(note.getVelocity() - 1);
225                                         }
226                                         Moosique.setEdited();
227                                         calculateString();
228                                         repaint();
229                                 }
230                         } else {
231                                 select();
232                                 // Play the note
233                                 maybeShowPopup(e);
234                         }
235                 }
236
237                 public void mouseReleased(MouseEvent e) {
238                         if (!maybeShowPopup(e) && !mouseIn) {
239                                 int y = e.getY();
240                                 if (y < 0) mtv.maybeMoveSelectedNotes((int)Math.floor((double)y / MooTrackView.NOTE_HEIGHT) * MooTrackView.NOTE_HEIGHT);
241                                 if (y > getHeight()) mtv.maybeMoveSelectedNotes((int)Math.ceil(((double)y - getHeight()) / MooTrackView.NOTE_HEIGHT) * MooTrackView.NOTE_HEIGHT);
242                                 
243                         }
244                 }
245
246                 /**
247                  * Shows the menu if an OS-specific popup-trigger was activated.
248                  */
249                 private boolean maybeShowPopup(MouseEvent e) {
250                         if (!e.isPopupTrigger()) return false;
251                         if (!e.isControlDown()) {
252                                 if (!selected || mtv.isTheOnlySelected((MooNoteElement)e.getComponent())) popup.show(e.getComponent(), e.getX(), e.getY());
253                                 else mtv.showSelectionPopup(e.getComponent(), e.getX(), e.getY());
254                         }
255                         return true;
256                 }
257         }
258
259         /**
260          * Listens on the actions made to the popupmenu.
261          */
262         class PopupListener implements ActionListener {
263                 public void actionPerformed(ActionEvent e) {
264                         Object source = e.getSource();
265                         if (source == popupProp) {
266                                 System.out.println("Duration: " + note.getDuration());
267                                 new MooDialog(note);
268                                 System.out.println("Duration: " + note.getDuration());
269                                 newLayout();
270                                 repaint();
271                         } else if (source == popupRemove) {
272                                 remove();
273                         } else if (source == popupTranspOctUp) {
274                                 transpose(12);
275                         } else if (source == popupTranspOctDown) {
276                                 transpose(-12);
277                         }
278                 }
279         }
280 }