1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4 
5 #include "cspecialdigit.h"
6 #include "../cdrawcontext.h"
7 #include "../cbitmap.h"
8 #include <cmath>
9 
10 namespace VSTGUI {
11 
12 //------------------------------------------------------------------------
13 // CSpecialDigit
14 //------------------------------------------------------------------------
15 /*! @class CSpecialDigit
16 Can be used to display a counter with maximum 7 digits.
17 All digit have the same size and are stacked in height in the bitmap.
18 */
19 //------------------------------------------------------------------------
20 /**
21  * CSpecialDigit constructor.
22  * @param size the size of this view
23  * @param listener the listener
24  * @param tag the control tag
25  * @param dwPos actual value
26  * @param iNumbers amount of numbers (max 7)
27  * @param xpos array of all X positions, can be NULL
28  * @param ypos array of all Y positions, can be NULL
29  * @param width width of one number in the bitmap
30  * @param height height of one number in the bitmap
31  * @param background bitmap
32  */
33 //------------------------------------------------------------------------
CSpecialDigit(const CRect & size,IControlListener * listener,int32_t tag,int32_t dwPos,int32_t inNumbers,int32_t * xpos,int32_t * ypos,int32_t width,int32_t height,CBitmap * background)34 CSpecialDigit::CSpecialDigit (const CRect& size, IControlListener* listener, int32_t tag, int32_t dwPos, int32_t inNumbers, int32_t* xpos, int32_t* ypos, int32_t width, int32_t height, CBitmap* background)
35 : CControl (size, listener, tag, background)
36 , iNumbers (inNumbers)
37 , width (width)
38 , height (height)
39 {
40 	setValue ((float)dwPos);          // actual value
41 
42 	if (iNumbers > 7)
43 		iNumbers = 7;
44 
45 	if (xpos == nullptr)
46 	{
47 		// automatically init xpos/ypos if not provided by caller
48 		const int32_t numw = (const int32_t)background->getWidth();
49 		int32_t x = (int32_t)size.left;
50 		for (int32_t i = 0; i < inNumbers; i++)
51 		{
52 			this->xpos[i] = x;
53 			this->ypos[i] = (int32_t)size.top;
54 			x += numw;
55 		}
56 	}
57 	else if (xpos && ypos)
58 	{
59 		// store coordinates of x/y pos of each digit
60 		for (int32_t i = 0; i < inNumbers; i++)
61 		{
62 			this->xpos[i] = xpos[i];
63 			this->ypos[i] = ypos[i];
64 		}
65 	}
66 
67 	setMax ((float)pow (10.f, (float)inNumbers) - 1.0f);
68 	setMin (0.0f);
69 }
70 
71 //------------------------------------------------------------------------
CSpecialDigit(const CSpecialDigit & v)72 CSpecialDigit::CSpecialDigit (const CSpecialDigit& v)
73 : CControl (v)
74 , iNumbers (v.iNumbers)
75 , width (v.width)
76 , height (v.height)
77 {
78 	for (int32_t i = 0; i < 7; i++)
79 	{
80 		xpos[i] = v.xpos[i];
81 		ypos[i] = v.ypos[i];
82 	}
83 }
84 
85 //------------------------------------------------------------------------
draw(CDrawContext * pContext)86 void CSpecialDigit::draw (CDrawContext *pContext)
87 {
88 	CPoint where;
89 	CRect rectDest;
90 	int32_t i, j;
91 	int32_t one_digit[16] = {};
92 
93 	int32_t dwValue = static_cast<int32_t> (getValue ());
94 	int32_t intMax = static_cast<int32_t> (getMax ());
95 	if (dwValue > intMax)
96 		dwValue = intMax;
97 	else if (dwValue < static_cast<int32_t> (getMin ()))
98 		dwValue = static_cast<int32_t> (getMin ());
99 
100 	for (i = 0, j = (intMax + 1) / 10; i < iNumbers; i++, j /= 10)
101 	{
102 		one_digit[i] = dwValue / j;
103 		dwValue -= (one_digit[i] * j);
104 	}
105 
106 	where.x = 0;
107 	for (i = 0; i < iNumbers; i++)
108 	{
109 		j = one_digit[i];
110 		if (j > 9)
111 			j = 9;
112 
113 		rectDest.left   = (CCoord)xpos[i];
114 		rectDest.top    = (CCoord)ypos[i];
115 
116 		rectDest.right  = rectDest.left + width;
117 		rectDest.bottom = rectDest.top  + height;
118 
119 		// where = src from bitmap
120 		where.y = (CCoord)j * height;
121 		if (getDrawBackground ())
122 		{
123 			getDrawBackground ()->draw (pContext, rectDest, where);
124 		}
125 	}
126 
127 	setDirty (false);
128 }
129 
130 } // VSTGUI
131