1 /* TIATracker, (c) 2016 Andre "Kylearan" Wichmann.
2  * Website: https://bitbucket.org/kylearan/tiatracker
3  * Email: andre.wichmann@gmx.de
4  * See the file "license.txt" for information on usage and redistribution
5  * of this file.
6  */
7 
8 #ifndef PATTERNEDITOR_H
9 #define PATTERNEDITOR_H
10 
11 #include <QObject>
12 #include <QWidget>
13 #include "track/track.h"
14 #include <QFontDatabase>
15 #include "tiasound/pitchguide.h"
16 #include <QMenu>
17 #include "instrumentselector.h"
18 #include "emulation/player.h"
19 
20 
21 class PatternEditor : public QWidget
22 {
23     Q_OBJECT
24 public:
25     explicit PatternEditor(QWidget *parent = 0);
26 
27     void registerTrack(Track::Track *newTrack);
28     void registerPitchGuide(TiaSound::PitchGuide *newGuide);
29     void registerPlayer(Emulation::Player *newPlayer);
30     void registerMuteAction(QAction *newAction);
31     void registerPatternMenu(QMenu *newPatternMenu);
32     void registerChannelMenu(QMenu *newChannelMenu);
33     void registerInstrumentSelector(InstrumentSelector *selector);
34 
35     int getEditPos();
36     int getSelectedChannel();
37 
38     QString constructRowString(int curPatternNoteIndex, Track::Pattern *curPattern);
39 
40     QSize sizeHint() const;
41 
42 signals:
43     void editPosChanged(int newPos);
44     void channelContextEvent(int channel, int row);
45     void editChannelChanged(int newChannel);
46 
47 public slots:
48     // Global actions
49     void moveUp(bool);
50     void moveDown(bool);
51     void moveLeft(bool);
52     void moveRight(bool);
53     void switchChannel(bool);
54     void gotoFirstRow(bool);
55     void gotoLastRow(bool);
56     void gotoNextPattern(bool);
57     void gotoPreviousPattern(bool);
58 
59     void setEditPos(int newPos);
60     void setEditPos(int newChannel, int newPos);
61 
62     void validateEditPos();
63     void advanceEditPos();
64     void setRowsPerBeat(int value);
65 
66     void setRowToInstrument(int frequency);
67 
68     void newPlayerPos(int pos1, int pos2);
69 
70     // Slot for QCheckBox "follow"
71     void toggleFollow_clicked(bool toggle);
72 
73     void toggleLoop_clicked(bool toggle);
74 
75 protected:
76     void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE;
77     void wheelEvent(QWheelEvent *) Q_DECL_OVERRIDE;
78     void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
79     void contextMenuEvent(QContextMenuEvent *event) Q_DECL_OVERRIDE;
80 
81 private:
82     static const int noteFontSize = 12;
83     static const int legendFontSize = 12;
84 
85     static const int noteMargin = 6;
86     static const int patternNameWidth = 120;
87     static const int patternNameMargin = 4;
88     static const int minHeight = 400;
89 
90     void drawPatternNameAndSeparator(int yPos, int nameXPos, int curPatternNoteIndex, int channel, int xPos, int curEntryIndex, QPainter *painter, Track::Pattern *curPattern);
91     void drawGoto(int channel, int yPos, Track::Pattern *curPattern, Track::SequenceEntry *curEntry, QPainter *painter, int nameXPos, int curPatternNoteIndex);
92     void drawTimestamp(int row, QPainter *painter, int yPos, int channel);
93     void paintChannel(QPainter *painter, int channel, int xPos, int nameXPos);
94 
95     /* If x and y are in a valid row with regards to the channel clicked,
96      * the channel number, row and note index get written to the parameters
97      * and true is returned.
98      */
99     bool clickedInValidRow(int x, int y, int *channel, int *noteIndex);
100 
101     int calcChannelRowPos(int yPos);
102 
103     int numRows;    // number of visible rows
104     int topMargin;  // margin before first row is displayed
105 
106     int noteFontHeight;
107     int noteAreaWidth;
108     int timeAreaWidth;
109     int widgetWidth;
110 
111     QFont noteFont = QFontDatabase::systemFont(QFontDatabase::FixedFont);
112     QFont legendFont{"Helvetica"};
113     int legendFontHeight;
114     int timelineWidth;
115 
116     Track::Track *pTrack;
117     TiaSound::PitchGuide *pPitchGuide;
118     Emulation::Player *pPlayer = nullptr;
119     QAction *muteAction = nullptr;
120     QMenu *pPatternMenu = nullptr;
121     QMenu *pChannelMenu = nullptr;
122     InstrumentSelector *pInsSelector = nullptr;
123 
124     int selectedChannel = 0;
125     // Current editor note focus, i.e. middle-of-screen highlight
126     int editPos = 0;
127 
128     bool follow = false;
129     bool loop = false;
130 };
131 
132 #endif // PATTERNEDITOR_H
133