Ctrl_pat.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. /*
  2. * Ctrl_pat.h
  3. * ----------
  4. * Purpose: Pattern tab, upper panel.
  5. * Notes : (currently none)
  6. * Authors: Olivier Lapicque
  7. * OpenMPT Devs
  8. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  9. */
  10. #pragma once
  11. #include "openmpt/all/BuildSettings.hpp"
  12. #include "Globals.h"
  13. #include "PatternCursor.h"
  14. OPENMPT_NAMESPACE_BEGIN
  15. class COrderList;
  16. class CCtrlPatterns;
  17. struct OrdSelection
  18. {
  19. ORDERINDEX firstOrd = 0, lastOrd = 0;
  20. ORDERINDEX GetSelCount() const { return lastOrd - firstOrd + 1; }
  21. };
  22. class COrderList: public CWnd
  23. {
  24. friend class CCtrlPatterns;
  25. protected:
  26. HFONT m_hFont = nullptr;
  27. int m_cxFont = 0, m_cyFont = 0;
  28. //m_nXScroll : The order at the beginning of shown orderlist
  29. //m_nScrollPos: The same as order
  30. //m_nScrollPos2nd: 2nd selection point if multiple orders are selected
  31. // (not neccessarily the higher order - GetCurSel() is taking care of that.)
  32. ORDERINDEX m_nXScroll = 0, m_nScrollPos = 0, m_nScrollPos2nd = ORDERINDEX_INVALID, m_nDropPos, m_nMouseDownPos, m_playPos = ORDERINDEX_INVALID;
  33. ORDERINDEX m_nDragOrder;
  34. //To tell how many orders('orderboxes') to show at least
  35. //on both sides of current order(when updating orderslist position).
  36. int m_nOrderlistMargins;
  37. CModDoc &m_modDoc;
  38. CCtrlPatterns &m_pParent;
  39. bool m_bScrolling = false, m_bDragging = false;
  40. public:
  41. COrderList(CCtrlPatterns &parent, CModDoc &document);
  42. public:
  43. BOOL Init(const CRect&, HFONT hFont);
  44. void UpdateView(UpdateHint hint, CObject *pObj = nullptr);
  45. void InvalidateSelection();
  46. PATTERNINDEX GetCurrentPattern() const;
  47. // make the current selection the secondary selection (used for keyboard orderlist navigation)
  48. inline void SetCurSelTo2ndSel(bool isSelectionKeyPressed)
  49. {
  50. if(isSelectionKeyPressed && m_nScrollPos2nd == ORDERINDEX_INVALID) m_nScrollPos2nd = m_nScrollPos;
  51. else if(!isSelectionKeyPressed && m_nScrollPos2nd != ORDERINDEX_INVALID) m_nScrollPos2nd = ORDERINDEX_INVALID;
  52. };
  53. void SetSelection(ORDERINDEX firstOrd, ORDERINDEX lastOrd = ORDERINDEX_INVALID);
  54. // Why VC wants to inline this huge function is beyond my understanding...
  55. MPT_NOINLINE bool SetCurSel(ORDERINDEX sel, bool setPlayPos = true, bool shiftClick = false, bool ignoreCurSel = false);
  56. void UpdateScrollInfo();
  57. void UpdateInfoText();
  58. int GetFontWidth();
  59. void QueuePattern(CPoint pt);
  60. // Check if this module is currently playing
  61. bool IsPlaying() const;
  62. ORDERINDEX GetOrderFromPoint(const CPoint &pt) const;
  63. CRect GetRectFromOrder(ORDERINDEX ord) const;
  64. // Get the currently selected pattern(s).
  65. // Set ignoreSelection to true if only the first selected point is important.
  66. OrdSelection GetCurSel(bool ignoreSelection = false) const;
  67. // Sets target margin value and returns the effective margin value.
  68. ORDERINDEX SetMargins(int);
  69. // Returns the effective margin value.
  70. ORDERINDEX GetMargins() { return GetMargins(GetMarginsMax()); }
  71. // Returns the effective margin value.
  72. ORDERINDEX GetMargins(const ORDERINDEX maxMargins) const { return std::min(maxMargins, static_cast<ORDERINDEX>(m_nOrderlistMargins)); }
  73. // Returns maximum margin value given current window width.
  74. ORDERINDEX GetMarginsMax() { return GetMarginsMax(GetLength()); }
  75. // Returns maximum margin value when shown sequence has nLength orders.
  76. // For example: If length is 4 orders -> maxMargins = 4/2 - 1 = 1;
  77. // if maximum is 5 -> maxMargins = (int)5/2 = 2
  78. ORDERINDEX GetMarginsMax(const ORDERINDEX length) const { return (length > 0 && length % 2 == 0) ? length / 2 - 1 : length / 2; }
  79. // Returns the number of sequence items visible in the list.
  80. ORDERINDEX GetLength();
  81. // Return true if given order is in margins given that first shown order
  82. // is 'startOrder'. Begin part of the whole sequence
  83. // is not interpreted to be in margins regardless of the margin value.
  84. bool IsOrderInMargins(int order, int startOrder);
  85. // Ensure that a given order index is visible in the orderlist view.
  86. void EnsureVisible(ORDERINDEX order);
  87. // Set given sqeuence and update orderlist display.
  88. void SelectSequence(const SEQUENCEINDEX nSeq);
  89. // Helper function for entering pattern number
  90. void EnterPatternNum(int enterNum);
  91. void OnCopy(bool onlyOrders);
  92. // Update play state and order lock ranges after inserting order items.
  93. void InsertUpdatePlaystate(ORDERINDEX first, ORDERINDEX last);
  94. // Update play state and order lock ranges after deleting order items.
  95. void DeleteUpdatePlaystate(ORDERINDEX first, ORDERINDEX last);
  96. //{{AFX_VIRTUAL(COrderList)
  97. BOOL PreTranslateMessage(MSG *pMsg) override;
  98. INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const override;
  99. HRESULT get_accName(VARIANT varChild, BSTR *pszName) override;
  100. //}}AFX_VIRTUAL
  101. protected:
  102. ModSequence& Order();
  103. const ModSequence& Order() const;
  104. void SetScrollPos(int pos);
  105. int GetScrollPos(bool getTrackPos = false);
  106. // Resizes the order list if the specified order is past the order list length
  107. bool EnsureEditable(ORDERINDEX ord);
  108. //{{AFX_MSG(COrderList)
  109. afx_msg void OnPaint();
  110. afx_msg BOOL OnEraseBkgnd(CDC *) { return TRUE; }
  111. afx_msg void OnSetFocus(CWnd *);
  112. afx_msg void OnKillFocus(CWnd *);
  113. afx_msg void OnLButtonDown(UINT, CPoint);
  114. afx_msg void OnLButtonDblClk(UINT, CPoint);
  115. afx_msg void OnRButtonDown(UINT, CPoint);
  116. afx_msg void OnLButtonUp(UINT, CPoint);
  117. afx_msg void OnMButtonDown(UINT, CPoint);
  118. afx_msg void OnMouseMove(UINT, CPoint);
  119. afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar*);
  120. afx_msg void OnSize(UINT nType, int cx, int cy);
  121. afx_msg void OnSwitchToView();
  122. afx_msg void OnInsertOrder();
  123. afx_msg void OnInsertSeparatorPattern();
  124. afx_msg void OnDeleteOrder();
  125. afx_msg void OnRenderOrder();
  126. afx_msg void OnPatternProperties();
  127. afx_msg void OnPlayerPlay();
  128. afx_msg void OnPlayerPause();
  129. afx_msg void OnPlayerPlayFromStart();
  130. afx_msg void OnPatternPlayFromStart();
  131. afx_msg void OnCreateNewPattern();
  132. afx_msg void OnDuplicatePattern();
  133. afx_msg void OnMergePatterns();
  134. afx_msg void OnPatternCopy();
  135. afx_msg void OnPatternPaste();
  136. afx_msg void OnSetRestartPos();
  137. afx_msg void OnEditCopy() { OnCopy(false); }
  138. afx_msg void OnEditCopyOrders() { OnCopy(true); }
  139. afx_msg void OnEditCut();
  140. afx_msg LRESULT OnDragonDropping(WPARAM bDoDrop, LPARAM lParam);
  141. afx_msg LRESULT OnHelpHitTest(WPARAM, LPARAM lParam);
  142. afx_msg void OnSelectSequence(UINT nid);
  143. afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM);
  144. afx_msg void OnLockPlayback();
  145. afx_msg void OnUnlockPlayback();
  146. afx_msg BOOL OnToolTipText(UINT, NMHDR *pNMHDR, LRESULT *pResult);
  147. //}}AFX_MSG
  148. DECLARE_MESSAGE_MAP()
  149. };
  150. // CPatEdit: Edit control that switches back to the pattern view if Tab key is pressed.
  151. class CPatEdit: public CEdit
  152. {
  153. protected:
  154. CCtrlPatterns *m_pParent = nullptr;
  155. public:
  156. CPatEdit() = default;
  157. void SetParent(CCtrlPatterns *parent) { m_pParent = parent; }
  158. BOOL PreTranslateMessage(MSG *pMsg) override;
  159. };
  160. class CCtrlPatterns: public CModControlDlg
  161. {
  162. friend class COrderList;
  163. protected:
  164. COrderList m_OrderList;
  165. CButton m_BtnPrev, m_BtnNext;
  166. CComboBox m_CbnInstrument;
  167. CPatEdit m_EditSpacing, m_EditPatName, m_EditSequence;
  168. CSpinButtonCtrl m_SpinInstrument, m_SpinSpacing, m_SpinSequence;
  169. CModControlBar m_ToolBar;
  170. INSTRUMENTINDEX m_nInstrument = 0;
  171. PatternCursor::Columns m_nDetailLevel = PatternCursor::lastColumn; // Visible Columns
  172. bool m_bRecord = false, m_bVUMeters = false, m_bPluginNames = false;
  173. public:
  174. CCtrlPatterns(CModControlView &parent, CModDoc &document);
  175. Setting<LONG> &GetSplitPosRef() override { return TrackerSettings::Instance().glPatternWindowHeight; }
  176. public:
  177. const ModSequence &Order() const;
  178. ModSequence &Order();
  179. void SetCurrentPattern(PATTERNINDEX nPat);
  180. BOOL SetCurrentInstrument(UINT nIns);
  181. BOOL GetFollowSong() { return IsDlgButtonChecked(IDC_PATTERN_FOLLOWSONG); }
  182. BOOL GetLoopPattern() {return IsDlgButtonChecked(IDC_PATTERN_LOOP);}
  183. COrderList &GetOrderList() { return m_OrderList; }
  184. //{{AFX_VIRTUAL(CCtrlPatterns)
  185. BOOL OnInitDialog() override;
  186. void DoDataExchange(CDataExchange* pDX) override; // DDX/DDV support
  187. void RecalcLayout() override;
  188. void UpdateView(UpdateHint hint = UpdateHint(), CObject *pObj = nullptr) override;
  189. CRuntimeClass *GetAssociatedViewClass() override;
  190. LRESULT OnModCtrlMsg(WPARAM wParam, LPARAM lParam) override;
  191. void OnActivatePage(LPARAM) override;
  192. void OnDeactivatePage() override;
  193. BOOL GetToolTipText(UINT, LPTSTR) override;
  194. //}}AFX_VIRTUAL
  195. protected:
  196. //{{AFX_MSG(CCtrlPatterns)
  197. afx_msg void OnVScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
  198. afx_msg void OnSequenceNext();
  199. afx_msg void OnSequencePrev();
  200. afx_msg void OnChannelManager();
  201. afx_msg void OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags);
  202. afx_msg void OnPlayerPause();
  203. afx_msg void OnPatternNew();
  204. afx_msg void OnPatternDuplicate();
  205. afx_msg void OnPatternMerge();
  206. afx_msg void OnPatternStop();
  207. afx_msg void OnPatternPlay();
  208. afx_msg void OnPatternPlayNoLoop();
  209. afx_msg void OnPatternPlayRow();
  210. afx_msg void OnPatternPlayFromStart();
  211. afx_msg void OnPatternRecord();
  212. afx_msg void OnPatternVUMeters();
  213. afx_msg void OnPatternViewPlugNames();
  214. afx_msg void OnPatternProperties();
  215. afx_msg void OnPatternExpand();
  216. afx_msg void OnPatternShrink();
  217. afx_msg void OnPatternAmplify();
  218. afx_msg void OnPatternCopy();
  219. afx_msg void OnPatternPaste();
  220. afx_msg void OnFollowSong();
  221. afx_msg void OnChangeLoopStatus();
  222. afx_msg void OnSwitchToView();
  223. afx_msg void OnInstrumentChanged();
  224. afx_msg void OnPrevInstrument();
  225. afx_msg void OnNextInstrument();
  226. afx_msg void OnSpacingChanged();
  227. afx_msg void OnPatternNameChanged();
  228. afx_msg void OnSequenceNameChanged();
  229. afx_msg void OnChordEditor();
  230. afx_msg void OnDetailLo();
  231. afx_msg void OnDetailMed();
  232. afx_msg void OnDetailHi();
  233. afx_msg void OnEditUndo();
  234. afx_msg void OnUpdateRecord(CCmdUI *pCmdUI);
  235. afx_msg void TogglePluginEditor();
  236. afx_msg void OnToggleOverflowPaste();
  237. afx_msg void OnSequenceNumChanged();
  238. afx_msg LRESULT OnCustomKeyMsg(WPARAM, LPARAM);
  239. //}}AFX_MSG
  240. DECLARE_MESSAGE_MAP()
  241. private:
  242. bool HasValidPlug(INSTRUMENTINDEX instr) const;
  243. public:
  244. afx_msg BOOL OnMouseWheel(UINT nFlags, short zDelta, CPoint pt);
  245. afx_msg void OnXButtonUp(UINT nFlags, UINT nButton, CPoint point);
  246. afx_msg BOOL OnToolTip(UINT id, NMHDR *pTTTStruct, LRESULT *pResult);
  247. };
  248. OPENMPT_NAMESPACE_END