comparison widgets/LevelPanWidget.cpp @ 1306:5db672d6de4f

Better rendering for widget cells
author Chris Cannam
date Mon, 25 Jun 2018 15:29:47 +0100
parents 21342513c252
children 5af5c611f4cb
comparison
equal deleted inserted replaced
1305:21342513c252 1306:5db672d6de4f
390 double adj = thinLineWidth(rect)/2; 390 double adj = thinLineWidth(rect)/2;
391 return clr.adjusted(-adj, -adj, adj, adj); 391 return clr.adjusted(-adj, -adj, adj, adj);
392 } 392 }
393 393
394 QColor 394 QColor
395 LevelPanWidget::notchToColour(int notch) const 395 LevelPanWidget::cellToColour(int cell) const
396 { 396 {
397 if (notch < 3) return Qt::black; 397 if (cell < 1) return Qt::black;
398 if (notch < 5) return QColor(80, 0, 0); 398 if (cell < 2) return QColor(80, 0, 0);
399 if (notch < 7) return QColor(160, 0, 0); 399 if (cell < 3) return QColor(160, 0, 0);
400 if (notch < 9) return QColor(255, 0, 0); 400 if (cell < 4) return QColor(255, 0, 0);
401 return QColor(255, 255, 0); 401 return QColor(255, 255, 0);
402 } 402 }
403 403
404 void 404 void
405 LevelPanWidget::renderTo(QPaintDevice *dev, QRectF rect, bool asIfEditable) const 405 LevelPanWidget::renderTo(QPaintDevice *dev, QRectF rect, bool asIfEditable) const
406 { 406 {
407 QPainter paint(dev); 407 QPainter paint(dev);
408 408
409 paint.setRenderHint(QPainter::Antialiasing, true); 409 paint.setRenderHint(QPainter::Antialiasing, true);
410
411 QPen pen;
412 410
413 double thin = thinLineWidth(rect); 411 double thin = thinLineWidth(rect);
414 double radius = cornerRadius(rect); 412 double radius = cornerRadius(rect);
415 413
416 QColor columnBackground = QColor(180, 180, 180); 414 QColor columnBackground = QColor(180, 180, 180);
417 paint.setPen(Qt::NoPen); 415
418 paint.setBrush(columnBackground); 416 bool monitoring = (m_monitorLeft > 0.f || m_monitorRight > 0.f);
417
418 QPen pen;
419 if (isEnabled()) {
420 pen.setColor(Qt::black);
421 } else {
422 pen.setColor(Qt::darkGray);
423 }
424 pen.setWidthF(thin);
425 pen.setCapStyle(Qt::FlatCap);
426 pen.setJoinStyle(Qt::MiterJoin);
419 427
420 for (int pan = -maxPan; pan <= maxPan; ++pan) { 428 for (int pan = -maxPan; pan <= maxPan; ++pan) {
429
430 paint.setPen(Qt::NoPen);
431 paint.setBrush(columnBackground);
432
421 QRectF top = cellOutlineRect(rect, m_maxNotch/2 - 1, pan); 433 QRectF top = cellOutlineRect(rect, m_maxNotch/2 - 1, pan);
422 QRectF bottom = cellOutlineRect(rect, 0, pan); 434 QRectF bottom = cellOutlineRect(rect, 0, pan);
423 paint.drawRoundedRect(QRectF(top.x(), 435 paint.drawRoundedRect(QRectF(top.x(),
424 top.y(), 436 top.y(),
425 top.width(), 437 top.width(),
426 bottom.y() + bottom.height() - top.y()), 438 bottom.y() + bottom.height() - top.y()),
427 radius, radius); 439 radius, radius);
428 } 440
429 441 if (!asIfEditable && m_includeMute && m_notch == 0) {
430 bool monitoring = (m_monitorLeft > 0.f || m_monitorRight > 0.f); 442 // We will instead be drawing a single big X for mute,
431 443 // after this loop
432 if (isEnabled()) { 444 continue;
433 pen.setColor(Qt::black); 445 }
434 } else { 446
435 pen.setColor(Qt::darkGray); 447 if (!monitoring && m_pan != pan) {
448 continue;
449 }
450
451 int monitorNotch = 0;
452 if (monitoring) {
453 float rprop = float(pan - (-maxPan)) / float(maxPan * 2);
454 float lprop = float(maxPan - pan) / float(maxPan * 2);
455 float monitorLevel =
456 lprop * m_monitorLeft * m_monitorLeft +
457 rprop * m_monitorRight * m_monitorRight;
458 monitorNotch = audioLevelToNotch(monitorLevel);
459 }
460
461 int firstCell = 0;
462 int lastCell = m_maxNotch / 2 - 1;
463
464 for (int cell = firstCell; cell <= lastCell; ++cell) {
465
466 QRectF clr = cellLightRect(rect, cell, pan);
467
468 if (m_includeMute && m_pan == pan && m_notch == 0) {
469 // X for mute in the bottom cell
470 paint.setPen(pen);
471 paint.drawLine(clr.topLeft(), clr.bottomRight());
472 paint.drawLine(clr.bottomLeft(), clr.topRight());
473 break;
474 }
475
476 const int none = 0, half = 1, full = 2;
477
478 int fill = none;
479
480 int outline = none;
481 if (m_pan == pan && m_notch > cell * 2 + 1) {
482 outline = full;
483 } else if (m_pan == pan && m_notch == cell * 2 + 1) {
484 outline = half;
485 }
486
487 if (monitoring) {
488 if (monitorNotch > cell * 2 + 1) {
489 fill = full;
490 } else if (monitorNotch == cell * 2 + 1) {
491 fill = half;
492 }
493 } else {
494 if (isEnabled()) {
495 fill = outline;
496 }
497 }
498
499 // If one of {fill, outline} is "full" and the other is
500 // "half", then we draw the "half" one first (because we
501 // need to erase half of it)
502
503 if (fill == half || outline == half) {
504 if (fill == half) {
505 paint.setBrush(cellToColour(cell));
506 } else {
507 paint.setBrush(Qt::NoBrush);
508 }
509 if (outline == half) {
510 paint.setPen(pen);
511 } else {
512 paint.setPen(Qt::NoPen);
513 }
514
515 paint.drawRoundedRect(clr, radius, radius);
516
517 paint.setBrush(columnBackground);
518
519 if (cell == lastCell) {
520 QPen bgpen(pen);
521 bgpen.setColor(columnBackground);
522 paint.setPen(bgpen);
523 paint.drawRoundedRect(QRectF(clr.x(),
524 clr.y(),
525 clr.width(),
526 clr.height()/4),
527 radius, radius);
528 paint.drawRect(QRectF(clr.x(),
529 clr.y() + clr.height()/4,
530 clr.width(),
531 clr.height()/4));
532 } else {
533 paint.setPen(Qt::NoPen);
534 if (outline == half) {
535 clr = cellOutlineRect(rect, cell, pan);
536 }
537 paint.drawRect(QRectF(clr.x(),
538 clr.y() - 0.5,
539 clr.width(),
540 clr.height()/2));
541 }
542 }
543
544 if (outline == full || fill == full) {
545
546 if (fill == full) {
547 paint.setBrush(cellToColour(cell));
548 } else {
549 paint.setBrush(Qt::NoBrush);
550 }
551 if (outline == full) {
552 paint.setPen(pen);
553 } else {
554 paint.setPen(Qt::NoPen);
555 }
556
557 paint.drawRoundedRect(clr, radius, radius);
558 }
559 }
436 } 560 }
437 561
438 if (!asIfEditable && m_includeMute && m_notch == 0) { 562 if (!asIfEditable && m_includeMute && m_notch == 0) {
439 // The X for mute takes up the whole display when we're not 563 // The X for mute takes up the whole display when we're not
440 // being rendered in editable style 564 // being rendered in editable style
565 pen.setColor(Qt::black);
441 pen.setWidthF(thin * 2); 566 pen.setWidthF(thin * 2);
442 pen.setCapStyle(Qt::RoundCap); 567 pen.setCapStyle(Qt::RoundCap);
443 paint.setPen(pen); 568 paint.setPen(pen);
444 paint.drawLine(cellCentre(rect, 0, -maxPan), 569 paint.drawLine(cellCentre(rect, 0, -maxPan),
445 cellCentre(rect, m_maxNotch/2 - 1, maxPan)); 570 cellCentre(rect, m_maxNotch/2 - 1, maxPan));
446 paint.drawLine(cellCentre(rect, m_maxNotch/2 - 1, -maxPan), 571 paint.drawLine(cellCentre(rect, m_maxNotch/2 - 1, -maxPan),
447 cellCentre(rect, 0, maxPan)); 572 cellCentre(rect, 0, maxPan));
448 } else {
449 // the normal case
450
451 // pen a bit less thin than in theory, so that we can erase
452 // semi-circles later without leaving a faint edge
453 pen.setWidthF(thin * 0.8);
454 pen.setCapStyle(Qt::FlatCap);
455 paint.setPen(pen);
456
457 if (m_includeMute && m_notch == 0) {
458 QRectF clr = cellLightRect(rect, 0, m_pan);
459 paint.drawLine(clr.topLeft(), clr.bottomRight());
460 paint.drawLine(clr.bottomLeft(), clr.topRight());
461 } else {
462 for (int notch = 1; notch <= m_notch; notch += 2) {
463 if (isEnabled() && !monitoring) {
464 paint.setBrush(notchToColour(notch));
465 } else {
466 paint.setBrush(Qt::NoBrush);
467 }
468 QRectF clr = cellLightRect(rect, notch/2, m_pan);
469 paint.drawRoundedRect(clr, radius, radius);
470 }
471 if (m_notch % 2 != 0) {
472 QRectF clr = cellOutlineRect(rect, (m_notch-1)/2, m_pan);
473 paint.save();
474 paint.setPen(Qt::NoPen);
475 paint.setBrush(columnBackground);
476 paint.drawRoundedRect(QRectF(clr.x(),
477 clr.y(),
478 clr.width(),
479 clr.height()/4 + thin),
480 radius, radius);
481 paint.drawRect(QRectF(clr.x(),
482 clr.y() + clr.height()/4 - thin,
483 clr.width(),
484 clr.height()/4 + thin));
485 paint.restore();
486 }
487 }
488 }
489
490 if (monitoring) {
491 paint.setPen(Qt::NoPen);
492
493 for (int pan = -maxPan; pan <= maxPan; ++pan) {
494 float rprop = float(pan - (-maxPan)) / float(maxPan * 2);
495 float lprop = float(maxPan - pan) / float(maxPan * 2);
496 float audioLevel =
497 lprop * m_monitorLeft * m_monitorLeft +
498 rprop * m_monitorRight * m_monitorRight;
499 int notchHere = audioLevelToNotch(audioLevel);
500
501 for (int notch = 1; notch <= notchHere; notch += 2) {
502
503 paint.setBrush(notchToColour(notch));
504 QRectF clr = cellLightRect(rect, (notch-1)/2, pan);
505 // double adj = thinLineWidth(rect)/2;
506 // clr = clr.adjusted(adj, adj, -adj, -adj);
507 paint.drawRoundedRect(clr, radius, radius);
508
509 if (notch + 2 > notchHere && notchHere % 2 != 0) {
510 paint.save();
511 paint.setBrush(columnBackground);
512 paint.drawRoundedRect(QRectF(clr.x(),
513 clr.y()-0.5,
514 clr.width(),
515 clr.height()/4 + thin),
516 radius, radius);
517 paint.drawRect(QRectF(clr.x(),
518 clr.y() + clr.height()/4 - thin,
519 clr.width(),
520 clr.height()/4 + thin));
521 paint.restore();
522 }
523 }
524 }
525 } 573 }
526 } 574 }
527 575
528 void 576 void
529 LevelPanWidget::paintEvent(QPaintEvent *) 577 LevelPanWidget::paintEvent(QPaintEvent *)