Skip to content

Commit

Permalink
[Imp] Quick Start: Allow multi selection in file list.
Browse files Browse the repository at this point in the history
git-svn-id: https://source.openmpt.org/svn/openmpt/trunk/OpenMPT@22302 56274372-70c3-4bfc-bfc3-4c3a0b034d27
  • Loading branch information
sagamusix committed Nov 25, 2024
1 parent 71c6e06 commit 3af691e
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 70 deletions.
134 changes: 79 additions & 55 deletions mptrack/QuickStartDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ BEGIN_MESSAGE_MAP(QuickStartDlg, ResizableDialog)

ON_NOTIFY(NM_DBLCLK, IDC_LIST1, &QuickStartDlg::OnOpenFile)
ON_NOTIFY(NM_RCLICK, IDC_LIST1, &QuickStartDlg::OnRightClickFile)
ON_NOTIFY(LVN_ITEMCHANGED, IDC_LIST1, &QuickStartDlg::OnItemChanged)
END_MESSAGE_MAP()


Expand All @@ -41,7 +42,6 @@ void QuickStartDlg::DoDataExchange(CDataExchange *pDX)
ResizableDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BUTTON1, m_newButton);
DDX_Control(pDX, IDC_BUTTON2, m_openButton);
DDX_Control(pDX, IDCANCEL, m_closeButton);
DDX_Control(pDX, IDC_LIST1, m_list);
DDX_Control(pDX, IDC_EDIT1, m_find);
}
Expand All @@ -51,7 +51,6 @@ QuickStartDlg::QuickStartDlg(const std::vector<mpt::PathString> &templates, cons
{
m_newButton.SetAccessibleText(_T("New Module"));
m_openButton.SetAccessibleText(_T("Open Module"));
m_closeButton.SetAccessibleText(_T("Close"));
Create(IDD_QUICKSTART, parent);

m_groupsEnabled = m_list.EnableGroupView();
Expand Down Expand Up @@ -98,11 +97,11 @@ QuickStartDlg::QuickStartDlg(const std::vector<mpt::PathString> &templates, cons
m_paths[groupId] = PathGroups[groupId].first;
}
UpdateFileList();
m_list.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
m_list.SetColumnWidth(0, LVSCW_AUTOSIZE);
m_list.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);
m_list.SetRedraw(TRUE);
m_list.Invalidate(FALSE);
OnItemChanged(nullptr, nullptr);
UpdateHeight();
}

Expand Down Expand Up @@ -133,10 +132,6 @@ void QuickStartDlg::OnDPIChanged()
m_list.SetColumnWidth(0, LVSCW_AUTOSIZE);
m_list.SetColumnWidth(1, LVSCW_AUTOSIZE_USEHEADER);

m_buttonFont.DeleteObject();
m_buttonFont.CreateFont(mpt::saturate_round<int>(14 * scaling), 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, FF_DONTCARE, _T("Marlett"));
m_closeButton.SetFont(&m_buttonFont);

m_bmpNew.DeleteObject();
m_bmpOpen.DeleteObject();

Expand All @@ -158,30 +153,20 @@ void QuickStartDlg::OnDPIChanged()
}


INT_PTR QuickStartDlg::OnToolHitTest(CPoint point, TOOLINFO *pTI) const
{
auto result = ResizableDialog::OnToolHitTest(point, pTI);
if(result == IDCANCEL)
{
// MFC will free() the text
mpt::tstring text = _T("Close");
TCHAR *textP = static_cast<TCHAR *>(calloc(text.size() + 1, sizeof(TCHAR)));
std::copy(text.begin(), text.end(), textP);
pTI->lpszText = textP;
}
return result;
}


BOOL QuickStartDlg::PreTranslateMessage(MSG *pMsg)
{
// Use up/down keys to navigate in list, even if search field is focussed. This also skips the group headers during navigation
if(pMsg->message == WM_KEYDOWN && (pMsg->wParam == VK_UP || pMsg->wParam == VK_DOWN) && GetFocus() == &m_find)
{
m_list.ModifyStyle(0, LVS_SHOWSELALWAYS);
int selItem = std::clamp(m_list.GetSelectionMark() + (pMsg->wParam == VK_UP ? -1 : 1), 0, m_list.GetItemCount() - 1);
m_list.SetItemState(selItem, LVIS_SELECTED, LVIS_SELECTED);
m_list.SetSelectionMark(selItem);
const int curSel = m_list.GetSelectionMark();
const int selItem = std::clamp(curSel + (pMsg->wParam == VK_UP ? -1 : 1), 0, m_list.GetItemCount() - 1);
if(curSel != selItem)
{
if(curSel != -1)
m_list.SetItemState(curSel, 0, LVIS_SELECTED);
m_list.SetItemState(selItem, LVIS_SELECTED, LVIS_SELECTED);
m_list.SetSelectionMark(selItem);
}
return TRUE;
}

Expand All @@ -203,7 +188,7 @@ void QuickStartDlg::UpdateHeight()
viewRect.bottom += itemRect.Height() * 2; // View height calculation seems to be a bit off and would still cause a vertical scrollbar to appear without this adjustment
if(viewRect.bottom > listRect.bottom)
windowRect.bottom += viewRect.bottom - listRect.bottom;
const int maxHeight = Util::muldiv(parentRect.bottom, 9, 10);
const int maxHeight = std::max(HighDPISupport::ScalePixels(154, m_hWnd), Util::muldiv(parentRect.bottom, 9, 10));
LimitMax(windowRect.bottom, maxHeight);
HighDPISupport::AdjustWindowRectEx(windowRect, GetStyle(), FALSE, GetExStyle(), GetDPI());
SetWindowPos(nullptr, 0, 0, windowRect.Width(), windowRect.Height(), SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE);
Expand Down Expand Up @@ -232,22 +217,23 @@ void QuickStartDlg::OnOpen()

void QuickStartDlg::OnOK()
{
if(const CWnd *focus = GetFocus(); focus == &m_list || focus == &m_find)
OnOpenFile(nullptr, nullptr);
OnOpenFile(nullptr, nullptr);
}


void QuickStartDlg::OnRemoveMRUItem()
{
const int index = m_list.GetSelectionMark();
if(index < 0)
return;
auto &mruFiles= TrackerSettings::Instance().mruFiles;
if(static_cast<size_t>(index) >= mruFiles.size())
return;
mruFiles.erase(mruFiles.begin() + index);
m_paths[GetItemGroup(index)][GetItemIndex(index)] = {};
m_list.DeleteItem(index);
auto &mruFiles = TrackerSettings::Instance().mruFiles;
int i = -1;
while((i = m_list.GetNextItem(i, LVNI_SELECTED | LVNI_ALL)) != -1)
{
if(GetItemGroup(i) != 0)
continue;
mruFiles.erase(mruFiles.begin() + i);
m_paths[0][GetItemIndex(i)] = {};
m_list.DeleteItem(i);
i--;
}
CMainFrame::GetMainFrame()->UpdateMRUList();
}

Expand All @@ -268,15 +254,18 @@ void QuickStartDlg::OnRemoveAllMRUItems()
void QuickStartDlg::OnUpdateFilter()
{
m_list.SetRedraw(FALSE);
LPARAM highlight = LPARAM(-1);
if(int sel = m_list.GetSelectionMark(); sel != -1)
highlight = m_list.GetItemData(sel);
m_list.DeleteAllItems();
CString filter;
m_find.GetWindowText(filter);
UpdateFileList(filter);
UpdateFileList(highlight, filter);
m_list.SetRedraw(TRUE);
}


void QuickStartDlg::UpdateFileList(CString filter)
void QuickStartDlg::UpdateFileList(LPARAM highlight, CString filter)
{
const bool applyFilter = !filter.IsEmpty();
if(applyFilter)
Expand All @@ -293,6 +282,7 @@ void QuickStartDlg::UpdateFileList(CString filter)
lvi.iImage = TIMAGE_MODULE_FILE;
lvi.iIndent = 0;

bool highlightFound = false;
int itemId = -1;
for(size_t groupId = 0; groupId < m_paths.size(); groupId++)
{
Expand All @@ -307,29 +297,57 @@ void QuickStartDlg::UpdateFileList(CString filter)
lvi.pszText = const_cast<TCHAR *>(filename.c_str());
m_list.InsertItem(&lvi);
m_list.SetItemText(itemId, 1, m_paths[groupId][i].GetDirectoryWithDrive().AsNative().c_str());
if(lvi.lParam == highlight)
{
m_list.SetItemState(itemId, LVIS_SELECTED, LVIS_SELECTED);
m_list.SetSelectionMark(itemId);
highlightFound = true;
}
}
}
if(!highlightFound)
{
m_list.SetItemState(0, LVIS_SELECTED, LVIS_SELECTED);
m_list.SetSelectionMark(0);
}
}


void QuickStartDlg::OnOpenFile(NMHDR *, LRESULT *)
{
const int i = m_list.GetSelectionMark();
if(i < 0)
return;
const size_t index = GetItemIndex(i);
const int group = GetItemGroup(i);
const auto &path = m_paths[group][index];
CDocument *doc = nullptr;
if(group != 1)
doc = theApp.OpenDocumentFile(path.ToCString());
else
doc = theApp.OpenTemplateFile(path);

if(!doc)
struct OpenItem
{
m_list.DeleteItem(i);
m_paths[group][i] = {};
const mpt::PathString path; // Must create copy because dialog will get destroyed after successfully loading the first file
const int item;
const int group;
const size_t index;
};
std::vector<OpenItem> files;
int i = -1;
while((i = m_list.GetNextItem(i, LVNI_SELECTED | LVNI_ALL)) != -1)
{
const int group = GetItemGroup(i);
const size_t index = GetItemIndex(i);
const auto &path = m_paths[group][index];
files.push_back({path, i, group, index});
}
bool success = false;
for(const auto &item : files)
{
if(item.group != 1)
success |= (theApp.OpenDocumentFile(item.path.ToCString()) != nullptr);
else
success |= (theApp.OpenTemplateFile(item.path) != nullptr);
}

if(!success)
{
// If at least one item managed to load, the dialog will now be destroyed, and there are no items to delete from the list
for(auto it = files.rbegin(); it != files.rend(); it++)
{
m_paths[it->group][it->index] = {};
m_list.DeleteItem(it->item);
}
}
}

Expand All @@ -352,4 +370,10 @@ void QuickStartDlg::OnRightClickFile(NMHDR *nmhdr, LRESULT *)
menu.DestroyMenu();
}


void QuickStartDlg::OnItemChanged(NMHDR *, LRESULT *)
{
GetDlgItem(IDOK)->EnableWindow(m_list.GetSelectedCount() != 0 ? TRUE : FALSE);
}

OPENMPT_NAMESPACE_END
7 changes: 3 additions & 4 deletions mptrack/QuickStartDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,11 @@ class QuickStartDlg : public ResizableDialog
void DoDataExchange(CDataExchange *pDX) override;
BOOL OnInitDialog() override;
void OnDPIChanged() override;
INT_PTR OnToolHitTest(CPoint point, TOOLINFO* pTI) const override;
BOOL PreTranslateMessage(MSG *pMsg) override;
void OnOK() override;
void OnCancel() override { DestroyWindow(); }

void UpdateFileList(CString filter = {});
void UpdateFileList(LPARAM highlight = LPARAM(-1), CString filter = {});
size_t GetItemIndex(int index) const { return static_cast<size_t>(m_list.GetItemData(index) & 0x00FF'FFFF); }
int GetItemGroup(int index) const { return static_cast<int>(m_list.GetItemData(index) >> 24); }

Expand All @@ -47,13 +46,13 @@ class QuickStartDlg : public ResizableDialog
afx_msg void OnUpdateFilter();
afx_msg void OnOpenFile(NMHDR *, LRESULT *);
afx_msg void OnRightClickFile(NMHDR *, LRESULT *);
afx_msg void OnItemChanged(NMHDR *, LRESULT *);

DECLARE_MESSAGE_MAP()

CListCtrlEx m_list;
CEdit m_find;
AccessibleButton m_newButton, m_openButton, m_closeButton;
CFont m_buttonFont;
AccessibleButton m_newButton, m_openButton;
CBitmap m_bmpNew, m_bmpOpen;
std::array<std::vector<mpt::PathString>, 3> m_paths;
CSize m_prevSize;
Expand Down
24 changes: 13 additions & 11 deletions mptrack/mptrack.rc
Original file line number Diff line number Diff line change
Expand Up @@ -2304,17 +2304,18 @@ BEGIN
LTEXT "Warning: Only samples are affected by these settings! Modifying them will change the balance between samples and plugins in songs with mix levels set to 1.17RC2 or earlier in the Song Properties! ",IDC_STATIC,12,222,252,30
END

IDD_QUICKSTART DIALOGEX 0, 0, 332, 185
IDD_QUICKSTART DIALOGEX 0, 0, 332, 211
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_CHILD | WS_CLIPSIBLINGS
EXSTYLE WS_EX_CONTROLPARENT | WS_EX_NOACTIVATE
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
PUSHBUTTON " &New Module",IDC_BUTTON1,6,6,90,30
PUSHBUTTON " &Open Module",IDC_BUTTON2,108,6,90,30
LTEXT "F&ind:",IDC_STATIC,6,45,30,8
EDITTEXT IDC_EDIT1,36,42,285,14,ES_AUTOHSCROLL
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SINGLESEL | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,6,60,315,114
PUSHBUTTON "r",IDCANCEL,308,6,13,12,BS_VCENTER
PUSHBUTTON " &New Module",IDC_BUTTON1,10,9,90,30
PUSHBUTTON " &Open Module",IDC_BUTTON2,108,9,90,30
LTEXT "F&ind:",IDC_STATIC,10,48,30,8
EDITTEXT IDC_EDIT1,36,45,285,14,ES_AUTOHSCROLL
CONTROL "",IDC_LIST1,"SysListView32",LVS_REPORT | LVS_SHOWSELALWAYS | LVS_ALIGNLEFT | WS_BORDER | WS_TABSTOP,10,65,311,109
PUSHBUTTON "&Close",IDCANCEL,261,184,60,18,BS_VCENTER
DEFPUSHBUTTON "Open &Selected",IDOK,195,184,60,18
END


Expand Down Expand Up @@ -2583,10 +2584,10 @@ BEGIN

IDD_QUICKSTART, DIALOG
BEGIN
LEFTMARGIN, 6
LEFTMARGIN, 10
RIGHTMARGIN, 321
TOPMARGIN, 6
BOTTOMMARGIN, 174
TOPMARGIN, 9
BOTTOMMARGIN, 202
END
END
#endif // APSTUDIO_INVOKED
Expand Down Expand Up @@ -2752,7 +2753,8 @@ BEGIN
0, 0, 0, 0,
0, 0, 100, 0,
0, 0, 100, 100,
100, 0, 0, 0
100, 100, 0, 0,
100, 100, 0, 0
END


Expand Down

0 comments on commit 3af691e

Please sign in to comment.