void
IntonationWidget::smoothPoints(QPainter& painter)
{
	if (intonationPointList_.size() < 2U) return;

	for (unsigned int i = 0, end = intonationPointList_.size() - 1; i < end; ++i) {
		const auto& point1 = intonationPointList_[i];
		const auto& point2 = intonationPointList_[i + 1];

		double x1 = point1.absoluteTime();
		double y1 = point1.semitone();
		double m1 = point1.slope();

		double x2 = point2.absoluteTime();
		double y2 = point2.semitone();
		double m2 = point2.slope();

		double x12 = x1  * x1;
		double x13 = x12 * x1;

		double x22 = x2  * x2;
		double x23 = x22 * x2;

		double denominator = x2 - x1;
		denominator = denominator * denominator * denominator;

		double d = (-(y2 * x13) + 3.0 * y2 * x12 * x2 + m2 * x13 * x2 + m1 * x12 * x22 - m2 * x12 * x22 - 3.0 * x1 * y1 * x22 - m1 * x1 * x23 + y1 * x23)
			/ denominator;
		double c = (-(m2 * x13) - 6.0 * y2 * x1 * x2 - 2.0 * m1 * x12 * x2 - m2 * x12 * x2 + 6.0 * x1 * y1 * x2 + m1 * x1 * x22 + 2.0 * m2 * x1 * x22 + m1 * x23)
			/ denominator;
		double b = (3.0 * y2 * x1 + m1 * x12 + 2.0 * m2 * x12 - 3.0 * x1 * y1 + 3.0 * x2 * y2 + m1 * x1 * x2 - m2 * x1 * x2 - 3.0 * y1 * x2 - 2.0 * m1 * x22 - m2 * x22)
			/ denominator;
		double a = (-2.0 * y2 - m1 * x1 - m2 * x1 + 2.0 * y1 + m1 * x2 + m2 * x2) / denominator;

		QPointF prevPoint(0.5 + timeToX(x1), 0.5 + valueToY(y1));

		for (unsigned int j = static_cast<unsigned int>(x1); j <= static_cast<unsigned int>(x2); j += SMOOTH_POINTS_X_INCREMENT) {
			double x = j;
			double y = x * (x * (x * a + b) + c) + d;

			QPointF currPoint(0.5 + timeToX(x), 0.5 + valueToY(y));

			painter.drawLine(prevPoint, currPoint);

			prevPoint = currPoint;
		}

		QPointF lastPoint(0.5 + timeToX(x2), 0.5 + valueToY(y2));
		painter.drawLine(prevPoint, lastPoint);
	}
}
    void updateCursorPosition()
    {
        currentPositionMarker.setVisible (transportSource.isPlaying() || isMouseButtonDown());

        currentPositionMarker.setRectangle (Rectangle<float> (timeToX (transportSource.getCurrentPosition()) - 0.75f, 0,
                                                              1.5f, (float) (getHeight() - scrollbar.getHeight())));
    }
void
IntonationWidget::mousePressEvent(QMouseEvent* event)
{
	if (eventList_ == nullptr || eventList_->list().empty() || intonationPointList_.empty()) {
		return;
	}
	if (event->button() != Qt::LeftButton) return;

#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
	QPointF clickPoint = event->localPos();
#else
	QPointF clickPoint = event->posF();
#endif
	double minDist = 1.0e10;
	for (unsigned int i = 0, size = intonationPointList_.size(); i < size; ++i) {
		QPointF point(
			timeToX(intonationPointList_[i].absoluteTime()),
			valueToY(intonationPointList_[i].semitone()));

		// Simplified "distance".
		double dist = std::abs(point.x() - clickPoint.x()) + std::abs(point.y() - clickPoint.y());
		if (dist < minDist) {
			minDist = dist;
			selectedPoint_ = i;
		}
	}
	sendSelectedPointData();

	update();
}
    void timerCallback()
    {
        currentPositionMarker.setVisible (transportSource.isPlaying() || isMouseButtonDown());

        double currentPlayPosition = transportSource.getCurrentPosition();

        currentPositionMarker.setRectangle (Rectangle<float> (timeToX (currentPlayPosition) - 0.75f, 0,
                                                              1.5f, (float) getHeight()));
    }
Exemple #5
0
void
TimelineComponent::updateClip (TimelineClip* clip)
{
    jassert (clip);

    ClipRange<double> time;
    clip->getClipRange (time);

    const Range<int> hrange (trackHeight (clip->trackIndex()));
    clip->setBounds (timeToX (time.getStart(), clip->getTimeUnit()), hrange.getStart(),
                     timeToWidth (time, clip->getTimeUnit()), hrange.getLength());
}
// Note: with no antialiasing, the coordinates in QPointF are rounded to the nearest integer.
void
TransitionWidget::paintEvent(QPaintEvent*)
{
	if (pointList_ == nullptr) {
		return;
	}

	QPainter painter(this);
	painter.setFont(QFont("monospace"));

	if (dataUpdated_) {
		QFontMetrics fm = painter.fontMetrics();
		textYOffset_ = 0.5 * fm.ascent();
		leftMargin_ = MARGIN + TEXT_MARGIN + fm.width(transitionYLabels[0]);
		updateScales();

		dataUpdated_ = false;
	}

	if (special_) {
		// Gray area.
		painter.fillRect(QRectF(QPointF(leftMargin_, MARGIN + 7.0 * yStep_), QPointF(leftMargin_ + graphWidth_, MARGIN + 14.0 * yStep_)), Qt::gray);

		// Y labels.
		for (unsigned int i = 0; i < specialTransitionYLabels.size(); ++i) {
			double y = MARGIN + i * yStep_ + textYOffset_;
			painter.drawText(QPointF(MARGIN, y), specialTransitionYLabels[i]);
			painter.drawText(QPointF(leftMargin_ + graphWidth_ + TEXT_MARGIN, y), specialTransitionYLabels[i]);
		}
	} else {
		// Gray areas.
		painter.fillRect(QRectF(QPointF(leftMargin_, MARGIN), QPointF(leftMargin_ + graphWidth_, MARGIN + 2.0 * yStep_)), Qt::gray);
		painter.fillRect(QRectF(QPointF(leftMargin_, MARGIN + 12.0 * yStep_), QPointF(leftMargin_ + graphWidth_, MARGIN + 14.0 * yStep_)), Qt::gray);

		// Y labels.
		for (unsigned int i = 0; i < transitionYLabels.size(); ++i) {
			double y = MARGIN + i * yStep_ + textYOffset_;
			painter.drawText(QPointF(MARGIN, y), transitionYLabels[i]);
			painter.drawText(QPointF(leftMargin_ + graphWidth_ + TEXT_MARGIN, y), transitionYLabels[i]);
		}
	}
	// Horizontal lines.
	for (int i = 0; i < 15; ++i) {
		double y = MARGIN + i * yStep_;
		painter.drawLine(QPointF(leftMargin_, y), QPointF(leftMargin_ + graphWidth_, y));
	}

	QPen pen;
	QPen pen2;
	pen2.setWidth(2);

	painter.setRenderHint(QPainter::Antialiasing);

	// Lines.
	if (!pointList_->empty()) {
		painter.setPen(pen2);

		QPointF prevP(0.5 + timeToX(0.0), 0.5 + valueToY(0.0));

		for (unsigned int i = 0, size = pointList_->size(); i < size; ++i) {
			const auto& point = (*pointList_)[i];
			QPointF p(0.5 + timeToX(point.time), 0.5 + valueToY(point.value));
			painter.drawLine(prevP, p);

			prevP = p;
			if (i != size - 1) {
				if (point.type != (*pointList_)[i + 1].type) {
					prevP.setY(0.5 + valueToY(0.0));
				}
			}
		}

		QPointF p(0.5 + timeToX(ruleDuration_), 0.5 + valueToY(special_ ? 0.0 : 100.0));
		painter.drawLine(prevP, p);

		painter.setPen(pen);
	}

	painter.setBrush(QBrush(Qt::black));

	// Points.
	if (!pointList_->empty()) {
		for (auto& point : *pointList_) {
			double x = 0.5 + timeToX(point.time);
			double y = 0.5 + valueToY(point.value);
			switch (point.type) {
			case TRMControlModel::Transition::Point::TYPE_DIPHONE:
				drawDiPoint(painter, x, y);
				break;
			case TRMControlModel::Transition::Point::TYPE_TRIPHONE:
				drawTriPoint(painter, x, y);
				break;
			case TRMControlModel::Transition::Point::TYPE_TETRAPHONE:
				drawTetraPoint(painter, x, y);
				break;
			default:
				break;
			}
		}
	}

	// Posture markers.
	double yMarker = 0.5 + 0.5 * yStep_ + textYOffset_;
	switch (transitionType_) {
	case TRMControlModel::Transition::TYPE_DIPHONE:
		drawDiPoint(painter, 0.5 + timeToX(ruleDuration_), yMarker);
		break;
	case TRMControlModel::Transition::TYPE_TRIPHONE:
		drawDiPoint( painter, 0.5 + timeToX(mark1_)       , yMarker);
		drawTriPoint(painter, 0.5 + timeToX(ruleDuration_), yMarker);
		break;
	case TRMControlModel::Transition::TYPE_TETRAPHONE:
		drawDiPoint(   painter, 0.5 + timeToX(mark1_)       , yMarker);
		drawTriPoint(  painter, 0.5 + timeToX(mark2_)       , yMarker);
		drawTetraPoint(painter, 0.5 + timeToX(ruleDuration_), yMarker);
		break;
	default:
		break;
	}

	painter.setBrush(QBrush());
	painter.setRenderHint(QPainter::Antialiasing, false);

	// Posture vertical lines.
	double yPosture1 = special_ ? valueToY(-140.0) : valueToY(-20.0);
	double yPosture2 = special_ ? valueToY( 140.0) : valueToY(120.0);

	double x = timeToX(0.0);
	painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));

	switch (transitionType_) {
	case TRMControlModel::Transition::TYPE_DIPHONE:
		x = timeToX(ruleDuration_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		break;
	case TRMControlModel::Transition::TYPE_TRIPHONE:
		x = timeToX(mark1_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		x = timeToX(ruleDuration_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		break;
	case TRMControlModel::Transition::TYPE_TETRAPHONE:
		x = timeToX(mark1_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		x = timeToX(mark2_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		x = timeToX(ruleDuration_);
		painter.drawLine(QPointF(x, yPosture1), QPointF(x, yPosture2));
		break;
	default:
		break;
	}

	if (!pointList_->empty()) {
		if (!special_) {
			// Slopes.
			double y1 = MARGIN + 15.0 * yStep_;
			double y2 = y1 + yStep_;
			double yText = y2 - 0.5 * yStep_ + textYOffset_;
			for (unsigned int i = 0, end = pointList_->size() - 1; i < end; ++i) {
				const auto& point1 = (*pointList_)[i];
				if (point1.hasSlope) {
					const auto& point2 = (*pointList_)[i + 1];
					painter.setPen(Qt::gray);
					painter.drawRect(QRectF(QPointF(timeToX(point1.time), y1), QPointF(timeToX(point2.time), y2)));
					painter.setPen(Qt::black);

					painter.drawText(
						QPointF(timeToX(point1.time) + SLOPE_TEXT_MARGIN, yText),
						QString("%1").arg(point1.slope, 0, 'f', 1));
				}
			}
		}

		// Selected point.
		if (selectedPointIndex_ >= 0 && static_cast<std::size_t>(selectedPointIndex_) < pointList_->size()) {
			const auto& point = (*pointList_)[selectedPointIndex_];
			double x = timeToX(point.time);
			double y = valueToY(point.value);
			painter.drawRect(QRectF(
				 QPointF(x - SELECTION_SIZE, y - SELECTION_SIZE),
				 QPointF(x + SELECTION_SIZE, y + SELECTION_SIZE)));
		}
	}
}
// Note: with no antialiasing, the coordinates in QPointF are rounded to the nearest integer.
void
IntonationWidget::paintEvent(QPaintEvent*)
{
	if (eventList_ == nullptr || eventList_->list().empty()) {
		return;
	}

	QPainter painter(this);
	painter.setFont(QFont("monospace"));

	if (modelUpdated_) {
		QFontMetrics fm = painter.fontMetrics();
		textYOffset_ = 0.5 * fm.ascent();
		leftMargin_ = MARGIN + TEXT_MARGIN + fm.width(yLabels[0]);

		modelUpdated_ = false;
	}

	totalWidth_ = std::ceil(leftMargin_ + graphWidth_ + 6.0 * MARGIN);
	if (totalWidth_ < MININUM_WIDTH) {
		totalWidth_ = MININUM_WIDTH;
	}
	totalHeight_ = std::ceil(2.0 * MARGIN + 3.0 * TRACK_HEIGHT + 15.0 * yStep_);
	if (totalHeight_ < MININUM_HEIGHT) {
		totalHeight_ = MININUM_HEIGHT;
	}
	setMinimumWidth(totalWidth_);
	setMinimumHeight(totalHeight_);

	double xStart = timeToX(0.0);
	double yStart = valueToY(MIN_VALUE);
	double xEnd = timeToX(maxTime_);
	double yEnd = valueToY(MAX_VALUE);

	// Y labels.
	for (unsigned int i = 0; i < yLabels.size(); ++i) {
		double y = MARGIN + (i + 3) * yStep_ + textYOffset_;
		painter.drawText(QPointF(MARGIN, y), yLabels[i]);
	}
	// Horizontal lines.
	painter.setPen(Qt::lightGray);
	for (int i = 1; i < 15; ++i) {
		double y = MARGIN + (i + 3) * yStep_;
		painter.drawLine(QPointF(xStart, y), QPointF(xEnd, y));
	}
	painter.setPen(Qt::black);

	postureTimeList_.clear();

	double yPosture = MARGIN + 3.0 * TRACK_HEIGHT - 0.5 * (TRACK_HEIGHT - 1.0) + textYOffset_;
	unsigned int postureIndex = 0;
	for (const TRMControlModel::Event_ptr& ev : eventList_->list()) {
		double x = timeToX(ev->time);
		if (ev->flag) {
			postureTimeList_.push_back(ev->time);
			const TRMControlModel::Posture* posture = eventList_->getPostureAtIndex(postureIndex++);
			if (posture) {
				painter.setPen(Qt::black);
				// Posture name.
				painter.drawText(QPointF(x, yPosture), posture->name().c_str());
			}
			painter.setPen(Qt::lightGray);
			// Event vertical line.
			painter.drawLine(QPointF(x, yStart), QPointF(x, yEnd));
		}
	}
	painter.setPen(Qt::black);

	// Frame.
	painter.drawRect(QRectF(QPointF(xStart, yStart), QPointF(xEnd, yEnd)));

	double yRuleText  = MARGIN + TRACK_HEIGHT - 0.5 * (TRACK_HEIGHT - 1.0) + textYOffset_;
	double yRuleText2 = yRuleText + TRACK_HEIGHT;

	for (int i = 0; i < eventList_->numberOfRules(); ++i) {
		auto* ruleData = eventList_->getRuleAtIndex(i);
		if (ruleData) {
			unsigned int firstPosture = ruleData->firstPosture;
			unsigned int lastPosture = ruleData->lastPosture;

			int postureTime1, postureTime2;
			if (firstPosture < postureTimeList_.size()) {
				postureTime1 = postureTimeList_[firstPosture];
			} else {
				postureTime1 = 0; // invalid
			}
			if (lastPosture < postureTimeList_.size()) {
				postureTime2 = postureTimeList_[lastPosture];
			} else {
				postureTime2 = postureTime1 + ruleData->duration;
			}

			// Rule frame.
			painter.drawRect(QRectF(
					QPointF(timeToX(postureTime1), MARGIN),
					QPointF(timeToX(postureTime2), MARGIN + 2.0 * TRACK_HEIGHT)));
			// Rule number.
			painter.drawText(QPointF(timeToX(postureTime1) + TEXT_MARGIN, yRuleText), QString::number(ruleData->number));

			// Rule duration.
			painter.drawText(QPointF(timeToX(postureTime1) + TEXT_MARGIN, yRuleText2), QString::number(ruleData->duration, 'f', 0));
		}
	}

	QPen pen;
	QPen pen2;
	pen2.setWidth(2);

	painter.setRenderHint(QPainter::Antialiasing);
	painter.setBrush(QBrush(Qt::black));

	// Lines between intonation points.
	QPointF prevPoint(0.5 + xStart, 0.5 + yStart);
	for (unsigned int i = 0, size = intonationPointList_.size(); i < size; ++i) {
		QPointF currPoint(
			0.5 + timeToX(intonationPointList_[i].absoluteTime()),
			0.5 + valueToY(intonationPointList_[i].semitone()));

		painter.setPen(pen2);
		painter.drawLine(prevPoint, currPoint);

		painter.setPen(pen);
		drawPointMarker(painter, 0.5 + currPoint.x(), 0.5 + currPoint.y());

		prevPoint = currPoint;
	}

	painter.setBrush(QBrush());

	painter.setPen(pen2);
	smoothPoints(painter);
	painter.setPen(pen);

	painter.setRenderHint(QPainter::Antialiasing, false);

	// Point selection.
	if (selectedPoint_ >= 0) {
		double x = timeToX(intonationPointList_[selectedPoint_].absoluteTime());
		double y = valueToY(intonationPointList_[selectedPoint_].semitone());
		painter.drawRect(QRectF(
			 QPointF(x - SELECTION_SIZE, y - SELECTION_SIZE),
			 QPointF(x + SELECTION_SIZE, y + SELECTION_SIZE)));
	}

	// Beat lines.
	for (unsigned int i = 0, size = intonationPointList_.size(); i < size; ++i) {
		double x = timeToX(intonationPointList_[i].beatTime());
		painter.drawLine(QPointF(x, yStart), QPointF(x, yEnd));
	}

	// Time scale.
	double yTick1 = yStart + TIME_DIVISION_MARK_SIZE;
	double yTick2 = yStart + 2.0 * TIME_DIVISION_MARK_SIZE;
	double yTimeText = yTick2 + 0.5 * TRACK_HEIGHT + textYOffset_;
	for (int time = 0, end = static_cast<int>(maxTime_); time <= end; time += 10) {
		double x = timeToX(time);
		if (time % 100 == 0) {
			painter.drawLine(QPointF(x, yStart), QPointF(x, yTick2));
			painter.drawText(QPointF(x, yTimeText), QString::number(time));
		} else {
			painter.drawLine(QPointF(x, yStart), QPointF(x, yTick1));
		}
	}
}
Exemple #8
0
int TimelineComponent::timeToWidth (const Range<double>& time, const TimeUnit unit) const
{
    return timeToX (time.getEnd(), unit) - timeToX (time.getStart(), unit);
}
Exemple #9
0
void TimelineComponent::paint (Graphics& g)
{
    g.setColour (Colour (0xff454545));
    g.fillAll();

    // track header divider line
    g.setColour (Colours::black.withAlpha (0.5f));
    g.drawVerticalLine (mTrackWidth + 1, 0, getHeight());

    int track = heights.trackAtY (0);
    Rectangle<int> r;
    while (true)
    {
        if (r.getY() > getHeight() || track >= getNumTracks())
            break;

        if (! heights.trackIsVisible (track)) {
            ++track;
            continue;
        }

        r.setX (mTrackWidth);
        r.setY (heights.trackY (track));
        r.setWidth (getWidth() - mTrackWidth);
        r.setHeight (heights.get (track) + heights.spacing());

        g.saveState();
        paintTrackLane (g, track, r);
        g.restoreState();

        ++track;
    }

#if 0
    int track = heights.trackAtY (0);
    Rectangle<int> r;

    while (true)
    {
        r.setX (0);
        r.setWidth (mTrackWidth);
        r.setY (heights.trackY (track));
        r.setHeight (heights.get (track));

        if (r.getY() > getHeight() || track >= getNumTracks())
            break;

        if (! heights.trackIsVisible (track)) {
            ++track;
            continue;
        }

        if (mTrackWidth > 0) {
            g.saveState();
            paintTrackHeader (g, track, r);
            g.restoreState();
        }

        r.setX (mTrackWidth);
        r.setWidth (getWidth() - mTrackWidth);
        r.setHeight (r.getHeight() + heights.spacing());

        g.saveState();
        paintTrackLane (g, track, r);
        g.restoreState();

        ++track;
    }
#endif

#if 0
    // paint grid lines
    g.saveState();
    g.setColour (Colours::white);

    for (int beat = scale.beatFromPixel (timeToX (timeSpan.getStart())) - 1;
         ++beat;)
    {
        const int pixel = scale.pixelFromBeat (beat) + mTrackWidth;

        if (pixel < 0)
            continue;

        if (scale.beatIsBar (beat))
        {
            g.saveState();
            g.setColour(Colours::white);
            g.drawText (String(beat), pixel, 0, 20, 16, Justification::left, true);
            g.restoreState();
            g.setOpacity (0.20);
        }
        else
            g.setOpacity (0.10);

        g.drawVerticalLine (pixel, 0, getHeight());

        if (pixel > getWidth())
            break;
    }

    g.restoreState();
    g.resetToDefaultState();
#endif

}