hydrogen 1.2.3
LayerPreview.cpp
Go to the documentation of this file.
1/*
2 * Hydrogen
3 * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4 * Copyright(c) 2008-2024 The hydrogen development team [hydrogen-devel@lists.sourceforge.net]
5 *
6 * http://www.hydrogen-music.org
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY, without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see https://www.gnu.org/licenses
20 *
21 */
22
23#include <QtGui>
24#include <QtWidgets>
25
26#include <core/Hydrogen.h>
27#include <core/Basics/Song.h>
32#include <core/Basics/Note.h>
36
37using namespace H2Core;
38
39#include "../Skin.h"
40#include "../HydrogenApp.h"
42#include "LayerPreview.h"
43
44LayerPreview::LayerPreview( QWidget* pParent )
45 : QWidget( pParent )
46 , m_pInstrument( nullptr )
47 , m_nSelectedComponent( 0 )
48 , m_nSelectedLayer( 0 )
49 , m_bMouseGrab( false )
50 , m_bGrabLeft( false )
51{
52 setAttribute(Qt::WA_OpaquePaintEvent);
53
54 setMouseTracking( true );
55
56 int width = 276;
58 width = 261;
59 }
60
62 resize( width, height );
63
64 m_speakerPixmap.load( Skin::getSvgImagePath() + "/icons/white/speaker.svg" );
65
67
69
73 this->setStyleSheet("font-size: 9px; font-weight: bold;");
74}
75
76LayerPreview::~ LayerPreview()
77{
78 //INFOLOG( "DESTROY" );
79}
80
81void LayerPreview::set_selected_component( int SelectedComponent )
82{
83 m_nSelectedComponent = SelectedComponent;
84}
85
86void LayerPreview::paintEvent(QPaintEvent *ev)
87{
88 QPainter p( this );
89
91
92 QFont fontText( pPref->getLevel2FontFamily(), getPointSize( pPref->getFontSize() ) );
93 QFont fontButton( pPref->getLevel2FontFamily(), getPointSizeButton() );
94
95 p.fillRect( ev->rect(), pPref->getColorTheme()->m_windowColor );
96
97 int nLayers = 0;
98 for ( int i = 0; i < InstrumentComponent::getMaxLayers(); i++ ) {
99 if ( m_pInstrument ) {
101 if(pComponent) {
102 auto pLayer = pComponent->get_layer( i );
103 if ( pLayer != nullptr ) {
104 nLayers++;
105 }
106 }
107 }
108 }
109
110 // How much the color of the labels for the individual layers
111 // are allowed to diverge from the general window color.
112 int nColorScalingWidth = 90;
113 int nColorScaling = 100;
114
115 QColor layerLabelColor, layerSegmentColor;
116
117 int nLayer = 0;
118 for ( int i = InstrumentComponent::getMaxLayers() - 1; i >= 0; i-- ) {
119 int y = 20 + m_nLayerHeight * i;
120 QString label = "< - >";
121
122 if ( m_pInstrument ) {
124 if( pComponent ) {
125 auto pLayer = pComponent->get_layer( i );
126
127 if ( pLayer && nLayers > 0 ) {
128 auto pSample = pLayer->get_sample();
129 if( pSample != nullptr) {
130 label = pSample->get_filename();
131 layerSegmentColor =
132 pPref->getColorTheme()->m_accentColor.lighter( 130 );
133 } else {
134 layerSegmentColor =
135 pPref->getColorTheme()->m_buttonRedColor;
136 }
137
138
139 int x1 = (int)( pLayer->get_start_velocity() * width() );
140 int x2 = (int)( pLayer->get_end_velocity() * width() );
141
142 // Labels for layers to the left will have a
143 // lighter color as those to the right.
144 nColorScaling =
145 static_cast<int>(std::round( static_cast<float>(nLayer) /
146 static_cast<float>(nLayers) * 2 *
147 static_cast<float>(nColorScalingWidth) ) ) -
148 nColorScalingWidth + 100;
149 layerLabelColor =
150 pPref->getColorTheme()->m_windowColor.lighter( nColorScaling );
151
152 p.fillRect( x1, 0, x2 - x1, 19, layerLabelColor );
153 p.setPen( pPref->getColorTheme()->m_windowTextColor );
154 p.setFont( fontButton );
155 p.drawText( x1, 0, x2 - x1, 20, Qt::AlignCenter, QString("%1").arg( i + 1 ) );
156
157 if ( m_nSelectedLayer == i ) {
158 p.setPen( pPref->getColorTheme()->m_highlightColor );
159 } else {
160 p.setPen( pPref->getColorTheme()->m_windowTextColor.darker( 145 ) );
161 }
162 p.drawRect( x1, 1, x2 - x1 - 1, 18 ); // bordino in alto
163
164 // layer view
165 p.fillRect( 0, y, width(), m_nLayerHeight,
166 pPref->getColorTheme()->m_windowColor );
167 p.fillRect( x1, y, x2 - x1, m_nLayerHeight, layerSegmentColor );
168
169 nLayer++;
170 }
171 else {
172 // layer view
173 p.fillRect( 0, y, width(), m_nLayerHeight,
174 pPref->getColorTheme()->m_windowColor );
175 }
176 }
177 else {
178 // layer view
179 p.fillRect( 0, y, width(), m_nLayerHeight,
180 pPref->getColorTheme()->m_windowColor );
181 }
182 }
183 else {
184 // layer view
185 p.fillRect( 0, y, width(), m_nLayerHeight,
186 pPref->getColorTheme()->m_windowColor );
187 }
188 QColor layerTextColor = pPref->getColorTheme()->m_windowTextColor;
189 layerTextColor.setAlpha( 155 );
190 p.setPen( layerTextColor );
191 p.setFont( fontText );
192 p.drawText( 10, y, width() - 10, 20, Qt::AlignLeft, QString( "%1: %2" ).arg( i + 1 ).arg( label ) );
193 p.setPen( layerTextColor.darker( 145 ) );
194 p.drawRect( 0, y, width() - 1, m_nLayerHeight );
195 }
196
197 // selected layer
198 p.setPen( pPref->getColorTheme()->m_highlightColor );
199 int y = 20 + m_nLayerHeight * m_nSelectedLayer;
200 p.drawRect( 0, y, width() - 1, m_nLayerHeight );
201}
202
206
208 // A new song got loaded
209 if ( nValue == 0 ) {
211 }
212}
213
215{
217
218 bool bSelectedLayerChanged = false;
219
220 // select the last valid layer
221 if ( m_pInstrument != nullptr ) {
222 for (int i = InstrumentComponent::getMaxLayers() - 1; i >= 0; i-- ) {
224 if ( p_compo ) {
225 if ( p_compo->get_layer( i ) ) {
227 bSelectedLayerChanged = true;
228 break;
229 }
230 }
231 else {
233 bSelectedLayerChanged = true;
234 }
235 }
236 }
237 else {
239 bSelectedLayerChanged = true;
240 }
241
242 if ( bSelectedLayerChanged ) {
244 }
245
246 update();
247}
248
250{
251 m_bMouseGrab = false;
252 setCursor( QCursor( Qt::ArrowCursor ) );
253
254 if ( m_pInstrument == nullptr ) {
255 return;
256 }
257
258 /*
259 * We want the tooltip to still show if mouse pointer
260 * is over an active layer's boundary
261 */
263 if ( pCompo ) {
264 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
265
266 if ( pLayer ) {
267 int x1 = (int)( pLayer->get_start_velocity() * width() );
268 int x2 = (int)( pLayer->get_end_velocity() * width() );
269
270 if ( ( ev->x() < x1 + 5 ) && ( ev->x() > x1 - 5 ) ){
271 setCursor( QCursor( Qt::SizeHorCursor ) );
272 showLayerStartVelocity(pLayer, ev);
273 }
274 else if ( ( ev->x() < x2 + 5 ) && ( ev->x() > x2 - 5 ) ) {
275 setCursor( QCursor( Qt::SizeHorCursor ) );
276 showLayerEndVelocity(pLayer, ev);
277 }
278 }
279 }
280}
281
282void LayerPreview::mousePressEvent(QMouseEvent *ev)
283{
284 const int nPosition = 0;
285
286 if ( m_pInstrument == nullptr ) {
287 return;
288 }
289 if ( ev->y() < 20 ) {
290 const float fVelocity = (float)ev->x() / (float)width();
291
292 if ( m_pInstrument->hasSamples() ) {
293 Note * pNote = new Note( m_pInstrument, nPosition, fVelocity );
296 }
297
298 for ( int i = 0; i < InstrumentComponent::getMaxLayers(); i++ ) {
300 if(pCompo){
301 auto pLayer = pCompo->get_layer( i );
302 if ( pLayer ) {
303 if ( ( fVelocity > pLayer->get_start_velocity()) && ( fVelocity < pLayer->get_end_velocity() ) ) {
304 if ( i != m_nSelectedLayer ) {
306 update();
308 }
309 break;
310 }
311 }
312 }
313 }
314 }
315 else {
316 m_nSelectedLayer = ( ev->y() - 20 ) / m_nLayerHeight;
317
318 update();
320
322 if( pCompo != nullptr ) {
323 auto pLayer = pCompo->get_layer( m_nSelectedLayer );
324 if ( pLayer != nullptr ) {
325 const float fVelocity = pLayer->get_end_velocity() - 0.01;
326 Note *note = new Note( m_pInstrument, nPosition, fVelocity );
329
330 int x1 = (int)( pLayer->get_start_velocity() * width() );
331 int x2 = (int)( pLayer->get_end_velocity() * width() );
332
333 if ( ( ev->x() < x1 + 5 ) && ( ev->x() > x1 - 5 ) ){
334 setCursor( QCursor( Qt::SizeHorCursor ) );
335 m_bGrabLeft = true;
336 m_bMouseGrab = true;
337 showLayerStartVelocity(pLayer, ev);
338 }
339 else if ( ( ev->x() < x2 + 5 ) && ( ev->x() > x2 - 5 ) ){
340 setCursor( QCursor( Qt::SizeHorCursor ) );
341 m_bGrabLeft = false;
342 m_bMouseGrab = true;
343 showLayerEndVelocity(pLayer, ev);
344 }
345 else {
346 setCursor( QCursor( Qt::ArrowCursor ) );
347 }
348 }
349 }
350 }
351}
352
353void LayerPreview::mouseMoveEvent( QMouseEvent *ev )
354{
355 if ( !m_pInstrument ) {
356 return;
357 }
358
359 int x = ev->pos().x();
360 int y = ev->pos().y();
361
362 float fVel = (float)x / (float)width();
363 if (fVel < 0 ) {
364 fVel = 0;
365 }
366 else if (fVel > 1) {
367 fVel = 1;
368 }
369
370 if ( y < 20 ) {
371 setCursor( QCursor( m_speakerPixmap ) );
372 return;
373 }
374 if ( m_bMouseGrab ) {
376 if ( pLayer ) {
377 if ( m_bMouseGrab ) {
378 bool bChanged = false;
379 if ( m_bGrabLeft ) {
380 if ( fVel < pLayer->get_end_velocity()) {
381 pLayer->set_start_velocity( fVel );
382 bChanged = true;
383 showLayerStartVelocity( pLayer, ev );
384 }
385 }
386 else {
387 if ( fVel > pLayer->get_start_velocity()) {
388 pLayer->set_end_velocity( fVel );
389 bChanged = true;
390 showLayerEndVelocity( pLayer, ev );
391 }
392 }
393
394 if ( bChanged ) {
395 update();
397 }
398 }
399 }
400 }
401 else {
402 m_nSelectedLayer = ( ev->y() - 20 ) / m_nLayerHeight;
405 if( pComponent ){
406 auto pLayer = pComponent->get_layer( m_nSelectedLayer );
407 if ( pLayer ) {
408 int x1 = (int)( pLayer->get_start_velocity() * width() );
409 int x2 = (int)( pLayer->get_end_velocity() * width() );
410
411 if ( ( x < x1 + 5 ) && ( x > x1 - 5 ) ){
412 setCursor( QCursor( Qt::SizeHorCursor ) );
413 showLayerStartVelocity(pLayer, ev);
414 }
415 else if ( ( x < x2 + 5 ) && ( x > x2 - 5 ) ){
416 setCursor( QCursor( Qt::SizeHorCursor ) );
417 showLayerEndVelocity(pLayer, ev);
418 }
419 else {
420 setCursor( QCursor( Qt::ArrowCursor ) );
421 QToolTip::hideText();
422 }
423 }
424 else {
425 setCursor( QCursor( Qt::ArrowCursor ) );
426 QToolTip::hideText();
427 }
428 }
429 else {
430 setCursor( QCursor( Qt::ArrowCursor ) );
431 QToolTip::hideText();
432 }
433 }
434 }
435}
436
438{
439 update();
440}
441
443{
444 return static_cast<int> (raw * 127);
445}
446
447void LayerPreview::showLayerStartVelocity( const std::shared_ptr<InstrumentLayer> pLayer, const QMouseEvent* pEvent )
448{
449 const float fVelo = pLayer->get_start_velocity();
450
451 QToolTip::showText( pEvent->globalPos(),
452 tr( "Dec. = %1\nMIDI = %2" )
453 .arg( QString::number( fVelo, 'f', 2) )
454 .arg( getMidiVelocityFromRaw( fVelo ) +1 ),
455 this);
456}
457
458void LayerPreview::showLayerEndVelocity( const std::shared_ptr<InstrumentLayer> pLayer, const QMouseEvent* pEvent )
459{
460 const float fVelo = pLayer->get_end_velocity();
461
462 QToolTip::showText( pEvent->globalPos(),
463 tr( "Dec. = %1\nMIDI = %2" )
464 .arg( QString::number( fVelo, 'f', 2) )
465 .arg( getMidiVelocityFromRaw( fVelo ) +1 ),
466 this);
467}
468
470{
472
473 int nPointSize;
474
475 switch( pPref->getFontSize() ) {
477 nPointSize = 6;
478 break;
480 nPointSize = 8;
481 break;
483 nPointSize = 12;
484 break;
485 }
486
487 return nPointSize;
488}
489
Sampler * getSampler() const
static Hydrogen * get_instance()
Returns the current Hydrogen instance __instance.
Definition Hydrogen.h:83
AudioEngine * getAudioEngine() const
Definition Hydrogen.h:649
std::shared_ptr< Instrument > getSelectedInstrument() const
void setIsModified(bool bIsModified)
Wrapper around Song::setIsModified() that checks whether a song is set.
std::shared_ptr< InstrumentComponent > get_component(int DrumkitComponentID)
bool hasSamples() const
Whether the instrument contains at least one non-missing sample.
A note plays an associated instrument with a velocity left and right pan.
Definition Note.h:102
void set_specific_compo_id(int value)
__specific_compo_id setter
Definition Note.h:520
static Preferences * get_instance()
Returns a pointer to the current Preferences singleton stored in __instance.
Changes
Bitwise or-able options showing which part of the Preferences were altered using the PreferencesDialo...
@ Font
Either the font size or font family have changed.
@ Colors
At least one of the colors has changed.
void noteOn(Note *pNote)
Start playing a note.
Definition Sampler.cpp:190
void addEventListener(EventListener *pListener)
static HydrogenApp * get_instance()
Returns the instance of HydrogenApp class.
void preferencesChanged(H2Core::Preferences::Changes changes)
Propagates a change in the Preferences through the GUI.
static InstrumentEditorPanel * get_instance()
virtual void mouseMoveEvent(QMouseEvent *ev) override
LayerPreview(QWidget *pParent)
virtual void mousePressEvent(QMouseEvent *ev) override
QPixmap m_speakerPixmap
void showLayerEndVelocity(const std::shared_ptr< H2Core::InstrumentLayer > pLayer, const QMouseEvent *pEvent)
display a layer's end velocity in a tooltip
static const int m_nLayerHeight
void onPreferencesChanged(H2Core::Preferences::Changes changes)
int m_nSelectedComponent
virtual void drumkitLoadedEvent() override
virtual void mouseReleaseEvent(QMouseEvent *ev) override
virtual void selectedInstrumentChangedEvent() override
virtual void updateSongEvent(int) override
void paintEvent(QPaintEvent *ev) override
std::shared_ptr< H2Core::Instrument > m_pInstrument
void showLayerStartVelocity(const std::shared_ptr< H2Core::InstrumentLayer > pLayer, const QMouseEvent *pEvent)
display a layer's start velocity in a tooltip
void set_selected_component(int SelectedComponent)
int getMidiVelocityFromRaw(const float raw)
convert a raw velocity value (0.0 to 1.0) into a MIDI velocity value (0 to 127)
int getPointSizeButton() const
Used to detect changed in the font.
static QString getSvgImagePath()
Definition Skin.h:40
constexpr int getPointSize(H2Core::FontTheme::FontSize fontSize) const