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