mono/packages/media/cpp/src/win/ui_next/SettingsPanel.cpp

265 lines
9.1 KiB
C++

#include "stdafx.h"
#include "SettingsPanel.h"
#include "Resource.h"
#include <shlobj.h>
static std::string wide_to_utf8(const std::wstring& w) {
if (w.empty()) return {};
int n = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), nullptr, 0, nullptr, nullptr);
if (n <= 0) return {};
std::string s(n, '\0');
WideCharToMultiByte(CP_UTF8, 0, w.c_str(), (int)w.size(), s.data(), n, nullptr, nullptr);
return s;
}
static std::wstring utf8_to_wide(const std::string& s) {
if (s.empty()) return {};
int n = MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), nullptr, 0);
if (n <= 0) return {};
std::wstring w(n, L'\0');
MultiByteToWideChar(CP_UTF8, 0, s.c_str(), (int)s.size(), w.data(), n);
return w;
}
static std::wstring get_edit_text(HWND h) {
int n = ::GetWindowTextLengthW(h);
if (n <= 0) return {};
std::wstring w(n + 1, L'\0');
::GetWindowTextW(h, w.data(), n + 1);
w.resize(n);
return w;
}
//////////////////////////////////////////
// CSettingsView
//////////////////////////////////////////
static BOOL CALLBACK SetChildFont(HWND hwnd, LPARAM lparam)
{
::SendMessageW(hwnd, WM_SETFONT, (WPARAM)lparam, TRUE);
return TRUE;
}
int CSettingsView::OnCreate(CREATESTRUCT&)
{
CreateControls();
HFONT hFont = static_cast<HFONT>(::GetStockObject(DEFAULT_GUI_FONT));
EnumChildWindows(GetHwnd(), SetChildFont, (LPARAM)hFont);
return 0;
}
void CSettingsView::CreateControls()
{
const int x0 = 8, lw = 100, gap = 6;
const int ew = 140, eh = 22;
int y = 10;
HINSTANCE inst = GetModuleHandleW(nullptr);
auto label = [&](LPCWSTR text, int yoff = 0) {
CreateWindowExW(0, L"STATIC", text, WS_CHILD | WS_VISIBLE,
x0, y + yoff, lw, 18, GetHwnd(), nullptr, inst, nullptr);
};
// Output preset
label(L"Output preset:");
m_hPreset = CreateWindowExW(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
x0 + lw + gap, y - 2, ew + 40, 140, GetHwnd(), (HMENU)(UINT_PTR)IDC_COMBO_PRESET_OUT, inst, nullptr);
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Next to source");
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Next to source (_resized)");
::SendMessageW(m_hPreset, CB_ADDSTRING, 0, (LPARAM)L"Custom folder");
::SendMessageW(m_hPreset, CB_SETCURSEL, 0, 0);
y += 30;
// Output directory
label(L"Output folder:");
m_hOutDir = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL,
x0 + lw + gap, y, ew, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_OUT_DIR, inst, nullptr);
m_hBtnBrowse = CreateWindowExW(0, L"BUTTON", L"...",
WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON,
x0 + lw + gap + ew + 4, y, 28, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_BTN_BROWSE_OUT, inst, nullptr);
y += 30;
// Max width / height
label(L"Max width:");
m_hMaxW = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"0",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
x0 + lw + gap, y, 60, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_MAX_W, inst, nullptr);
CreateWindowExW(0, L"STATIC", L"Max height:", WS_CHILD | WS_VISIBLE,
x0 + lw + gap + 68, y, 80, 18, GetHwnd(), nullptr, inst, nullptr);
m_hMaxH = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"0",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
x0 + lw + gap + 68 + 84, y, 60, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_MAX_H, inst, nullptr);
y += 30;
// Fit
label(L"Fit:");
m_hFit = CreateWindowExW(WS_EX_CLIENTEDGE, L"COMBOBOX", L"",
WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | CBS_HASSTRINGS,
x0 + lw + gap, y - 2, ew, 140, GetHwnd(), (HMENU)(UINT_PTR)IDC_COMBO_FIT, inst, nullptr);
const LPCWSTR fits[] = { L"inside", L"cover", L"contain", L"fill", L"outside" };
for (auto f : fits) ::SendMessageW(m_hFit, CB_ADDSTRING, 0, (LPARAM)f);
::SendMessageW(m_hFit, CB_SETCURSEL, 0, 0);
y += 30;
// Quality
label(L"Quality (1-100):");
m_hQuality = CreateWindowExW(WS_EX_CLIENTEDGE, L"EDIT", L"85",
WS_CHILD | WS_VISIBLE | ES_AUTOHSCROLL | ES_NUMBER,
x0 + lw + gap, y, 48, eh, GetHwnd(), (HMENU)(UINT_PTR)IDC_EDIT_QUALITY, inst, nullptr);
y += 30;
// Checkboxes
m_hEnlarge = CreateWindowExW(0, L"BUTTON", L"Allow enlargement",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
x0, y, 180, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_ENLARGE, inst, nullptr);
y += 24;
m_hAutorot = CreateWindowExW(0, L"BUTTON", L"EXIF autorotate",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
x0, y, 180, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_AUTOROT, inst, nullptr);
::SendMessageW(m_hAutorot, BM_SETCHECK, BST_CHECKED, 0);
y += 24;
m_hStrip = CreateWindowExW(0, L"BUTTON", L"Strip metadata on save",
WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
x0, y, 200, 22, GetHwnd(), (HMENU)(UINT_PTR)IDC_CHK_STRIP, inst, nullptr);
::SendMessageW(m_hStrip, BM_SETCHECK, BST_CHECKED, 0);
}
void CSettingsView::ReadOptions(media::ResizeOptions& opt, std::string& out_dir) const
{
int preset = (int)::SendMessageW(m_hPreset, CB_GETCURSEL, 0, 0);
opt.output_stem_suffix.clear();
if (preset == 1) opt.output_stem_suffix = "_resized";
out_dir.clear();
if (preset == 2 || !get_edit_text(m_hOutDir).empty())
out_dir = wide_to_utf8(get_edit_text(m_hOutDir));
wchar_t buf[32]{};
::GetWindowTextW(m_hMaxW, buf, 32);
opt.max_width = _wtoi(buf);
if (opt.max_width < 0) opt.max_width = 0;
::GetWindowTextW(m_hMaxH, buf, 32);
opt.max_height = _wtoi(buf);
if (opt.max_height < 0) opt.max_height = 0;
int fi = (int)::SendMessageW(m_hFit, CB_GETCURSEL, 0, 0);
const char* fits[] = { "inside", "cover", "contain", "fill", "outside" };
if (fi >= 0 && fi < 5) opt.fit = fits[fi];
::GetWindowTextW(m_hQuality, buf, 32);
opt.quality = _wtoi(buf);
if (opt.quality < 1) opt.quality = 1;
if (opt.quality > 100) opt.quality = 100;
opt.without_enlargement = ::SendMessageW(m_hEnlarge, BM_GETCHECK, 0, 0) != BST_CHECKED;
opt.autorotate = ::SendMessageW(m_hAutorot, BM_GETCHECK, 0, 0) == BST_CHECKED;
opt.strip_metadata = ::SendMessageW(m_hStrip, BM_GETCHECK, 0, 0) == BST_CHECKED;
}
void CSettingsView::WriteOptions(const media::ResizeOptions& opt, const std::string& out_dir)
{
int preset = 0;
if (!out_dir.empty()) preset = 2;
else if (opt.output_stem_suffix == "_resized") preset = 1;
::SendMessageW(m_hPreset, CB_SETCURSEL, preset, 0);
::SetWindowTextW(m_hOutDir, utf8_to_wide(out_dir).c_str());
wchar_t buf[32]{};
swprintf_s(buf, L"%d", opt.max_width);
::SetWindowTextW(m_hMaxW, buf);
swprintf_s(buf, L"%d", opt.max_height);
::SetWindowTextW(m_hMaxH, buf);
swprintf_s(buf, L"%d", opt.quality);
::SetWindowTextW(m_hQuality, buf);
::SendMessageW(m_hEnlarge, BM_SETCHECK, opt.without_enlargement ? BST_UNCHECKED : BST_CHECKED, 0);
::SendMessageW(m_hAutorot, BM_SETCHECK, opt.autorotate ? BST_CHECKED : BST_UNCHECKED, 0);
::SendMessageW(m_hStrip, BM_SETCHECK, opt.strip_metadata ? BST_CHECKED : BST_UNCHECKED, 0);
}
void CSettingsView::OnBrowseOutput()
{
BROWSEINFOW bi{};
bi.hwndOwner = GetHwnd();
bi.lpszTitle = L"Choose output folder";
bi.ulFlags = BIF_RETURNONLYFSDIRS | BIF_NEWDIALOGSTYLE;
wchar_t dn[MAX_PATH]{};
bi.pszDisplayName = dn;
PIDLIST_ABSOLUTE pidl = SHBrowseForFolderW(&bi);
if (!pidl) return;
wchar_t path[MAX_PATH * 4]{};
if (SHGetPathFromIDListW(pidl, path))
::SetWindowTextW(m_hOutDir, path);
CoTaskMemFree(pidl);
}
LRESULT CSettingsView::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
try {
if (msg == WM_COMMAND) {
if (LOWORD(wparam) == IDC_BTN_BROWSE_OUT) {
OnBrowseOutput();
return 0;
}
}
return WndProcDefault(msg, wparam, lparam);
}
catch (const CException& e) {
CString s;
s << e.GetText() << L'\n' << e.GetErrorString();
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
}
return 0;
}
//////////////////////////////////////////
// CSettingsContainer
//////////////////////////////////////////
CSettingsContainer::CSettingsContainer()
{
SetTabText(L"Settings");
SetDockCaption(L"Resize Settings");
SetView(m_view);
}
LRESULT CSettingsContainer::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
try { return WndProcDefault(msg, wparam, lparam); }
catch (const CException& e) {
CString s;
s << e.GetText() << L'\n' << e.GetErrorString();
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
}
return 0;
}
//////////////////////////////////////////
// CDockSettings
//////////////////////////////////////////
CDockSettings::CDockSettings()
{
SetView(m_container);
SetBarWidth(8);
}
LRESULT CDockSettings::WndProc(UINT msg, WPARAM wparam, LPARAM lparam)
{
try { return WndProcDefault(msg, wparam, lparam); }
catch (const CException& e) {
CString s;
s << e.GetText() << L'\n' << e.GetErrorString();
::MessageBox(nullptr, s, L"Error", MB_ICONERROR);
}
return 0;
}