/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ /* Rosegarden A MIDI and audio sequencer and musical notation editor. Copyright 2000-2011 the Rosegarden development team. Other copyrights also apply to some parts of this work. Please see the AUTHORS file and individual file headers for details. 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 (at your option) any later version. See the file COPYING included with this distribution for more information. */ #include "MatrixElement.h" #include "MatrixScene.h" #include "misc/Debug.h" #include "base/RulerScale.h" #include #include #include #include #include "base/Event.h" #include "base/NotationTypes.h" #include "base/BaseProperties.h" #include "gui/general/GUIPalette.h" #include "gui/rulers/DefaultVelocityColour.h" namespace Rosegarden { static const int MatrixElementData = 2; MatrixElement::MatrixElement(MatrixScene *scene, Event *event, bool drum, long pitchOffset) : ViewElement(event), m_scene(scene), m_drum(drum), m_current(true), m_item(0), m_pitchOffset(pitchOffset) { reconfigure(); } MatrixElement::~MatrixElement() { delete m_item; } void MatrixElement::reconfigure() { timeT time = event()->getAbsoluteTime(); timeT duration = event()->getDuration(); reconfigure(time, duration); } void MatrixElement::reconfigure(int velocity) { timeT time = event()->getAbsoluteTime(); timeT duration = event()->getDuration(); long pitch = 60; event()->get(BaseProperties::PITCH, pitch); reconfigure(time, duration, pitch, velocity); } void MatrixElement::reconfigure(timeT time, timeT duration) { long pitch = 60; event()->get(BaseProperties::PITCH, pitch); reconfigure(time, duration, pitch); } void MatrixElement::reconfigure(timeT time, timeT duration, int pitch) { long velocity = 100; event()->get(BaseProperties::VELOCITY, velocity); reconfigure(time, duration, pitch, velocity); } void MatrixElement::reconfigure(timeT time, timeT duration, int pitch, int velocity) { const RulerScale *scale = m_scene->getRulerScale(); int resolution = m_scene->getYResolution(); double x0 = scale->getXForTime(time); double x1 = scale->getXForTime(time + duration); m_width = x1 - x0; m_velocity = velocity; // if the note has TIED_FORWARD or TIED_BACK properties, draw it with a // different fill pattern bool tiedNote = (event()->has(BaseProperties::TIED_FORWARD) || event()->has(BaseProperties::TIED_BACKWARD)); Qt::BrushStyle brushPattern = (tiedNote ? Qt::Dense2Pattern : Qt::SolidPattern); QColor colour; if (event()->has(BaseProperties::TRIGGER_SEGMENT_ID)) { //!!! Using gray for trigger events and events from other, non-active // segments won't work. This should be handled some other way, with a // color outside the range of possible velocity choices, which probably // leaves some kind of curious light blue or something colour = Qt::cyan; } else { colour = DefaultVelocityColour::getInstance()->getColour(velocity); } colour.setAlpha(160); double fres(resolution); if (m_drum) { fres = resolution + 1; QGraphicsPolygonItem *item = dynamic_cast(m_item); if (!item) { delete m_item; item = new QGraphicsPolygonItem; m_item = item; m_scene->addItem(m_item); } QPolygonF polygon; polygon << QPointF(0, 0) << QPointF(fres/2, fres/2) << QPointF(0, fres) << QPointF(-fres/2, fres/2) << QPointF(0, 0); item->setPolygon(polygon); item->setPen (QPen(GUIPalette::getColour(GUIPalette::MatrixElementBorder), 0)); item->setBrush(QBrush(colour, brushPattern)); } else { QGraphicsRectItem *item = dynamic_cast(m_item); if (!item) { delete m_item; item = new QGraphicsRectItem; m_item = item; m_scene->addItem(m_item); } float width = m_width; if (width < 1) width = 1; QRectF rect(0, 0, width, fres + 1); item->setRect(rect); item->setPen (QPen(GUIPalette::getColour(GUIPalette::MatrixElementBorder), 0)); item->setBrush(QBrush(colour, brushPattern)); } setLayoutX(x0); m_item->setData(MatrixElementData, QVariant::fromValue((void *)this)); // set the Y position taking m_pitchOffset into account, subtracting the // opposite of whatever the originating segment transpose was // std::cout << "TRANSPOSITION TEST: event pitch: " // << (pitch ) << " m_pitchOffset: " << m_pitchOffset // << std::endl; m_item->setPos(x0, (127 - pitch - m_pitchOffset) * (resolution + 1)); // set a tooltip explaining why this event is drawn in a different pattern if (tiedNote) m_item->setToolTip(QObject::tr("This event is tied to another event.")); } bool MatrixElement::isNote() const { return event()->isa(Note::EventType); } void MatrixElement::setSelected(bool selected) { QAbstractGraphicsShapeItem *item = dynamic_cast(m_item); if (!item) return; QColor colour; if (selected) { item->setPen(QPen(GUIPalette::getColour(GUIPalette::SelectedElement), 2, Qt::SolidLine, Qt::SquareCap, Qt::MiterJoin)); } else { item->setPen (QPen(GUIPalette::getColour(GUIPalette::MatrixElementBorder), 0)); } } void MatrixElement::setCurrent(bool current) { if (m_current == current) return; QAbstractGraphicsShapeItem *item = dynamic_cast(m_item); if (!item) return; QColor colour; if (!current) { colour = QColor(200, 200, 200); } else { if (event()->has(BaseProperties::TRIGGER_SEGMENT_ID)) { colour = Qt::gray; } else { long velocity = 100; event()->get(BaseProperties::VELOCITY, velocity); colour = DefaultVelocityColour::getInstance()->getColour(velocity); } } item->setBrush(colour); item->setZValue(current ? 1 : 0); if (current) { item->setPen (QPen(GUIPalette::getColour(GUIPalette::MatrixElementBorder), 0)); } else { item->setPen (QPen(GUIPalette::getColour(GUIPalette::MatrixElementLightBorder), 0)); } m_current = current; } MatrixElement * MatrixElement::getMatrixElement(QGraphicsItem *item) { QVariant v = item->data(MatrixElementData); if (v.isNull()) return 0; return (MatrixElement *)v.value(); } }