TuningDialog.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * TuningDialog.h
  3. * --------------
  4. * Purpose: Alternative sample tuning configuration dialog.
  5. * Notes : (currently none)
  6. * Authors: OpenMPT Devs
  7. * The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
  8. */
  9. #pragma once
  10. #include "openmpt/all/BuildSettings.hpp"
  11. #include "tuningRatioMapWnd.h"
  12. #include "tuningcollection.h"
  13. #include <vector>
  14. #include <string>
  15. #include "resource.h"
  16. #include "CDecimalSupport.h"
  17. OPENMPT_NAMESPACE_BEGIN
  18. // Tunings exist even outside of CSoundFile objects. We thus cannot use the
  19. // GetCharsetInternal() encoding consistently. For now, just always treat
  20. // tuning strings as Charset::Locale. As of OpenMPT 1.27, this distinction does
  21. // not yet matter, because GetCharsetInteral() is always mpt::Charset::Locale if
  22. // MODPLUG_TRACKER anyway.
  23. extern const mpt::Charset TuningCharsetFallback;
  24. template<class T1, class T2>
  25. class CBijectiveMap
  26. {
  27. public:
  28. CBijectiveMap(const T1& a, const T2& b)
  29. : m_NotFoundT1(a),
  30. m_NotFoundT2(b)
  31. {}
  32. void AddPair(const T1& a, const T2& b)
  33. {
  34. m_T1.push_back(a);
  35. m_T2.push_back(b);
  36. }
  37. void ClearMapping()
  38. {
  39. m_T1.clear();
  40. m_T2.clear();
  41. }
  42. size_t Size() const
  43. {
  44. ASSERT(m_T1.size() == m_T2.size());
  45. return m_T1.size();
  46. }
  47. void RemoveValue_1(const T1& a)
  48. {
  49. auto iter = find(m_T1.begin(), m_T1.end(), a);
  50. if(iter != m_T1.end())
  51. {
  52. m_T2.erase(m_T2.begin() + (iter-m_T1.begin()));
  53. m_T1.erase(iter);
  54. }
  55. }
  56. void RemoveValue_2(const T2& b)
  57. {
  58. auto iter = find(m_T2.begin(), m_T2.end(), b);
  59. if(iter != m_T2.end())
  60. {
  61. m_T1.erase(m_T1.begin() + (iter-m_T2.begin()));
  62. m_T2.erase(iter);
  63. }
  64. }
  65. T2 GetMapping_12(const T1& a) const
  66. {
  67. auto iter = find(m_T1.begin(), m_T1.end(), a);
  68. if(iter != m_T1.end())
  69. {
  70. return m_T2[iter-m_T1.begin()];
  71. }
  72. else
  73. return m_NotFoundT2;
  74. }
  75. T1 GetMapping_21(const T2& b) const
  76. {
  77. auto iter = find(m_T2.begin(), m_T2.end(), b);
  78. if(iter != m_T2.end())
  79. {
  80. return m_T1[iter-m_T2.begin()];
  81. }
  82. else
  83. return m_NotFoundT1;
  84. }
  85. private:
  86. //Elements are collected to two arrays so that elements with the
  87. //same index are mapped to each other.
  88. std::vector<T1> m_T1;
  89. std::vector<T2> m_T2;
  90. T1 m_NotFoundT1;
  91. T2 m_NotFoundT2;
  92. };
  93. class CTuningDialog;
  94. class CTuningTreeCtrl : public CTreeCtrl
  95. {
  96. private:
  97. CTuningDialog& m_rParentDialog;
  98. bool m_Dragging;
  99. public:
  100. CTuningTreeCtrl(CTuningDialog* parent)
  101. : m_rParentDialog(*parent)
  102. , m_Dragging(false)
  103. {}
  104. //Note: Parent address may be given in its initializer list.
  105. void SetDragging(bool state = true) {m_Dragging = state;}
  106. bool IsDragging() {return m_Dragging;}
  107. afx_msg void OnMouseMove(UINT nFlags, CPoint point);
  108. afx_msg void OnLButtonUp(UINT nFlags, CPoint point);
  109. DECLARE_MESSAGE_MAP()
  110. };
  111. class CTuningTreeItem
  112. {
  113. private:
  114. CTuning* m_pTuning;
  115. CTuningCollection* m_pTuningCollection;
  116. public:
  117. CTuningTreeItem() : m_pTuning(NULL),
  118. m_pTuningCollection(NULL)
  119. {}
  120. CTuningTreeItem(CTuning* pT) :
  121. m_pTuning(pT),
  122. m_pTuningCollection(NULL)
  123. {}
  124. CTuningTreeItem(CTuningCollection* pTC) :
  125. m_pTuning(NULL),
  126. m_pTuningCollection(pTC)
  127. {}
  128. bool operator==(const CTuningTreeItem& ti) const
  129. {
  130. if(m_pTuning == ti.m_pTuning &&
  131. m_pTuningCollection == ti.m_pTuningCollection)
  132. return true;
  133. else
  134. return false;
  135. }
  136. void Reset() {m_pTuning = NULL; m_pTuningCollection = NULL;}
  137. void Set(CTuning* pT)
  138. {
  139. m_pTuning = pT;
  140. m_pTuningCollection = NULL;
  141. }
  142. void Set(CTuningCollection* pTC)
  143. {
  144. m_pTuning = NULL;
  145. m_pTuningCollection = pTC;
  146. }
  147. operator bool () const
  148. {
  149. return m_pTuning || m_pTuningCollection;
  150. }
  151. bool operator ! () const
  152. {
  153. return !operator bool();
  154. }
  155. CTuningCollection* GetTC() {return m_pTuningCollection;}
  156. CTuning* GetT() {return m_pTuning;}
  157. };
  158. // CTuningDialog dialog
  159. class CTuningDialog : public CDialog
  160. {
  161. friend class CTuningTreeCtrl;
  162. enum EnSclImport
  163. {
  164. enSclImportOk,
  165. enSclImportFailTooLargeNumDenomIntegers,
  166. enSclImportFailZeroDenominator,
  167. enSclImportFailNegativeRatio,
  168. enSclImportFailUnableToOpenFile,
  169. enSclImportLineCountMismatch,
  170. enSclImportTuningCreationFailure,
  171. enSclImportAddTuningFailure,
  172. enSclImportFailTooManyNotes
  173. };
  174. public:
  175. using TUNINGVECTOR = std::vector<CTuningCollection*>;
  176. public:
  177. CTuningDialog(CWnd* pParent, INSTRUMENTINDEX inst, CSoundFile &csf);
  178. virtual ~CTuningDialog();
  179. BOOL OnInitDialog();
  180. void UpdateRatioMapEdits(const Tuning::NOTEINDEXTYPE&);
  181. bool GetModifiedStatus(const CTuningCollection* const pTc) const;
  182. // Dialog Data
  183. enum { IDD = IDD_TUNING };
  184. protected:
  185. virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
  186. private:
  187. bool CanEdit(CTuningCollection * pTC) const;
  188. bool CanEdit(CTuning * pT, CTuningCollection * pTC) const;
  189. void UpdateView(const int UpdateMask = 0);
  190. void UpdateTuningType();
  191. HTREEITEM AddTreeItem(CTuningCollection* pTC, HTREEITEM parent, HTREEITEM insertAfter);
  192. HTREEITEM AddTreeItem(CTuning* pT, HTREEITEM parent, HTREEITEM insertAfter);
  193. void DeleteTreeItem(CTuning* pT);
  194. void DeleteTreeItem(CTuningCollection* pTC);
  195. // Check if item can be dropped here. If yes, the target collection is returned, otherwise nullptr.
  196. CTuningCollection *CanDrop(HTREEITEM dragDestItem);
  197. void OnEndDrag(HTREEITEM dragDestItem);
  198. //Returns pointer to the tuning collection where tuning given as argument
  199. //belongs to.
  200. CTuningCollection* GetpTuningCollection(const CTuning* const) const;
  201. //Returns the address of corresponding tuningcollection; if it points
  202. //to tuning-entry, returning the owning tuningcollection
  203. CTuningCollection* GetpTuningCollection(HTREEITEM ti) const;
  204. //Checks whether tuning collection can be deleted.
  205. bool IsDeletable(const CTuningCollection* const pTC) const;
  206. // Scl-file import.
  207. EnSclImport ImportScl(const mpt::PathString &filename, const mpt::ustring &name, std::unique_ptr<CTuning> & result);
  208. EnSclImport ImportScl(std::istream& iStrm, const mpt::ustring &name, std::unique_ptr<CTuning> & result);
  209. private:
  210. CSoundFile & m_sndFile;
  211. CTuningRatioMapWnd m_RatioMapWnd;
  212. TUNINGVECTOR m_TuningCollections;
  213. std::vector<CTuningCollection*> m_DeletableTuningCollections;
  214. std::map<const CTuningCollection*, CString> m_TuningCollectionsNames;
  215. std::map<const CTuningCollection*, mpt::PathString> m_TuningCollectionsFilenames;
  216. CTuning* m_pActiveTuning;
  217. CTuningCollection* m_pActiveTuningCollection;
  218. CComboBox m_CombobTuningType;
  219. //Tuning Edits-->
  220. CEdit m_EditSteps;
  221. CNumberEdit m_EditRatioPeriod;
  222. CNumberEdit m_EditRatio;
  223. CEdit m_EditNotename;
  224. CEdit m_EditMiscActions;
  225. CEdit m_EditFineTuneSteps;
  226. CEdit m_EditName;
  227. //<--Tuning Edits
  228. CButton m_ButtonSet;
  229. CButton m_ButtonNew;
  230. CButton m_ButtonExport;
  231. CButton m_ButtonImport;
  232. CButton m_ButtonRemove;
  233. CTuningTreeCtrl m_TreeCtrlTuning;
  234. private:
  235. using TUNINGTREEITEM = CTuningTreeItem;
  236. using TREETUNING_MAP = CBijectiveMap<HTREEITEM, TUNINGTREEITEM>;
  237. TREETUNING_MAP m_TreeItemTuningItemMap;
  238. TUNINGTREEITEM m_DragItem;
  239. TUNINGTREEITEM m_CommandItemSrc;
  240. TUNINGTREEITEM m_CommandItemDest;
  241. //Commanditem is used when receiving context menu-commands,
  242. //m_CommandItemDest is used when the command really need only
  243. //one argument.
  244. using MODIFIED_MAP = std::map<const CTuningCollection* const, bool>;
  245. MODIFIED_MAP m_ModifiedTCs;
  246. //If tuning collection seems to have been modified, its address
  247. //is added to this map.
  248. enum
  249. {
  250. TT_TUNINGCOLLECTION = 1,
  251. TT_TUNING
  252. };
  253. static CString GetSclImportFailureMsg(EnSclImport);
  254. static constexpr size_t s_nSclImportMaxNoteCount = 256;
  255. //To indicate whether to apply changes made to
  256. //those edit boxes(they are modified by certain activities
  257. //in case which the modifications should not be applied to
  258. //tuning data.
  259. bool m_NoteEditApply;
  260. bool m_RatioEditApply;
  261. enum
  262. {
  263. UM_TUNINGDATA = 1, //UM <-> Update Mask
  264. UM_TUNINGCOLLECTION = 2,
  265. };
  266. static const TUNINGTREEITEM s_notFoundItemTuning;
  267. static const HTREEITEM s_notFoundItemTree;
  268. bool AddTuning(CTuningCollection*, CTuning* pT);
  269. bool AddTuning(CTuningCollection*, Tuning::Type type);
  270. //Flag to prevent multiple exit error-messages.
  271. bool m_DoErrorExit;
  272. void DoErrorExit();
  273. virtual void OnOK();
  274. //Treectrl context menu functions.
  275. public:
  276. afx_msg void OnRemoveTuning();
  277. afx_msg void OnAddTuningGeneral();
  278. afx_msg void OnAddTuningGroupGeometric();
  279. afx_msg void OnAddTuningGeometric();
  280. afx_msg void OnCopyTuning();
  281. afx_msg void OnRemoveTuningCollection();
  282. //Event-functions
  283. public:
  284. afx_msg void OnEnChangeEditSteps();
  285. afx_msg void OnEnChangeEditRatioperiod();
  286. afx_msg void OnEnChangeEditNotename();
  287. afx_msg void OnBnClickedButtonSetvalues();
  288. afx_msg void OnEnChangeEditRatiovalue();
  289. afx_msg void OnBnClickedButtonNew();
  290. afx_msg void OnBnClickedButtonExport();
  291. afx_msg void OnBnClickedButtonImport();
  292. afx_msg void OnBnClickedButtonRemove();
  293. afx_msg void OnEnChangeEditFinetunesteps();
  294. afx_msg void OnEnKillfocusEditFinetunesteps();
  295. afx_msg void OnEnKillfocusEditName();
  296. afx_msg void OnEnKillfocusEditSteps();
  297. afx_msg void OnEnKillfocusEditRatioperiod();
  298. afx_msg void OnEnKillfocusEditRatiovalue();
  299. afx_msg void OnEnKillfocusEditNotename();
  300. //Treeview events
  301. afx_msg void OnTvnSelchangedTreeTuning(NMHDR *pNMHDR, LRESULT *pResult);
  302. afx_msg void OnTvnDeleteitemTreeTuning(NMHDR *pNMHDR, LRESULT *pResult);
  303. afx_msg void OnNMRclickTreeTuning(NMHDR *pNMHDR, LRESULT *pResult);
  304. afx_msg void OnTvnBegindragTreeTuning(NMHDR *pNMHDR, LRESULT *pResult);
  305. DECLARE_MESSAGE_MAP()
  306. };
  307. OPENMPT_NAMESPACE_END