Implements #2635: Draws a transparent rectangle in the loop area (plus CSS exposure) (#2657)

* Draws a transparent rectangle in the loop area (plus CSS exposure)

The color for the rectangle can be defined in the style CSS for the
active and inactive case. The following properties of the TimeLineWidget
are exposed through the CSS:
- The color of the lines that are drawn for each bar
- The color of the bar numbers
- The font size (given in pt)
- The minimum and the maximum height of the widget (given in em so that it scales with the font size). Set both to the same value to set a fixed size.
- The background of the widget
- A loop color: The color for the main rectangle's pen
- A loop brush: The brush used to fill the main rectangle
- An inner loop color: The color used for the pen that draws the inner border.
- loopRectangleVerticalPadding: specifies the padding used for the loop indicator rectangle.

The bar numbers are drawn conditionally like the bar lines. The
numbers are drawn with a constant distance to the tact line. This gives
a more consistent picture at different zoom levels and also fixes the
broken look at very small zoom sizes like for example 12.5%.

The bar numbers are drawn with hinting so that they show up less blurry on low DPI displays.

Remove the pixmaps that have been used up to now to draw the loop
boundaries.

Removes the unused "TimeLine" from style.css.

Document the style sheet properties for the loop indicator rectangle.
This commit is contained in:
Michael Gregorius
2016-06-12 18:13:23 +02:00
committed by GitHub
parent 1abbbc2ef6
commit ec95ef1ba9
8 changed files with 159 additions and 52 deletions

View File

@@ -48,13 +48,20 @@
QPixmap * TimeLineWidget::s_posMarkerPixmap = NULL;
QPixmap * TimeLineWidget::s_loopPointBeginPixmap = NULL;
QPixmap * TimeLineWidget::s_loopPointEndPixmap = NULL;
TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt,
Song::PlayPos & pos, const MidiTime & begin,
QWidget * parent ) :
QWidget( parent ),
m_inactiveLoopColor( 52, 63, 53, 64 ),
m_inactiveLoopBrush( QColor( 255, 255, 255, 32 ) ),
m_inactiveLoopInnerColor( 255, 255, 255, 32 ),
m_activeLoopColor( 52, 63, 53, 255 ),
m_activeLoopBrush( QColor( 55, 141, 89 ) ),
m_activeLoopInnerColor( 74, 155, 100, 255 ),
m_loopRectangleVerticalPadding( 1 ),
m_barLineColor( 192, 192, 192 ),
m_barNumberColor( m_barLineColor.darker( 120 ) ),
m_autoScroll( AutoScrollEnabled ),
m_loopPoints( LoopPointsDisabled ),
m_behaviourAtStop( BackToZero ),
@@ -77,20 +84,9 @@ TimeLineWidget::TimeLineWidget( const int xoff, const int yoff, const float ppt,
s_posMarkerPixmap = new QPixmap( embed::getIconPixmap(
"playpos_marker" ) );
}
if( s_loopPointBeginPixmap == NULL )
{
s_loopPointBeginPixmap = new QPixmap( embed::getIconPixmap(
"loop_point_b" ) );
}
if( s_loopPointEndPixmap == NULL )
{
s_loopPointEndPixmap = new QPixmap( embed::getIconPixmap(
"loop_point_e" ) );
}
setAttribute( Qt::WA_OpaquePaintEvent, true );
move( 0, yoff );
setFixedHeight( 18 );
m_xOffset -= s_posMarkerPixmap->width() / 2;
@@ -224,55 +220,71 @@ void TimeLineWidget::paintEvent( QPaintEvent * )
{
QPainter p( this );
QColor bg_color = QApplication::palette().color( QPalette::Active,
QPalette::Background );
QLinearGradient g( 0, 0, 0, height() );
g.setColorAt( 0, bg_color.lighter( 150 ) );
g.setColorAt( 1, bg_color.darker( 150 ) );
p.fillRect( 0, 0, width(), height(), g );
// Draw background
p.fillRect( 0, 0, width(), height(), p.background() );
// Clip so that we only draw everything starting from the offset
p.setClipRect( m_xOffset, 0, width() - m_xOffset, height() );
p.setPen( QColor( 0, 0, 0 ) );
p.setOpacity( loopPointsEnabled() ? 0.9 : 0.2 );
p.drawPixmap( markerX( loopBegin() )+2, 2, *s_loopPointBeginPixmap );
p.drawPixmap( markerX( loopEnd() )+2, 2, *s_loopPointEndPixmap );
p.setOpacity( 1.0 );
// Draw the loop rectangle
int const & loopRectMargin = getLoopRectangleVerticalPadding();
int const loopRectHeight = this->height() - 2 * loopRectMargin;
int const loopStart = markerX( loopBegin() ) + 8;
int const loopEndR = markerX( loopEnd() ) + 9;
int const loopRectWidth = loopEndR - loopStart;
bool const loopPointsActive = loopPointsEnabled();
tact_t tact_num = m_begin.getTact();
int x = m_xOffset + s_posMarkerPixmap->width() / 2 -
( ( static_cast<int>( m_begin * m_ppt ) / MidiTime::ticksPerTact() ) % static_cast<int>( m_ppt ) );
// Draw the main rectangle (inner fill only)
QRect outerRectangle( loopStart, loopRectMargin, loopRectWidth - 1, loopRectHeight - 1 );
p.fillRect( outerRectangle, loopPointsActive ? getActiveLoopBrush() : getInactiveLoopBrush());
QColor lineColor( 192, 192, 192 );
QColor tactColor( lineColor.darker( 120 ) );
// Set font to half of the widgets size (in pixels)
// Draw the bar lines and numbers
// Activate hinting on the font
QFont font = p.font();
font.setPixelSize( this->height() * 0.5 );
p.setFont( font );
font.setHintingPreference( QFont::PreferFullHinting );
p.setFont(font);
int const fontAscent = p.fontMetrics().ascent();
int const fontHeight = p.fontMetrics().height();
QColor const & barLineColor = getBarLineColor();
QColor const & barNumberColor = getBarNumberColor();
tact_t barNumber = m_begin.getTact();
int const x = m_xOffset + s_posMarkerPixmap->width() / 2 -
( ( static_cast<int>( m_begin * m_ppt ) / MidiTime::ticksPerTact() ) % static_cast<int>( m_ppt ) );
for( int i = 0; x + i * m_ppt < width(); ++i )
{
const int cx = x + qRound( i * m_ppt );
p.setPen( lineColor );
p.drawLine( cx, 5, cx, height() - 6 );
++tact_num;
if( ( tact_num - 1 ) %
++barNumber;
if( ( barNumber - 1 ) %
qMax( 1, qRound( 1.0f / 3.0f *
MidiTime::ticksPerTact() / m_ppt ) ) == 0 )
{
const QString s = QString::number( tact_num );
p.setPen( tactColor );
p.drawText( cx + qRound( ( m_ppt - p.fontMetrics().
width( s ) ) / 2 ),
height() - p.fontMetrics().ascent() / 2, s );
const int cx = x + qRound( i * m_ppt );
p.setPen( barLineColor );
p.drawLine( cx, 5, cx, height() - 6 );
const QString s = QString::number( barNumber );
p.setPen( barNumberColor );
p.drawText( cx + 5, ((height() - fontHeight) / 2) + fontAscent, s );
}
}
// Draw the main rectangle (outer border)
p.setPen( loopPointsActive ? getActiveLoopColor() : getInactiveLoopColor() );
p.setBrush( Qt::NoBrush );
p.drawRect( outerRectangle );
// Draw the inner border outline (no fill)
QRect innerRectangle = outerRectangle.adjusted( 1, 1, -1, -1 );
p.setPen( loopPointsActive ? getActiveLoopInnerColor() : getInactiveLoopInnerColor() );
p.setBrush( Qt::NoBrush );
p.drawRect( innerRectangle );
// Draw the position marker
p.setOpacity( 0.6 );
p.drawPixmap( m_posMarkerX, height() - s_posMarkerPixmap->height(),
*s_posMarkerPixmap );
p.drawPixmap( m_posMarkerX, height() - s_posMarkerPixmap->height(), *s_posMarkerPixmap );
}