dolphin/Source/Core/DolphinWX/DolphinSlider.cpp

127 lines
3.9 KiB
C++

// Copyright 2016 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#include <wx/utils.h>
#include "DolphinWX/DolphinSlider.h"
#ifdef __WXMSW__
#define WIN32_LEAN_AND_MEAN 1
// clang-format off
#include <Windows.h>
#include <CommCtrl.h>
// clang-format on
#endif
static constexpr int SLIDER_MIN_LENGTH = 100;
DolphinSlider::DolphinSlider() = default;
DolphinSlider::~DolphinSlider() = default;
bool DolphinSlider::Create(wxWindow* parent, wxWindowID id, int value, int min_val, int max_val,
const wxPoint& pos, const wxSize& size, long style,
const wxValidator& validator, const wxString& name)
{
// Sanitize the style flags.
// We don't want any label flags because those break DPI scaling on wxMSW,
// wxWidgets will internally lock the height of the slider to 32 pixels.
style &= ~wxSL_LABELS;
return wxSlider::Create(parent, id, value, min_val, max_val, pos, size, style, validator, name);
}
wxSize DolphinSlider::DoGetBestClientSize() const
{
#ifdef __WXMSW__
int ticks = 0;
int default_length = FromDIP(SLIDER_MIN_LENGTH);
if (HasFlag(wxSL_TICKS))
{
// NOTE: Ticks do not scale at all (on Win7)
default_length += 4;
ticks = 6;
}
int metric = 0;
{
// We need to determine the maximum thumb size because unfortunately the thumb size
// is controlled by the theme so may have a varying maximum size limit.
// NOTE: We can't use ourself because we're const so we can't change our size.
// NOTE: This is less inefficient then it seems, DoGetBestSize() is only called once
// per instance and cached until InvalidateBestSize() is called.
wxSlider* helper = new wxSlider(GetParent(), wxID_ANY, GetValue(), GetMin(), GetMax(),
wxDefaultPosition, FromDIP(wxSize(100, 100)), GetWindowStyle());
::RECT r{};
::SendMessageW(reinterpret_cast<HWND>(helper->GetHWND()), TBM_GETTHUMBRECT, 0,
reinterpret_cast<LPARAM>(&r));
helper->Destroy();
// Breakdown metrics
int computed_size;
int scroll_size;
if (HasFlag(wxSL_VERTICAL))
{
// Trackbar thumb does not directly touch the edge, we add the padding
// a second time to pad the other edge to make it symmetric.
computed_size = static_cast<int>(r.right + r.left);
scroll_size = ::GetSystemMetrics(SM_CXVSCROLL);
}
else
{
computed_size = static_cast<int>(r.bottom + r.top);
scroll_size = ::GetSystemMetrics(SM_CYHSCROLL);
}
// This is based on how Microsoft calculates trackbar sizes in the .Net Framework
// when using automatic sizing in WinForms.
int max = scroll_size * 2;
metric = wxClip(computed_size, scroll_size, max);
}
if (HasFlag(wxSL_VERTICAL))
return wxSize(metric + ticks, default_length);
return wxSize(default_length, metric + ticks);
#else
wxSize base_size = wxSlider::DoGetBestClientSize();
// If the base class is not using DoGetBestClientSize(), fallback to DoGetBestSize()
if (base_size == wxDefaultSize)
return wxDefaultSize;
return CorrectMinSize(base_size);
#endif
}
wxSize DolphinSlider::DoGetBestSize() const
{
return CorrectMinSize(wxSlider::DoGetBestSize());
}
wxSize DolphinSlider::CorrectMinSize(wxSize size) const
{
wxSize default_length = FromDIP(wxSize(SLIDER_MIN_LENGTH, SLIDER_MIN_LENGTH));
// GTK Styles sometimes don't return a default length.
// NOTE: Vertical is the dominant flag if both are set.
if (HasFlag(wxSL_VERTICAL))
{
if (size.GetHeight() < default_length.GetHeight())
{
size.SetHeight(default_length.GetHeight());
}
}
else if (size.GetWidth() < default_length.GetWidth())
{
size.SetWidth(default_length.GetWidth());
}
return size;
}
#ifdef __WXMSW__
WXLRESULT DolphinSlider::MSWWindowProc(WXUINT msg, WXWPARAM wp, WXLPARAM lp)
{
if (msg == WM_THEMECHANGED)
InvalidateBestSize();
return wxSlider::MSWWindowProc(msg, wp, lp);
}
#endif