/* ============================================================================== This file is part of the JUCETICE project - Copyright 2009 by Lucio Asnaghi. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions" Copyright 2007 by Julian Storer. ------------------------------------------------------------------------------ JUCE and JUCETICE can be redistributed and/or modified 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. JUCE and JUCETICE are distributed in the hope that they 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 JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ============================================================================== */ BEGIN_JUCE_NAMESPACE #include "jucetice_PianoGrid.h" //============================================================================== MidiGridItem::MidiGridItem () : beat(0), hasBeenSelected (false), isDragging (false) { } MidiGridItem::~MidiGridItem () { } //============================================================================== void MidiGridItem::startDragging (const MouseEvent& e) { isDragging = true; dragger.startDraggingComponent (this, e); toFront (true); repaint (); } void MidiGridItem::continueDragging (const MouseEvent& e) { dragger.dragComponent (this, e, 0); } void MidiGridItem::endDragging (const MouseEvent& e) { isDragging = false; repaint (); } //============================================================================== PianoGridNote::PianoGridNote (PianoGrid* owner_) : note (0), length (0.0f), velocity (1.0f), owner (owner_), isResizing (false), isEditingVelocity (false) { setOpaque (false); toFront (false); } PianoGridNote::~PianoGridNote() { } //============================================================================== void PianoGridNote::initialize (const int note_, const float beat_, const float length_, const float velocity_) { note = note_; beat = beat_; length = length_; velocity = velocity_; } //============================================================================== bool PianoGridNote::isNoteToggled (const int note_, const float beat_) { return ((beat_ >= beat && beat_ <= (int)(beat + length)) && (note_ == note)); } void PianoGridNote::continueDragging (const MouseEvent& e) { int originalX = getX(); int originalY = getY(); dragger.dragComponent (this, e, 0); int newNote = -1; float newBeat = -1; if (owner->getRowsColsByMousePosition (getX(), getY(), newNote, newBeat)) { if (newNote != note || newBeat != beat) { owner->moveNote (this, newNote, newBeat); } setBounds (owner->getNoteRect (this)); } else { setTopLeftPosition (originalX, originalY); } } //============================================================================== void PianoGridNote::startResizing (const MouseEvent& e) { isResizing = true; toFront (true); repaint (); } void PianoGridNote::continueResizing (const MouseEvent& e) { int newNote = -1; float newBeat = -1; if (owner->getRowsColsByMousePosition (getX() + e.x, getY() + e.y, newNote, newBeat)) { if (newBeat > beat) { float newLength = newBeat - beat; if (newLength != length) { owner->resizeNote (this, beat, newLength); setBounds (owner->getNoteRect (this)); } } } } void PianoGridNote::endResizing (const MouseEvent& e) { isResizing = false; repaint (); } //============================================================================== void PianoGridNote::startVelocity (const MouseEvent& e) { isEditingVelocity = true; setMouseCursor (MouseCursor (MouseCursor::UpDownResizeCursor)); toFront (true); repaint (); } void PianoGridNote::continueVelocity (const MouseEvent& e) { float newVelocity = velocity + e.getDistanceFromDragStartY () / 100.0f; if (newVelocity != velocity) { owner->changeNoteVelocity (this, newVelocity); repaint(); } } void PianoGridNote::endVelocity (const MouseEvent& e) { isEditingVelocity = false; setMouseCursor (MouseCursor (MouseCursor::NormalCursor)); repaint (); } //============================================================================== void PianoGridNote::mouseMove (const MouseEvent& e) { if (e.x >= getWidth() - 2) { setMouseCursor (MouseCursor (MouseCursor::LeftRightResizeCursor)); } else { setMouseCursor (MouseCursor (MouseCursor::NormalCursor)); } } void PianoGridNote::mouseDown (const MouseEvent& e) { if (! owner) return; SelectedItemSet selection = owner->getLassoSelection (); if (! selection.isSelected (this)) owner->selectNote (this, true); if (e.mods.isLeftButtonDown()) { if (e.x >= getWidth() - 2) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->startResizing (e); } } else { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->startDragging (component == this ? e : e.getEventRelativeTo (component)); } } DBG ("Note: " + String (note) + " " + String (beat) + " " + String (length)); } else if (e.mods.isMiddleButtonDown()) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->startVelocity (e); } } } void PianoGridNote::mouseDrag (const MouseEvent& e) { if (! owner) return; SelectedItemSet selection = owner->getLassoSelection (); if (e.mods.isLeftButtonDown()) { if (isResizing) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->continueResizing (e); } } else if (isDragging) { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->continueDragging (component == this ? e : e.getEventRelativeTo (component)); } } } else if (e.mods.isMiddleButtonDown()) { if (isEditingVelocity) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->continueVelocity (e); } } } } void PianoGridNote::mouseUp (const MouseEvent& e) { if (owner) { SelectedItemSet selection = owner->getLassoSelection (); if (e.mods.isLeftButtonDown()) { if (isResizing) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->endResizing (e); } } else if (isDragging) { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->endDragging (e); } } repaint (); } else if (e.mods.isMiddleButtonDown()) { if (isEditingVelocity) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component) component->endVelocity (component == this ? e : e.getEventRelativeTo (component)); } } } else if (e.mods.isRightButtonDown()) { for (int i = 0; i < selection.getNumSelected (); i++) { PianoGridNote* component = dynamic_cast(selection.getSelectedItem (i)); if (component && component != this) owner->removeNote (component, true); } owner->removeNote (this, false); delete (this); } } } void PianoGridNote::paint (Graphics& g) { Colour fillColour = findColour (PianoGrid::noteFillColourId); Colour borderColour = findColour (PianoGrid::noteBorderColourId); if (isDragging || isResizing) { if (hasBeenSelected) { fillColour = fillColour.darker (0.4f); borderColour = borderColour.darker (0.4f); } else { fillColour = fillColour.brighter (0.4f); borderColour = borderColour.brighter (0.4f); } } else { if (hasBeenSelected) { fillColour = fillColour.brighter (0.4f); borderColour = borderColour.brighter (0.4f); } } float alphaStep = 0.2f + velocity * 0.8f; fillColour = fillColour.withAlpha (alphaStep); borderColour = borderColour.withAlpha (alphaStep); g.fillAll (fillColour); g.setColour (borderColour); g.drawRect (0, 0, getWidth(), getHeight()); } //============================================================================== AutomationEvent::AutomationEvent (AutomationGrid* owner_) : owner (owner_), value (0), controller(0) { } AutomationEvent::~AutomationEvent() { } void AutomationEvent::initialize (const int controller_, const double value_, const double beat_, const Colour colour_, const Colour outlineColour_) { controller = controller_; value = value_; beat = beat_; colour = colour_; outlineColour = outlineColour_; } void AutomationEvent::setValue (const double value_) { value = value_; value = std::max(value, 0.0); value = std::min(value, 1.0); } void AutomationEvent::mouseDown (const MouseEvent& e) { if (! owner) return; SelectedItemSet selection = owner->getLassoSelection (); if (! selection.isSelected (this)) owner->selectNote (this, true); if (e.mods.isLeftButtonDown()) { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->startDragging (component == this ? e : e.getEventRelativeTo (component)); owner->repaint(); } } } void AutomationEvent::mouseDrag (const MouseEvent& e) { if (! owner) return; SelectedItemSet selection = owner->getLassoSelection (); if (e.mods.isLeftButtonDown()) { if (isDragging) { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->continueDragging (component == this ? e : e.getEventRelativeTo (component)); owner->repaint(); } } } } void AutomationEvent::mouseUp (const MouseEvent& e) { if (owner) { SelectedItemSet selection = owner->getLassoSelection (); if (e.mods.isLeftButtonDown()) { for (int i = 0; i < selection.getNumSelected (); i++) { MidiGridItem* component = selection.getSelectedItem (i); component->endDragging (e); owner->repaint(); } repaint (); } else if (e.mods.isRightButtonDown()) { for (int i = 0; i < selection.getNumSelected (); i++) { AutomationEvent* component = dynamic_cast(selection.getSelectedItem (i)); if (component && component != this) owner->removeNote (component, true); } owner->removeNote (this, false); delete (this); } } } void AutomationEvent::continueDragging (const MouseEvent& e) { int originalX = getX(); int originalY = getY(); dragger.dragComponent (this, e, 0); double newValue = -1; double newBeat = -1; if (owner->getRowsColsByMousePosition (getX(), getY(), newValue, newBeat)) { if (newValue != value || newBeat != beat) { owner->moveEvent (this, newBeat, newValue); } setBounds (owner->getNoteRect (this)); } else { setTopLeftPosition (originalX, originalY); } } void AutomationEvent::paint (Graphics& g) { Colour fillColour = colour; Colour borderColour = outlineColour; int borderWidth = 1; if (hasBeenSelected) { fillColour = fillColour.darker (0.6); borderColour = borderColour.darker (); borderWidth = 2; } g.setColour (fillColour); g.fillEllipse (0, 0, getWidth(), getHeight()); g.setColour (borderColour); g.drawEllipse (0, 0, getWidth(), getHeight(), borderWidth); } END_JUCE_NAMESPACE