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