#include "osslider_win.inl"
#include "osgui_win.inl"
#include "oscontrol_win.inl"
#include "ospanel_win.inl"
#include "oswindow_win.inl"
#include "../osslider.h"
#include <core/event.h>
#include <core/heap.h>
#include <sewer/cassert.h>
#include <sewer/ptr.h>
#if !defined(__WINDOWS__)
#error This file is only for Windows
#endif
#include <sewer/nowarn.hxx>
#include <Commctrl.h>
#include <sewer/warn.hxx>
struct _osslider_t
{
OSControl control;
uint32_t flags;
Listener *OnMoved;
};
#define i_SLIDER_MAX 2048
static LRESULT CALLBACK i_WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
OSSlider *slider = cast(GetWindowLongPtr(hwnd, GWLP_USERDATA), OSSlider);
cassert_no_null(slider);
switch (uMsg)
{
case WM_ERASEBKGND:
return 1;
case WM_LBUTTONDOWN:
case WM_LBUTTONDBLCLK:
if (_oswindow_mouse_down(cast(slider, OSControl)) == TRUE)
break;
return 0;
}
return CallWindowProc(slider->control.def_wnd_proc, hwnd, uMsg, wParam, lParam);
}
static DWORD i_slider_style(const uint32_t flags)
{
DWORD dwStyle = WS_CHILD | WS_CLIPSIBLINGS | TBS_NOTICKS;
#if _MSC_VER > 1400
dwStyle |= TBS_TRANSPARENTBKGND;
#endif
if (slider_get_type(flags) == ekSLIDER_HORZ)
dwStyle |= TBS_HORZ;
else
dwStyle |= TBS_VERT;
return dwStyle;
}
OSSlider *osslider_create(const uint32_t flags)
{
OSSlider *slider = NULL;
DWORD dwStyle = 0;
slider = heap_new(OSSlider);
slider->control.type = ekGUI_TYPE_SLIDER;
slider->flags = flags;
slider->OnMoved = NULL;
dwStyle = i_slider_style(flags);
_oscontrol_init(cast(slider, OSControl), PARAM(dwExStyle, WS_EX_NOPARENTNOTIFY), dwStyle, TRACKBAR_CLASS, 0, 0, i_WndProc, kDEFAULT_PARENT_WINDOW);
SendMessage(slider->control.hwnd, TBM_SETRANGE, (WPARAM)TRUE, (LPARAM)MAKELONG(0, i_SLIDER_MAX));
SendMessage(slider->control.hwnd, TBM_SETPAGESIZE, (WPARAM)0, (LPARAM)(i_SLIDER_MAX / 10));
SendMessage(slider->control.hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)0);
return slider;
}
void osslider_destroy(OSSlider **slider)
{
cassert_no_null(slider);
cassert_no_null(*slider);
listener_destroy(&(*slider)->OnMoved);
_oscontrol_destroy(&(*slider)->control);
heap_delete(slider, OSSlider);
}
void osslider_OnMoved(OSSlider *slider, Listener *listener)
{
cassert_no_null(slider);
listener_update(&slider->OnMoved, listener);
}
void osslider_tooltip(OSSlider *slider, const char_t *text)
{
_oscontrol_set_tooltip(cast(slider, OSControl), text);
}
void osslider_tickmarks(OSSlider *slider, const uint32_t num_tickmarks, const bool_t tickmarks_at_left_top)
{
LPARAM psize = (LPARAM)(i_SLIDER_MAX / 10);
cassert_no_null(slider);
cassert(num_tickmarks > 1);
if (num_tickmarks != UINT32_MAX)
psize = (LPARAM)(i_SLIDER_MAX / (num_tickmarks - 1));
SendMessage(slider->control.hwnd, TBM_SETPAGESIZE, (WPARAM)0, psize);
unref(tickmarks_at_left_top);
}
static real32_t i_get_pos(HWND hwnd)
{
LRESULT pos = SendMessage(hwnd, TBM_GETPOS, (WPARAM)0, (LPARAM)0);
cassert(pos >= 0 && pos <= i_SLIDER_MAX);
return (real32_t)pos / (real32_t)i_SLIDER_MAX;
}
void osslider_position(OSSlider *slider, const real32_t position)
{
int pos = (int)(position * i_SLIDER_MAX);
cassert_no_null(slider);
cassert(position >= 0.f && position <= 1.f);
SendMessage(slider->control.hwnd, TBM_SETPOS, (WPARAM)TRUE, (LPARAM)pos);
}
real32_t osslider_get_position(const OSSlider *slider)
{
cassert_no_null(slider);
return i_get_pos(slider->control.hwnd);
}
static real32_t i_thickness(const gui_size_t knob_size)
{
switch (knob_size)
{
case ekGUI_SIZE_MINI:
return 15.f;
case ekGUI_SIZE_SMALL:
return 20.f;
case ekGUI_SIZE_REGULAR:
return 20.f;
cassert_default();
}
return 0.f;
}
void osslider_bounds(const OSSlider *slider, const real32_t length, const gui_size_t knob_size, real32_t *width, real32_t *height)
{
cassert_no_null(slider);
cassert_no_null(width);
cassert_no_null(height);
if (slider_get_type(slider->flags) == ekSLIDER_HORZ)
{
*width = length;
*height = i_thickness(knob_size);
}
else
{
*width = i_thickness(knob_size);
*height = length;
}
}
void osslider_attach(OSSlider *slider, OSPanel *panel)
{
_ospanel_attach_control(panel, cast(slider, OSControl));
}
void osslider_detach(OSSlider *slider, OSPanel *panel)
{
_ospanel_detach_control(panel, cast(slider, OSControl));
}
void osslider_visible(OSSlider *slider, const bool_t visible)
{
_oscontrol_set_visible(cast(slider, OSControl), visible);
}
void osslider_enabled(OSSlider *slider, const bool_t enabled)
{
_oscontrol_set_enabled(cast(slider, OSControl), enabled);
}
void osslider_size(const OSSlider *slider, real32_t *width, real32_t *height)
{
_oscontrol_get_size(cast_const(slider, OSControl), width, height);
}
void osslider_origin(const OSSlider *slider, real32_t *x, real32_t *y)
{
_oscontrol_get_origin(cast_const(slider, OSControl), x, y);
}
void osslider_frame(OSSlider *slider, const real32_t x, const real32_t y, const real32_t width, const real32_t height)
{
cassert_no_null(slider);
_oscontrol_set_frame(cast(slider, OSControl), x, y, width, height);
InvalidateRect(slider->control.hwnd, NULL, FALSE);
}
void _osslider_message(OSSlider *slider, WPARAM wParam)
{
cassert_no_null(slider);
if (LOWORD(wParam) != SB_ENDSCROLL)
{
if (IsWindowEnabled(slider->control.hwnd) && slider->OnMoved != NULL)
{
EvSlider params;
params.pos = i_get_pos(slider->control.hwnd);
params.incr = 0;
params.step = UINT32_MAX;
listener_event(slider->OnMoved, ekGUI_EVENT_SLIDER, slider, ¶ms, NULL, OSSlider, EvSlider, void);
}
}
}