127 lines
3.9 KiB
C++
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
|