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 "ccontrol.h"
6 #include "icontrollistener.h"
7 #include "../cframe.h"
8 #include "../cgraphicspath.h"
9 #include <cassert>
10 
11 #define VSTGUI_CCONTROL_LOG_EDITING 0 //DEBUG
12 
13 namespace VSTGUI {
14 
15 #if VSTGUI_ENABLE_DEPRECATED_METHODS
16 IdStringPtr CControl::kMessageValueChanged = "kMessageValueChanged";
17 IdStringPtr CControl::kMessageBeginEdit = "kMessageBeginEdit";
18 IdStringPtr CControl::kMessageEndEdit = "kMessageEndEdit";
19 #endif
20 
21 //------------------------------------------------------------------------
22 // CControl
23 //------------------------------------------------------------------------
24 /*! @class CControl
25 This object manages the tag identification and the value of a control object.
26 */
CControl(const CRect & size,IControlListener * listener,int32_t tag,CBitmap * pBackground)27 CControl::CControl (const CRect& size, IControlListener* listener, int32_t tag, CBitmap *pBackground)
28 : CView (size)
29 , listener (listener)
30 , tag (tag)
31 , oldValue (1)
32 , defaultValue (0.5f)
33 , value (0)
34 , vmin (0)
35 , vmax (1.f)
36 , wheelInc (0.1f)
37 , editing (0)
38 {
39 	setTransparency (false);
40 	setMouseEnabled (true);
41 	setBackground (pBackground);
42 }
43 
44 //------------------------------------------------------------------------
CControl(const CControl & c)45 CControl::CControl (const CControl& c)
46 : CView (c)
47 , listener (c.listener)
48 , tag (c.tag)
49 , oldValue (c.oldValue)
50 , defaultValue (c.defaultValue)
51 , value (c.value)
52 , vmin (c.vmin)
53 , vmax (c.vmax)
54 , wheelInc (c.wheelInc)
55 , editing (0)
56 {
57 }
58 
59 //------------------------------------------------------------------------
registerControlListener(IControlListener * subListener)60 void CControl::registerControlListener (IControlListener* subListener)
61 {
62 	vstgui_assert (listener != subListener, "the subListener is already the main listener");
63 	subListeners.add (subListener);
64 }
65 
66 //------------------------------------------------------------------------
unregisterControlListener(IControlListener * subListener)67 void CControl::unregisterControlListener (IControlListener* subListener)
68 {
69 	subListeners.remove (subListener);
70 }
71 
72 //------------------------------------------------------------------------
73 int32_t CControl::kZoomModifier = kShift;
74 int32_t CControl::kDefaultValueModifier = kControl;
75 
76 //------------------------------------------------------------------------
setTag(int32_t val)77 void CControl::setTag (int32_t val)
78 {
79 	if (listener)
80 		listener->controlTagWillChange (this);
81 	tag = val;
82 	if (listener)
83 		listener->controlTagDidChange (this);
84 }
85 
86 //------------------------------------------------------------------------
beginEdit()87 void CControl::beginEdit ()
88 {
89 	// begin of edit parameter
90 	editing++;
91 	if (editing == 1)
92 	{
93 		if (listener)
94 			listener->controlBeginEdit (this);
95 		subListeners.forEach ([this] (IControlListener* l) { l->controlBeginEdit (this); });
96 #if VSTGUI_ENABLE_DEPRECATED_METHODS
97 		changed (kMessageBeginEdit);
98 #endif
99 		if (getFrame ())
100 			getFrame ()->beginEdit (tag);
101 	}
102 #if VSTGUI_CCONTROL_LOG_EDITING
103 	DebugPrint("beginEdit [%d] - %d\n", tag, editing);
104 #endif
105 }
106 
107 //------------------------------------------------------------------------
endEdit()108 void CControl::endEdit ()
109 {
110 	editing--;
111 	vstgui_assert(editing >= 0);
112 	if (editing == 0)
113 	{
114 		if (getFrame ())
115 			getFrame ()->endEdit (tag);
116 		if (listener)
117 			listener->controlEndEdit (this);
118 		subListeners.forEach ([this] (IControlListener* l) { l->controlEndEdit (this); });
119 #if VSTGUI_ENABLE_DEPRECATED_METHODS
120 		changed (kMessageEndEdit);
121 #endif
122 	}
123 #if VSTGUI_CCONTROL_LOG_EDITING
124 	DebugPrint("endEdit [%d] - %d\n", tag, editing);
125 #endif
126 }
127 
128 //------------------------------------------------------------------------
setValue(float val)129 void CControl::setValue (float val)
130 {
131 	if (val < getMin ())
132 		val = getMin ();
133 	else if (val > getMax ())
134 		val = getMax ();
135 	if (val != value)
136 	{
137 		value = val;
138 #if VSTGUI_ENABLE_DEPRECATED_METHODS
139 		changed (kMessageValueChanged);
140 #endif
141 	}
142 }
143 
144 //------------------------------------------------------------------------
setValueNormalized(float val)145 void CControl::setValueNormalized (float val)
146 {
147 	if (val > 1.f)
148 		val = 1.f;
149 	else if (val < 0.f)
150 		val = 0.f;
151 	setValue (getRange () * val + getMin ());
152 }
153 
154 //------------------------------------------------------------------------
getValueNormalized() const155 float CControl::getValueNormalized () const
156 {
157 	return (value - getMin ()) / getRange ();
158 }
159 
160 //------------------------------------------------------------------------
valueChanged()161 void CControl::valueChanged ()
162 {
163 	if (listener)
164 		listener->valueChanged (this);
165 	subListeners.forEach ([this] (IControlListener* l) { l->valueChanged (this); });
166 #if VSTGUI_ENABLE_DEPRECATED_METHODS
167 	changed (kMessageValueChanged);
168 #endif
169 }
170 
171 //------------------------------------------------------------------------
isDirty() const172 bool CControl::isDirty () const
173 {
174 	if (getOldValue () != value || CView::isDirty ())
175 		return true;
176 	return false;
177 }
178 
179 //------------------------------------------------------------------------
setDirty(bool val)180 void CControl::setDirty (bool val)
181 {
182 	CView::setDirty (val);
183 	if (val)
184 	{
185 		if (value != -1.f)
186 			setOldValue (-1.f);
187 		else
188 			setOldValue (0.f);
189 	}
190 	else
191 		setOldValue (value);
192 }
193 
194 //------------------------------------------------------------------------
bounceValue()195 void CControl::bounceValue ()
196 {
197 	if (value > getMax ())
198 		value = getMax ();
199 	else if (value < getMin ())
200 		value = getMin ();
201 }
202 
203 //-----------------------------------------------------------------------------
checkDefaultValue(CButtonState button)204 bool CControl::checkDefaultValue (CButtonState button)
205 {
206 #if TARGET_OS_IPHONE
207 	if (button.isDoubleClick ())
208 #else
209 	if (button.isLeftButton () && button.getModifierState () == kDefaultValueModifier)
210 #endif
211 	{
212 		float defValue = getDefaultValue ();
213 		if (defValue != getValue ())
214 		{
215 			// begin of edit parameter
216 			beginEdit ();
217 
218 			setValue (defValue);
219 			valueChanged ();
220 
221 			// end of edit parameter
222 			endEdit ();
223 
224 			setDirty ();
225 		}
226 		return true;
227 	}
228 	return false;
229 }
230 
231 //------------------------------------------------------------------------
drawFocusOnTop()232 bool CControl::drawFocusOnTop ()
233 {
234 	return false;
235 }
236 
237 //------------------------------------------------------------------------
getFocusPath(CGraphicsPath & outPath)238 bool CControl::getFocusPath (CGraphicsPath& outPath)
239 {
240 	if (wantsFocus ())
241 	{
242 		CCoord focusWidth = getFrame ()->getFocusWidth ();
243 		CRect r (getVisibleViewSize ());
244 		if (!r.isEmpty ())
245 		{
246 			outPath.addRect (r);
247 			r.extend (focusWidth, focusWidth);
248 			outPath.addRect (r);
249 		}
250 	}
251 	return true;
252 }
253 
254 //-----------------------------------------------------------------------------
mapVstKeyModifier(int32_t vstModifier)255 int32_t CControl::mapVstKeyModifier (int32_t vstModifier)
256 {
257 	int32_t modifiers = 0;
258 	if (vstModifier & MODIFIER_SHIFT)
259 		modifiers |= kShift;
260 	if (vstModifier & MODIFIER_ALTERNATE)
261 		modifiers |= kAlt;
262 	if (vstModifier & MODIFIER_COMMAND)
263 		modifiers |= kApple;
264 	if (vstModifier & MODIFIER_CONTROL)
265 		modifiers |= kControl;
266 	return modifiers;
267 }
268 
269 //------------------------------------------------------------------------
270 //------------------------------------------------------------------------
271 //------------------------------------------------------------------------
autoComputeHeightOfOneImage()272 void IMultiBitmapControl::autoComputeHeightOfOneImage ()
273 {
274 	auto* view = dynamic_cast<CView*>(this);
275 	if (view)
276 	{
277 		const CRect& viewSize = view->getViewSize ();
278 		heightOfOneImage = viewSize.getHeight ();
279 	}
280 }
281 
282 } // namespace
283