add oversampler

This commit is contained in:
2024-05-24 13:28:31 +02:00
parent e4a4a661a0
commit 989dba5a6b
484 changed files with 313937 additions and 0 deletions

View File

@@ -0,0 +1,216 @@
/*
WDL - dlgitemborder.h
Copyright (C) 1998-2003, Nullsoft Inc.
Copyright (C) 2005 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides code to aide in drawing additional borders in dialogs.
*/
#ifndef _WDL_DLGITEMBORDER_H_
#define _WDL_DLGITEMBORDER_H_
#define DCW_SUNKENBORDER 0x00010000
#define DCW_SUNKENBORDER_NOTOP 0x00020000
#define DCW_DIVIDER_VERT 0x00030000
#define DCW_DIVIDER_HORZ 0x00040000
#define DCW_HWND_FOLLOW 0x40000000
#ifndef WDL_DLGITEMBORDER_MAXCLIPCHILDREN
#define WDL_DLGITEMBORDER_MAXCLIPCHILDREN 200
#endif
#ifndef WDL_DLGITEMBORDER_NOIMPL
#ifdef _WIN32
static void Dlg_removeFromRgn(HRGN hrgn, int left, int top, int right, int bottom)
{
if (hrgn)
{
RECT r = { left, top, right, bottom };
if (RectInRegion(hrgn,&r))
{
HRGN rgn2=CreateRectRgnIndirect(&r);
CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF);
DeleteObject(rgn2);
}
}
}
#else
#define Dlg_removeFromRgn(a,b,c,d,e) do{ } while(0)
#endif
static void WDL_STATICFUNC_UNUSED Dlg_DrawChildWindowBorders(HWND hwndDlg, INT_PTR *tab, int tabsize, int (*GSC)(int)=0, PAINTSTRUCT *__use_ps=NULL
#ifdef WDL_DLGITEMBORDER_CUSTOMPARMS
, WDL_DLGITEMBORDER_CUSTOMPARMS
#endif
)
{
PAINTSTRUCT ps;
if (!__use_ps)
{
BeginPaint(hwndDlg,&ps);
__use_ps=&ps;
}
RECT r;
#ifdef _WIN32
HRGN hrgn=CreateRectRgnIndirect(&__use_ps->rcPaint);
int n = WDL_DLGITEMBORDER_MAXCLIPCHILDREN;
HWND h = GetWindow(hwndDlg,GW_CHILD);
while (h && --n >= 0)
{
if (IsWindowVisible(h))
{
GetWindowRect(h,&r);
ScreenToClient(hwndDlg,(LPPOINT)&r);
ScreenToClient(hwndDlg,((LPPOINT)&r) + 1);
if (RectInRegion(hrgn,&r))
#ifdef DLG_ITEM_BORDER_WANT_EXCLUDE
if (!DLG_ITEM_BORDER_WANT_EXCLUDE(h))
#endif
{
HRGN rgn2=CreateRectRgnIndirect(&r);
const int ret = CombineRgn(hrgn,hrgn,rgn2,RGN_DIFF);
DeleteObject(rgn2);
if (ret == NULLREGION || ret == ERROR) break;
}
}
h = GetWindow(h,GW_HWNDNEXT);
}
#endif
if (tabsize > 0)
{
HPEN pen=CreatePen(PS_SOLID,0,GSC?GSC(COLOR_3DHILIGHT):GetSysColor(COLOR_3DHILIGHT));
HPEN pen2=CreatePen(PS_SOLID,0,GSC?GSC(COLOR_3DSHADOW):GetSysColor(COLOR_3DSHADOW));
while (tabsize--)
{
int a=(int)*tab++;
if (a & DCW_HWND_FOLLOW)
{
a&=~DCW_HWND_FOLLOW;
if (!tabsize) break;
GetWindowRect((HWND)*tab++,&r);
tabsize--;
ScreenToClient(hwndDlg,(LPPOINT)&r);
ScreenToClient(hwndDlg,((LPPOINT)&r)+1);
}
else
{
int sa=a&0xffff;
if (sa == 0)
{
GetClientRect(hwndDlg,&r);
}
else
{
GetWindowRect(GetDlgItem(hwndDlg,sa),&r);
#ifdef CUSTOM_CHILDWNDBORDERCODE
CUSTOM_CHILDWNDBORDERCODE
#endif
ScreenToClient(hwndDlg,(LPPOINT)&r);
ScreenToClient(hwndDlg,((LPPOINT)&r)+1);
}
}
RECT tmp, er = r;
er.right++; er.bottom++;
if (IntersectRect(&tmp,&__use_ps->rcPaint,&er))
{
if ((a & 0xffff0000) == DCW_SUNKENBORDER || (a&0xffff0000) == DCW_SUNKENBORDER_NOTOP)
{
MoveToEx(__use_ps->hdc,r.left-1,r.bottom,NULL);
HGDIOBJ o=SelectObject(__use_ps->hdc,pen);
LineTo(__use_ps->hdc,r.right,r.bottom);
LineTo(__use_ps->hdc,r.right,r.top-1);
SelectObject(__use_ps->hdc,pen2);
if ((a&0xffff0000) == DCW_SUNKENBORDER_NOTOP)
MoveToEx(__use_ps->hdc,r.left-1,r.top-1,NULL);
else
LineTo(__use_ps->hdc,r.left-1,r.top-1);
LineTo(__use_ps->hdc,r.left-1,r.bottom);
SelectObject(__use_ps->hdc,o);
Dlg_removeFromRgn(hrgn,r.left,r.bottom,r.right,r.bottom+1);
Dlg_removeFromRgn(hrgn,r.right,r.top,r.right+1,r.bottom);
if ((a&0xffff0000) != DCW_SUNKENBORDER_NOTOP)
Dlg_removeFromRgn(hrgn,r.left,r.top-1,r.right,r.top);
Dlg_removeFromRgn(hrgn,r.left-1,r.top,r.left,r.bottom);
}
else if ((a & 0xffff0000) == DCW_DIVIDER_VERT || (a & 0xffff0000) == DCW_DIVIDER_HORZ)
{
if ((a & 0xffff0000) == DCW_DIVIDER_VERT) // vertical
{
int left=r.left;
HGDIOBJ o=SelectObject(__use_ps->hdc,pen2);
MoveToEx(__use_ps->hdc,left,r.top,NULL);
LineTo(__use_ps->hdc,left,r.bottom+1);
SelectObject(__use_ps->hdc,pen);
MoveToEx(__use_ps->hdc,left+1,r.top,NULL);
LineTo(__use_ps->hdc,left+1,r.bottom+1);
SelectObject(__use_ps->hdc,o);
Dlg_removeFromRgn(hrgn,left,r.top,left+2,r.bottom);
}
else // horiz
{
int top=r.top+1;
HGDIOBJ o=SelectObject(__use_ps->hdc,pen2);
MoveToEx(__use_ps->hdc,r.left,top,NULL);
LineTo(__use_ps->hdc,r.right+1,top);
SelectObject(__use_ps->hdc,pen);
MoveToEx(__use_ps->hdc,r.left,top+1,NULL);
LineTo(__use_ps->hdc,r.right+1,top+1);
SelectObject(__use_ps->hdc,o);
Dlg_removeFromRgn(hrgn,r.left,top,r.right,top+2);
}
}
}
}
DeleteObject(pen);
DeleteObject(pen2);
}
#ifdef _WIN32
if(hrgn)
{
HBRUSH b=NULL;
if (!GSC)
{
LRESULT res = SendMessage(hwndDlg,WM_CTLCOLORDLG, (WPARAM)__use_ps->hdc, (LPARAM)hwndDlg);
if (res > 65536) b=(HBRUSH)(INT_PTR)res;
}
if (!b) b=CreateSolidBrush(GSC?GSC(COLOR_3DFACE):GetSysColor(COLOR_3DFACE));
FillRgn(__use_ps->hdc,hrgn,b);
DeleteObject(b);
DeleteObject(hrgn);
}
#endif
if (__use_ps == &ps) EndPaint(hwndDlg,&ps);
}
#endif
#endif

View File

@@ -0,0 +1,94 @@
/*
WDL - membitmap.h
Copyright (C) 2005 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides a wrapper around the win32 bitmaps, to allow the callee to easily
manage a framebuffer. It's mostly deprecated by LICE/, however.
*/
#ifndef _WDL_WINMEMBITMAP_H_
#define _WDL_WINMEMBITMAP_H_
#ifndef _WIN32
#include "../swell/swell.h"
#endif
class WDL_WinMemBitmap
{
public:
WDL_WinMemBitmap()
{
m_w=m_h=-100;
m_hdc=0;
#ifdef _WIN32
m_bm=0; m_oldbm=0;
#endif
}
~WDL_WinMemBitmap()
{
#ifdef _WIN32
if (m_oldbm) SelectObject(m_hdc,m_oldbm);
if (m_bm) DeleteObject(m_bm);
if (m_hdc) DeleteDC(m_hdc);
#else
if (m_hdc) SWELL_DeleteGfxContext(m_hdc);
#endif
}
int DoSize(HDC compatDC, int w, int h) // returns 1 if it was resized
{
if (m_w == w && m_h == h && m_hdc
#ifdef _WIN32
&& m_bm
#endif
) return 0;
#ifdef _WIN32
if (!m_hdc) m_hdc=CreateCompatibleDC(compatDC);
if (m_oldbm) SelectObject(m_hdc,m_oldbm);
if (m_bm) DeleteObject(m_bm);
m_bm=CreateCompatibleBitmap(compatDC,m_w=w,m_h=h);
m_oldbm=SelectObject(m_hdc,m_bm);
#else
if (m_hdc) SWELL_DeleteGfxContext(m_hdc);
m_hdc=SWELL_CreateMemContext(compatDC,m_w=w,m_h=h);
#endif
return 1;
}
int GetW() { return m_w; }
int GetH() { return m_h; }
HDC GetDC() { return m_hdc; }
private:
HDC m_hdc;
#ifdef _WIN32
HBITMAP m_bm;
HGDIOBJ m_oldbm;
#endif
int m_w,m_h;
};
#endif

View File

@@ -0,0 +1,83 @@
/*
WDL - richeditctrl.h
Copyright (C) 2005 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _WDL_RICHEDITCTRL_H
#define _WDL_RICHEDITCTRL_H
#include <windows.h>
#include <richedit.h>
class WDL_RichEditCtrl
{
public:
WDL_RichEditCtrl() { setWnd(NULL); m_color=0; m_bold=0; }
WDL_RichEditCtrl(HWND hwnd) { setWnd(hwnd); m_color=0; m_bold=0; }
~WDL_RichEditCtrl() { };
void setWnd(HWND hwnd) {
m_hwnd=hwnd;
if(hwnd) {
SendMessage(m_hwnd, EM_SETEVENTMASK, 0, ENM_LINK);
SendMessage(m_hwnd, EM_AUTOURLDETECT, 1, 0);
}
}
HWND getWnd() { return m_hwnd; }
int getLength() { return GetWindowTextLength(m_hwnd); }
void getText(char *txt, int size) { GetWindowText(m_hwnd, txt, size); }
void setText(char *txt) { SetWindowText(m_hwnd, txt); }
void addText(char *txt)
{
setSel(getLength(), getLength());
CHARFORMAT2 cf2;
cf2.cbSize=sizeof(cf2);
cf2.dwMask=CFM_COLOR|CFM_BOLD;
cf2.dwEffects=m_bold?CFE_BOLD:0;
cf2.crTextColor=m_color;
SendMessage(m_hwnd, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf2);
replaceSel(txt);
int mi,ma;
GetScrollRange(m_hwnd,SB_VERT,&mi,&ma);
SendMessage(m_hwnd, WM_VSCROLL, (ma<<16)+SB_THUMBPOSITION,0);
//SetScrollPos(m_hwnd,SB_VERT,ma,TRUE);
//SendMessage(m_hwnd, WM_VSCROLL, SB_BOTTOM,0); // buggy on windows ME
}
void setSel(int start, int end) { SendMessage(m_hwnd, EM_SETSEL, start, end); }
void replaceSel(char *txt) { SendMessage(m_hwnd, EM_REPLACESEL, 0L, (LPARAM)txt); }
void clear() { setText(""); }
void setTextColor(int color) { m_color=color; }
void setBold(int b) { m_bold=b; }
protected:
HWND m_hwnd;
COLORREF m_color;
int m_bold;
};
#endif//_WDL_RICHEDITCTRL_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,96 @@
#ifndef _COOLSBLIB_INCLUDED
#define _COOLSBLIB_INCLUDED
/*
WDL - Skinned/Resizing thumb scrollbar library
Based on the "Cool Scrollbar Library v1.2" by James Brown - http://www.catch22.net
Original version Copyright(c) 2001 J Brown
Modifications copyright (C) 2006 and later Cockos Incorporated
Note: for a more featureful, less hacked up version, you may wish to download the
original from catch22.net. It has lots of added features, whereas this version is
very much tailored for Cockos' needs.
License:
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifdef __cplusplus
extern "C"{
#endif
/*
Public interface to the Cool Scrollbar library
*/
// notifications sent on user actions
#define WM_SB_RESIZE (WM_USER+511)
#define WM_SB_ZOOM (WM_USER+512)
#define WM_SB_TRESIZE_HL (WM_USER+513)
#define WM_SB_TRESIZE_HR (WM_USER+514)
#define WM_SB_TRESIZE_VT (WM_USER+515)
#define WM_SB_TRESIZE_VB (WM_USER+516)
#define WM_SB_TRESIZE_START (WM_USER+517)
#define WM_SB_DBLCLK (WM_USER+518) // wParam has SB_HORZ or SB_VERT
#ifndef COOLSB_NO_FUNC_DEFS
BOOL WINAPI InitializeCoolSB(HWND hwnd);
HRESULT WINAPI UninitializeCoolSB(HWND hwnd); // call in WM_DESTROY -- not strictly required, but recommended
int WINAPI CoolSB_IsScrollCaptured(HWND hwnd); // LOWORD()==1 if hscroll, 2, if vscroll. hiword is element or 0
BOOL WINAPI CoolSB_SetMinThumbSize(HWND hwnd, UINT wBar, UINT size);
BOOL WINAPI CoolSB_IsThumbTracking(HWND hwnd);
BOOL WINAPI CoolSB_IsCoolScrollEnabled(HWND hwnd);
void CoolSB_SetVScrollPad(HWND hwnd, UINT topamt, UINT botamt, void *(*getDeadAreaBitmap)(int which, HWND hwnd, RECT *, int defcol));
//
BOOL WINAPI CoolSB_GetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
int WINAPI CoolSB_GetScrollPos(HWND hwnd, int nBar);
BOOL WINAPI CoolSB_GetScrollRange(HWND hwnd, int nBar, LPINT lpMinPos, LPINT lpMaxPos);
//
int WINAPI CoolSB_SetScrollInfo(HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
int WINAPI CoolSB_SetScrollPos(HWND hwnd, int nBar, int nPos, BOOL fRedraw);
int WINAPI CoolSB_SetScrollRange(HWND hwnd, int nBar, int nMinPos, int nMaxPos, BOOL fRedraw);
BOOL WINAPI CoolSB_ShowScrollBar(HWND hwnd, int wBar, BOOL fShow);
BOOL WINAPI CoolSB_SetResizingThumb(HWND hwnd, BOOL active);
BOOL WINAPI CoolSB_SetResizingThumbEx(HWND hwnd, int nBar, BOOL active);
BOOL WINAPI CoolSB_SetThemeIndex(HWND hwnd, int idx);
void CoolSB_SetScale(float scale); // sets scale to use for scrollbars (does not refresh, though -- set this at startup/etc)
void CoolSB_OnColorThemeChange(); // refreshes all
// TO BE IMPLEMENTED BY APP:
void *GetIconThemePointer(const char *name); // implemented by calling app, can return a LICE_IBitmap **img for "scrollbar"
int CoolSB_GetSysColor(HWND hwnd, int val); // can be a passthrough to GetSysColor()
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,416 @@
/*
WDL - virtwnd-controls.h
Copyright (C) 2006 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#ifndef _WDL_VIRTWND_CONTROLS_H_
#define _WDL_VIRTWND_CONTROLS_H_
#include "virtwnd.h"
#include "virtwnd-skin.h"
#include "../lice/lice_text.h"
// an app should implement these
extern int WDL_STYLE_WantGlobalButtonBorders();
extern bool WDL_STYLE_WantGlobalButtonBackground(int *col);
// this is the default, you can override per painter if you want
extern bool WDL_STYLE_GetBackgroundGradient(double *gradstart, double *gradslope); // return values 0.0-1.0 for each, return false if no gradient desired
// for slider
extern LICE_IBitmap *WDL_STYLE_GetSliderBitmap2(bool vert);
extern bool WDL_STYLE_AllowSliderMouseWheel();
extern int WDL_STYLE_GetSliderDynamicCenterPos();
// functions for handling knob drawing in non-vwnds
extern WDL_VirtualWnd_BGCfg *vwnd_slider_getknobimageforsize(WDL_VirtualWnd_BGCfg *knoblist, int nknoblist,int *vieww, int *viewh, int *ksw, int *ksh, int *ks_offs);
extern void vwnd_slider_drawknobstack(LICE_IBitmap *drawbm, double val, WDL_VirtualWnd_BGCfg *knobimage, int ksw, int ksh, int ks_offs, int dx, int dy, int dw, int dh, float alpha=1.0f);
/* recommended defaults for the above:
int WDL_STYLE_WantGlobalButtonBorders() { return 0; }
bool WDL_STYLE_WantGlobalButtonBackground(int *col) { return false; }
bool WDL_STYLE_GetBackgroundGradient(double *gradstart, double *gradslope) { return false; }
LICE_IBitmap *WDL_STYLE_GetSliderBitmap2(bool vert) { return NULL; }
bool WDL_STYLE_AllowSliderMouseWheel() { return true; }
int WDL_STYLE_GetSliderDynamicCenterPos() { return 500; }
*/
// virtwnd-iconbutton.cpp
class WDL_VirtualIconButton : public WDL_VWnd
{
public:
WDL_VirtualIconButton();
virtual ~WDL_VirtualIconButton();
virtual const char *GetType() { return "vwnd_iconbutton"; }
virtual int OnMouseDown(int xpos, int ypos); // return -1 to eat, >0 to capture
virtual void OnMouseMove(int xpos, int ypos);
virtual void OnMouseUp(int xpos, int ypos);
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual void OnPaintOver(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual bool WantsPaintOver();
virtual void GetPositionPaintOverExtent(RECT *r, int rscale);
void SetEnabled(bool en) {m_en=en; }
bool GetEnabled() { return m_en; }
void SetGrayed(bool grayed) { m_grayed = grayed; SetEnabled(!grayed); }
virtual void SetIcon(WDL_VirtualIconButton_SkinConfig *cfg, float alpha=1.0f, bool buttonownsicon=false);
void SetIsButton(bool isbutton) { m_is_button=isbutton; }
bool GetIsButton() { return m_is_button; }
void SetImmediate(bool immediate) { m_immediate=immediate; } // send message on mousedown, not mouseup
void SetBGCol1Callback(int msg) { m_bgcol1_msg=msg; }
void SetForceBorder(bool fb) { m_forceborder=fb; }
// only used if no icon config set, or if force is set
void SetTextLabel(const char *text); // no change of alignment etc
void SetTextLabel(const char *text, int align, LICE_IFont *font=NULL);
const char* GetTextLabel() { return m_textlbl.Get(); }
void SetMargins(int l, int r) { m_margin_l=l; m_margin_r=r; }
void SetVMargins(int t, int b) { m_margin_t=t; m_margin_b=b; };
// if icon config is set, check state == 1 will swap the up and down image
void SetCheckState(char state, bool redraw=true); // -1 = no checkbox, 0=unchecked, 1=checked. -10= checked for accessibility/GetCheckState() but does not affect drawing
char GetCheckState() { return m_checkstate == -10 ? 1 : m_checkstate; }
WDL_VirtualIconButton_SkinConfig* GetIcon() { return m_iconCfg; } // note button does not own m_iconCfg
bool ButtonOwnsIcon() { return m_ownsicon; }
void SetForceText(bool ft, int color=0) { m_forcetext=ft; m_forcetext_color=color; }
bool GetForceText() { return m_forcetext; }
void SetTextLabelAlign(char align) { m_textalign=align; }
void SetFont(LICE_IFont *font, LICE_IFont *vfont=NULL) { m_textfont=font; m_textfontv=vfont; }
LICE_IFont *GetFont(bool vfont=false) { return vfont?m_textfontv:m_textfont; }
protected:
void DoSendCommand(int xpos, int ypos);
WDL_VirtualIconButton_SkinConfig *m_iconCfg;
int m_bgcol1_msg;
int m_margin_r, m_margin_l;
int m_margin_t, m_margin_b;
float m_alpha;
bool m_is_button,m_forceborder;
char m_pressed;
bool m_en, m_grayed, m_ownsicon;
bool m_immediate;
char m_textalign;
char m_checkstate;
bool m_forcetext;
int m_forcetext_color;
WDL_FastString m_textlbl;
LICE_IFont *m_textfont,*m_textfontv;
};
class WDL_VirtualStaticText : public WDL_VWnd
{
public:
WDL_VirtualStaticText();
virtual ~WDL_VirtualStaticText();
virtual const char *GetType() { return "vwnd_statictext"; }
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual int OnMouseDown(int xpos, int ypos);
virtual void GetPositionPaintExtent(RECT *r, int rscale);
void SetWantSingleClick(bool ws) {m_wantsingle=ws; }
void SetFont(LICE_IFont *font, LICE_IFont *vfont=NULL) { m_font=font; m_vfont=vfont; }
LICE_IFont *GetFont(bool vfont=false) { return vfont?m_vfont:m_font; }
void SetAlign(int align) { m_align=align; } // -1=left,0=center,1=right
void SetText(const char *text, bool redraw=true);
void SetBorder(bool bor) { m_wantborder=bor; }
const char *GetText() { return m_text.Get(); }
void SetColors(int fg=0, int bg=0, bool tint=false) { m_fg=fg; m_bg=bg; m_dotint=tint; }
void SetMargins(int l, int r) { m_margin_l=l; m_margin_r=r; }
void SetVMargins(int t, int b) { m_margin_t=t; m_margin_b=b; };
void SetBkImage(WDL_VirtualWnd_BGCfg *bm) { m_bkbm=bm; }
WDL_VirtualWnd_BGCfg* GetBkImage() { return m_bkbm; }
void SetWantPreserveTrailingNumber(bool preserve); // if the text ends in a number, make sure the number is always displayed
protected:
WDL_VirtualWnd_BGCfg *m_bkbm;
int m_align;
bool m_dotint;
int m_fg,m_bg;
int m_margin_r, m_margin_l;
int m_margin_t, m_margin_b;
bool m_wantborder;
bool m_wantsingle;
bool m_wantabbr;
LICE_IFont *m_font,*m_vfont;
WDL_FastString m_text;
bool m_didvert; // true if text was drawn vertically on the last paint
int m_didalign; // the actual alignment used on the last paint
public:
int m_scale_for_text;
void (*calculate_text)(WDL_VirtualStaticText *ctl, void *ctx, WDL_FastString *fs); // if set, this will be called from paint
void *calculate_text_ctx;
};
class WDL_VirtualComboBox : public WDL_VWnd
{
public:
WDL_VirtualComboBox();
virtual ~WDL_VirtualComboBox();
virtual const char *GetType() { return "vwnd_combobox"; }
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual int OnMouseDown(int xpos, int ypos);
void SetFont(LICE_IFont *font) { m_font=font; }
LICE_IFont *GetFont() { return m_font; }
void SetAlign(int align) { m_align=align; } // -1=left,0=center,1=right
int GetCurSel() { if (m_items.Get(m_curitem)) return m_curitem; return -1; }
void SetCurSel(int sel) { if (!m_items.Get(sel)) sel=-1; if (m_curitem != sel) { m_curitem=sel; RequestRedraw(NULL); } }
int GetCount() { return m_items.GetSize(); }
void Empty() { m_items.Empty(true,free); m_itemdatas.Empty(); }
int AddItem(const char *str, void *data=NULL) { m_items.Add(strdup(str)); m_itemdatas.Add(data); return m_items.GetSize()-1; }
const char *GetItem(int item) { return m_items.Get(item); }
void *GetItemData(int item) { return m_itemdatas.Get(item); }
protected:
int m_align;
int m_curitem;
LICE_IFont *m_font;
WDL_PtrList<char> m_items;
WDL_PtrList<void> m_itemdatas;
};
class WDL_VirtualSlider : public WDL_VWnd
{
public:
WDL_VirtualSlider();
virtual ~WDL_VirtualSlider();
virtual const char *GetType() { return "vwnd_slider"; }
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual int OnMouseDown(int xpos, int ypos);
virtual void OnMouseMove(int xpos, int ypos);
virtual void OnMouseUp(int xpos, int ypos);
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual bool OnMouseWheel(int xpos, int ypos, int amt) { return OnMouseWheelInternal(xpos,ypos,amt,0); }
virtual void GetPositionPaintExtent(RECT *r, int rscale);
bool OnMouseWheelInternal(int xpos, int ypos, int amt, int sc);
virtual void OnCaptureLost();
void SetBGCol1Callback(int msg) { m_bgcol1_msg=msg; }
void SetScrollMessage(int msg) { m_scrollmsg=msg; }
void SetRange(int minr, int maxr, int center) { m_minr=minr; m_maxr=maxr; m_center=center; }
void GetRange(int *minr, int *maxr, int *center) { if (minr) *minr=m_minr; if (maxr) *maxr=m_maxr; if (center) *center=m_center; }
int GetSliderPosition();
void SetSliderPosition(int pos);
bool GetIsVert();
void SetNotifyOnClick(bool en) { m_sendmsgonclick=en; } // default false
void SetDblClickCallback(int msg) { m_dblclickmsg=msg; }
int GetDblClickCallback() { return m_dblclickmsg; }
void SetGrayed(bool grayed) { m_grayed = grayed; }
void GetButtonSize(int *w, int *h, int rscale);
void SetSkinImageInfo(WDL_VirtualSlider_SkinConfig *cfg, WDL_VirtualWnd_BGCfg *knobbg=NULL, WDL_VirtualWnd_BGCfg *knobbgsm=NULL, WDL_VirtualWnd_BGCfg *knobstacks=NULL, int nknobstacks=0)
{
m_skininfo=cfg;
m_knobbg[0]=knobbgsm;
m_knobbg[1]=knobbg;
m_knobstacks=knobstacks;
m_nknobstacks=nknobstacks;
}
void SetFGColors(int knobcol, int zlcol) { m_knob_color=knobcol; m_zl_color = zlcol; }
void SetKnobBias(int knobbias, int knobextrasize=0) { m_knobbias=knobbias; m_knob_lineextrasize=knobextrasize; } // 1=force knob, -1=prevent knob
void SetAccessDescCopy(const char *str);
void SetAccessValueDesc(const char *str);
virtual bool GetAccessValueDesc(char *buf, int bufsz);
protected:
WDL_FastString m_valueText;
WDL_VirtualSlider_SkinConfig *m_skininfo;
WDL_VirtualWnd_BGCfg *m_knobbg[2];
WDL_VirtualWnd_BGCfg *getKnobBackgroundForSize(int sz) const;
WDL_VirtualWnd_BGCfg *m_knobstacks;
char *m_accessDescCopy;
int m_nknobstacks;
int m_bgcol1_msg;
int m_scrollmsg;
int m_dblclickmsg;
void OnMoveOrUp(int xpos, int ypos, int isup);
int m_minr, m_maxr, m_center, m_pos;
int m_tl_extra, m_br_extra;
int m_knob_color,m_zl_color;
int m_last_rscale, m_last_advscale;
signed char m_knobbias;
signed char m_knob_lineextrasize;
bool m_captured;
bool m_needflush;
bool m_sendmsgonclick;
bool m_grayed;
bool m_is_knob;
public:
int (*calculate_slider_position)(WDL_VirtualSlider *ctl, void *ctx); // if set, this will be called from paint (unless captured)
void *calculate_slider_position_ctx;
};
class WDL_VirtualListBox : public WDL_VWnd
{
public:
WDL_VirtualListBox();
virtual ~WDL_VirtualListBox();
virtual const char *GetType() { return "vwnd_listbox"; }
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual int OnMouseDown(int xpos, int ypos);
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual bool OnMouseWheel(int xpos, int ypos, int amt);
virtual void OnMouseMove(int xpos, int ypos);
virtual void OnMouseUp(int xpos, int ypos);
void SetFont(LICE_IFont *font, int lsadj=-1000) { m_font=font; m_lsadj=lsadj; }
LICE_IFont *GetFont() { return m_font; }
int GetLineSpacingAdjust() const { return m_lsadj; }
void SetAlign(int align) { m_align=align; } // -1=left,0=center,1=right
void SetRowHeight(int rh) { m_rh=rh; }
void SetMaxColWidth(int cw) { m_maxcolwidth=cw; } // 0 = default = allow any sized columns
void SetMinColWidth(int cw) { m_mincolwidth = cw; } // 0 = default = full width columns
void SetMargins(int l, int r) { m_margin_l=l; m_margin_r=r; }
void SetScrollbarSize(int sz, int borderl=1) { m_scrollbar_size = sz; m_scrollbar_border=borderl; }
int GetScrollbarSize() const { return m_scrollbar_size; }
void SetScrollbarColor(LICE_pixel color, float alpha=1.0f, int blendmode=0) { m_scrollbar_color = color; m_scrollbar_alpha=alpha; m_scrollbar_blendmode=blendmode; }
bool IsScrollbarHovered() const { return m_scrollbar_expanded; }
int GetRowHeight() { return m_rh; }
int GetItemHeight(int idx, int *flag=NULL); // flag gets set to 0 or ITEMH_FLAG_NOSQUISH etc
int GetMaxColWidth() { return m_maxcolwidth; }
int GetMinColWidth() { return m_mincolwidth; }
void SetColGap(int gap) { m_colgap = gap; }
int GetColGap() const { return m_colgap; }
void SetDroppedMessage(int msg) { m_dropmsg=msg; }
void SetClickedMessage(int msg) { m_clickmsg=msg; }
void SetDragMessage(int msg) { m_dragmsg=msg; }
int IndexFromPt(int x, int y);
bool GetItemRect(int item, RECT *r); // returns FALSE if not onscreen
void SetGrayed(bool grayed) { m_grayed=grayed; }
void SetViewOffset(int offs);
int GetViewOffset();
RECT *GetScrollButtonRect(bool isDown);
// idx<0 means return count of items
int (*m_GetItemInfo)(WDL_VirtualListBox *sender, int idx, char *nameout, int namelen, int *color, WDL_VirtualWnd_BGCfg **bkbg);
void (*m_CustomDraw)(WDL_VirtualListBox *sender, int idx, RECT *r, LICE_IBitmap *drawbm, int rscale);
enum { ITEMH_FLAG_NOSQUISH=0x1000000, ITEMH_MASK=0xffffff };
int (*m_GetItemHeight)(WDL_VirtualListBox *sender, int idx); // returns -1 for default height
void *m_GetItemInfo_ctx;
bool m_want_wordwise_cols; // only used if multiple columns drawn and m_GetItemHeight==NULL (causes vertical scrollbar in that case)
protected:
struct layout_info {
int startpos; // first visible item index
int columns; // 1 or more
int item_area_w, item_area_h; // area for items
int vscrollbar_w;
int hscrollbar_h;
WDL_TypedBuf<int> *heights; // visible heights of items starting at startpos
int GetHeight(int idx, int *flag=NULL) const {
int v = heights->Get()[idx];
if (flag) *flag = v & ~ITEMH_MASK;
return v & ITEMH_MASK;
};
};
bool AreItemsWordWise(const layout_info &layout) const { return m_GetItemHeight == NULL && layout.columns > 1 && m_want_wordwise_cols && !layout.hscrollbar_h; }
bool ScrollbarHit(int xpos, int ypos, const layout_info &layout);
int ScrollbarGetInfo(int *start, int *size, int num_items, const layout_info &layout); // returns 1 for vscroll, 2 for hscroll, 0 if no scrolling
int IndexFromPtInt(int x, int y, const layout_info &layout);
void CalcLayout(int num_items, layout_info *layout);
void DoScroll(int dir, const layout_info *layout);
int m_cap_state;
POINT m_cap_startpos;
int m_cap_startitem;
int m_clickmsg,m_dropmsg,m_dragmsg;
int m_viewoffs;
int m_align;
int m_margin_r, m_margin_l;
int m_rh;
int m_maxcolwidth, m_mincolwidth;
int m_colgap;
int m_scrollbar_size,m_scrollbar_border;
LICE_pixel m_scrollbar_color;
int m_scrollbar_blendmode;
float m_scrollbar_alpha;
int m_lsadj;
LICE_IFont *m_font;
bool m_grayed;
bool m_scrollbar_expanded; // mouseover
};
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,692 @@
#include "../swell/swell.h"
#include "virtwnd-controls.h"
#include <AppKit/AppKit.h>
@class VWndNSAccessibility;
static VWndNSAccessibility *GetVWndNSAccessible(WDL_VWnd *vwnd);
static WDL_VWnd *__focus;
class VWndBridgeNS;
@interface VWndNSAccessibility : NSObject
{
@public
VWndBridgeNS *m_br;
NSArray *m_cached_children;
int m_cached_children_lastcnt;
NSArray *m_cached_attrnames;
}
-(id) initWithVWnd:(WDL_VWnd *)vw;
-(void)dealloc;
-(void)clearCaches;
// attribute methods
- (NSArray *)accessibilityAttributeNames;
- (id)accessibilityAttributeValue:(NSString *)attribute;
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute;
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute;
// parameterized attribute methods
- (NSArray *)accessibilityParameterizedAttributeNames;
- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter;
// action methods
- (NSArray *)accessibilityActionNames;
- (NSString *)accessibilityActionDescription:(NSString *)action;
- (void)accessibilityPerformAction:(NSString *)action;
// Return YES if the UIElement doesn't show up to the outside world - i.e. its parent should return the UIElement's children as its own - cutting the UIElement out. E.g. NSControls are ignored when they are single-celled.
- (BOOL)accessibilityIsIgnored;
// Returns the deepest descendant of the UIElement hierarchy that contains the point. You can assume the point has already been determined to lie within the receiver. Override this method to do deeper hit testing within a UIElement - e.g. a NSMatrix would test its cells. The point is bottom-left relative screen coordinates.
- (id)accessibilityHitTest:(NSPoint)point;
// Returns the UI Element that has the focus. You can assume that the search for the focus has already been narrowed down to the reciever. Override this method to do a deeper search with a UIElement - e.g. a NSMatrix would determine if one of its cells has the focus.
- (id)accessibilityFocusedUIElement;
- (BOOL)accessibilityPerformShowMenu;
@end
class VWndBridgeNS : public WDL_VWnd_IAccessibleBridge
{
public:
VWndBridgeNS(VWndNSAccessibility *p, WDL_VWnd *vw)
{
[(par=p) retain];
(vwnd=vw)->SetAccessibilityBridge(this);
}
virtual ~VWndBridgeNS()
{
// if (vwnd) printf("Destroying self before Released, wtf!\n");
}
virtual void Release()
{
if (__focus == vwnd) __focus=0;
vwnd=0;
if (par)
{
NSAccessibilityPostNotification(par,NSAccessibilityUIElementDestroyedNotification);
[par release];
// this is probably no longer valid!
}
}
virtual void ClearCaches()
{
if (par) [par clearCaches];
}
virtual void OnFocused()
{
if (vwnd && __focus != vwnd && par)
{
__focus = vwnd;
// NSAccessibilityPostNotification(par,NSAccessibilityFocusedWindowChangedNotification);
NSAccessibilityPostNotification(par,NSAccessibilityFocusedUIElementChangedNotification);
}
}
virtual void OnStateChange()
{
if (par) NSAccessibilityPostNotification(par,NSAccessibilityValueChangedNotification);
}
VWndNSAccessibility *par;
WDL_VWnd *vwnd;
};
@implementation VWndNSAccessibility
-(id) initWithVWnd:(WDL_VWnd *)vw
{
if ((self = [super init]))
{
m_br = new VWndBridgeNS(self,vw);
m_cached_children=0;
m_cached_attrnames = 0;
m_cached_children_lastcnt=0;
}
return self;
}
-(void)clearCaches
{
if (m_cached_children)
{
[m_cached_children release];
m_cached_children=0;
m_cached_children_lastcnt=0;
}
if (m_cached_attrnames)
{
[m_cached_attrnames release];
m_cached_attrnames = 0;
}
}
-(void)dealloc
{
[self clearCaches];
delete m_br;
[super dealloc];
}
- (NSArray *)accessibilityAttributeNames
{
if (m_cached_attrnames) return m_cached_attrnames;
NSString *s[64];
int sidx=0;
const char *type = NULL;
if (m_br->vwnd)
{
type = m_br->vwnd->GetType();
if (!type) type = "";
}
if (type)
{
// if (m_br->vwnd->GetNumChildren())
{
s[sidx++] = NSAccessibilityChildrenAttribute;
s[sidx++] = NSAccessibilityVisibleChildrenAttribute;
}
s[sidx++]=NSAccessibilityTitleAttribute;
if (!strcmp(type,"vwnd_iconbutton")) s[sidx++] = NSAccessibilityEnabledAttribute;
s[sidx++] = NSAccessibilityFocusedAttribute;
s[sidx++] = NSAccessibilityParentAttribute;
RECT r;
m_br->vwnd->GetPosition(&r);
if (m_br->vwnd->IsVisible() && r.right>r.left && r.bottom>r.top)
{
s[sidx++] = NSAccessibilityPositionAttribute;
s[sidx++] = NSAccessibilitySizeAttribute;
}
s[sidx++] = NSAccessibilityRoleAttribute;
s[sidx++] = NSAccessibilityRoleDescriptionAttribute;
if (!strcmp(type,"vwnd_statictext"))
{
// s[sidx++]=NSAccessibilityDescriptionAttribute;
// s[sidx++]=NSAccessibilityValueDescriptionAttribute;
}
s[sidx++] = NSAccessibilityWindowAttribute;
bool hasState = false;
if (!strcmp(type,"vwnd_iconbutton"))
{
hasState = ((WDL_VirtualIconButton*)m_br->vwnd)->GetCheckState()>=0;
}
else if (!strcmp(type,"vwnd_combobox")) hasState=true;
else if (!strcmp(type,"vwnd_slider"))
{
// eventually we could remove this check and just query GetAccessValueDesc() directly
// (but for now do not, because some controls may be plug-in created and not have the
// updated base class)
s[sidx++] = NSAccessibilityValueDescriptionAttribute;
hasState=true;
}
else if (!strcmp(type,"vwnd_tabctrl_proxy"))
{
s[sidx++] = NSAccessibilityTabsAttribute;
}
if (hasState)
{
s[sidx++] = NSAccessibilityMaxValueAttribute;
s[sidx++] = NSAccessibilityMinValueAttribute;
s[sidx++] = NSAccessibilityValueAttribute;
}
}
if (m_cached_attrnames) [m_cached_attrnames release];
m_cached_attrnames = [NSArray arrayWithObjects:s count:sidx];
[m_cached_attrnames retain];
return m_cached_attrnames;
}
- (id)accessibilityAttributeValue:(NSString *)attribute
{
char buf[2048];
if (!m_br->vwnd) return nil;
const char *type = m_br->vwnd->GetType();
if (!type) type="";
//NSLog(@"Requesting attribute: %@ %s %p\n",attribute,type,m_br->vwnd);
int a = [attribute isEqual:NSAccessibilityChildrenAttribute]?1:0;
if (!a) a= [attribute isEqual:NSAccessibilityVisibleChildrenAttribute]?2:0;
if (!a && !strcmp(type,"vwnd_tabctrl_proxy") && [attribute isEqual:NSAccessibilityTabsAttribute])
{
a=1;
}
if (a) // if 2, only add visible items
{
int nc = m_br->vwnd->GetNumChildren();
// if (!nc) { if (m_cached_children) { [m_cached_children release]; m_cached_children=0; } printf("ret nil\n"); return nil; }
if (m_cached_children && nc == m_cached_children_lastcnt) return m_cached_children;
NSMutableArray *ar = [NSMutableArray arrayWithCapacity:nc];
int x;
for (x=0;x<nc;x++)
{
WDL_VWnd *ch = m_br->vwnd->EnumChildren(x);
if (!ch) continue;
RECT r;
ch->GetPosition(&r);
if (a==1 || (ch->IsVisible() && r.right>r.left && r.bottom>r.top))
{
VWndNSAccessibility *cid = GetVWndNSAccessible(ch);
if (cid)
{
[ar addObject:cid];
[cid release];
}
}
}
[m_cached_children release];
m_cached_children_lastcnt = nc;
m_cached_children = NSAccessibilityUnignoredChildren(ar);
[m_cached_children retain];
return m_cached_children;
}
if ([attribute isEqual:NSAccessibilityEnabledAttribute])
{
if (!strcmp(type,"vwnd_iconbutton"))
{
return [NSNumber numberWithBool:!!((WDL_VirtualIconButton *)m_br->vwnd)->GetEnabled()];
}
return nil;
}
if ([attribute isEqual:NSAccessibilityFocusedAttribute])
{
return [NSNumber numberWithBool:(__focus == m_br->vwnd || (m_br->vwnd && m_br->vwnd->IsDescendent(__focus)))]; // todo focus bleh
}
if ([attribute isEqual:NSAccessibilityParentAttribute])
{
WDL_VWnd *parw = m_br->vwnd->GetParent();
if (parw)
{
VWndNSAccessibility *cid = GetVWndNSAccessible(parw);
if (cid) return NSAccessibilityUnignoredAncestor([cid autorelease]);
}
HWND h =m_br->vwnd->GetRealParent();
if (h) return NSAccessibilityUnignoredAncestor((id)h);
return NULL;
}
if ([attribute isEqual:NSAccessibilityPositionAttribute])
{
RECT r;
m_br->vwnd->GetPosition(&r);
r.top = r.bottom; // this wants the lower left corner
WDL_VWnd *p = m_br->vwnd->GetParent();
while (p)
{
RECT tr;
p->GetPosition(&tr);
r.left += tr.left;
r.top += tr.top;
p = p->GetParent();
}
HWND h = m_br->vwnd->GetRealParent();
if (h)
{
ClientToScreen(h,(LPPOINT)&r);
}
//printf("position of (%s) %d,%d\n",m_br->vwnd->GetAccessDesc()?m_br->vwnd->GetAccessDesc():"nul",r.left,r.top);
return [NSValue valueWithPoint:NSMakePoint(r.left,r.top)];
}
if ([attribute isEqual:NSAccessibilitySizeAttribute])
{
RECT r;
m_br->vwnd->GetPosition(&r);
// printf("size of (%s) %d,%d\n",m_br->vwnd->GetAccessDesc()?m_br->vwnd->GetAccessDesc():"nul",r.right-r.left,r.bottom-r.top);
return [NSValue valueWithSize:NSMakeSize(r.right-r.left,r.bottom-r.top)];
}
if ([attribute isEqual:NSAccessibilityRoleDescriptionAttribute])
{
const char *str= NULL;
if (!str || !*str)
{
if (!strcmp(type,"vwnd_statictext")) str = "text";
else if (!strcmp(type,"vwnd_slider")) str = "slider";
else if (!strcmp(type,"vwnd_combobox")) str = "selection box";
else if (!strcmp(type,"vwnd_tabctrl_proxy")) str = "tab list";
else if (!strcmp(type,"vwnd_tabctrl_child")) str = "tab";
else if (!strcmp(type,"vwnd_iconbutton"))
{
WDL_VirtualIconButton *b = (WDL_VirtualIconButton *)m_br->vwnd;
if (b->GetCheckState()>=0) str = "check box";
else str = "button";
}
if (!str) str = m_br->vwnd->GetAccessDesc();
}
if (str && *str) return [(id)SWELL_CStringToCFString(str) autorelease];
}
if ([attribute isEqual:NSAccessibilityRoleAttribute])
{
if (!strcmp(type,"vwnd_statictext")) return NSAccessibilityButtonRole; // fail: seems to need 10.5+ to deliver text? NSAccessibilityStaticTextRole;
if (!strcmp(type,"vwnd_slider")) return NSAccessibilitySliderRole;
if (!strcmp(type,"vwnd_tabctrl_proxy")) return NSAccessibilityTabGroupRole; // bleh easiest way to get this to work
if (!strcmp(type,"vwnd_combobox")) return NSAccessibilityPopUpButtonRole;
if (!strcmp(type,"vwnd_iconbutton"))
{
WDL_VirtualIconButton *b = (WDL_VirtualIconButton *)m_br->vwnd;
if (b->GetCheckState()>=0)
return NSAccessibilityCheckBoxRole;
return NSAccessibilityButtonRole;
}
return NSAccessibilityUnknownRole;
}
if ([attribute isEqual:NSAccessibilityTitleAttribute] || [attribute isEqual:NSAccessibilityDescriptionAttribute])// || [attribute isEqual:NSAccessibilityValueDescriptionAttribute])
{
const char *str=NULL;
if (!strcmp(type,"vwnd_statictext"))
{
WDL_VirtualStaticText *t = (WDL_VirtualStaticText *)m_br->vwnd;
str = t->GetText();
}
if (!strcmp(type,"vwnd_combobox"))
{
WDL_VirtualComboBox *cb = (WDL_VirtualComboBox *)m_br->vwnd;
str = cb->GetItem(cb->GetCurSel());
}
if (!strcmp(type,"vwnd_iconbutton"))
{
WDL_VirtualIconButton *b = (WDL_VirtualIconButton *)m_br->vwnd;
str = b->GetTextLabel();
}
if (!str || !*str) str= m_br->vwnd->GetAccessDesc();
else
{
const char *p = m_br->vwnd->GetAccessDesc();
if (p && *p)
{
if (!strcmp(type,"vwnd_iconbutton"))
snprintf(buf,sizeof(buf),"%.512s: %.512s",str,p);
else
snprintf(buf,sizeof(buf),"%.512s: %.512s",p,str);
str=buf;
}
}
if (str && *str) return [(id)SWELL_CStringToCFString(str) autorelease];
}
if ([attribute isEqual:NSAccessibilityWindowAttribute])
{
HWND h = m_br->vwnd->GetRealParent();
if (h)
{
return [(NSView *)h window];
}
}
int s;
if ([attribute isEqual:NSAccessibilityValueDescriptionAttribute])
{
if (!strcmp(type,"vwnd_slider")) // eventually we can remove this check
{
WDL_VWnd *w = (WDL_VWnd *)m_br->vwnd;
buf[0]=0;
if (w->GetAccessValueDesc(buf,sizeof(buf)) && buf[0])
{
return [(id)SWELL_CStringToCFString(buf) autorelease];
}
}
}
if ((s=!![attribute isEqual:NSAccessibilityMaxValueAttribute]) ||
(s=[attribute isEqual:NSAccessibilityValueAttribute]?2:0) ||
[attribute isEqual:NSAccessibilityMinValueAttribute])
{
if (!strcmp(type,"vwnd_slider"))
{
WDL_VirtualSlider *slid = (WDL_VirtualSlider *)m_br->vwnd;
int v=0;
if (s!=2) slid->GetRange(s ? NULL : &v, s ? &v :NULL,NULL);
else v= slid->GetSliderPosition();
return [NSNumber numberWithInt:v];
}
if (!strcmp(type,"vwnd_combobox"))
{
int v=0;
if (s==1) v=((WDL_VirtualComboBox*)m_br->vwnd)->GetCount();
else if (s==2) v= !!((WDL_VirtualComboBox *)m_br->vwnd)->GetCurSel();
if (v<0)v=0;
return [NSNumber numberWithInt:v];
}
if (!strcmp(type,"vwnd_iconbutton"))
{
int v=0;
if (s==1) v=1;
else if (s==2) v= !!((WDL_VirtualIconButton *)m_br->vwnd)->GetCheckState()>0;
return [NSNumber numberWithInt:v];
}
}
return nil;
}
- (BOOL)accessibilityIsAttributeSettable:(NSString *)attribute
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
// NSLog(@"accessibilityIsAttributeSettable: %@ %s %p\n",attribute,type,m_br->vwnd);
}
if ([attribute isEqual:NSAccessibilityFocusedAttribute]) return YES;
return false;
}
- (void)accessibilitySetValue:(id)value forAttribute:(NSString *)attribute
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
//NSLog(@"accessibilitySetValue: %@ %s %p\n",attribute,type,m_br->vwnd);
}
if ([attribute isEqual:NSAccessibilityFocusedAttribute])
{
if ([value isKindOfClass:[NSNumber class]])
{
NSNumber *p = (NSNumber *)value;
if ([p boolValue]) __focus = m_br->vwnd;
else if (__focus == m_br->vwnd) __focus=NULL;
}
}
}
// parameterized attribute methods
- (NSArray *)accessibilityParameterizedAttributeNames
{
// {
// const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
// if (!type) type="";
// NSLog(@"accessibilityParameterizedAttributeNames: %@ %s %p\n",@"",type,m_br->vwnd);
// }
return [NSArray array];
}
- (id)accessibilityAttributeValue:(NSString *)attribute forParameter:(id)parameter
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
//NSLog(@"accessibilityAttributeValue: %@ %s %p\n",attribute,type,m_br->vwnd);
}
return nil;
}
// action methods
- (NSArray *)accessibilityActionNames
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
//NSLog(@"accessibilityActionNames: %@ %s %p\n",@"",type,m_br->vwnd);
}
NSString *s[32];
int sidx=0;
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (type)
{
if (!strcmp(type,"vwnd_combobox") ||
!strcmp(type,"vwnd_iconbutton") ||
!strcmp(type,"vwnd_tabctrl_child") ||
!strcmp(type,"vwnd_statictext")
) s[sidx++] = NSAccessibilityPressAction;
if (!strcmp(type,"vwnd_slider"))
{
s[sidx++] = NSAccessibilityDecrementAction;
s[sidx++] = NSAccessibilityIncrementAction;
}
}
return [NSArray arrayWithObjects:s count:sidx];
}
- (NSString *)accessibilityActionDescription:(NSString *)action
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
//NSLog(@"accessibilityActionDescription: %@ %s %p\n",action,type,m_br->vwnd);
}
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (type)
{
if ([action isEqual:NSAccessibilityPressAction])
{
if (!strcmp(type,"vwnd_combobox")) return @"Choose item";
if (!strcmp(type,"vwnd_iconbutton")) return @"Press button";
if (!strcmp(type,"vwnd_statictext")) return @"Doubleclick text";
if (!strcmp(type,"vwnd_tabctrl_child")) return @"Select tab";
}
else if (!strcmp(type,"vwnd_slider"))
{
if ([action isEqual:NSAccessibilityDecrementAction]) return @"Decrease value of control";
else if ([action isEqual:NSAccessibilityIncrementAction])return @"Increase value of control";
}
}
return nil;
}
- (void)accessibilityPerformAction:(NSString *)action
{
if (m_br->vwnd)
{
const char *type = m_br->vwnd->GetType();
if (!type) type="";
if ([action isEqual:NSAccessibilityPressAction])
{
if (!strcmp(type,"vwnd_statictext")) m_br->vwnd->OnMouseDblClick(0,0);
else
{
m_br->vwnd->OnMouseDown(0,0);
m_br->vwnd->OnMouseUp(0,0);
}
}
else if ([action isEqual:NSAccessibilityDecrementAction])
{
m_br->vwnd->OnMouseWheel(-100,-100,-1);
}
else if ([action isEqual:NSAccessibilityIncrementAction])
{
m_br->vwnd->OnMouseWheel(-100,-100,1);
}
//NSLog(@"accessibilityPerformAction: %@ %s %p\n",action,type,m_br->vwnd);
}
// todo
}
// Return YES if the UIElement doesn't show up to the outside world - i.e. its parent should return the UIElement's children as its own - cutting the UIElement out. E.g. NSControls are ignored when they are single-celled.
- (BOOL)accessibilityIsIgnored
{
if (m_br->vwnd)
{
if (!m_br->vwnd->IsVisible()) return YES;
if (m_br->vwnd->GetNumChildren())
{
const char *type = m_br->vwnd->GetType();
if (type) if (!strcmp(type,"vwnd_unknown") || strstr(type,"container")) return YES;
}
else
{
RECT r;
m_br->vwnd->GetPosition(&r);
if (r.right <= r.left || r.bottom <= r.top) return YES;
}
}
return NO;
}
// Returns the deepest descendant of the UIElement hierarchy that contains the point. You can assume the point has already been determined to lie within the receiver. Override this method to do deeper hit testing within a UIElement - e.g. a NSMatrix would test its cells. The point is bottom-left relative screen coordinates.
- (id)accessibilityHitTest:(NSPoint)point
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
// NSLog(@"accessibilityHitTest: %f,%f %s %p\n",point.x,point.y,type,m_br->vwnd);
}
if (m_br->vwnd)
{
HWND h = m_br->vwnd->GetRealParent();
if (h)
{
POINT pt = {(int)point.x,(int)point.y};
ScreenToClient(h,&pt);
WDL_VWnd *par = m_br->vwnd;
while (par->GetParent()) par=par->GetParent();
RECT r;
par->GetPosition(&r);
WDL_VWnd *hit = par->VirtWndFromPoint(pt.x-r.left,pt.y-r.top);
if (hit)
{
VWndNSAccessibility *a = GetVWndNSAccessible(hit);
if (a)
{
[a autorelease];
return a;
}
}
}
}
return nil;
}
// Returns the UI Element that has the focus. You can assume that the search for the focus has already been narrowed down to the reciever. Override this method to do a deeper search with a UIElement - e.g. a NSMatrix would determine if one of its cells has the focus.
- (id)accessibilityFocusedUIElement
{
{
const char *type = m_br->vwnd ? m_br->vwnd->GetType() : NULL;
if (!type) type="";
//NSLog(@"accessibilityFocusedUIElement: %s %p\n",type,m_br->vwnd);
}
if (__focus && m_br && m_br->vwnd && m_br->vwnd->IsDescendent(__focus))
{
VWndBridgeNS *p = (VWndBridgeNS *)__focus->GetAccessibilityBridge();
if (p) return p->par;
}
return self;
}
- (BOOL)accessibilityPerformShowMenu
{
if (m_br->vwnd)
{
HWND h = m_br->vwnd->GetRealParent();
if (h)
{
RECT r;
WDL_VWnd *v = m_br->vwnd;
v->GetPosition(&r);
r.left = (r.right+r.left)/2;
r.bottom = (r.bottom+r.top)/2;
for (;;)
{
v=v->GetParent();
if (!v) break;
RECT r2;
v->GetPosition(&r2);
r.left += r2.left;
r.top += r2.top;
}
ClientToScreen(h,(LPPOINT)&r);
SendMessage(h,WM_CONTEXTMENU,(WPARAM)h,MAKELONG(r.left,r.top));
return YES;
}
}
return NO;
}
@end
static VWndNSAccessibility *GetVWndNSAccessible(WDL_VWnd *vwnd)
{
if (!vwnd) return NULL;
VWndBridgeNS *p = (VWndBridgeNS *)vwnd->GetAccessibilityBridge();
if (p)
{
if (p->par) [p->par retain];
return p->par;
}
return [[VWndNSAccessibility alloc] initWithVWnd:vwnd];
}
LRESULT WDL_AccessibilityHandleForVWnd(bool isDialog, HWND hwnd, WDL_VWnd *vw, WPARAM wParam, LPARAM lParam)
{
if (vw && lParam && wParam==0x1001)
{
VWndNSAccessibility *nsa = GetVWndNSAccessible(vw);
if (nsa) *(id *)lParam = nsa;
}
return 0;
}

View File

@@ -0,0 +1,91 @@
#ifndef _WDL_VIRTWND_SKIN_H_
#define _WDL_VIRTWND_SKIN_H_
class LICE_IBitmap;
#include "../ptrlist.h"
typedef struct // if set these override the default virtualwnd styles for this object
{
LICE_IBitmap *bgimage;
int bgimage_lt[2],bgimage_rb[2]; // size of
int bgimage_lt_out[2],bgimage_rb_out[2]; // size of outside area (like shadows)
int bgimage_noalphaflags; // 4x4 flags of "no alpha", so 65535 is image has no alpha whatsoever
} WDL_VirtualWnd_BGCfg;
class WDL_VirtualWnd_BGCfgCache_ar;
class WDL_VirtualWnd_BGCfgCache
{
public:
WDL_VirtualWnd_BGCfgCache(int want_size=15, int max_size=30);
~WDL_VirtualWnd_BGCfgCache();
void Invalidate();
LICE_IBitmap *GetCachedBG(int w, int h, int sinfo2, void *owner_hint, const LICE_IBitmap *bgbmp);
LICE_IBitmap *SetCachedBG(int w, int h, int sinfo2, LICE_IBitmap *bm, void *owner_hint, const LICE_IBitmap *bgbmp);
private:
WDL_VirtualWnd_BGCfgCache_ar *m_ar;
int m_want_size, m_max_size;
};
void WDL_VirtualWnd_PreprocessBGConfig(WDL_VirtualWnd_BGCfg *a);
// used by elements to draw a WDL_VirtualWnd_BGCfg
#define WDL_VWND_SCALEDBLITBG_IGNORE_LR 0x40000000
#define WDL_VWND_SCALEDBLITBG_IGNORE_INSIDE 0x20000000
#define WDL_VWND_SCALEDBLITBG_IGNORE_OUTSIDE 0x10000000
void WDL_VirtualWnd_ScaledBlitBG(LICE_IBitmap *dest,
WDL_VirtualWnd_BGCfg *src,
int destx, int desty, int destw, int desth,
int clipx, int clipy, int clipw, int cliph,
float alpha, int mode);
int WDL_VirtualWnd_ScaledBG_GetPix(WDL_VirtualWnd_BGCfg *src,
int ww, int wh,
int x, int y);
void WDL_VirtualWnd_ScaledBlitSubBG(LICE_IBitmap *dest,
WDL_VirtualWnd_BGCfg *src,
int destx, int desty, int destw, int desth,
int clipx, int clipy, int clipw, int cliph,
int srcx, int srcy, int srcw, int srch, // these coordinates are not including pink lines (i.e. if pink lines are present, use src->bgimage->getWidth()-2, etc)
float alpha, int mode);
typedef struct // if set these override the default virtualwnd styles for this object
{
WDL_VirtualWnd_BGCfg bgimagecfg[2];
LICE_IBitmap *thumbimage[2]; // h,v
int thumbimage_lt[2],thumbimage_rb[2];
unsigned int zeroline_color; // needs alpha channel set!
} WDL_VirtualSlider_SkinConfig;
void WDL_VirtualSlider_PreprocessSkinConfig(WDL_VirtualSlider_SkinConfig *a);
typedef struct
{
LICE_IBitmap *image; // 3x width, second third is "mouseover" image. then mousedown, or straight image if image_issingle set
LICE_IBitmap *olimage; // drawn in second pass
union
{
char flags; // &1 = overlay, &2=main
bool asBool; // on PPC this is 4 bytes, need to preserve it
}
image_ltrb_used;
bool image_issingle;
short image_ltrb_ol[4]; // extents outside the rect
short image_ltrb_main[4]; // unscaled areas of main image (not used if single)
} WDL_VirtualIconButton_SkinConfig;
void WDL_VirtualIconButton_PreprocessSkinConfig(WDL_VirtualIconButton_SkinConfig *a);
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,267 @@
/*
WDL - virtwnd.h
Copyright (C) 2006 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
This file provides interfaces for the WDL Virtual Windows layer, a system that allows
creating many controls within one system device context.
The base class is a WDL_VWnd.
If you create a WDL_VWnd, you should send it (or its parent) mouse messages etc.
To paint a WDL_VWnd, use a WDL_VWnd_Painter in WM_PAINT etc.
More documentation should follow...
*/
#ifndef _WDL_VIRTWND_H_
#define _WDL_VIRTWND_H_
#ifdef _WIN32
#include <windows.h>
#else
#include "../swell/swell.h"
#endif
#include "../ptrlist.h"
#include "../wdlstring.h"
class WDL_VWnd_Painter;
class LICE_IBitmap;
#define WDL_VWND_SCALEBASE 256 // .8 fixed point scale
// deprecated
#define WDL_VirtualWnd_ChildList WDL_VWnd
#define WDL_VirtualWnd WDL_VWnd
#define WDL_VirtualWnd_Painter WDL_VWnd_Painter
class WDL_VWnd;
class WDL_VWnd_IAccessibleBridge
{
public:
virtual void Release()=0;
virtual void ClearCaches(){}
virtual void OnFocused() {}
virtual void OnStateChange() {}
protected:
virtual ~WDL_VWnd_IAccessibleBridge(){}
};
#include "../destroycheck.h"
#define WDL_VWND_DCHK(n) WDL_DestroyCheck n(&m_destroystate)
class WDL_VWnd
{
public:
WDL_VWnd();
virtual ~WDL_VWnd();
virtual const char *GetType() { return "vwnd_unknown"; }
virtual void SetID(int id) { m_id=id; }
virtual int GetID() { return m_id; }
virtual INT_PTR GetUserData() { return m_userdata; }
virtual INT_PTR SetUserData(INT_PTR ud) { INT_PTR od=m_userdata; m_userdata=ud; return od; }
virtual void SetPosition(const RECT *r) { m_position=*r; }
virtual void GetPosition(RECT *r) { *r=m_position; }
virtual void GetPositionPaintExtent(RECT *r, int rscale) { *r=m_position; ScaleRect(r,rscale); }
virtual void GetPositionPaintOverExtent(RECT *r, int rscale) { *r=m_position; ScaleRect(r,rscale); }
virtual void SetVisible(bool vis) { m_visible=vis; }
virtual bool IsVisible() { return m_visible; }
virtual bool WantsPaintOver() { return m_children && m_children->GetSize(); }
virtual WDL_VWnd *GetParent() { return m_parent; }
virtual void SetParent(WDL_VWnd *par) { m_parent=par; }
virtual void RequestRedraw(RECT *r);
virtual void OnPaint(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual void OnPaintOver(LICE_IBitmap *drawbm, int origin_x, int origin_y, RECT *cliprect, int rscale);
virtual int OnMouseDown(int xpos, int ypos); // return -1 to eat, >0 to capture
virtual bool OnMouseDblClick(int xpos, int ypos);
virtual bool OnMouseWheel(int xpos, int ypos, int amt);
virtual void OnMouseMove(int xpos, int ypos);
virtual void OnMouseUp(int xpos, int ypos);
// child windows
virtual WDL_VWnd *EnumChildren(int x);
virtual int GetNumChildren();
virtual WDL_VWnd *GetChildByID(int id);
virtual void AddChild(WDL_VWnd *wnd, int pos=-1);
virtual void RemoveChild(WDL_VWnd *wnd, bool dodel=false);
virtual void RemoveAllChildren(bool dodel=true);
virtual WDL_VWnd *GetCaptureWnd() { return m_children ? m_children->Get(m_captureidx) : 0; }
virtual WDL_VWnd *VirtWndFromPoint(int xpos, int ypos, int maxdepth=-1); // maxdepth=0 only direct children, etc, -1 is unlimited
// OS access
virtual HWND GetRealParent() { if (m_realparent) return m_realparent; if (GetParent()) return GetParent()->GetRealParent(); return 0; }
virtual void SetRealParent(HWND par) { m_realparent=par; }
virtual INT_PTR SendCommand(int command, INT_PTR parm1, INT_PTR parm2, WDL_VWnd *src);
// request if window has cursor
virtual int UpdateCursor(int xpos, int ypos); // >0 if set, 0 if cursor wasnt set , <0 if cursor should be default...
virtual bool GetToolTipString(int xpos, int ypos, char *bufOut, int bufOutSz); // true if handled
virtual void GetPositionInTopVWnd(RECT *r);
// these do not store a copy, usually you set them to static strings etc, but a control can override, too...
virtual void SetAccessDesc(const char *desc) { m__iaccess_desc=desc; }
virtual const char *GetAccessDesc() { return m__iaccess_desc; }
virtual WDL_VWnd_IAccessibleBridge *GetAccessibilityBridge() { return m__iaccess; }
virtual void SetAccessibilityBridge(WDL_VWnd_IAccessibleBridge *br) { m__iaccess=br; }
virtual void SetChildPosition(WDL_VWnd *ch, int pos);
virtual void SetCurPainter(WDL_VWnd_Painter *p) { m_curPainter=p; }
virtual bool IsDescendent(WDL_VWnd *w);
virtual void OnCaptureLost();
virtual bool GetAccessValueDesc(char *buf, int bufsz) { return false; } // allow control to format value string
virtual bool PrepareToDrawChild(WDL_VWnd *child, int stage) { return true; } // stage=0 for onPaint, 1=onPaintOver, the rest are reserved
virtual bool DoNotHitTest() { return false; }
static void ScaleRect(RECT *r, int sc)
{
if (sc != WDL_VWND_SCALEBASE)
{
r->left = r->left * sc / WDL_VWND_SCALEBASE;
r->top = r->top * sc / WDL_VWND_SCALEBASE;
r->right = r->right * sc / WDL_VWND_SCALEBASE;
r->bottom = r->bottom * sc / WDL_VWND_SCALEBASE;
}
}
protected:
WDL_VWnd *m_parent;
WDL_VWnd_IAccessibleBridge *m__iaccess;
bool m_visible;
int m_id;
RECT m_position;
INT_PTR m_userdata;
HWND m_realparent;
int m_captureidx;
int m_lastmouseidx;
WDL_PtrList<WDL_VWnd> *m_children;
const char *m__iaccess_desc;
WDL_VWnd_Painter *m_curPainter;
virtual int GSC(int a);
WDL_DestroyState m_destroystate;
public:
int m_focused_child; // (currently) only used by caller and read by WDL_VWnd_IAccessibleBridge (-2 is default, if unsupported by caller)
};
// painting object (can be per window or per thread or however you like)
#define WDL_VWP_SUNKENBORDER 0x00010000
#define WDL_VWP_SUNKENBORDER_NOTOP 0x00020000
#define WDL_VWP_DIVIDER_VERT 0x00030000
#define WDL_VWP_DIVIDER_HORZ 0x00040000
#include "virtwnd-skin.h"
class WDL_VWnd_Painter
{
public:
WDL_VWnd_Painter();
~WDL_VWnd_Painter();
void SetGSC(int (*GSC)(int));
void PaintBegin(HWND hwnd, int bgcolor=-1, const RECT *limitBGrect=NULL, const RECT *windowRect=NULL, HDC hdcOut=NULL, const RECT *clip_r=NULL); // if hwnd is NULL, windowRect/hdcOut/clip_r must be set
void SetBGImage(WDL_VirtualWnd_BGCfg *bitmap, int tint=-1, WDL_VirtualWnd_BGCfgCache *cacheObj=NULL, bool tintUnderMode=false) // call before every paintbegin (resets if you dont)
{
m_bgbm=bitmap;
m_bgbmtintcolor=tint;
m_bgcache=cacheObj;
m_bgbmtintUnderMode = tintUnderMode;
}
void SetBGGradient(int wantGradient, double start, double slope); // wantg < 0 to use system defaults
void PaintBGCfg(WDL_VirtualWnd_BGCfg *bitmap, const RECT *coords, bool allowTint=true, float alpha=1.0, int mode=0);
void PaintVirtWnd(WDL_VWnd *vwnd, int borderflags=0, int x_xlate=0, int y_xlate=0);
void PaintBorderForHWND(HWND hwnd, int borderflags);
void PaintBorderForRect(const RECT *r, int borderflags);
void GetPaintInfo(RECT *rclip, int *xoffsdraw, int *yoffsdraw);
void SetRenderScale(int render_scale, int advisory_scale=WDL_VWND_SCALEBASE) { m_render_scale = render_scale; m_advisory_scale = advisory_scale; }
int GetRenderScale() const { return m_render_scale; }
int GetAdvisoryScale() const { return m_advisory_scale; }
void RenderScaleRect(RECT *r) const
{
WDL_VWnd::ScaleRect(r,m_render_scale);
}
LICE_IBitmap *GetBuffer(int *xo, int *yo)
{
*xo = -m_paint_xorig;
*yo = -m_paint_yorig;
return m_bm;
}
void PaintEnd(int xoffs=0, int yoffs=0);
int GSC(int a);
private:
double m_gradstart,m_gradslope;
int m_wantg;
int (*m_GSC)(int);
void DoPaintBackground(LICE_IBitmap *bmOut, int bgcolor, const RECT *clipr, int wnd_w, int wnd_h, int xoffs, int yoffs);
void tintRect(LICE_IBitmap *bmOut, const RECT *clipr, int xoffs, int yoffs, bool isCopy);
LICE_IBitmap *m_bm;
WDL_VirtualWnd_BGCfg *m_bgbm;
int m_bgbmtintcolor;
bool m_bgbmtintUnderMode;
int m_render_scale, m_advisory_scale;
WDL_VirtualWnd_BGCfgCache *m_bgcache;
HWND m_cur_hwnd;
public:
PAINTSTRUCT m_ps;
int m_paint_xorig, m_paint_yorig;
};
void WDL_VWnd_regHelperClass(const char *classname, void *icon=NULL, void *iconsm=NULL); // register this class if you wish to make your dialogs use it (better paint behavior)
// in virtwnd-iaccessible.cpp
LRESULT WDL_AccessibilityHandleForVWnd(bool isDialog, HWND hwnd, WDL_VWnd *vw, WPARAM wParam, LPARAM lParam);
extern bool wdl_virtwnd_nosetcursorpos; // set to true to prevent SetCursorPos() from being called in sliders/etc (for pen/tablet mode)
#endif

View File

@@ -0,0 +1,436 @@
/*
WDL - wndsize.cpp
Copyright (C) 2004 and later, Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
For information on how to use this class, see wndsize.h :)
*/
#ifndef _WIN32
#include "../swell/swell.h"
#else
#include <windows.h>
#endif
#include "wndsize.h"
#include "virtwnd.h"
void WDL_WndSizer::init(HWND hwndDlg, RECT *initr)
{
m_hwnd=hwndDlg;
RECT r={0,};
if (initr)
r=*initr;
else if (m_hwnd)
GetClientRect(m_hwnd,&r);
set_orig_rect(&r);
if (m_base_dpi>0) m_base_dpi = calc_dpi(hwndDlg);
m_list.Resize(0);
memset(&m_margins,0,sizeof(m_margins));
}
void WDL_WndSizer::init_item(int dlg_id, float *scales, RECT *initr)
{
init_item(dlg_id,scales[0],scales[1],scales[2],scales[3],initr);
}
void WDL_WndSizer::init_itemvirt(WDL_VWnd *vwnd, float *scales)
{
init_itemvirt(vwnd,scales[0],scales[1],scales[2],scales[3]);
}
void WDL_WndSizer::init_itemvirt(WDL_VirtualWnd *vwnd,
float left_scale, float top_scale, float right_scale, float bottom_scale)
{
RECT this_r={0,};
if (vwnd) vwnd->GetPosition(&this_r);
const int osize=m_list.GetSize();
m_list.Resize(osize+1);
if (m_list.GetSize() != osize + 1) return;
WDL_WndSizer__rec *rec=m_list.Get()+osize;
rec->hwnd=0;
rec->vwnd=vwnd;
rec->scales[0]=left_scale;
rec->scales[1]=top_scale;
rec->scales[2]=right_scale;
rec->scales[3]=bottom_scale;
rec->real_orig = rec->last = rec->orig = this_r;
}
POINT WDL_WndSizer::get_min_size(bool applyMargins) const
{
POINT p = m_min_size;
if (applyMargins)
{
p.x += m_margins.left+m_margins.right;
p.y += m_margins.top+m_margins.bottom;
}
return p;
}
void WDL_WndSizer::init_itemhwnd(HWND h, float left_scale, float top_scale, float right_scale, float bottom_scale, RECT *srcr)
{
RECT this_r={0,};
if (srcr) this_r=*srcr;
else if (h)
{
GetWindowRect(h,&this_r);
if (m_hwnd)
{
ScreenToClient(m_hwnd,(LPPOINT) &this_r);
ScreenToClient(m_hwnd,((LPPOINT) &this_r)+1);
}
#ifndef _WIN32
if (this_r.bottom < this_r.top)
{
int oh=this_r.top-this_r.bottom;
this_r.bottom=this_r.top;
this_r.top -= oh;
}
#endif
}
const int osize=m_list.GetSize();
m_list.Resize(osize+1);
if (m_list.GetSize() != osize + 1) return;
WDL_WndSizer__rec *rec=m_list.Get()+osize;
rec->hwnd=h;
rec->vwnd=0;
rec->scales[0]=left_scale;
rec->scales[1]=top_scale;
rec->scales[2]=right_scale;
rec->scales[3]=bottom_scale;
rec->real_orig = rec->last = rec->orig = this_r;
}
void WDL_WndSizer::init_item(int dlg_id, float left_scale, float top_scale, float right_scale, float bottom_scale, RECT *initr)
{
if (m_hwnd)
{
HWND h = GetDlgItem(m_hwnd, dlg_id);
if (h) init_itemhwnd(h, left_scale, top_scale, right_scale, bottom_scale, initr);
}
}
#ifdef _WIN32
BOOL CALLBACK WDL_WndSizer::enum_RegionRemove(HWND hwnd,LPARAM lParam)
{
WDL_WndSizer *_this=(WDL_WndSizer *)lParam;
if (IsWindowVisible(hwnd))
{
if(GetParent(hwnd)!=_this->m_hwnd) return TRUE;
RECT r;
GetWindowRect(hwnd,&r);
if (_this->m_hwnd)
{
ScreenToClient(_this->m_hwnd,(LPPOINT)&r);
ScreenToClient(_this->m_hwnd,((LPPOINT)&r)+1);
}
if (RectInRegion(_this->m_enum_rgn,&r))
{
HRGN rgn2=CreateRectRgnIndirect(&r);
const int ret = CombineRgn(_this->m_enum_rgn,_this->m_enum_rgn,rgn2,RGN_DIFF);
DeleteObject(rgn2);
if (ret == NULLREGION || ret == ERROR) return FALSE;
}
}
return TRUE;
}
#endif
void WDL_WndSizer::remove_item(int dlg_id)
{
int x = m_list.GetSize();
while (--x >= 0)
{
const WDL_WndSizer__rec *rec = m_list.Get() + x;
if ((rec->hwnd && GetWindowLong(rec->hwnd,GWL_ID) == dlg_id) ||
(rec->vwnd && rec->vwnd->GetID() == dlg_id)) m_list.Delete(x);
}
}
void WDL_WndSizer::remove_itemhwnd(HWND h)
{
if (h)
{
int x = m_list.GetSize();
while (--x >= 0)
{
if (m_list.Get()[x].hwnd == h) m_list.Delete(x);
}
}
}
void WDL_WndSizer::remove_itemvirt(WDL_VirtualWnd *vwnd)
{
if (vwnd)
{
int x = m_list.GetSize();
while (--x >= 0)
{
if (m_list.Get()[x].vwnd == vwnd) m_list.Delete(x);
}
}
}
void WDL_WndSizer::transformRect(RECT *r, const float *scales, const RECT *wndSize) const
{
POINT sz = { wndSize->right, wndSize->bottom };
sz.x -= m_margins.left+m_margins.right;
sz.y -= m_margins.top+m_margins.bottom;
if (sz.x < m_min_size.x) sz.x=m_min_size.x;
if (sz.y < m_min_size.y) sz.y=m_min_size.y;
sz.x -= m_orig_size.x;
sz.y -= m_orig_size.y;
if (scales[0] >= 1.0) r->left += sz.x;
else if (scales[0]>0.0) r->left += (int) (sz.x*scales[0]);
if (scales[1] >= 1.0) r->top += sz.y;
else if (scales[1]>0.0) r->top += (int) (sz.y*scales[1]);
if (scales[2] >= 1.0) r->right += sz.x;
else if (scales[2]>0.0) r->right += (int) (sz.x*scales[2]);
if (scales[3] >= 1.0) r->bottom += sz.y;
else if (scales[3]>0.0) r->bottom += (int) (sz.y*scales[3]);
r->left += m_margins.left;
r->right += m_margins.left;
r->top += m_margins.top;
r->bottom += m_margins.top;
if (r->bottom < r->top) r->bottom=r->top;
if (r->right < r->left) r->right=r->left;
}
void WDL_WndSizer::onResizeVirtual(int width, int height)
{
RECT new_rect = {0,0,width,height};
for (int x = 0; x < m_list.GetSize(); x ++)
{
WDL_WndSizer__rec *rec=m_list.Get() + x;
if (rec->vwnd)
{
RECT r=rec->orig;
transformRect(&r,rec->scales,&new_rect);
rec->last = r;
rec->vwnd->SetPosition(&r);
}
}
}
void WDL_WndSizer::onResize(HWND only, int notouch, int xtranslate, int ytranslate)
{
if (!m_hwnd) return;
RECT new_rect;
const int dpi = m_base_dpi > 0 ? calc_dpi(m_hwnd) : 0;
GetClientRect(m_hwnd,&new_rect);
RECT new_rect_sc = new_rect;
if (dpi > 0 && dpi != m_base_dpi)
{
new_rect_sc.left = new_rect_sc.left * m_base_dpi / dpi;
new_rect_sc.top = new_rect_sc.top * m_base_dpi / dpi;
new_rect_sc.right = new_rect_sc.right * m_base_dpi / dpi;
new_rect_sc.bottom = new_rect_sc.bottom * m_base_dpi / dpi;
}
#ifdef _WIN32
m_enum_rgn=CreateRectRgnIndirect(&new_rect);
HDWP hdwndpos=NULL;
int has_dfwp=0;
#endif
int x;
for (x = 0; x < m_list.GetSize(); x ++)
{
WDL_WndSizer__rec *rec=m_list.Get() + x;
if ((rec->vwnd && !only) || (rec->hwnd && (!only || only == rec->hwnd)))
{
RECT r=rec->orig;
transformRect(&r,rec->scales,&new_rect_sc);
rec->last = r;
if (rec->hwnd && m_base_dpi > 0 && dpi != m_base_dpi)
{
r.left = r.left * dpi / m_base_dpi;
r.top = r.top* dpi / m_base_dpi;
r.right = r.right * dpi / m_base_dpi;
r.bottom = r.bottom * dpi / m_base_dpi;
}
if (!notouch)
{
if (rec->hwnd)
{
#ifdef _WIN32
if (!has_dfwp)
{
has_dfwp=1;
if (!only
#ifdef WDL_SUPPORT_WIN9X
&& GetVersion() < 0x80000000
#endif
) hdwndpos=BeginDeferWindowPos(m_list.GetSize() - x);
}
if (!hdwndpos)
#endif
SetWindowPos(rec->hwnd, NULL, r.left+xtranslate,r.top+ytranslate,r.right-r.left,r.bottom-r.top, SWP_NOZORDER|SWP_NOACTIVATE);
#ifdef _WIN32
else
hdwndpos=DeferWindowPos(hdwndpos, rec->hwnd, NULL, r.left+xtranslate,r.top+ytranslate,r.right-r.left,r.bottom-r.top, SWP_NOZORDER|SWP_NOACTIVATE);
#endif
}
if (rec->vwnd)
{
rec->vwnd->SetPosition(&r);
}
}
}
}
#ifdef _WIN32
if (hdwndpos) EndDeferWindowPos(hdwndpos);
EnumChildWindows(m_hwnd,enum_RegionRemove,(LPARAM)this);
InvalidateRgn(m_hwnd,m_enum_rgn,FALSE);
DeleteObject(m_enum_rgn);
#endif
}
WDL_WndSizer__rec *WDL_WndSizer::get_itembyindex(int idx) const
{
if (idx >= 0 && idx < m_list.GetSize()) return m_list.Get()+idx;
return NULL;
}
WDL_WndSizer__rec *WDL_WndSizer::get_itembywnd(HWND h) const
{
if (h)
{
WDL_WndSizer__rec *rec=m_list.Get();
int cnt=m_list.GetSize();
while (cnt--)
{
if (rec->hwnd == h) return rec;
rec++;
}
}
return 0;
}
WDL_WndSizer__rec *WDL_WndSizer::get_itembyvirt(WDL_VirtualWnd *vwnd) const
{
if (!vwnd) return 0;
WDL_WndSizer__rec *rec=m_list.Get();
int cnt=m_list.GetSize();
while (cnt--)
{
if (rec->vwnd == vwnd) return rec;
rec++;
}
return 0;
}
WDL_WndSizer__rec *WDL_WndSizer::get_item(int dlg_id) const
{
WDL_WndSizer__rec *rec=m_list.Get();
int cnt=m_list.GetSize();
while (cnt--)
{
if (rec->vwnd && rec->vwnd->GetID() == dlg_id) return rec;
if (rec->hwnd && GetWindowLong(rec->hwnd, GWL_ID) == dlg_id) return rec;
rec++;
}
return NULL;
}
bool WDL_WndSizer::sizer_to_dpi_rect(RECT *r, int dpi) const // returns true if modified
{
if (r && m_base_dpi>0)
{
if (dpi<=0) dpi = calc_dpi(m_hwnd);
if (dpi > 0 && dpi != m_base_dpi)
{
r->left = r->left * dpi / m_base_dpi;
r->top = r->top * dpi / m_base_dpi;
r->right = r->right * dpi / m_base_dpi;
r->bottom = r->bottom * dpi / m_base_dpi;
return true;
}
}
return false;
}
int WDL_WndSizer::calc_dpi(HWND hwnd)
{
#ifdef _WIN32
static UINT (WINAPI *__GetDpiForWindow)(HWND);
if (!__GetDpiForWindow)
{
HINSTANCE h = GetModuleHandle("user32.dll");
if (h)
{
BOOL (WINAPI *__AreDpiAwarenessContextsEqual)(void *, void *);
void * (WINAPI *__GetThreadDpiAwarenessContext )();
*(void **)&__GetThreadDpiAwarenessContext = GetProcAddress(h,"GetThreadDpiAwarenessContext");
*(void **)&__AreDpiAwarenessContextsEqual = GetProcAddress(h,"AreDpiAwarenessContextsEqual");
if (__GetThreadDpiAwarenessContext && __AreDpiAwarenessContextsEqual)
{
if (__AreDpiAwarenessContextsEqual(__GetThreadDpiAwarenessContext(),(void*)(INT_PTR)-4))
*(void **)&__GetDpiForWindow = GetProcAddress(h,"GetDpiForWindow");
}
}
if (!__GetDpiForWindow)
*(INT_PTR*)&__GetDpiForWindow = 1;
}
if (*(INT_PTR*)&__GetDpiForWindow != 1)
{
if (!hwnd) return 256;
return __GetDpiForWindow(hwnd)*256 / 96;
}
#endif
return 0;
}

View File

@@ -0,0 +1,175 @@
/*
WDL - wndsize.h
Copyright (C) 2004 and later Cockos Incorporated
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/*
This file provides the interface for a simple class that allows one to easily
make resizeable dialogs and have controls that move according to ratios of the
new size.
Usually, one does a
static WDL_WndSizer resize;
in their DlgProc, and in WM_INITDIALOG:
resize.init(hwndDlg);
// add a list of items
resize.init_item(IDC_MASTERVOL, // dialog id
0.0, // left position, 0=left anchor, 1=right anchor, etc
0.0, // top position, 0=anchored to its initial top position, 1=anchored to distance from bottom, etc
0.7f, // right position
0.0); // bottom position
...
then, in WM_SIZE,
if (wParam != SIZE_MINIMIZED)
{
resize.onResize(); // don't actually resize, just compute the rects
}
is about all that's needed.
*/
/*
* Additional note from late-2019
* If on Windows and Multimonitor v2 DPI awareness mode is enabled
* The coordinates for WDL_WndSizer__rec will be based on the DPI-scaling at init() time, which is m_base_dpi.
*
* One can use dpi_to_sizer() and sizer_to_dpi() to convert to/from (if DPI-scaling is disabled, then these functions no-op)
*
* If m_base_dpi is set to <=0 this functionality is disabled (disable if you want to manage this all at the caller level)
*/
#ifndef _WNDSIZE_H_
#define _WNDSIZE_H_
#include "../heapbuf.h"
class WDL_VWnd;
struct WDL_WndSizer__rec
{
HWND hwnd;
RECT orig;
RECT real_orig;
RECT last;
float scales[4];
WDL_VWnd *vwnd;
};
class WDL_WndSizer
{
public:
WDL_WndSizer()
{
m_hwnd=NULL;
m_base_dpi=256;
memset(&m_min_size,0,sizeof(m_min_size));
memset(&m_orig_size,0,sizeof(m_orig_size));
memset(&m_margins,0,sizeof(m_margins));
}
~WDL_WndSizer() { }
void init(HWND hwndDlg, RECT *initr=NULL);
// 1.0 means it moves completely with the point, 0.0 = not at all
void init_item(int dlg_id, float left_scale=0.0, float top_scale=0.0, float right_scale=1.0, float bottom_scale=1.0, RECT *initr=NULL);
void init_itemvirt(WDL_VWnd *vwnd, float left_scale=0.0, float top_scale=0.0, float right_scale=1.0, float bottom_scale=1.0);
void init_item(int dlg_id, float *scales, RECT *initr=NULL);
void init_itemvirt(WDL_VWnd *vwnd, float *scales);
void init_itemhwnd(HWND h, float left_scale=0.0, float top_scale=0.0, float right_scale=1.0, float bottom_scale=1.0, RECT *srcr=NULL);
void remove_item(int dlg_id);
void remove_itemvirt(WDL_VWnd *vwnd);
void remove_itemhwnd(HWND h);
WDL_WndSizer__rec *get_item(int dlg_id) const;
WDL_WndSizer__rec *get_itembyindex(int idx) const;
WDL_WndSizer__rec *get_itembywnd(HWND h) const;
WDL_WndSizer__rec *get_itembyvirt(WDL_VWnd *vwnd) const;
RECT get_orig_rect() const { RECT r={0,0,m_orig_size.x,m_orig_size.y}; return r; }
RECT get_orig_rect_dpi(int dpi=0) const {
RECT r = get_orig_rect();
sizer_to_dpi_rect(&r,dpi);
return r;
}
void set_orig_rect(const RECT *r, const POINT *minSize=NULL)
{
if (r) { m_orig_size.x = r->right; m_orig_size.y = r->bottom; }
if (minSize) m_min_size = *minSize;
else m_min_size.x=m_min_size.y=0;
}
POINT get_min_size(bool applyMargins=false) const;
void onResize(HWND only=0, int notouch=0, int xtranslate=0, int ytranslate=0);
void onResizeVirtual(int width, int height);
void set_margins(int left, int top, int right, int bottom) { m_margins.left=left; m_margins.top=top; m_margins.right=right; m_margins.bottom=bottom; }
void get_margins(int *left, int *top, int *right, int *bottom) const
{
if (left) *left=m_margins.left;
if (top) *top=m_margins.top;
if (right) *right=m_margins.right;
if (bottom) *bottom=m_margins.bottom;
}
void transformRect(RECT *r, const float *scales, const RECT *wndSize) const;
int m_base_dpi; // if set <=0, all DPI functionality will be skipped. 256=normal
static int calc_dpi(HWND hwnd); // returns 0 if not windows or not in multimonitorv2 awareness mode
bool sizer_to_dpi_rect(RECT *r, int dpi=0) const; // returns true if modified, converts to current DPI from sizer base DPI
int dpi_to_sizer(int x, int dpi=0) const // convert dpi-specific coordinate to sizer coordinate (orig.left etc) if in DPI mode
{
if (m_base_dpi<=0 || !x) return x;
if (dpi<=0) dpi=calc_dpi(m_hwnd);
return dpi>0 && dpi != m_base_dpi ? x * m_base_dpi / dpi : x;
}
int sizer_to_dpi(int x, int dpi=0) const // convert sizer coordinate (orig.left etc) to dpi-specific coordinate, if in DPI mode
{
if (m_base_dpi<=0 || !x) return x;
if (dpi<=0) dpi=calc_dpi(m_hwnd);
return dpi>0 && dpi != m_base_dpi ? x * dpi / m_base_dpi : x;
}
private:
#ifdef _WIN32
static BOOL CALLBACK enum_RegionRemove(HWND hwnd,LPARAM lParam);
HRGN m_enum_rgn;
#endif
HWND m_hwnd;
POINT m_orig_size,m_min_size;
RECT m_margins;
WDL_TypedBuf<WDL_WndSizer__rec> m_list;
};
#endif//_WNDSIZE_H_