winamp/Src/external_dependencies/openmpt-trunk/mptrack/PatternGotoDialog.cpp
2024-09-24 14:54:57 +02:00

204 lines
5.2 KiB
C++

/*
* PatternGotoDialog.cpp
* ---------------------
* Purpose: Implementation of pattern "go to" dialog.
* Notes : (currently none)
* Authors: OpenMPT Devs
* The OpenMPT source code is released under the BSD license. Read LICENSE for more details.
*/
#include "stdafx.h"
#include "Mptrack.h"
#include "PatternGotoDialog.h"
#include "Sndfile.h"
OPENMPT_NAMESPACE_BEGIN
// CPatternGotoDialog dialog
CPatternGotoDialog::CPatternGotoDialog(CWnd *pParent, ROWINDEX row, CHANNELINDEX chan, PATTERNINDEX pat, ORDERINDEX ord, CSoundFile &sndFile)
: CDialog(IDD_EDIT_GOTO, pParent)
, m_SndFile(sndFile)
, m_nRow(row)
, m_nChannel(chan)
, m_nPattern(pat)
, m_nOrder(ord)
, m_nActiveOrder(ord)
{ }
void CPatternGotoDialog::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_SPIN1, m_SpinRow);
DDX_Control(pDX, IDC_SPIN2, m_SpinChannel);
DDX_Control(pDX, IDC_SPIN3, m_SpinPattern);
DDX_Control(pDX, IDC_SPIN4, m_SpinOrder);
}
BEGIN_MESSAGE_MAP(CPatternGotoDialog, CDialog)
ON_EN_CHANGE(IDC_GOTO_PAT, &CPatternGotoDialog::OnPatternChanged)
ON_EN_CHANGE(IDC_GOTO_ORD, &CPatternGotoDialog::OnOrderChanged)
ON_EN_CHANGE(IDC_GOTO_ROW, &CPatternGotoDialog::OnRowChanged)
ON_EN_CHANGE(IDC_EDIT5, &CPatternGotoDialog::OnTimeChanged)
ON_EN_CHANGE(IDC_EDIT6, &CPatternGotoDialog::OnTimeChanged)
END_MESSAGE_MAP()
BOOL CPatternGotoDialog::OnInitDialog()
{
CDialog::OnInitDialog();
HICON icon = ::LoadIcon(AfxGetResourceHandle(), MAKEINTRESOURCE(IDR_MODULETYPE));
SetIcon(icon, FALSE);
SetIcon(icon, TRUE);
UpdateNumRows();
m_SpinChannel.SetRange32(1, m_SndFile.GetNumChannels());
m_SpinPattern.SetRange32(0, std::max(m_SndFile.Patterns.GetNumPatterns(), PATTERNINDEX(1)) - 1);
m_SpinOrder.SetRange32(0, std::max(m_SndFile.Order().GetLengthTailTrimmed(), ORDERINDEX(1)) - 1);
SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
SetDlgItemInt(IDC_GOTO_CHAN, m_nChannel);
SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
UpdateTime();
UnlockControls();
return TRUE;
}
void CPatternGotoDialog::OnOK()
{
const auto &Order = m_SndFile.Order();
m_nRow = mpt::saturate_cast<ROWINDEX>(GetDlgItemInt(IDC_GOTO_ROW));
m_nChannel = mpt::saturate_cast<CHANNELINDEX>(GetDlgItemInt(IDC_GOTO_CHAN));
// Valid order item?
if(m_nOrder >= Order.size())
{
MessageBeep(MB_ICONWARNING);
GetDlgItem(IDC_GOTO_ORD)->SetFocus();
return;
}
// Does order match pattern? Does pattern exist?
if(Order[m_nOrder] != m_nPattern || !Order.IsValidPat(m_nOrder))
{
MessageBeep(MB_ICONWARNING);
GetDlgItem(IDC_GOTO_PAT)->SetFocus();
return;
}
LimitMax(m_nRow, m_SndFile.Patterns[m_nPattern].GetNumRows() - ROWINDEX(1));
Limit(m_nChannel, CHANNELINDEX(1), m_SndFile.GetNumChannels());
CDialog::OnOK();
}
void CPatternGotoDialog::OnPatternChanged()
{
if(ControlsLocked())
return; // The change to textbox did not come from user.
m_nPattern = mpt::saturate_cast<PATTERNINDEX>(GetDlgItemInt(IDC_GOTO_PAT));
m_nOrder = m_SndFile.Order().FindOrder(m_nPattern, m_nActiveOrder);
if(m_nOrder == ORDERINDEX_INVALID)
{
m_nOrder = 0;
}
LockControls();
SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
UpdateNumRows();
UpdateTime();
UnlockControls();
}
void CPatternGotoDialog::OnOrderChanged()
{
if(ControlsLocked())
return; // The change to textbox did not come from user.
m_nOrder = mpt::saturate_cast<ORDERINDEX>(GetDlgItemInt(IDC_GOTO_ORD));
if(m_SndFile.Order().IsValidPat(m_nOrder))
{
m_nPattern = m_SndFile.Order()[m_nOrder];
}
LockControls();
SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
UpdateNumRows();
UpdateTime();
UnlockControls();
}
void CPatternGotoDialog::OnRowChanged()
{
if(ControlsLocked())
return; // The change to textbox did not come from user.
m_nRow = mpt::saturate_cast<ROWINDEX>(GetDlgItemInt(IDC_GOTO_ROW));
UpdateTime();
}
void CPatternGotoDialog::OnTimeChanged()
{
if(ControlsLocked())
return; // The change to textbox did not come from user.
BOOL success = TRUE;
auto minutes = GetDlgItemInt(IDC_EDIT5, &success);
if(!success)
return;
auto seconds = GetDlgItemInt(IDC_EDIT6, &success);
if(!success)
return;
auto result = m_SndFile.GetLength(eNoAdjust, GetLengthTarget(minutes * 60.0 + seconds)).back();
if(!result.targetReached)
return;
m_nOrder = result.lastOrder;
m_nRow = result.lastRow;
if(m_SndFile.Order().IsValidPat(m_nOrder))
m_nPattern = m_SndFile.Order()[m_nOrder];
LockControls();
SetDlgItemInt(IDC_GOTO_ORD, m_nOrder);
SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
SetDlgItemInt(IDC_GOTO_PAT, m_nPattern);
UnlockControls();
}
void CPatternGotoDialog::UpdateNumRows()
{
const ROWINDEX maxRow = (m_SndFile.Patterns.IsValidPat(m_nPattern) ? m_SndFile.Patterns[m_nPattern].GetNumRows() : MAX_PATTERN_ROWS) - 1;
m_SpinRow.SetRange32(0, maxRow);
if(m_nRow > maxRow)
{
m_nRow = maxRow;
SetDlgItemInt(IDC_GOTO_ROW, m_nRow);
}
}
void CPatternGotoDialog::UpdateTime()
{
const double length = m_SndFile.GetPlaybackTimeAt(m_nOrder, m_nRow, false, false);
if(length < 0.0)
return;
const double minutes = std::floor(length / 60.0), seconds = std::fmod(length, 60.0);
LockControls();
SetDlgItemInt(IDC_EDIT5, static_cast<int>(minutes));
SetDlgItemInt(IDC_EDIT6, static_cast<int>(seconds));
UnlockControls();
}
OPENMPT_NAMESPACE_END