1 /*
2  * Hydrogen
3  * Copyright(c) 2002-2008 by Alex >Comix< Cominu [comix@users.sourceforge.net]
4  *
5  * http://www.hydrogen-music.org
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY, without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  *
21  */
22 
23 #include <hydrogen/Preferences.h>
24 #include <hydrogen/hydrogen.h>
25 #include <hydrogen/basics/instrument.h>
26 #include <hydrogen/basics/instrument_list.h>
27 #include <hydrogen/basics/pattern.h>
28 #include <hydrogen/basics/pattern_list.h>
29 #include <hydrogen/audio_engine.h>
30 #include <hydrogen/event_queue.h>
31 using namespace H2Core;
32 
33 
34 #include "HydrogenApp.h"
35 #include "PatternEditorPanel.h"
36 #include "PatternEditorInstrumentList.h"
37 #include "PatternEditorRuler.h"
38 #include "NotePropertiesRuler.h"
39 #include "DrumPatternEditor.h"
40 #include "PianoRollEditor.h"
41 
42 #include "../MainForm.h"
43 #include "../Widgets/Button.h"
44 #include "../Widgets/Fader.h"
45 #include "../Widgets/PixmapWidget.h"
46 #include "../Widgets/LCDCombo.h"
47 
48 #include "../Skin.h"
49 #include "../SongEditor/SongEditorPanel.h"
50 
51 #include <cmath>
52 
53 
updateSLnameLabel()54 void PatternEditorPanel::updateSLnameLabel( )
55 {
56 	QFont font;
57 	font.setBold( true );
58 	pSLlabel->setFont( font );
59 	pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit  );
60 }
61 
62 const char* PatternEditorPanel::__class_name = "PatternEditorPanel";
63 
64 
PatternEditorPanel(QWidget * pParent)65 PatternEditorPanel::PatternEditorPanel( QWidget *pParent )
66  : QWidget( pParent )
67  , Object( __class_name )
68  , m_pPattern( nullptr )
69 {
70 	setAcceptDrops(true);
71 
72 	Preferences *pPref = Preferences::get_instance();
73 
74 
75 // Editor TOP
76 	PixmapWidget *editor_top = new PixmapWidget(nullptr);
77 	editor_top->setPixmap("/patternEditor/editor_top.png", true);
78 	editor_top->setFixedHeight(24);
79 
80 	PixmapWidget *editor_top_2 = new PixmapWidget(nullptr);
81 	editor_top_2->setPixmap("/patternEditor/editor_top.png", true);
82 	editor_top_2->setFixedHeight(24);
83 
84 	QHBoxLayout *editor_top_hbox = new QHBoxLayout(editor_top);
85 	editor_top_hbox->setSpacing(0);
86 	editor_top_hbox->setMargin(0);
87 	editor_top_hbox->setAlignment(Qt::AlignLeft);
88 
89 	QHBoxLayout *editor_top_hbox_2 = new QHBoxLayout(editor_top_2);
90 	editor_top_hbox_2->setSpacing(0);
91 	editor_top_hbox_2->setMargin(0);
92 	editor_top_hbox_2->setAlignment(Qt::AlignLeft);
93 
94 
95 	//soundlibrary name
96 	pSLlabel = new QLabel( nullptr );
97 	pSLlabel->setText( Hydrogen::get_instance()->m_currentDrumkit );
98 	pSLlabel->setFixedSize( 170, 20 );
99 	pSLlabel->move( 10, 3 );
100 	pSLlabel->setToolTip( tr("Loaded Soundlibrary") );
101 	editor_top_hbox->addWidget( pSLlabel );
102 
103 //wolke some background images back_size_res
104 	PixmapWidget *pSizeResol = new PixmapWidget( nullptr );
105 	pSizeResol->setFixedSize( 200, 20 );
106 	pSizeResol->setPixmap( "/patternEditor/background_res-new.png" );
107 	pSizeResol->move( 0, 3 );
108 	editor_top_hbox_2->addWidget( pSizeResol );
109 
110 	// PATTERN size
111 	__pattern_size_combo = new LCDCombo(pSizeResol, 4);
112 	__pattern_size_combo->move( 34, 2 );
113 	__pattern_size_combo->setToolTip( tr("Select pattern size") );
114 	for ( int i = 1; i <= 32; i++) {
115 		__pattern_size_combo->addItem( QString( "%1" ).arg( i ) );
116 	}
117 	// is triggered from inside selectedPatternChangedEvent()
118 	connect(__pattern_size_combo, SIGNAL( valueChanged( int ) ), this, SLOT( patternSizeChanged( int ) ) );
119 
120 
121 	// GRID resolution
122 	__resolution_combo = new LCDCombo( pSizeResol , 7);
123 	__resolution_combo->setToolTip(tr("Select grid resolution"));
124 	__resolution_combo->addItem( "4" );
125 	__resolution_combo->addItem( "8" );
126 	__resolution_combo->addItem( "16" );
127 	__resolution_combo->addItem( "32" );
128 	__resolution_combo->addItem( "64" );
129 	__resolution_combo->addSeparator();
130 	__resolution_combo->addItem( "4T" );
131 	__resolution_combo->addItem( "8T" );
132 	__resolution_combo->addItem( "16T" );
133 	__resolution_combo->addItem( "32T" );
134 	__resolution_combo->addSeparator();
135 	__resolution_combo->addItem( "off" );
136 	__resolution_combo->move( 121, 2 );
137 	// is triggered from inside PatternEditorPanel()
138 	connect(__resolution_combo, SIGNAL(valueChanged( int )), this, SLOT(gridResolutionChanged( int )));
139 
140 
141 	PixmapWidget *pRec = new PixmapWidget( nullptr );
142 	pRec->setFixedSize( 158, 20 );
143 	pRec->setPixmap( "/patternEditor/background_rec-new.png" );
144 	pRec->move( 0, 3 );
145 	editor_top_hbox_2->addWidget( pRec );
146 
147 
148 	// Hear notes btn
149 	ToggleButton *hearNotesBtn = new ToggleButton(
150 			pRec,
151 			"/patternEditor/btn_hear_on.png",
152 			"/patternEditor/btn_hear_off.png",
153 			"/patternEditor/btn_hear_off.png",
154 			QSize(15, 13)
155 	);
156 	hearNotesBtn->move( 34, 3 );
157 	hearNotesBtn->setToolTip( tr( "Hear new notes" ) );
158 	connect( hearNotesBtn, SIGNAL(clicked(Button*)), this, SLOT( hearNotesBtnClick(Button*)));
159 	hearNotesBtn->setPressed( pPref->getHearNewNotes() );
160 
161 
162 	// quantize
163 	ToggleButton* quantizeEventsBtn = new ToggleButton(
164 			pRec,
165 			"/patternEditor/btn_quant_on.png",
166 			"/patternEditor/btn_quant_off.png",
167 			"/patternEditor/btn_quant_off.png",
168 			QSize(15, 13)
169 	);
170 	quantizeEventsBtn->move( 90, 3 );
171 	quantizeEventsBtn->setPressed( pPref->getQuantizeEvents());
172 	quantizeEventsBtn->setToolTip( tr( "Quantize keyboard/midi events to grid" ) );
173 	connect( quantizeEventsBtn, SIGNAL(clicked(Button*)), this, SLOT( quantizeEventsBtnClick(Button*)));
174 
175 	// Editor mode
176 	__show_drum_btn = new ToggleButton(
177 				pRec,
178 				"/patternEditor/btn_drum_piano_on.png",
179 				"/patternEditor/btn_drum_piano_off.png",
180 				"/patternEditor/btn_drum_piano_off.png",
181 				QSize(17, 13)
182 				);
183 	__show_drum_btn->move( 137, 3 );
184 	__show_drum_btn->setPressed( false );
185 	__show_drum_btn->setToolTip( tr( "Show piano roll editor" ) );
186 	connect(__show_drum_btn, SIGNAL(clicked(Button*)), this, SLOT( showDrumEditorBtnClick(Button*)));
187 
188 	__recpredelete = new QComboBox( nullptr );
189 	__recpredelete->setFixedSize( 130, 20 );
190 	__recpredelete->move( 2, 1 );
191 	__recpredelete->addItem ( QString( "On play" ));
192 	__recpredelete->addItem ( QString( "On rec: once fp" ));
193 	__recpredelete->addItem ( QString( "On rec: 1/1 fp" ));
194 	__recpredelete->addItem ( QString( "On rec: 1/2 fp" ));
195 	__recpredelete->addItem ( QString( "On rec: 1/4 fp" ));
196 	__recpredelete->addItem ( QString( "On rec: 1/8 fp" ));
197 	__recpredelete->addItem ( QString( "On rec: 1/16 fp" ));
198 	__recpredelete->addItem ( QString( "On rec: 1/32 fp" ));
199 	__recpredelete->addItem ( QString( "On rec: 1/64 fp" ));
200 	__recpredelete->addItem ( QString( "On rec: 1/64" ));
201 	__recpredelete->addItem ( QString( "On rec: 1/32" ));
202 	__recpredelete->addItem ( QString( "On rec: 1/16" ));
203 	__recpredelete->addItem ( QString( "On rec: 1/8" ));
204 	__recpredelete->addItem ( QString( "On rec: 1/4" ));
205 	__recpredelete->addItem ( QString( "On rec: 1/2" ));
206 	__recpredelete->addItem ( QString( "On rec: 1/1" ));
207 	__recpredelete->addItem ( QString( "On rec: once" ));
208 	__recpredelete->update();
209 	__recpredelete->setToolTip( tr( "destructive mode pre delete settings" ) );
210 	editor_top_hbox_2->addWidget( __recpredelete );
211 	connect( __recpredelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPreDeleteSelect( int) ) );
212 
213 	__recpostdelete = new QComboBox( nullptr );
214 	__recpostdelete->setFixedSize( 60, 20 );
215 	__recpostdelete->move( 2, 1 );
216 	__recpostdelete->addItem ( QString( "off" ));
217 	__recpostdelete->addItem ( QString( "1/64" ));
218 	__recpostdelete->addItem ( QString( "1/32" ));
219 	__recpostdelete->addItem ( QString( "1/16" ));
220 	__recpostdelete->addItem ( QString( "1/8" ));
221 	__recpostdelete->addItem ( QString( "1/4" ));
222 	__recpostdelete->addItem ( QString( "1/2" ));
223 	__recpostdelete->addItem ( QString( "1/1" ));
224 	__recpostdelete->update();
225 	__recpostdelete->setToolTip( tr( "destructive mode post delete settings" ) );
226 	editor_top_hbox_2->addWidget( __recpostdelete );
227 	connect( __recpostdelete, SIGNAL( currentIndexChanged( int ) ), this, SLOT( recPostDeleteSelect( int) ) );
228 
229 
230 	// zoom-in btn
231 	Button *zoom_in_btn = new Button(
232 			nullptr,
233 			"/songEditor/btn_new_on.png",
234 			"/songEditor/btn_new_off.png",
235 			"/songEditor/btn_new_over.png",
236 			QSize(19, 13)
237 	);
238 	zoom_in_btn->setToolTip( tr( "Zoom in" ) );
239 	connect(zoom_in_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomInBtnClicked(Button*) ) );
240 
241 
242 	// zoom-out btn
243 	Button *zoom_out_btn = new Button(
244 			nullptr,
245 			"/songEditor/btn_minus_on.png",
246 			"/songEditor/btn_minus_off.png",
247 			"/songEditor/btn_minus_over.png",
248 			QSize(19, 13)
249 	);
250 	zoom_out_btn->setToolTip( tr( "Zoom out" ) );
251 	connect( zoom_out_btn, SIGNAL(clicked(Button*)), this, SLOT( zoomOutBtnClicked(Button*) ) );
252 
253 
254 // End Editor TOP
255 
256 
257 // RULER____________________________________
258 
259 	// Ruler ScrollView
260 	m_pRulerScrollView = new QScrollArea( nullptr );
261 	m_pRulerScrollView->setFrameShape( QFrame::NoFrame );
262 	m_pRulerScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
263 	m_pRulerScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
264 	m_pRulerScrollView->setFixedHeight( 25 );
265 	// Ruler
266 	m_pPatternEditorRuler = new PatternEditorRuler( m_pRulerScrollView->viewport() );
267 
268 	m_pRulerScrollView->setWidget( m_pPatternEditorRuler );
269 	connect( m_pRulerScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
270 
271 //~ RULER
272 
273 
274 // EDITOR _____________________________________
275 	// Editor scrollview
276 	m_pEditorScrollView = new QScrollArea( nullptr );
277 	m_pEditorScrollView->setFrameShape( QFrame::NoFrame );
278 	m_pEditorScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
279 	m_pEditorScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
280 
281 
282 	// Editor
283 	m_pDrumPatternEditor = new DrumPatternEditor( m_pEditorScrollView->viewport(), this );
284 
285 	m_pEditorScrollView->setWidget( m_pDrumPatternEditor );
286 
287 	connect( m_pEditorScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorVScroll(int) ) );
288 	connect( m_pEditorScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
289 
290 
291 //PianoRollEditor
292 	m_pPianoRollScrollView = new QScrollArea( nullptr );
293 	m_pPianoRollScrollView->setFrameShape( QFrame::NoFrame );
294 	m_pPianoRollScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAsNeeded );
295 	m_pPianoRollScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
296 	m_pPianoRollEditor = new PianoRollEditor( m_pPianoRollScrollView->viewport(), this );
297 	m_pPianoRollScrollView->setWidget( m_pPianoRollEditor );
298 	connect( m_pPianoRollScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
299 
300 	m_pPianoRollScrollView->hide();
301 
302 //~ EDITOR
303 
304 
305 
306 
307 
308 
309 // INSTRUMENT LIST
310 	// Instrument list scrollview
311 	m_pInstrListScrollView = new QScrollArea( nullptr );
312 	m_pInstrListScrollView->setFrameShape( QFrame::NoFrame );
313 	m_pInstrListScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
314 	m_pInstrListScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
315 
316 	// Instrument list
317 	m_pInstrumentList = new PatternEditorInstrumentList( m_pInstrListScrollView->viewport(), this );
318 	m_pInstrListScrollView->setWidget( m_pInstrumentList );
319 	m_pInstrListScrollView->setFixedWidth( m_pInstrumentList->width() );
320 
321 	connect( m_pInstrListScrollView->verticalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorVScroll(int) ) );
322 //~ INSTRUMENT LIST
323 
324 
325 
326 
327 // NOTE_VELOCITY EDITOR
328 	m_pNoteVelocityScrollView = new QScrollArea( nullptr );
329 	m_pNoteVelocityScrollView->setFrameShape( QFrame::NoFrame );
330 	m_pNoteVelocityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
331 	m_pNoteVelocityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
332 	m_pNoteVelocityEditor = new NotePropertiesRuler( m_pNoteVelocityScrollView->viewport(), this, NotePropertiesRuler::VELOCITY );
333 	m_pNoteVelocityScrollView->setWidget( m_pNoteVelocityEditor );
334 	m_pNoteVelocityScrollView->setFixedHeight( 100 );
335 	connect( m_pNoteVelocityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
336 
337 //~ NOTE_VELOCITY EDITOR
338 
339 
340 // NOTE_PAN EDITOR
341 	m_pNotePanScrollView = new QScrollArea( nullptr );
342 	m_pNotePanScrollView->setFrameShape( QFrame::NoFrame );
343 	m_pNotePanScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
344 	m_pNotePanScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
345 	m_pNotePanEditor = new NotePropertiesRuler( m_pNotePanScrollView->viewport(), this, NotePropertiesRuler::PAN );
346 	m_pNotePanScrollView->setWidget( m_pNotePanEditor );
347 	m_pNotePanScrollView->setFixedHeight( 100 );
348 	connect( m_pNotePanScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
349 //~ NOTE_PAN EDITOR
350 
351 
352 // NOTE_LEADLAG EDITOR
353 	m_pNoteLeadLagScrollView = new QScrollArea( nullptr );
354 	m_pNoteLeadLagScrollView->setFrameShape( QFrame::NoFrame );
355 	m_pNoteLeadLagScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
356 	m_pNoteLeadLagScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
357 	m_pNoteLeadLagEditor = new NotePropertiesRuler( m_pNoteLeadLagScrollView->viewport(), this, NotePropertiesRuler::LEADLAG );
358 	m_pNoteLeadLagScrollView->setWidget( m_pNoteLeadLagEditor );
359 	m_pNoteLeadLagScrollView->setFixedHeight( 100 );
360 	connect( m_pNoteLeadLagScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
361 //~ NOTE_LEADLAG EDITOR
362 
363 
364 // NOTE_NOTEKEY EDITOR
365 
366 
367 	m_pNoteNoteKeyScrollView = new QScrollArea( nullptr );
368 	m_pNoteNoteKeyScrollView->setFrameShape( QFrame::NoFrame );
369 	m_pNoteNoteKeyScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
370 	m_pNoteNoteKeyScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
371 	m_pNoteNoteKeyEditor = new NotePropertiesRuler( m_pNoteNoteKeyScrollView->viewport(), this, NotePropertiesRuler::NOTEKEY );
372 	m_pNoteNoteKeyScrollView->setWidget( m_pNoteNoteKeyEditor );
373 	m_pNoteNoteKeyScrollView->setFixedHeight( 210 );
374 	connect( m_pNoteNoteKeyScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
375 
376 
377 //~ NOTE_NOTEKEY EDITOR
378 
379 // NOTE_PROBABILITY EDITOR
380 	m_pNoteProbabilityScrollView = new QScrollArea( nullptr );
381 	m_pNoteProbabilityScrollView->setFrameShape( QFrame::NoFrame );
382 	m_pNoteProbabilityScrollView->setVerticalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
383 	m_pNoteProbabilityScrollView->setHorizontalScrollBarPolicy( Qt::ScrollBarAlwaysOff );
384 	m_pNoteProbabilityEditor = new NotePropertiesRuler( m_pNoteProbabilityScrollView->viewport(), this, NotePropertiesRuler::PROBABILITY );
385 	m_pNoteProbabilityScrollView->setWidget( m_pNoteProbabilityEditor );
386 	m_pNoteProbabilityScrollView->setFixedHeight( 100 );
387 	connect( m_pNoteProbabilityScrollView->horizontalScrollBar(), SIGNAL( valueChanged(int) ), this, SLOT( on_patternEditorHScroll(int) ) );
388 //~ NOTE_PROBABILITY EDITOR
389 
390 
391 
392 	// external horizontal scrollbar
393 	m_pPatternEditorHScrollBar = new QScrollBar( Qt::Horizontal , nullptr  );
394 	connect( m_pPatternEditorHScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
395 
396 	// external vertical scrollbar
397 	m_pPatternEditorVScrollBar = new QScrollBar( Qt::Vertical, nullptr );
398 	connect( m_pPatternEditorVScrollBar, SIGNAL(valueChanged(int)), this, SLOT( syncToExternalHorizontalScrollbar(int) ) );
399 
400 	QHBoxLayout *pPatternEditorHScrollBarLayout = new QHBoxLayout();
401 	pPatternEditorHScrollBarLayout->setSpacing( 0 );
402 	pPatternEditorHScrollBarLayout->setMargin( 0 );
403 	pPatternEditorHScrollBarLayout->addWidget( m_pPatternEditorHScrollBar );
404 	pPatternEditorHScrollBarLayout->addWidget( zoom_in_btn );
405 	pPatternEditorHScrollBarLayout->addWidget( zoom_out_btn );
406 
407 	QWidget *pPatternEditorHScrollBarContainer = new QWidget();
408 	pPatternEditorHScrollBarContainer->setLayout( pPatternEditorHScrollBarLayout );
409 
410 
411 	QPalette label_palette;
412 	label_palette.setColor( QPalette::Foreground, QColor( 230, 230, 230 ) );
413 
414 	QFont boldFont;
415 	boldFont.setBold( true );
416 	m_pPatternNameLbl = new QLabel( nullptr );
417 	m_pPatternNameLbl->setFont( boldFont );
418 	m_pPatternNameLbl->setText( "pattern name label" );
419 	m_pPatternNameLbl->setPalette(label_palette);
420 
421 
422 
423 
424 
425 
426 // NOTE_PROPERTIES BUTTONS
427 	PixmapWidget *pPropertiesPanel = new PixmapWidget( nullptr );
428 	pPropertiesPanel->setColor( QColor( 58, 62, 72 ) );
429 
430 	pPropertiesPanel->setFixedSize( 181, 100 );
431 
432 	QVBoxLayout *pPropertiesVBox = new QVBoxLayout( pPropertiesPanel );
433 	pPropertiesVBox->setSpacing( 0 );
434 	pPropertiesVBox->setMargin( 0 );
435 
436 
437 	__pPropertiesCombo = new LCDCombo( nullptr, 20);
438 	__pPropertiesCombo->setToolTip(tr("Select note properties"));
439 	__pPropertiesCombo->addItem( tr("Velocity") );
440 	__pPropertiesCombo->addItem( tr("Pan") );
441 	__pPropertiesCombo->addItem( tr("Lead and Lag") );
442 	__pPropertiesCombo->addItem( tr("NoteKey") );
443 	__pPropertiesCombo->addItem( tr("Probability") );
444 	/* __pPropertiesCombo->addItem( tr("Cutoff") ); */
445 	/* __pPropertiesCombo->addItem( tr("Resonance") ); */
446 	// is triggered here below
447 	connect( __pPropertiesCombo, SIGNAL(valueChanged( int )), this, SLOT(propertiesComboChanged( int )));
448 
449 	pPropertiesVBox->addWidget( __pPropertiesCombo );
450 
451 //~ NOTE_PROPERTIES BUTTONS
452 
453 
454 // LAYOUT
455 	QWidget *pMainPanel = new QWidget();
456 
457 	QGridLayout *pGrid = new QGridLayout();
458 	pGrid->setSpacing( 0 );
459 	pGrid->setMargin( 0 );
460 
461 	pGrid->addWidget( editor_top, 0, 0);
462 	pGrid->addWidget( editor_top_2, 0, 1, 1, 3);
463 	pGrid->addWidget( m_pPatternNameLbl, 1, 0 );
464 	pGrid->addWidget( m_pRulerScrollView, 1, 1 );
465 
466 	pGrid->addWidget( m_pInstrListScrollView, 2, 0 );
467 
468 	pGrid->addWidget( m_pEditorScrollView, 2, 1 );
469 	pGrid->addWidget( m_pPianoRollScrollView, 2, 1 );
470 
471 	pGrid->addWidget( m_pPatternEditorVScrollBar, 2, 2 );
472 	pGrid->addWidget( pPatternEditorHScrollBarContainer, 10, 1 );
473 	pGrid->addWidget( m_pNoteVelocityScrollView, 4, 1 );
474 	pGrid->addWidget( m_pNotePanScrollView, 4, 1 );
475 	pGrid->addWidget( m_pNoteLeadLagScrollView, 4, 1 );
476 	pGrid->addWidget( m_pNoteNoteKeyScrollView, 4, 1 );
477 	pGrid->addWidget( m_pNoteProbabilityScrollView, 4, 1 );
478 
479 	pGrid->addWidget( pPropertiesPanel, 4, 0 );
480 	pGrid->setRowStretch( 2, 100 );
481 	pMainPanel->setLayout( pGrid );
482 
483 
484 	// restore grid resolution
485 	int nIndex;
486 	int nRes = pPref->getPatternEditorGridResolution();
487 	if (nRes == MAX_NOTES) {
488 		nIndex = 11;
489 	} else if ( pPref->isPatternEditorUsingTriplets() == false ) {
490 		switch ( nRes ) {
491 			case  4: nIndex = 0; break;
492 			case  8: nIndex = 1; break;
493 			case 16: nIndex = 2; break;
494 			case 32: nIndex = 3; break;
495 			case 64: nIndex = 4; break;
496 			default:
497 				nIndex = 0;
498 				ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
499 		}
500 	} else {
501 		switch ( nRes ) {
502 			case  8: nIndex = 6; break;
503 			case 16: nIndex = 7; break;
504 			case 32: nIndex = 8; break;
505 			case 64: nIndex = 9; break;
506 			default:
507 				nIndex = 6;
508 				ERRORLOG( QString("Wrong grid resolution: %1").arg( pPref->getPatternEditorGridResolution() ) );
509 		}
510 	}
511 	__resolution_combo->select( nIndex );
512 
513 	//set pre delete
514 	__recpredelete->setCurrentIndex(pPref->m_nRecPreDelete);
515 	__recpostdelete->setCurrentIndex(pPref->m_nRecPostDelete);
516 	displayorHidePrePostCB();
517 
518 	// LAYOUT
519 	QVBoxLayout *pVBox = new QVBoxLayout();
520 	pVBox->setSpacing( 0 );
521 	pVBox->setMargin( 0 );
522 	this->setLayout( pVBox );
523 
524 	pVBox->addWidget( pMainPanel );
525 
526 	HydrogenApp::get_instance()->addEventListener( this );
527 
528 	// update
529 	__pPropertiesCombo->select( 0 );
530 	selectedPatternChangedEvent();
531 }
532 
533 
534 
535 
~PatternEditorPanel()536 PatternEditorPanel::~PatternEditorPanel()
537 {
538 }
539 
540 
541 
syncToExternalHorizontalScrollbar(int)542 void PatternEditorPanel::syncToExternalHorizontalScrollbar(int)
543 {
544 	//INFOLOG( "[syncToExternalHorizontalScrollbar]" );
545 
546 	// drum Editor
547 	m_pEditorScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
548 	m_pEditorScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
549 
550 	// piano roll Editor
551 	m_pPianoRollScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
552 
553 	// Ruler
554 	m_pRulerScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
555 
556 	// Instrument list
557 	m_pInstrListScrollView->verticalScrollBar()->setValue( m_pPatternEditorVScrollBar->value() );
558 
559 	// Velocity ruler
560 	m_pNoteVelocityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
561 
562 	// pan ruler
563 	m_pNotePanScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
564 
565 	// leadlag ruler
566 	m_pNoteLeadLagScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
567 
568 	// notekey ruler
569 	m_pNoteNoteKeyScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
570 
571 	// Probability ruler
572 	m_pNoteProbabilityScrollView->horizontalScrollBar()->setValue( m_pPatternEditorHScrollBar->value() );
573 }
574 
575 
on_patternEditorVScroll(int nValue)576 void PatternEditorPanel::on_patternEditorVScroll(int nValue)
577 {
578 	//INFOLOG( "[on_patternEditorVScroll] " + QString::number(nValue)  );
579 	m_pPatternEditorVScrollBar->setValue( nValue );
580 	resizeEvent(nullptr);
581 }
582 
on_patternEditorHScroll(int nValue)583 void PatternEditorPanel::on_patternEditorHScroll(int nValue)
584 {
585 	//INFOLOG( "[on_patternEditorHScroll] " + QString::number(nValue)  );
586 	m_pPatternEditorHScrollBar->setValue( nValue );
587 	resizeEvent(nullptr);
588 }
589 
590 
591 
592 
gridResolutionChanged(int nSelected)593 void PatternEditorPanel::gridResolutionChanged( int nSelected )
594 {
595 	int nResolution;
596 	bool bUseTriplets = false;
597 
598 	if ( nSelected == 11 ) {
599 		nResolution = MAX_NOTES;
600 	}
601 	else if ( nSelected > 4 ) {
602 		bUseTriplets = true;
603 		nResolution = 0x1 << (nSelected - 3);
604 	}
605 	else {
606 		nResolution = 0x1 << (nSelected + 2);
607 	}
608 
609 	// INFOLOG( QString("idx %1 -> %2 resolution").arg( nSelected ).arg( nResolution ) );
610 	m_pDrumPatternEditor->setResolution( nResolution, bUseTriplets );
611 	m_pPianoRollEditor->setResolution( nResolution, bUseTriplets );
612 
613 	Preferences::get_instance()->setPatternEditorGridResolution( nResolution );
614 	Preferences::get_instance()->setPatternEditorUsingTriplets( bUseTriplets );
615 }
616 
617 
618 
selectedPatternChangedEvent()619 void PatternEditorPanel::selectedPatternChangedEvent()
620 {
621 	PatternList *pPatternList = Hydrogen::get_instance()->getSong()->get_pattern_list();
622 	int nSelectedPatternNumber = Hydrogen::get_instance()->getSelectedPatternNumber();
623 
624 	if ( (nSelectedPatternNumber != -1) && ( (uint)nSelectedPatternNumber < pPatternList->size() ) ) {
625 		// update pattern name text
626 		m_pPattern = pPatternList->get( nSelectedPatternNumber );
627 		QString sCurrentPatternName = m_pPattern->get_name();
628 		this->setWindowTitle( ( tr( "Pattern editor - %1").arg( sCurrentPatternName ) ) );
629 		m_pPatternNameLbl->setText( sCurrentPatternName );
630 
631 		// update pattern size combobox
632 		int nPatternSize = m_pPattern->get_length();
633 		int nEighth = MAX_NOTES / 8;
634 
635 		// do no emit the changed value, otherwise patternSizeChanged() would be triggered,
636 		// which handles a manual pattern size change
637 		__pattern_size_combo->select( (nPatternSize / nEighth) - 1 , false);
638 	}
639 	else {
640 		m_pPattern = nullptr;
641 
642 		this->setWindowTitle( ( tr( "Pattern editor - %1").arg(QString("No pattern selected.")) ) );
643 		m_pPatternNameLbl->setText( tr( "No pattern selected" ) );
644 	}
645 
646 	resizeEvent( nullptr ); // force an update of the scrollbars
647 }
648 
649 
650 
hearNotesBtnClick(Button * ref)651 void PatternEditorPanel::hearNotesBtnClick(Button *ref)
652 {
653 	Preferences *pref = ( Preferences::get_instance() );
654 	pref->setHearNewNotes( ref->isPressed() );
655 
656 	if (ref->isPressed() ) {
657 		( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Hear new notes = On" ), 2000 );
658 	}
659 	else {
660 		( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Hear new notes = Off" ), 2000 );
661 	}
662 
663 }
664 
quantizeEventsBtnClick(Button * ref)665 void PatternEditorPanel::quantizeEventsBtnClick(Button *ref)
666 {
667 	Preferences *pref = ( Preferences::get_instance() );
668 	pref->setQuantizeEvents( ref->isPressed() );
669 
670 	if (ref->isPressed() ) {
671 		( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Quantize incoming keyboard/midi events = On" ), 2000 );
672 	}
673 	else {
674 		( HydrogenApp::get_instance() )->setStatusBarMessage( tr( "Quantize incoming keyboard/midi events = Off" ), 2000 );
675 	}
676 }
677 
syncScrollBarSize(QScrollBar * pDest,QScrollBar * pSrc)678 static void syncScrollBarSize(QScrollBar *pDest, QScrollBar *pSrc)
679 {
680 	pDest->setMinimum( pSrc->minimum() );
681 	pDest->setMaximum( pSrc->maximum() );
682 	pDest->setSingleStep( pSrc->singleStep() );
683 	pDest->setPageStep( pSrc->pageStep() );
684 }
685 
resizeEvent(QResizeEvent * ev)686 void PatternEditorPanel::resizeEvent( QResizeEvent *ev )
687 {
688 	UNUSED( ev );
689 	QScrollArea *pScrollArea = m_pEditorScrollView;
690 
691 	syncScrollBarSize( m_pPatternEditorHScrollBar, pScrollArea->horizontalScrollBar() );
692 	syncScrollBarSize( m_pPatternEditorVScrollBar, pScrollArea->verticalScrollBar() );
693 
694 	syncScrollBarSize( m_pRulerScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
695 	syncScrollBarSize( m_pNoteVelocityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
696 	syncScrollBarSize( m_pNotePanScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
697 	syncScrollBarSize( m_pNoteLeadLagScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar()) ;
698 	syncScrollBarSize( m_pNoteNoteKeyScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
699 	syncScrollBarSize( m_pNoteProbabilityScrollView->horizontalScrollBar(), pScrollArea->horizontalScrollBar() );
700 }
701 
showEvent(QShowEvent * ev)702 void PatternEditorPanel::showEvent ( QShowEvent *ev )
703 {
704 	UNUSED( ev );
705 }
706 
707 
708 /// richiamato dall'uso dello scroll del mouse
contentsMoving(int dummy)709 void PatternEditorPanel::contentsMoving(int dummy)
710 {
711 	UNUSED( dummy );
712 	//INFOLOG( "contentsMoving" );
713 	syncToExternalHorizontalScrollbar(0);
714 }
715 
716 
717 
selectedInstrumentChangedEvent()718 void PatternEditorPanel::selectedInstrumentChangedEvent()
719 {
720   //m_pNoteVelocityEditor->updateEditor();
721   //m_pNotePanEditor->updateEditor();
722   //m_pNoteLeadLagEditor->updateEditor();
723 
724 	resizeEvent(nullptr);	// force a scrollbar update
725 }
726 
727 
showDrumEditorBtnClick(Button * ref)728 void PatternEditorPanel::showDrumEditorBtnClick(Button *ref)
729 {
730 	UNUSED( ref );
731 	if ( !__show_drum_btn->isPressed() ){
732 		__show_drum_btn->setToolTip( tr( "Show piano roll editor" ) );
733 		m_pPianoRollScrollView->hide();
734 		m_pEditorScrollView->show();
735 		m_pInstrListScrollView->show();
736 
737 		m_pDrumPatternEditor->selectedInstrumentChangedEvent(); // force an update
738 
739 		// force a re-sync of extern scrollbars
740 		resizeEvent( nullptr );
741 
742 	}
743 	else
744 	{
745 		__show_drum_btn->setToolTip( tr( "Show drum editor" ) );
746 		m_pPianoRollScrollView->show();
747 		m_pPianoRollScrollView->verticalScrollBar()->setValue( 250 );
748 		m_pEditorScrollView->show();
749 		m_pInstrListScrollView->show();
750 
751 		m_pPianoRollEditor->selectedPatternChangedEvent();
752 		m_pPianoRollEditor->updateEditor(); // force an update
753 		// force a re-sync of extern scrollbars
754 		resizeEvent( nullptr );
755 	}
756 }
757 
758 
zoomInBtnClicked(Button * ref)759 void PatternEditorPanel::zoomInBtnClicked(Button *ref)
760 {
761 	if(m_pPatternEditorRuler->getGridWidth() >=24){
762 		return;
763 	}
764 	UNUSED( ref );
765 	m_pPatternEditorRuler->zoomIn();
766 	m_pDrumPatternEditor->zoom_in();
767 	m_pNoteVelocityEditor->zoomIn();
768 	m_pNoteLeadLagEditor->zoomIn();
769 	m_pNoteNoteKeyEditor->zoomIn();
770 	m_pNoteProbabilityEditor->zoomIn();
771 	m_pNotePanEditor->zoomIn();
772 	m_pPianoRollEditor->zoom_in();
773 
774 	resizeEvent( nullptr );
775 }
776 
777 
778 
zoomOutBtnClicked(Button * ref)779 void PatternEditorPanel::zoomOutBtnClicked(Button *ref)
780 {
781 	UNUSED( ref );
782 	m_pPatternEditorRuler->zoomOut();
783 	m_pDrumPatternEditor->zoom_out();
784 	m_pNoteVelocityEditor->zoomOut();
785 	m_pNoteLeadLagEditor->zoomOut();
786 	m_pNoteNoteKeyEditor->zoomOut();
787 	m_pNoteProbabilityEditor->zoomOut();
788 	m_pNotePanEditor->zoomOut();
789 	m_pPianoRollEditor->zoom_out();
790 
791 	resizeEvent( nullptr );
792 }
793 
794 
795 
patternSizeChanged(int nSelected)796 void PatternEditorPanel::patternSizeChanged( int nSelected )
797 {
798 	// INFOLOG( QString("idx %1 -> %2 eighth").arg( nSelected ).arg( ( MAX_NOTES / 8 ) * ( nSelected + 1 ) ) );
799 
800 	if ( !m_pPattern ) {
801 		return;
802 	}
803 
804 	int nEighth = MAX_NOTES / 8;
805 
806 	Hydrogen *pEngine = Hydrogen::get_instance();
807 
808 	if ( pEngine->getState() != STATE_READY ) {
809 		__pattern_size_combo->select( ((m_pPattern->get_length() / nEighth) - 1), false );
810 		QMessageBox::information( this, "Hydrogen", tr( "Is not possible to change the pattern size when playing." ) );
811 		return;
812 	}
813 
814 	m_pPattern->set_length( nEighth * ( nSelected + 1 ) );
815 
816 	m_pPatternEditorRuler->updateEditor( true );	// redraw all
817 	m_pNoteVelocityEditor->updateEditor();
818 	m_pNotePanEditor->updateEditor();
819 	m_pNoteLeadLagEditor->updateEditor();
820 	m_pNoteNoteKeyEditor->updateEditor();
821 	m_pNoteProbabilityEditor->updateEditor();
822 	m_pPianoRollEditor->updateEditor();
823 
824 	resizeEvent( nullptr );
825 
826 	EventQueue::get_instance()->push_event( EVENT_SELECTED_PATTERN_CHANGED, -1 );
827 }
828 
829 
830 
moveUpBtnClicked(Button *)831 void PatternEditorPanel::moveUpBtnClicked(Button *)
832 {
833 	Hydrogen *engine = Hydrogen::get_instance();
834 	int nSelectedInstrument = engine->getSelectedInstrumentNumber();
835 
836 	AudioEngine::get_instance()->lock( RIGHT_HERE );
837 
838 	Song *pSong = engine->getSong();
839 	InstrumentList *pInstrumentList = pSong->get_instrument_list();
840 
841 	if ( ( nSelectedInstrument - 1 ) >= 0 ) {
842 		pInstrumentList->swap( nSelectedInstrument -1, nSelectedInstrument );
843 
844 		AudioEngine::get_instance()->unlock();
845 		engine->setSelectedInstrumentNumber( nSelectedInstrument - 1 );
846 
847 		pSong->set_is_modified( true );
848 	}
849 	else {
850 		AudioEngine::get_instance()->unlock();
851 	}
852 }
853 
854 
855 
moveDownBtnClicked(Button *)856 void PatternEditorPanel::moveDownBtnClicked(Button *)
857 {
858 	Hydrogen *engine = Hydrogen::get_instance();
859 	int nSelectedInstrument = engine->getSelectedInstrumentNumber();
860 
861 	AudioEngine::get_instance()->lock( RIGHT_HERE );
862 
863 	Song *pSong = engine->getSong();
864 	InstrumentList *pInstrumentList = pSong->get_instrument_list();
865 
866 	if ( ( nSelectedInstrument + 1 ) < (int)pInstrumentList->size() ) {
867 		pInstrumentList->swap( nSelectedInstrument, nSelectedInstrument + 1 );
868 
869 		AudioEngine::get_instance()->unlock();
870 		engine->setSelectedInstrumentNumber( nSelectedInstrument + 1 );
871 
872 		pSong->set_is_modified( true );
873 	}
874 	else {
875 		AudioEngine::get_instance()->unlock();
876 	}
877 
878 }
879 
880 
881 
882 
dragEnterEvent(QDragEnterEvent * event)883 void PatternEditorPanel::dragEnterEvent(QDragEnterEvent *event)
884 {
885 	m_pInstrumentList->dragEnterEvent( event );
886 }
887 
888 
889 
dropEvent(QDropEvent * event)890 void PatternEditorPanel::dropEvent(QDropEvent *event)
891 {
892 	m_pInstrumentList->dropEvent( event );
893 }
894 
895 
896 
propertiesComboChanged(int nSelected)897 void PatternEditorPanel::propertiesComboChanged( int nSelected )
898 {
899 	if ( nSelected == 0 ) {				// Velocity
900 		m_pNotePanScrollView->hide();
901 		m_pNoteLeadLagScrollView->hide();
902 		m_pNoteNoteKeyScrollView->hide();
903 		m_pNoteVelocityScrollView->show();
904 		m_pNoteProbabilityScrollView->hide();
905 
906 		m_pNoteVelocityEditor->updateEditor();
907 	}
908 	else if ( nSelected == 1 ) {		// Pan
909 		m_pNoteVelocityScrollView->hide();
910 		m_pNoteLeadLagScrollView->hide();
911 		m_pNoteNoteKeyScrollView->hide();
912 		m_pNotePanScrollView->show();
913 		m_pNoteProbabilityScrollView->hide();
914 
915 		m_pNotePanEditor->updateEditor();
916 	}
917 	else if ( nSelected == 2 ) {		// Lead and Lag
918 		m_pNoteVelocityScrollView->hide();
919 		m_pNotePanScrollView->hide();
920 		m_pNoteNoteKeyScrollView->hide();
921 		m_pNoteLeadLagScrollView->show();
922 		m_pNoteProbabilityScrollView->hide();
923 
924 		m_pNoteLeadLagEditor->updateEditor();
925 	}
926 	else if ( nSelected == 3 ) {		// NoteKey
927 		m_pNoteVelocityScrollView->hide();
928 		m_pNotePanScrollView->hide();
929 		m_pNoteLeadLagScrollView->hide();
930 		m_pNoteNoteKeyScrollView->show();
931 		m_pNoteProbabilityScrollView->hide();
932 
933 		m_pNoteNoteKeyEditor->updateEditor();
934 	}
935 	else if ( nSelected == 4 ) {		// Probability
936 		m_pNotePanScrollView->hide();
937 		m_pNoteLeadLagScrollView->hide();
938 		m_pNoteNoteKeyScrollView->hide();
939 		m_pNoteVelocityScrollView->hide();
940 		m_pNoteProbabilityScrollView->show();
941 
942 		m_pNoteProbabilityEditor->updateEditor();
943 	}
944 	/*
945 	else if ( nSelected == 5 ) {		// Cutoff
946 	}
947 	else if ( nSelected == 6 ) {		// Resonance
948 	}
949 	*/
950 	else {
951 		ERRORLOG( QString("unhandled value : %1").arg(nSelected) );
952 	}
953 }
954 
955 
recPreDeleteSelect(int index)956 void PatternEditorPanel::recPreDeleteSelect( int index )
957 {
958 	Preferences::get_instance()->m_nRecPreDelete = index;
959 	if( index>=9 && index <=15 ){
960 		__recpostdelete->show();
961 	}else{
962 		__recpostdelete->hide();
963 	}
964 }
965 
966 
recPostDeleteSelect(int index)967 void PatternEditorPanel::recPostDeleteSelect( int index )
968 {
969 	Preferences::get_instance()->m_nRecPostDelete = index;
970 }
971 
972 
displayorHidePrePostCB()973 void PatternEditorPanel::displayorHidePrePostCB()
974 {
975 	int index = __recpredelete->currentIndex();
976 	if( Preferences::get_instance()->getDestructiveRecord() ){
977 		__recpostdelete->show();
978 		if( index>=8 && index <=14 ){
979 			__recpostdelete->show();
980 		}else{
981 			__recpostdelete->hide();
982 		}
983 		__recpredelete->show();
984 	}else{
985 		__recpostdelete->hide();
986 		__recpredelete->hide();
987 	}
988 }
989 
updatePianorollEditor()990 void PatternEditorPanel::updatePianorollEditor()
991 {
992 	m_pDrumPatternEditor->updateEditor(); // force an update
993 }
994