PatternGotoDialog.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. /*
  2. * PatternGotoDialog.cpp
  3. * ---------------------
  4. * Purpose: Implementation of pattern "go to" 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. #include "stdafx.h"
  10. #include "Mptrack.h"
  11. #include "PatternGotoDialog.h"
  12. #include "Sndfile.h"
  13. OPENMPT_NAMESPACE_BEGIN
  14. // CPatternGotoDialog dialog
  15. CPatternGotoDialog::CPatternGotoDialog(CWnd *pParent, ROWINDEX row, CHANNELINDEX chan, PATTERNINDEX pat, ORDERINDEX ord, CSoundFile &sndFile)
  16. : CDialog(IDD_EDIT_GOTO, pParent)
  17. , m_SndFile(sndFile)
  18. , m_nRow(row)
  19. , m_nChannel(chan)
  20. , m_nPattern(pat)
  21. , m_nOrder(ord)
  22. , m_nActiveOrder(ord)
  23. { }
  24. void CPatternGotoDialog::DoDataExchange(CDataExchange* pDX)
  25. {
  26. CDialog::DoDataExchange(pDX);
  27. DDX_Control(pDX, IDC_SPIN1, m_SpinRow);
  28. DDX_Control(pDX, IDC_SPIN2, m_SpinChannel);
  29. DDX_Control(pDX, IDC_SPIN3, m_SpinPattern);
  30. DDX_Control(pDX, IDC_SPIN4, m_SpinOrder);
  31. }
  32. BEGIN_MESSAGE_MAP(CPatternGotoDialog, CDialog)
  33. ON_EN_CHANGE(IDC_GOTO_PAT, &CPatternGotoDialog::OnPatternChanged)
  34. ON_EN_CHANGE(IDC_GOTO_ORD, &CPatternGotoDialog::OnOrderChanged)
  35. ON_EN_CHANGE(IDC_GOTO_ROW, &CPatternGotoDialog::OnRowChanged)
  36. ON_EN_CHANGE(IDC_EDIT5, &CPatternGotoDialog::OnTimeChanged)
  37. ON_EN_CHANGE(IDC_EDIT6, &CPatternGotoDialog::OnTimeChanged)
  38. END_MESSAGE_MAP()
  39. BOOL CPatternGotoDialog::OnInitDialog()
  40. {
  41. CDialog::OnInitDialog();
  42. HICON icon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MODULETYPE));
  43. SetIcon(icon, FALSE);
  44. SetIcon(icon, TRUE);
  45. UpdateNumRows();
  46. m_SpinChannel.SetRange32(1, m_SndFile.GetNumChannels());
  47. m_SpinPattern.SetRange32(0, std::max(m_SndFile.Patterns.GetNumPatterns(), PATTERNINDEX(1)) - 1);
  48. m_SpinOrder.SetRange32(0, std::max(m_SndFile.Order().GetLengthTailTrimmed(), ORDERINDEX(1)) - 1);
  49. SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
  50. SetDlgItemInt(IDC_GOTO_CHAN, m_nChannel);
  51. SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
  52. SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
  53. UpdateTime();
  54. UnlockControls();
  55. return TRUE;
  56. }
  57. void CPatternGotoDialog::OnOK()
  58. {
  59. const auto &Order = m_SndFile.Order();
  60. m_nRow = mpt::saturate_cast<ROWINDEX>(GetDlgItemInt(IDC_GOTO_ROW));
  61. m_nChannel = mpt::saturate_cast<CHANNELINDEX>(GetDlgItemInt(IDC_GOTO_CHAN));
  62. // Valid order item?
  63. if(m_nOrder >= Order.size())
  64. {
  65. MessageBeep(MB_ICONWARNING);
  66. GetDlgItem(IDC_GOTO_ORD)->SetFocus();
  67. return;
  68. }
  69. // Does order match pattern? Does pattern exist?
  70. if(Order[m_nOrder] != m_nPattern || !Order.IsValidPat(m_nOrder))
  71. {
  72. MessageBeep(MB_ICONWARNING);
  73. GetDlgItem(IDC_GOTO_PAT)->SetFocus();
  74. return;
  75. }
  76. LimitMax(m_nRow, m_SndFile.Patterns[m_nPattern].GetNumRows() - ROWINDEX(1));
  77. Limit(m_nChannel, CHANNELINDEX(1), m_SndFile.GetNumChannels());
  78. CDialog::OnOK();
  79. }
  80. void CPatternGotoDialog::OnPatternChanged()
  81. {
  82. if(ControlsLocked())
  83. return; // The change to textbox did not come from user.
  84. m_nPattern = mpt::saturate_cast<PATTERNINDEX>(GetDlgItemInt(IDC_GOTO_PAT));
  85. m_nOrder = m_SndFile.Order().FindOrder(m_nPattern, m_nActiveOrder);
  86. if(m_nOrder == ORDERINDEX_INVALID)
  87. {
  88. m_nOrder = 0;
  89. }
  90. LockControls();
  91. SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
  92. UpdateNumRows();
  93. UpdateTime();
  94. UnlockControls();
  95. }
  96. void CPatternGotoDialog::OnOrderChanged()
  97. {
  98. if(ControlsLocked())
  99. return; // The change to textbox did not come from user.
  100. m_nOrder = mpt::saturate_cast<ORDERINDEX>(GetDlgItemInt(IDC_GOTO_ORD));
  101. if(m_SndFile.Order().IsValidPat(m_nOrder))
  102. {
  103. m_nPattern = m_SndFile.Order()[m_nOrder];
  104. }
  105. LockControls();
  106. SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
  107. UpdateNumRows();
  108. UpdateTime();
  109. UnlockControls();
  110. }
  111. void CPatternGotoDialog::OnRowChanged()
  112. {
  113. if(ControlsLocked())
  114. return; // The change to textbox did not come from user.
  115. m_nRow = mpt::saturate_cast<ROWINDEX>(GetDlgItemInt(IDC_GOTO_ROW));
  116. UpdateTime();
  117. }
  118. void CPatternGotoDialog::OnTimeChanged()
  119. {
  120. if(ControlsLocked())
  121. return; // The change to textbox did not come from user.
  122. BOOL success = TRUE;
  123. auto minutes = GetDlgItemInt(IDC_EDIT5, &success);
  124. if(!success)
  125. return;
  126. auto seconds = GetDlgItemInt(IDC_EDIT6, &success);
  127. if(!success)
  128. return;
  129. auto result = m_SndFile.GetLength(eNoAdjust, GetLengthTarget(minutes * 60.0 + seconds)).back();
  130. if(!result.targetReached)
  131. return;
  132. m_nOrder = result.lastOrder;
  133. m_nRow = result.lastRow;
  134. if(m_SndFile.Order().IsValidPat(m_nOrder))
  135. m_nPattern = m_SndFile.Order()[m_nOrder];
  136. LockControls();
  137. SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
  138. SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
  139. SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
  140. UnlockControls();
  141. }
  142. void CPatternGotoDialog::UpdateNumRows()
  143. {
  144. const ROWINDEX maxRow = (m_SndFile.Patterns.IsValidPat(m_nPattern) ? m_SndFile.Patterns[m_nPattern].GetNumRows() : MAX_PATTERN_ROWS) - 1;
  145. m_SpinRow.SetRange32(0, maxRow);
  146. if(m_nRow > maxRow)
  147. {
  148. m_nRow = maxRow;
  149. SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
  150. }
  151. }
  152. void CPatternGotoDialog::UpdateTime()
  153. {
  154. const double length = m_SndFile.GetPlaybackTimeAt(m_nOrder, m_nRow, false, false);
  155. if(length < 0.0)
  156. return;
  157. const double minutes = std::floor(length / 60.0), seconds = std::fmod(length, 60.0);
  158. LockControls();
  159. SetDlgItemInt(IDC_EDIT5, static_cast<int>(minutes));
  160. SetDlgItemInt(IDC_EDIT6, static_cast<int>(seconds));
  161. UnlockControls();
  162. }
  163. OPENMPT_NAMESPACE_END