2 WDL - virtwnd-iconbutton.cpp
3 Copyright (C) 2006 and later Cockos Incorporated
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
22 Implementation for virtual window icon buttons, icons, combo boxes, and static text controls.
27 #include "virtwnd-controls.h"
28 #include "../lice/lice.h"
31 #define WDL_WIN32_UTF8_IMPL static
32 #define WDL_WIN32_UTF8_NO_UI_IMPL
33 #include "../win32_utf8.c"
36 WDL_VirtualIconButton::WDL_VirtualIconButton()
54 m_margin_r
= m_margin_l
= 0;
55 m_margin_t
= m_margin_b
= 0;
58 WDL_VirtualIconButton::~WDL_VirtualIconButton()
60 if (m_ownsicon
&& m_iconCfg
)
62 delete m_iconCfg
->image
;
63 delete m_iconCfg
->olimage
;
68 void WDL_VirtualIconButton::SetTextLabel(const char *text
)
71 if (!m_iconCfg
|| m_forcetext
) RequestRedraw(NULL
);
74 void WDL_VirtualIconButton::SetTextLabel(const char *text
, int align
, LICE_IFont
*font
)
76 if (font
) m_textfont
=font
;
79 if (!m_iconCfg
|| m_forcetext
) RequestRedraw(NULL
);
82 void WDL_VirtualIconButton::SetCheckState(char state
)
84 if (state
!= m_checkstate
)
91 void WDL_VirtualIconButton::SetIcon(WDL_VirtualIconButton_SkinConfig
*cfg
, float alpha
, bool buttonownsicon
)
93 if (m_iconCfg
!= cfg
|| m_alpha
!= alpha
)
95 bool combineRects
=false;
97 if (m_iconCfg
&& m_iconCfg
!= cfg
&& m_iconCfg
->olimage
)
100 GetPositionPaintExtent(&r
,WDL_VWND_SCALEBASE
);
101 if (WantsPaintOver())
104 GetPositionPaintOverExtent(&r3
,WDL_VWND_SCALEBASE
);
105 if (r3
.left
<r
.left
) r
.left
=r3
.left
;
106 if (r3
.top
<r
.top
) r
.top
=r3
.top
;
107 if (r3
.right
>r
.right
) r
.right
=r3
.right
;
108 if (r3
.bottom
>r
.bottom
) r
.bottom
=r3
.bottom
;
111 if (m_ownsicon
&& m_iconCfg
&& m_iconCfg
!= cfg
)
113 delete m_iconCfg
->image
;
114 delete m_iconCfg
->olimage
;
123 GetPositionPaintExtent(&r3
,WDL_VWND_SCALEBASE
);
124 if (r3
.left
<r
.left
) r
.left
=r3
.left
;
125 if (r3
.top
<r
.top
) r
.top
=r3
.top
;
126 if (r3
.right
>r
.right
) r
.right
=r3
.right
;
127 if (r3
.bottom
>r
.bottom
) r
.bottom
=r3
.bottom
;
129 if (WantsPaintOver())
131 GetPositionPaintOverExtent(&r3
,WDL_VWND_SCALEBASE
);
132 if (r3
.left
<r
.left
) r
.left
=r3
.left
;
133 if (r3
.top
<r
.top
) r
.top
=r3
.top
;
134 if (r3
.right
>r
.right
) r
.right
=r3
.right
;
135 if (r3
.bottom
>r
.bottom
) r
.bottom
=r3
.bottom
;
138 r
.left
-= m_position
.left
;
139 r
.right
-= m_position
.left
;
140 r
.top
-= m_position
.top
;
141 r
.bottom
-= m_position
.top
;
149 m_ownsicon
= buttonownsicon
;
152 void WDL_VirtualIconButton::OnPaintOver(LICE_IBitmap
*drawbm
, int origin_x
, int origin_y
, RECT
*cliprect
, int rscale
)
154 if (m_iconCfg
&& m_iconCfg
->olimage
)
158 int w
=m_iconCfg
->olimage
->getWidth();
159 int h
=m_iconCfg
->olimage
->getHeight();
160 if (m_iconCfg
->image_ltrb_used
.flags
&1) { w
-=2; h
-= 2; sx
++,sy
++; }
168 if ((m_pressed
&2)) sx
+=(m_pressed
&1) ? w
*2 : w
;
171 if (m_iconCfg
->image_ltrb_used
.flags
&2) // use main image's stretch areas (outer areas become unstretched)
173 WDL_VirtualWnd_BGCfg cfg
={0,};
174 LICE_SubBitmap
sb(m_iconCfg
->olimage
,sx
,sy
,w
,h
);
176 cfg
.bgimage_lt
[0] = m_iconCfg
->image_ltrb_main
[0]+1; // image_ltrb_main expects 1-based number
177 cfg
.bgimage_lt
[1] = m_iconCfg
->image_ltrb_main
[1]+1;
178 cfg
.bgimage_rb
[0] = m_iconCfg
->image_ltrb_main
[2]+1;
179 cfg
.bgimage_rb
[1] = m_iconCfg
->image_ltrb_main
[3]+1;
180 cfg
.bgimage_lt_out
[0] = m_iconCfg
->image_ltrb_ol
[0]+1;
181 cfg
.bgimage_lt_out
[1] = m_iconCfg
->image_ltrb_ol
[1]+1;
182 cfg
.bgimage_rb_out
[0] = m_iconCfg
->image_ltrb_ol
[2]+1;
183 cfg
.bgimage_rb_out
[1] = m_iconCfg
->image_ltrb_ol
[3]+1;
184 cfg
.bgimage_noalphaflags
=0;
186 RECT r
=m_position
,r2
;
187 ScaleRect(&r
,rscale
);
188 GetPositionPaintOverExtent(&r2
,rscale
);
189 WDL_VirtualWnd_ScaledBlitBG(drawbm
,&cfg
,
190 r
.left
+origin_x
,r
.top
+origin_y
,r
.right
-r
.left
,r
.bottom
-r
.top
,
191 r2
.left
+origin_x
,r2
.top
+origin_y
,r2
.right
-r2
.left
,r2
.bottom
-r2
.top
,
192 m_alpha
,LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
197 GetPositionPaintOverExtent(&r
,rscale
);
198 LICE_ScaledBlit(drawbm
,m_iconCfg
->olimage
,r
.left
+origin_x
,r
.top
+origin_y
,
201 (float)sx
,(float)sy
,(float)w
,(float)h
, m_alpha
, // m_grayed?
202 LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
209 void WDL_VirtualIconButton::OnPaint(LICE_IBitmap
*drawbm
, int origin_x
, int origin_y
, RECT
*cliprect
, int rscale
)
213 float alpha
= (m_grayed
? 0.25f
: 1.0f
) * m_alpha
;
215 bool isdown
= !!(m_pressed
&1);
216 bool ishover
= !!(m_pressed
&2);
218 if (m_iconCfg
&& m_iconCfg
->image
&& !m_iconCfg
->image_issingle
)
220 bool swapupdown
= (m_checkstate
> 0);
221 bool isdownimg
= (swapupdown
!= isdown
);
224 ScaleRect(&r
,rscale
);
228 int w
=m_iconCfg
->image
->getWidth();
229 int h
=m_iconCfg
->image
->getHeight();
231 if (w
>0 && (m_iconCfg
->image_ltrb_used
.flags
&2))
239 if (isdownimg
) sx
+= w
*2;
240 else if (ishover
) sx
+= w
;
244 if (m_iconCfg
->image_ltrb_used
.flags
&2)
246 WDL_VirtualWnd_BGCfg cfg
={0,};
247 LICE_SubBitmap
sb(m_iconCfg
->image
,sx
+1,sy
+1,w
,h
-2);
249 cfg
.bgimage_lt
[0] = m_iconCfg
->image_ltrb_main
[0]+1; // image_ltrb_main expects 1-based number
250 cfg
.bgimage_lt
[1] = m_iconCfg
->image_ltrb_main
[1]+1;
251 cfg
.bgimage_rb
[0] = m_iconCfg
->image_ltrb_main
[2]+1;
252 cfg
.bgimage_rb
[1] = m_iconCfg
->image_ltrb_main
[3]+1;
253 cfg
.bgimage_noalphaflags
=0;
255 WDL_VirtualWnd_ScaledBlitBG(drawbm
,&cfg
,
256 r
.left
+origin_x
,r
.top
+origin_y
,r
.right
-r
.left
,r
.bottom
-r
.top
,
257 r
.left
+origin_x
,r
.top
+origin_y
,r
.right
-r
.left
,r
.bottom
-r
.top
,
258 alpha
,LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
262 LICE_ScaledBlit(drawbm
,m_iconCfg
->image
,r
.left
+origin_x
,r
.top
+origin_y
,
265 (float)sx
,(float)sy
,(float)w
,(float)h
, alpha
,
266 LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
272 ScaleRect(&r
,rscale
);
279 if (WDL_STYLE_WantGlobalButtonBackground(&col
))
281 LICE_FillRect(drawbm
,r
.left
,r
.top
,r
.right
-r
.left
,r
.bottom
-r
.top
,LICE_RGBA_FROMNATIVE(col
,255),alpha
,LICE_BLIT_MODE_COPY
);
284 if (ishover
|| m_forceborder
|| WDL_STYLE_WantGlobalButtonBorders())
286 int cidx
=isdown
?COLOR_3DSHADOW
:COLOR_3DHILIGHT
;
288 int pencol
= GSC(cidx
);
289 pencol
= LICE_RGBA_FROMNATIVE(pencol
,255);
291 LICE_Line(drawbm
,r
.left
,r
.bottom
-1,r
.left
,r
.top
,pencol
,alpha
,LICE_BLIT_MODE_COPY
,false);
292 LICE_Line(drawbm
,r
.left
,r
.top
,r
.right
-1,r
.top
,pencol
,alpha
,LICE_BLIT_MODE_COPY
,false);
293 cidx
= isdown
?COLOR_3DHILIGHT
:COLOR_3DSHADOW
;
295 pencol
= LICE_RGBA_FROMNATIVE(pencol
,255);
296 LICE_Line(drawbm
,r
.right
-1,r
.top
,r
.right
-1,r
.bottom
-1,pencol
,alpha
,LICE_BLIT_MODE_COPY
,false);
297 LICE_Line(drawbm
,r
.right
-1,r
.bottom
-1,r
.left
,r
.bottom
-1,pencol
,alpha
,LICE_BLIT_MODE_COPY
,false);
300 if (m_iconCfg
&& m_iconCfg
->image
)
303 WDL_STYLE_ScaleImageCoords(&sz
,&sz2
);
305 //if (m_position.right-m_position.left > 24) sz=m_position.right-m_position.left-8;
307 int x
=r
.left
+((r
.right
-r
.left
)-sz
)/2;
308 int y
=r
.top
+((r
.bottom
-r
.top
)-sz2
)/2;
311 if (isdown
&& ishover
) { x
++; y
++; }
314 LICE_ScaledBlit(drawbm
,m_iconCfg
->image
,x
,y
,sz
,sz2
,0.0f
,0.0f
,
315 (float)m_iconCfg
->image
->getWidth(),
316 (float)m_iconCfg
->image
->getHeight(),alpha
,LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
321 if (!m_iconCfg
|| m_forcetext
)
324 ScaleRect(&r2
,rscale
);
330 if (m_checkstate
>=0 && !m_iconCfg
)
333 int sz
=tr
.bottom
-tr
.top
;
334 int adj
= 2*rscale
/WDL_VWND_SCALEBASE
;
341 LICE_FillRect(drawbm
,tr
.left
,tr
.top
,sz
,sz
,LICE_RGBA(255,255,255,255),alpha
,LICE_BLIT_MODE_COPY
);
342 LICE_Line(drawbm
,tr
.left
,tr
.top
,tr
.left
+sz
,tr
.top
,LICE_RGBA(128,128,128,255),alpha
,LICE_BLIT_MODE_COPY
,false);
343 LICE_Line(drawbm
,tr
.left
+sz
,tr
.top
,tr
.left
+sz
,tr
.bottom
,LICE_RGBA(128,128,128,255),alpha
,LICE_BLIT_MODE_COPY
,false);
344 LICE_Line(drawbm
,tr
.left
+sz
,tr
.bottom
,tr
.left
,tr
.bottom
,LICE_RGBA(128,128,128,255),alpha
,LICE_BLIT_MODE_COPY
,false);
345 LICE_Line(drawbm
,tr
.left
,tr
.bottom
,tr
.left
,tr
.top
,LICE_RGBA(128,128,128,255),alpha
,LICE_BLIT_MODE_COPY
,false);
346 int nl
= (m_checkstate
>0) ? 3:0;
350 LICE_Line(drawbm
,tr
.left
+2,tr
.bottom
-2,tr
.left
+sz
-2,tr
.top
+2,LICE_RGBA(0,0,0,255),alpha
,LICE_BLIT_MODE_COPY
,false);
352 LICE_Line(drawbm
,tr
.left
+2,tr
.top
+2,tr
.left
+sz
-2,tr
.bottom
-2,LICE_RGBA(0,0,0,255),alpha
,LICE_BLIT_MODE_COPY
,false);
357 LICE_IFont
*font
= m_textfont
;
359 if (font
&& m_textfontv
&& m_position
.right
-m_position
.left
< m_position
.bottom
- m_position
.top
)
365 if (font
&&m_textlbl
.Get()[0])
367 int fgc
=m_forcetext_color
? m_forcetext_color
: LICE_RGBA_FROMNATIVE(GSC(COLOR_BTNTEXT
),255);
368 //font->SetCombineMode(LICE_BLIT_MODE_COPY, alpha); // this affects the glyphs that get cached
369 font
->SetBkMode(TRANSPARENT
);
370 font
->SetTextColor(fgc
);
372 r2
.left
+= m_margin_l
;
373 r2
.right
-= m_margin_r
;
374 r2
.top
+= m_margin_t
;
375 r2
.bottom
-= m_margin_b
;
379 if (m_textalign
<0) r2
.left
+=1;
380 else if (m_textalign
>0) r2
.right
+=1;
384 int f
= DT_SINGLELINE
|DT_NOPREFIX
;
387 if (m_textalign
== 0)
390 font
->DrawText(drawbm
,m_textlbl
.Get(),-1,&mr
,f
|DT_CALCRECT
);
391 f
|= (mr
.bottom
< r2
.bottom
-r2
.top
) ? DT_VCENTER
: DT_TOP
;
394 f
|= m_textalign
<0?DT_TOP
:DT_BOTTOM
;
400 if (m_textalign
== 0)
403 font
->DrawText(drawbm
,m_textlbl
.Get(),-1,&mr
,f
|DT_CALCRECT
);
404 f
|= (mr
.right
< r2
.right
-r2
.left
) ? DT_CENTER
: DT_LEFT
;
407 f
|= m_textalign
<0?DT_LEFT
:DT_RIGHT
;
411 font
->DrawText(drawbm
,m_textlbl
.Get(),-1,&r2
,f
);
419 SendCommand(m_bgcol1_msg
,(INT_PTR
)&brcol
,GetID(),this);
424 int bh
=(r
.bottom
-r
.top
)/5;
426 int bw
=(r
.right
-r
.left
)/5;
429 LICE_FillRect(drawbm
,
430 r
.left
+origin_x
,r
.top
+origin_y
,
432 bh
,LICE_RGBA_FROMNATIVE(brcol
,255),0.75,LICE_BLIT_MODE_COPY
);
434 LICE_FillRect(drawbm
,
435 r
.left
+origin_x
,r
.top
+origin_y
+bh
,
437 r
.bottom
-r
.top
-bh
*2,LICE_RGBA_FROMNATIVE(brcol
,255),0.75,LICE_BLIT_MODE_COPY
);
439 LICE_FillRect(drawbm
,
440 r
.right
+origin_x
-bw
,r
.top
+origin_y
+bh
,
442 r
.bottom
-r
.top
-bh
*2,LICE_RGBA_FROMNATIVE(brcol
,255),0.75,LICE_BLIT_MODE_COPY
);
444 LICE_FillRect(drawbm
,
445 r
.left
+origin_x
,r
.bottom
+origin_y
-bh
,
447 bh
,LICE_RGBA_FROMNATIVE(brcol
,255),0.75,LICE_BLIT_MODE_COPY
);
454 void WDL_VirtualIconButton::OnMouseMove(int xpos
, int ypos
)
456 if (m_en
&&m_is_button
)
460 WDL_VWnd
*parhit
= GetParent();
463 parhit
= parhit
->VirtWndFromPoint(m_position
.left
+xpos
,m_position
.top
+ypos
,0);
467 // special case if no parent
468 if (xpos
>= 0 && xpos
< m_position
.right
-m_position
.left
&& ypos
>= 0 && ypos
< m_position
.bottom
-m_position
.top
) parhit
=this;
480 if ((m_pressed
&3)!=(wp
&3))
487 int WDL_VirtualIconButton::OnMouseDown(int xpos
, int ypos
)
489 if (m_en
&&m_is_button
)
493 if (m__iaccess
) m__iaccess
->OnFocused();
497 DoSendCommand(xpos
, ypos
);
505 bool WDL_VirtualIconButton::OnMouseDblClick(int xpos
, int ypos
)
509 DoSendCommand(xpos
, ypos
);
515 void WDL_VirtualIconButton::OnMouseUp(int xpos
, int ypos
)
517 if (!m_is_button
) return;
519 int waspress
=!!m_pressed
;
523 if (waspress
&& !m_immediate
)
525 DoSendCommand(xpos
, ypos
);
529 void WDL_VirtualIconButton::DoSendCommand(int xpos
, int ypos
)
533 xpos
< m_position
.right
-m_position
.left
&&
535 ypos
< m_position
.bottom
-m_position
.top
)
538 if (!m_iconCfg
&& m_textlbl
.Get()[0] && m_checkstate
>= 0)
540 if (xpos
< m_position
.bottom
-m_position
.top
)
546 SendCommand(WM_COMMAND
,code
,0,this);
547 if (a
.isOK() && m__iaccess
&& m_checkstate
>=0) m__iaccess
->OnStateChange();
552 WDL_VirtualComboBox::WDL_VirtualComboBox()
559 WDL_VirtualComboBox::~WDL_VirtualComboBox()
561 m_items
.Empty(true,free
);
565 static void GenSubMenu(HMENU menu
, int *x
, WDL_PtrList
<char> *items
, int curitem
)
568 while (*x
< items
->GetSize())
570 MENUITEMINFO mi
={sizeof(mi
),MIIM_ID
|MIIM_STATE
|MIIM_TYPE
,MFT_STRING
, 0,1000u + *x
,NULL
,NULL
,NULL
,0};
571 mi
.dwTypeData
= (char *)items
->Get(*x
);
572 mi
.fState
= curitem
== *x
?MFS_CHECKED
:0;
574 (*x
) ++; // advance to next item
576 if (!strcmp(mi
.dwTypeData
,"<SEP>")) mi
.fType
=MFT_SEPARATOR
;
577 else if (!strcmp(mi
.dwTypeData
,"</SUB>")) break; // done!
578 else if (!strncmp(mi
.dwTypeData
,"<SUB>",5))
580 mi
.hSubMenu
= CreatePopupMenu();
581 GenSubMenu(mi
.hSubMenu
,x
,items
,curitem
);
582 mi
.fMask
|= MIIM_SUBMENU
;
583 mi
.dwTypeData
+= 5; // skip <SUB>
585 InsertMenuItem(menu
,pos
++,TRUE
,&mi
);
589 int WDL_VirtualComboBox::OnMouseDown(int xpos
, int ypos
)
591 if (m__iaccess
) m__iaccess
->OnFocused();
592 if (m_items
.GetSize())
594 //SendCommand(WM_COMMAND, GetID()|(CBN_DROPDOWN<<16), 0, this);
596 HMENU menu
=CreatePopupMenu();
598 GenSubMenu(menu
,&x
,&m_items
,m_curitem
);
600 HWND h
=GetRealParent();
602 WDL_VirtualWnd
*w
=this;
608 p
.y
+=w
==this?r
.bottom
:r
.top
;
613 ClientToScreen(h
,&p
);
619 int ret
=TrackPopupMenu(menu
,TPM_LEFTALIGN
|TPM_TOPALIGN
|TPM_RETURNCMD
|TPM_NONOTIFY
,p
.x
,p
.y
,0,h
,NULL
);
623 if (ret
>=1000 && a
.isOK())
628 SendCommand(WM_COMMAND
,GetID() | (CBN_SELCHANGE
<<16),0,this);
629 if (a
.isOK() && m__iaccess
) m__iaccess
->OnStateChange();
635 void WDL_VirtualComboBox::OnPaint(LICE_IBitmap
*drawbm
, int origin_x
, int origin_y
, RECT
*cliprect
, int rscale
)
638 if (m_font
) m_font
->SetBkMode(TRANSPARENT
);
641 WDL_VWnd::GetPositionPaintExtent(&r
,rscale
);
647 int col
=GSC(COLOR_WINDOW
);
648 col
= LICE_RGBA_FROMNATIVE(col
,255);
649 LICE_FillRect(drawbm
,r
.left
,r
.top
,r
.right
-r
.left
,r
.bottom
-r
.top
,col
,1.0f
,LICE_BLIT_MODE_COPY
);
653 tr
.left
=tr
.right
-(tr
.bottom
-tr
.top
);
654 //int col2=GSC(COLOR_BTNFACE);
655 // col2 = LICE_RGBA_FROMNATIVE(col2,255);
657 LICE_FillRect(drawbm
,tr
.left
,tr
.top
,tr
.right
-tr
.left
,tr
.bottom
-tr
.top
,col
,1.0f
,LICE_BLIT_MODE_COPY
);
661 int tcol
=GSC(COLOR_BTNTEXT
);
662 tcol
=LICE_RGBA_FROMNATIVE(tcol
,255);
663 if (m_font
&& m_items
.Get(m_curitem
)&&m_items
.Get(m_curitem
)[0])
668 m_font
->SetTextColor(tcol
);
672 m_font
->DrawText(drawbm
,m_items
.Get(m_curitem
),-1,&tr
,DT_SINGLELINE
|DT_CALCRECT
|DT_NOPREFIX
);
673 m_font
->DrawText(drawbm
,m_items
.Get(m_curitem
),-1,&tr
,DT_SINGLELINE
|DT_VCENTER
|(r2
.right
< tr
.right
-tr
.left
? DT_CENTER
: DT_LEFT
)|DT_NOPREFIX
);
676 m_font
->DrawText(drawbm
,m_items
.Get(m_curitem
),-1,&tr
,DT_SINGLELINE
|DT_VCENTER
|(m_align
<0?DT_LEFT
:DT_RIGHT
)|DT_NOPREFIX
);
681 int pencol
= GSC(COLOR_3DSHADOW
);
682 pencol
= LICE_RGBA_FROMNATIVE(pencol
,255);
683 int pencol2
= GSC(COLOR_3DHILIGHT
);
684 pencol2
= LICE_RGBA_FROMNATIVE(pencol2
,255);
686 // draw the down arrow button
688 int bs
=(r
.bottom
-r
.top
);
693 LICE_Line(drawbm
,l
,r
.top
,l
,r
.bottom
-1,pencol
,1.0f
,LICE_BLIT_MODE_COPY
,false);
694 LICE_Line(drawbm
,l
-1,r
.top
,l
-1,r
.bottom
-1,pencol2
,1.0f
,LICE_BLIT_MODE_COPY
,false);
696 LICE_Line(drawbm
,l
+bs
/2-a
,r
.top
+bs
/2-a
/2,
697 l
+bs
/2,r
.top
+bs
/2+a
/2,tcol
,1.0f
,LICE_BLIT_MODE_COPY
,true);
698 LICE_Line(drawbm
,l
+bs
/2,r
.top
+bs
/2+a
/2,
699 l
+bs
/2+a
,r
.top
+bs
/2-a
/2, tcol
,1.0f
,LICE_BLIT_MODE_COPY
,true);
705 LICE_Line(drawbm
,r
.left
,r
.bottom
-1,r
.left
,r
.top
,pencol
,1.0f
,0,false);
706 LICE_Line(drawbm
,r
.left
,r
.top
,r
.right
-1,r
.top
,pencol
,1.0f
,0,false);
707 LICE_Line(drawbm
,r
.right
-1,r
.top
,r
.right
-1,r
.bottom
-1,pencol2
,1.0f
,0,false);
708 LICE_Line(drawbm
,r
.left
,r
.bottom
-1,r
.right
-1,r
.bottom
-1,pencol2
,1.0f
,0,false);
715 WDL_VirtualStaticText::WDL_VirtualStaticText()
719 m_margin_r
=m_margin_l
=0;
720 m_margin_t
=m_margin_b
=0;
731 WDL_VirtualStaticText::~WDL_VirtualStaticText()
735 void WDL_VirtualStaticText::SetText(const char *text
)
737 if (strcmp(m_text
.Get(),text
?text
:""))
739 m_text
.Set(text
?text
:"");
740 if (m_font
) RequestRedraw(NULL
);
744 void WDL_VirtualStaticText::SetWantPreserveTrailingNumber(bool abbreviate
)
746 m_wantabbr
=abbreviate
;
747 if (m_font
) RequestRedraw(NULL
);
750 void WDL_VirtualStaticText::GetPositionPaintExtent(RECT
*r
, int rscale
)
752 // overridden in case m_bkbm has outer areas
753 WDL_VWnd::GetPositionPaintExtent(r
,rscale
);
754 if (m_bkbm
&& m_bkbm
->bgimage
)
756 if (m_bkbm
->bgimage_lt
[0]>0 &&
757 m_bkbm
->bgimage_lt
[1]>0 &&
758 m_bkbm
->bgimage_rb
[0]>0 &&
759 m_bkbm
->bgimage_rb
[1]>0 &&
760 m_bkbm
->bgimage_lt_out
[0]>0 &&
761 m_bkbm
->bgimage_lt_out
[1]>0 &&
762 m_bkbm
->bgimage_rb_out
[0]>0 &&
763 m_bkbm
->bgimage_rb_out
[1]>0)
765 r
->left
-= m_bkbm
->bgimage_lt_out
[0]-1;
766 r
->top
-= m_bkbm
->bgimage_lt_out
[1]-1;
767 r
->right
+= m_bkbm
->bgimage_rb_out
[0]-1;
768 r
->bottom
+= m_bkbm
->bgimage_rb_out
[1]-1;
773 int WDL_VirtualStaticText::OnMouseDown(int xpos
, int ypos
)
775 int a
= WDL_VWnd::OnMouseDown(xpos
,ypos
);
778 if (m__iaccess
) m__iaccess
->OnFocused();
782 SendCommand(WM_COMMAND
,GetID() | (STN_CLICKED
<<16),0,this);
788 void WDL_VirtualStaticText::OnPaint(LICE_IBitmap
*drawbm
, int origin_x
, int origin_y
, RECT
*cliprect
, int rscale
)
791 ScaleRect(&r
,rscale
);
795 r
.bottom
+= origin_y
;
797 if (m_bkbm
&& m_bkbm
->bgimage
)
799 WDL_VirtualWnd_ScaledBlitBG(drawbm
,m_bkbm
,
800 r
.left
,r
.top
,r
.right
-r
.left
,r
.bottom
-r
.top
,
801 r
.left
,r
.top
,r
.right
-r
.left
,r
.bottom
-r
.top
,
802 1.0,LICE_BLIT_MODE_COPY
|LICE_BLIT_FILTER_BILINEAR
|LICE_BLIT_USE_ALPHA
);
804 if (m_dotint
&& LICE_GETA(m_bg
))
806 float amt
= LICE_GETA(m_bg
)/255.0f
;
810 float rv
=LICE_GETR(m_bg
)/255.0f
;
811 float gv
=LICE_GETG(m_bg
)/255.0f
;
812 float bv
=LICE_GETB(m_bg
)/255.0f
;
814 float avg
=(rv
+gv
+bv
)*0.33333f
;
815 if (avg
<0.05f
)avg
=0.05f
;
818 float sc2
= (amt
-sc
)/avg
;
820 float sc3
=32.0f
* amt
;
821 float sc4
=64.0f
*(avg
-0.5f
) * amt
;
824 LICE_MultiplyAddRect(drawbm
,
828 sc
+rv
*sc2
+ (1.0f
-amt
),
829 sc
+gv
*sc2
+ (1.0f
-amt
),
830 sc
+bv
*sc2
+ (1.0f
-amt
),
842 LICE_FillRect(drawbm
,r
.left
,r
.top
,r
.right
-r
.left
,r
.bottom
-r
.top
,m_bg
,LICE_GETA(m_bg
)/255.0f
,LICE_BLIT_MODE_COPY
);
847 int cidx
=COLOR_3DSHADOW
;
849 int pencol
= GSC(cidx
);
850 pencol
= LICE_RGBA_FROMNATIVE(pencol
,255);
852 LICE_Line(drawbm
,r
.left
,r
.bottom
-1,r
.left
,r
.top
,pencol
,1.0f
,LICE_BLIT_MODE_COPY
,false);
853 LICE_Line(drawbm
,r
.left
,r
.top
,r
.right
-1,r
.top
,pencol
,1.0f
,LICE_BLIT_MODE_COPY
,false);
854 cidx
=COLOR_3DHILIGHT
;
856 pencol
= LICE_RGBA_FROMNATIVE(pencol
,255);
857 LICE_Line(drawbm
,r
.right
-1,r
.top
,r
.right
-1,r
.bottom
-1,pencol
,1.0f
,LICE_BLIT_MODE_COPY
,false);
858 LICE_Line(drawbm
,r
.right
-1,r
.bottom
-1,r
.left
,r
.bottom
-1,pencol
,1.0f
,LICE_BLIT_MODE_COPY
,false);
870 r
.left
+= m_margin_l
;
871 r
.right
-= m_margin_r
;
873 r
.bottom
-= m_margin_b
;
875 m_didvert
=m_vfont
&& (r
.right
-r
.left
)<(r
.bottom
-r
.top
)/2;
876 LICE_IFont
*font
= m_didvert
? m_vfont
: m_font
;
880 font
->SetBkMode(TRANSPARENT
);
886 font
->DrawText(drawbm
,m_text
.Get(),-1,&r2
,DT_SINGLELINE
|DT_NOPREFIX
|DT_CALCRECT
);
889 if (r2
.bottom
> r
.bottom
-r
.top
) m_didalign
=-1;
893 if (r2
.right
> r
.right
-r
.left
) m_didalign
=-1;
897 int dtflags
=DT_SINGLELINE
|DT_NOPREFIX
;
901 dtflags
|= DT_CENTER
;
902 if (m_didalign
< 0) dtflags
|= DT_TOP
;
903 else if (m_didalign
> 0) dtflags
|= DT_BOTTOM
;
904 else dtflags
|= DT_VCENTER
;
910 if (m_didalign
< 0) dtflags
|= DT_LEFT
;
911 else if (m_didalign
> 0) dtflags
|= DT_RIGHT
;
912 else dtflags
|= DT_CENTER
;
914 const char* txt
=m_text
.Get();
915 const int len
= m_text
.GetLength();
923 if (len
&& txt
[len
-1] > 0 && isdigit(txt
[len
-1]))
925 RECT tr
= { 0, 0, 0, 0 };
926 font
->DrawText(drawbm
, txt
, -1, &tr
, DT_SINGLELINE
|DT_NOPREFIX
|DT_CALCRECT
);
927 if (m_didvert
? (tr
.bottom
> r
.bottom
-r
.top
) : (tr
.right
> r
.right
-r
.left
))
929 strcpy(abbrbuf
, "..");
931 for (i
=len
-1; i
>= 0; --i
)
933 if (txt
[i
] < 0 || !isdigit(txt
[i
]) || len
-i
> 4) break;
935 strcat(abbrbuf
, txt
+i
+1);
937 int f
=dtflags
&~(DT_TOP
|DT_VCENTER
|DT_BOTTOM
|DT_LEFT
|DT_CENTER
|DT_RIGHT
);
938 RECT tr2
= { 0, 0, 0, 0 };
941 font
->DrawText(drawbm
, abbrbuf
, -1, &tr2
, f
|DT_CALCRECT
);
946 font
->DrawText(drawbm
, abbrbuf
, -1, &tr2
, f
|DT_CALCRECT
);
953 int tcol
=m_fg
? m_fg
: LICE_RGBA_FROMNATIVE(GSC(COLOR_BTNTEXT
));
954 font
->SetTextColor(tcol
);
955 if (m_fg
&& LICE_GETA(m_fg
) != 0xff) font
->SetCombineMode(LICE_BLIT_MODE_COPY
,LICE_GETA(m_fg
)/255.0f
);
957 if (abbrx
&& abbrbuf
[0])
961 int f
=dtflags
&~(DT_TOP
|DT_VCENTER
|DT_BOTTOM
);
962 RECT r1
= { r
.left
, r
.top
, r
.right
, r
.bottom
-abbrx
};
963 font
->DrawText(drawbm
, txt
, -1, &r1
, f
|DT_TOP
);
964 RECT r2
= { r
.left
, r
.bottom
-abbrx
, r
.right
, r
.bottom
};
965 font
->DrawText(drawbm
, abbrbuf
, -1, &r2
, f
|DT_BOTTOM
);
969 int f
=dtflags
&~(DT_LEFT
|DT_CENTER
|DT_RIGHT
);
970 RECT r1
= { r
.left
, r
.top
, r
.right
-abbrx
, r
.bottom
};
971 font
->DrawText(drawbm
, txt
, -1, &r1
, f
|DT_LEFT
);
972 RECT r2
= { r
.right
-abbrx
, r
.top
, r
.right
, r
.bottom
};
973 font
->DrawText(drawbm
, abbrbuf
, -1, &r2
, f
|DT_RIGHT
);
978 font
->DrawText(drawbm
,txt
,-1,&r
,dtflags
);
981 if (m_fg
&& LICE_GETA(m_fg
) != 0xff) font
->SetCombineMode(LICE_BLIT_MODE_COPY
,1.0f
);
986 WDL_VWnd::OnPaint(drawbm
,origin_x
,origin_y
,cliprect
,rscale
);
990 int WDL_VirtualStaticText::GetCharFromCoord(int xpos
, int ypos
)
992 LICE_IFont
*font
= (m_didvert
? m_vfont
: m_font
);
993 if (!font
) return -1;
995 const char* str
= m_text
.Get();
996 const int len
= m_text
.GetLength();
999 // for align left/right, we could DT_CALCRECT with 1 char, then 2, etc, but that won't work for align center
1000 // so we'll just estimate
1001 RECT tr
= { 0, 0, m_position
.right
-m_position
.left
, m_position
.bottom
-m_position
.top
};
1002 font
->DrawText(0, str
, len
, &tr
, DT_SINGLELINE
|DT_NOPREFIX
|DT_CALCRECT
);
1006 RECT r
= m_position
;
1014 r
.left
+= m_margin_l
;
1015 r
.top
+= m_margin_t
;
1016 r
.right
-= m_margin_r
;
1017 r
.bottom
-= m_margin_b
;
1018 int w
= r
.right
-r
.left
;
1019 int h
= r
.bottom
-r
.top
;
1024 r
.right
-= (w
-tw
)/2;
1029 r
.bottom
-= (h
-th
)/2;
1034 if (m_didvert
) r
.bottom
= r
.top
+th
;
1035 else r
.right
= r
.left
+tw
;
1037 else if (m_didalign
> 0)
1039 if (m_didvert
) r
.top
= r
.bottom
-th
;
1040 else r
.left
= r
.right
-tw
;
1047 r
.bottom
-= (h
-th
)/2;
1052 r
.right
-= (w
-tw
)/2;
1059 if (ypos
< r
.top
) c
=-1;
1060 else if (ypos
> r
.bottom
) c
=len
;
1061 else c
= (int)((double)len
*(double)(ypos
-r
.top
)/(double)(r
.bottom
-r
.top
));
1065 if (xpos
< r
.left
) c
=-1;
1066 else if (xpos
> r
.right
) c
=len
;
1067 else c
= (int)((double)len
*(double)(xpos
-r
.left
)/(double)(r
.right
-r
.left
));
1074 bool WDL_VirtualStaticText::OnMouseDblClick(int xpos
, int ypos
)
1076 if (!WDL_VWnd::OnMouseDblClick(xpos
,ypos
))
1078 SendCommand(WM_COMMAND
,GetID() | (STN_DBLCLK
<<16),0,this);
1085 bool WDL_VirtualIconButton::WantsPaintOver()
1087 return /*m_is_button && */m_iconCfg
&& m_iconCfg
->image
&& m_iconCfg
->olimage
;
1090 void WDL_VirtualIconButton::GetPositionPaintOverExtent(RECT
*r
, int rscale
)
1092 WDL_VWnd::GetPositionPaintOverExtent(r
,rscale
);
1093 if (m_iconCfg
&& m_iconCfg
->image
&& m_iconCfg
->olimage
&& (m_iconCfg
->image_ltrb_used
.flags
&1))
1095 if (m_iconCfg
->image_ltrb_used
.flags
&2) // main image has pink lines, use 1:1 pixel for outer area size
1097 r
->left
-= m_iconCfg
->image_ltrb_ol
[0];
1098 r
->top
-= m_iconCfg
->image_ltrb_ol
[1];
1099 r
->right
+= m_iconCfg
->image_ltrb_ol
[2];
1100 r
->bottom
+= m_iconCfg
->image_ltrb_ol
[3];
1104 int w
=(m_iconCfg
->olimage
->getWidth()-2)/3-m_iconCfg
->image_ltrb_ol
[0]-m_iconCfg
->image_ltrb_ol
[2];
1106 double wsc
=(r
->right
-r
->left
)/(double)w
;
1108 int h
=m_iconCfg
->olimage
->getHeight()-2-m_iconCfg
->image_ltrb_ol
[1]-m_iconCfg
->image_ltrb_ol
[3];
1110 double hsc
=(r
->bottom
-r
->top
)/(double)h
;
1112 r
->left
-=(int) (m_iconCfg
->image_ltrb_ol
[0]*wsc
);
1113 r
->top
-=(int) (m_iconCfg
->image_ltrb_ol
[1]*hsc
);
1114 r
->right
+=(int) (m_iconCfg
->image_ltrb_ol
[2]*wsc
);
1115 r
->bottom
+=(int) (m_iconCfg
->image_ltrb_ol
[3]*hsc
);
1119 void WDL_VirtualIconButton_PreprocessSkinConfig(WDL_VirtualIconButton_SkinConfig
*a
)
1123 a
->image_ltrb_used
.flags
=0;
1127 LICE_IBitmap
*srcimg
= wi
? a
->image
: a
->olimage
;
1128 if (!srcimg
) continue;
1129 int w
=srcimg
->getWidth();
1130 int h
=srcimg
->getHeight();
1132 if (LICE_GetPixel(srcimg
,0,0)==LICE_RGBA(255,0,255,255)&&
1133 LICE_GetPixel(srcimg
,w
-1,h
-1)==LICE_RGBA(255,0,255,255))
1135 int lext
=0,rext
=0,bext
=0,text
=0;
1137 for (x
= 1; x
< w
/3 && LICE_GetPixel(srcimg
,x
,0)==LICE_RGBA(255,0,255,255); x
++);
1139 for (x
= 1; x
< h
&& LICE_GetPixel(srcimg
,0,x
)==LICE_RGBA(255,0,255,255); x
++);
1142 for (x
= w
-2; x
>= (w
*2/3) && LICE_GetPixel(srcimg
,x
,h
-1)==LICE_RGBA(255,0,255,255); x
--);
1144 for (x
= h
-2; x
>= text
&& LICE_GetPixel(srcimg
,w
-1,x
)==LICE_RGBA(255,0,255,255); x
--);
1146 if (lext
||text
||rext
||bext
)
1148 a
->image_ltrb_used
.flags
|= 1 << wi
;
1149 short *buf
= wi
? a
->image_ltrb_main
: a
->image_ltrb_ol
;