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 /**
6 @page uidescription_attributes UI XML Attribute Definitions
7 
8 @section viewclasses View Classes and their attributes
9 - @ref cview @n
10 - @ref cviewcontainer @n
11 - @ref ccontrol @n
12 - @ref conoffbutton @n
13 - @ref cparamdisplay @n
14 - @ref ctextlabel @n
15 - @ref ctextedit @n
16 - @ref ctextbutton @n
17 - @ref csegmentbutton @n
18 - @ref cknob @n
19 - @ref cverticalswitch @n
20 - @ref chorizontalswitch @n
21 - @ref crockerswitch @n
22 - @ref cmoviebitmap @n
23 - @ref ckickbutton @n
24 - @ref cslider @n
25 - @ref cvumeter @n
26 - @ref coptionmenu @n
27 - @ref uiviewswitchcontainer @n
28 
29 @section cview CView
30 Declaration:
31 @verbatim <view class="CView" /> @endverbatim
32 
33 Attributes:
34 - \b origin [Point]
35 - \b size [Point]
36 - \b transparent [true/false]
37 - \b bitmap [bitmap name]
38 - \b autosize [combination of <i>left</i>, <i>top</i>, <i>right</i>, <i>bottom</i>, <i>row</i>, or <i>column</i> see VSTGUI::CViewAutosizing]
39 - \b tooltip [tooltip text]
40 
41 @section cviewcontainer CViewContainer
42 Declaration:
43 @verbatim <view class="CViewContainer" /> @endverbatim
44 
45 Inherites attributes from @ref cview @n
46 
47 Attributes:
48 - \b background-color [color]
49 
50 @section ccontrol CControl
51 A CControl is an abstract class and can not be created directly
52 
53 Inherites attributes from @ref cview @n
54 
55 Attributes:
56 - \b control-tag [tag name]
57 - \b default-value [float]
58 - \b min-value [float]
59 - \b max-value [float]
60 - \b wheel-inc-value [float]
61 - \b background-offset [Point]
62 
63 @section conoffbutton COnOffButton
64 Declaration:
65 @verbatim <view class="COnOffButton" /> @endverbatim
66 
67 Inherites attributes from @ref ccontrol @n
68 
69 @section cparamdisplay CParamDisplay
70 Declaration:
71 @verbatim <view class="CParamDisplay" /> @endverbatim
72 
73 Inherites attributes from @ref ccontrol @n
74 
75 Attributes:
76 - \b font [font name]
77 - \b font-color [color]
78 - \b back-color [color]
79 - \b frame-color [color]
80 - \b frame-width [float]
81 - \b round-rect-radius [float]
82 - \b shadow-color [color]
83 - \b font-antialias [true/false]
84 - \b style-3D-in [true/false]
85 - \b style-3D-out [true/false]
86 - \b style-no-frame [true/false]
87 - \b style-no-text [true/false]
88 - \b style-no-draw [true/false]
89 - \b style-round-rect [true/false]
90 - \b style-shadow-text [true/false]
91 - \b text-alignment [left/center/right]
92 - \b text-rotation [float]
93 - \b value-precision [integer]
94 
95 @section ctextlabel CTextLabel
96 Declaration:
97 @verbatim <view class="CTextLabel" /> @endverbatim
98 
99 Inherites attributes from @ref cparamdisplay @n
100 
101 Attributes:
102 - \b title [string]
103 
104 @section ctextedit CTextEdit
105 Declaration:
106 @verbatim <view class="CTextEdit" /> @endverbatim
107 
108 Inherites attributes from @ref cparamdisplay @n
109 
110 Attributes:
111 - \b title [string]
112 
113 @section cknob CKnob
114 Declaration:
115 @verbatim <view class="CKnob" /> @endverbatim
116 
117 Inherites attributes from @ref ccontrol @n
118 
119 Attributes:
120 - \b angle-start [float]
121 - \b angle-range [float]
122 - \b value-inset [int]
123 - \b zoom-factor [float]
124 - \b handle-shadow-color [color]
125 - \b handle-color [color]
126 - \b handle-bitmap [bitmap name]
127 
128 @section canimknob CAnimKnob
129 Declaration:
130 @verbatim <view class="CAnimKnob" /> @endverbatim
131 
132 Inherites attributes from @ref cknob @n
133 
134 Attributes:
135 - \b height-of-one-image [int]
136 
137 @section cverticalswitch CVerticalSwitch
138 Declaration:
139 @verbatim <view class="CVerticalSwitch" /> @endverbatim
140 
141 Inherites attributes from @ref ccontrol @n
142 
143 Attributes:
144 - \b height-of-one-image [int]
145 
146 @section chorizontalswitch CHorizontalSwitch
147 Declaration:
148 @verbatim <view class="CHorizontalSwitch" /> @endverbatim
149 
150 Inherites attributes from @ref ccontrol @n
151 
152 Attributes:
153 - \b height-of-one-image [int]
154 
155 @section crockerswitch CRockerSwitch
156 Declaration:
157 @verbatim <view class="CRockerSwitch" /> @endverbatim
158 
159 Inherites attributes from @ref ccontrol @n
160 
161 Attributes:
162 - \b height-of-one-image [int]
163 
164 @section cmoviebitmap CMovieBitmap
165 Declaration:
166 @verbatim <view class="CMovieBitmap" /> @endverbatim
167 
168 Inherites attributes from @ref ccontrol @n
169 
170 Attributes:
171 - \b height-of-one-image [int]
172 
173 @section cmoviebutton CMovieButton
174 Declaration:
175 @verbatim <view class="CMovieButton" /> @endverbatim
176 
177 Inherites attributes from @ref ccontrol @n
178 
179 Attributes:
180 - \b height-of-one-image [int]
181 
182 @section ckickbutton CKickButton
183 Declaration:
184 @verbatim <view class="CKickButton" /> @endverbatim
185 
186 Inherites attributes from @ref ccontrol @n
187 
188 Attributes:
189 - \b height-of-one-image [int]
190 
191 @section ctextbutton CTextButton
192 Declaration:
193 @verbatim <view class="CTextButton" /> @endverbatim
194 
195 Inherits attributes from @ref ccontrol @n
196 
197 New style (named) gradients are supported by:
198 - \b gradient
199 - \b gradient-highlighted
200 
201 Old style (parametric) gradients are supported by:
202 - \b gradient-start-color
203 - \b gradient-end-color
204 - \b gradient-start-color-hightlighted
205 - \b gradient-end-color-highlighted
206 
207 When named gradients are used, the parametric gradient information is discarded.
208 
209 Attributes:
210 - \b title [string]
211 - \b font [string]
212 - \b text-alignment [left/right/center]
213 - \b text-color [color string]
214 - \b text-color-highlighted [color string]
215 - \b frame-color [color string]
216 - \b frame-color-highlighted [color string]
217 - \b frame-width [float]
218 - \b round-radius [float]
219 - \b icon-text-margin [float]
220 - \b kick-style [true/false]
221 - \b icon [string]
222 - \b icon-highlighted [string]
223 - \b icon-position [left/right/center above text/center below text]
224 - \b gradient [string]
225 - \b gradient-highlighted [string]
226 - \b gradient-start-color [color string]
227 - \b graident-end-color [color string]
228 - \b gradient-start-color-hightlighted [color string]
229 - \b gradient-end-color-highlighted [color string]
230 
231 @section csegmentbutton CSegmentButton
232 Declaration:
233 @verbatim <view class="CSegmentButton" /> @endverbatim
234 
235 Inherits attributes from @ref ccontrol @n
236 
237 note: a string array is a comma seperated string: "one,two,three".
238 
239 Attributes:
240 - \b font [string]
241 - \b style [horizontal/vertical]
242 - \b text-alignment [left/right/center]
243 - \b text-color [color string]
244 - \b text-color-highlighted [color string]
245 - \b frame-color [color string]
246 - \b frame-color-highlighted [color string]
247 - \b frame-width [float]
248 - \b round-radius [float]
249 - \b icon-text-margin [float]
250 - \b gradient [string]
251 - \b gradient-highlighted [string]
252 - \b segment-names [string array]
253 - \b truncate-mode [head/tail/none]
254 
255 @section cslider CSlider
256 Declaration:
257 @verbatim <view class="CSlider" /> @endverbatim
258 
259 Inherites attributes from @ref ccontrol @n
260 
261 Attributes:
262 - \b transparent-handle [true/false]
263 - \b free-click [true/false]
264 - \b handle-bitmap [bitmap name]
265 - \b handle-offset [Point]
266 - \b mode [touch/relative touch/free click]
267 - \b draw-frame [true/false]
268 - \b draw-back [true/false]
269 - \b draw-value [true/false]
270 - \b draw-value-inverted [true/false]
271 - \b draw-value-from-center [true/false]
272 - \b draw-back-color [color string]
273 - \b draw-value-color [color string]
274 - \b bitmap-offset [Point]
275 - \b zoom-factor [float]
276 - \b orientation [vertical/horizontal]
277 - \b reverse-orientation [true/false]
278 
279 @section coptionmenu COptionMenu
280 Declaration:
281 @verbatim <view class="COptionMenu" /> @endverbatim
282 
283 Inherites attributes from @ref cparamdisplay @n
284 
285 Attributes:
286 - \b menu-popup-style [true/false]
287 - \b menu-check-style [true/false]
288 
289 @section cvumeter CVuMeter
290 Declaration:
291 @verbatim <view class="CVuMeter" /> @endverbatim
292 
293 Inherites attributes from @ref cviewcontainer @n
294 
295 Attributes:
296 - \b off-bitmap [bitmap name]
297 - \b num-led [integer]
298 - \b orientation [vertical/horizontal]
299 - \b decrease-step-value [float]
300 
301 @section uiviewswitchcontainer UIViewSwitchContainer
302 Declaration:
303 @verbatim <view class="UIViewSwitchContainer" /> @endverbatim
304 
305 - \b template-names [string array]
306 - \b template-switch-control [tag name]
307 - \b animation-style [fade/move/push]
308 - \b animation-time [integer]
309 
310 @cond ignore
311 */
312 
313 /*
314 class CViewCreator : public ViewCreatorAdapter
315 {
316 public:
317 	IdStringPtr getViewName () const { return "CView"; }
318 	IdStringPtr getBaseViewName () const { return 0; }
319 	CView* create (const UIAttributes& attributes, IUIDescription* description) const { return new CView (CRect (0, 0, 0, 0)); }
320 	bool apply (CView* view, const UIAttributes& attributes, IUIDescription* description) const
321 	{
322 		auto* control = dynamic_cast<CControl*> (view);
323 		if (control == 0)
324 			return false;
325 		return true;
326 	}
327 	bool getAttributeNames (std::list<std::string>& attributeNames) const
328 	{
329 		attributeNames.emplace_back ("empty");
330 		return true;
331 	}
332 	AttrType getAttributeType (const std::string& attributeName) const
333 	{
334 		if (attributeName == "empty") return kUnknownType;
335 		else if (attributeName == "empty2") return kUnknownType;
336 		return kUnknownType;
337 	}
338 
339 };
340 */
341 
342 #include "iviewfactory.h"
343 #include "iviewcreator.h"
344 #include "detail/uiviewcreatorattributes.h"
345 #include "uiviewcreator.h"
346 #include "uiviewfactory.h"
347 #include "uiviewswitchcontainer.h"
348 #include "uiattributes.h"
349 #include "uidescription.h"
350 #include "../vstgui.h"
351 #include <sstream>
352 #include <array>
353 
354 namespace VSTGUI {
355 namespace UIViewCreator {
356 
357 static constexpr auto strTrue = "true";
358 static constexpr auto strFalse = "false";
359 static constexpr auto strHorizontal = "horizontal";
360 static constexpr auto strVertical = "vertical";
361 
362 static constexpr auto strNone = "none";
363 static constexpr auto strHead = "head";
364 static constexpr auto strTail = "tail";
365 
366 static constexpr auto strLeft = "left";
367 static constexpr auto strRight = "right";
368 static constexpr auto strCenter = "center";
369 
370 //-----------------------------------------------------------------------------
numberToString(T value)371 template<typename T> std::string numberToString (T value)
372 {
373 	std::stringstream str;
374 	str << value;
375 	return str.str ();
376 }
377 
378 //-----------------------------------------------------------------------------
parseSize(const std::string & str,CPoint & point)379 bool parseSize (const std::string& str, CPoint& point)
380 {
381 	size_t sep = str.find (',', 0);
382 	if (sep != std::string::npos)
383 	{
384 		point.x = strtol (str.c_str (), nullptr, 10);
385 		point.y = strtol (str.c_str () + sep+1, nullptr, 10);
386 		return true;
387 	}
388 	return false;
389 }
390 
391 //-----------------------------------------------------------------------------
pointToString(const CPoint & p,std::string & string)392 bool pointToString (const CPoint& p, std::string& string)
393 {
394 	std::stringstream stream;
395 	stream << p.x;
396 	stream << ", ";
397 	stream << p.y;
398 	string = stream.str ();
399 	return true;
400 }
401 
402 //-----------------------------------------------------------------------------
bitmapToString(CBitmap * bitmap,std::string & string,const IUIDescription * desc)403 bool bitmapToString (CBitmap* bitmap, std::string& string, const IUIDescription* desc)
404 {
405 	UTF8StringPtr bitmapName = desc->lookupBitmapName (bitmap);
406 	if (bitmapName)
407 		string = bitmapName;
408 	else
409 	{
410 		const CResourceDescription& res = bitmap->getResourceDescription ();
411 		if (res.type == CResourceDescription::kStringType)
412 			string = res.u.name;
413 		else
414 			string = numberToString (res.u.id);
415 	}
416 	return true;
417 }
418 
419 //-----------------------------------------------------------------------------
colorToString(const CColor & color,std::string & string,const IUIDescription * desc)420 bool colorToString (const CColor& color, std::string& string, const IUIDescription* desc)
421 {
422 	UTF8StringPtr colorName = desc ? desc->lookupColorName (color) : nullptr;
423 	if (colorName)
424 		string = colorName;
425 	else
426 	{
427 		uint8_t red = color.red;
428 		uint8_t green = color.green;
429 		uint8_t blue = color.blue;
430 		uint8_t alpha = color.alpha;
431 		char strBuffer[10];
432 		sprintf (strBuffer, "#%02x%02x%02x%02x", red, green, blue, alpha);
433 		string = strBuffer;
434 	}
435 	return true;
436 }
437 
438 //-----------------------------------------------------------------------------
stringToColor(const std::string * value,CColor & color,const IUIDescription * desc)439 bool stringToColor (const std::string* value, CColor& color, const IUIDescription* desc)
440 {
441 	if (value && *value == "")
442 	{
443 		color = kTransparentCColor;
444 		return true;
445 	}
446 	return value ? desc->getColor (value->c_str (), color) : false;
447 }
448 
449 //-----------------------------------------------------------------------------
stringToBitmap(const std::string * value,CBitmap * & bitmap,const IUIDescription * desc)450 bool stringToBitmap (const std::string* value, CBitmap*& bitmap, const IUIDescription* desc)
451 {
452 	if (value)
453 	{
454 		if (*value == "")
455 			bitmap = nullptr;
456 		else
457 			bitmap = desc->getBitmap (value->c_str ());
458 		return true;
459 	}
460 	return false;
461 }
462 
463 //-----------------------------------------------------------------------------
applyStyleMask(const std::string * value,int32_t mask,int32_t & style)464 static void applyStyleMask (const std::string* value, int32_t mask, int32_t& style)
465 {
466 	if (value)
467 	{
468 		setBit (style, mask, *value == strTrue);
469 	}
470 }
471 
472 //------------------------------------------------------------------------
addGradientToUIDescription(const IUIDescription * description,CGradient * gradient,UTF8StringPtr baseName)473 static void addGradientToUIDescription (const IUIDescription* description, CGradient* gradient, UTF8StringPtr baseName)
474 {
475 	if (!description->lookupGradientName (gradient))
476 	{
477 		auto* uiDesc = dynamic_cast<UIDescription*>(const_cast<IUIDescription*> (description));
478 		if (uiDesc)
479 		{
480 			uint32_t index = 0;
481 			std::stringstream str;
482 			do {
483 				index++;
484 				str.str ("");
485 				str << baseName;
486 				if (index > 1)
487 				{
488 					str << " ";
489 					str << index;
490 				}
491 			} while (description->getGradient (str.str ().c_str ()) != nullptr);
492 			uiDesc->changeGradient (str.str ().c_str (), gradient);
493 		}
494 	}
495 }
496 
497 static bool getStandardAttributeListValues (const std::string& attributeName, std::list<const std::string*>& values);
498 
499 #if VSTGUI_LIVE_EDITING
500 //-----------------------------------------------------------------------------
501 class LiveEditingCView : public CView
502 {
503 public:
LiveEditingCView(const CRect & r)504 	LiveEditingCView (const CRect& r) : CView (r) {}
draw(CDrawContext * context)505 	void draw (CDrawContext* context) override
506 	{
507 		if (getDrawBackground ())
508 		{
509 			CView::draw (context);
510 			return;
511 		}
512 		context->setLineWidth (1.);
513 		context->setLineStyle (kLineSolid);
514 		context->setDrawMode (kAliasing);
515 		context->setFrameColor ({200, 200, 200, 100});
516 		context->setFillColor ({200, 200, 200, 100});
517 		constexpr auto width = 5.;
518 		CRect viewSize = getViewSize ();
519 		auto r = viewSize;
520 		r.setSize ({width,width});
521 		uint32_t row = 0u;
522 		while (r.top < viewSize.bottom)
523 		{
524 			uint32_t column = (row % 2) ? 0u : 1u;
525 			while (r.left < viewSize.right)
526 			{
527 				if (column % 2)
528 					context->drawRect (r, kDrawFilled);
529 				r.offset (width, 0);
530 				++column;
531 			}
532 			r.left = viewSize.left;
533 			r.right = r.left + width;
534 			r.offset (0, width);
535 			++row;
536 		}
537 		context->drawRect (viewSize, kDrawStroked);
538 		setDirty (false);
539 	}
540 };
541 using SimpleCView = LiveEditingCView;
542 #else
543 using SimpleCView = CView;
544 #endif
545 
546 //-----------------------------------------------------------------------------
547 class CViewCreator : public ViewCreatorAdapter
548 {
549 public:
CViewCreator()550 	CViewCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const551 	IdStringPtr getViewName () const override { return kCView; }
getBaseViewName() const552 	IdStringPtr getBaseViewName () const override { return nullptr; }
getDisplayName() const553 	UTF8StringPtr getDisplayName () const override { return "View"; }
create(const UIAttributes & attributes,const IUIDescription * description) const554 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new SimpleCView (CRect (0, 0, 50, 50)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const555 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
556 	{
557 		CPoint p;
558 		CRect size;
559 		if (attributes.getPointAttribute (kAttrOrigin, p))
560 		{
561 			CRect origViewSize = view->getViewSize ();
562 			size.setTopLeft (p);
563 			size.setWidth (origViewSize.getWidth ());
564 			size.setHeight (origViewSize.getHeight ());
565 			view->setViewSize (size, false);
566 			view->setMouseableArea (size);
567 		}
568 		if (attributes.getPointAttribute (kAttrSize, p))
569 		{
570 			size = view->getViewSize ();
571 			size.setSize (p);
572 			view->setViewSize (size, false);
573 			view->setMouseableArea (size);
574 		}
575 
576 		CBitmap* bitmap;
577 		if (stringToBitmap (attributes.getAttributeValue (kAttrBitmap), bitmap, description))
578 			view->setBackground (bitmap);
579 		if (stringToBitmap (attributes.getAttributeValue (kAttrDisabledBitmap), bitmap, description))
580 			view->setDisabledBackground (bitmap);
581 
582 		bool b;
583 		if (attributes.getBooleanAttribute (kAttrTransparent, b))
584 			view->setTransparency (b);
585 		if (attributes.getBooleanAttribute (kAttrMouseEnabled, b))
586 			view->setMouseEnabled (b);
587 		if (attributes.hasAttribute (kAttrWantsFocus) && attributes.getBooleanAttribute (kAttrWantsFocus, b))
588 			view->setWantsFocus (b);
589 
590 		const std::string* autosizeAttr = attributes.getAttributeValue (kAttrAutosize);
591 		if (autosizeAttr)
592 		{
593 			int32_t autosize = kAutosizeNone;
594 			if (autosizeAttr->find ("left") != std::string::npos)
595 				autosize |= kAutosizeLeft;
596 			if (autosizeAttr->find ("top") != std::string::npos)
597 				autosize |= kAutosizeTop;
598 			if (autosizeAttr->find ("right") != std::string::npos)
599 				autosize |= kAutosizeRight;
600 			if (autosizeAttr->find ("bottom") != std::string::npos)
601 				autosize |= kAutosizeBottom;
602 			if (autosizeAttr->find ("row") != std::string::npos)
603 				autosize |= kAutosizeRow;
604 			if (autosizeAttr->find ("column") != std::string::npos)
605 				autosize |= kAutosizeColumn;
606 			view->setAutosizeFlags (autosize);
607 		}
608 		const std::string* tooltipAttr = attributes.getAttributeValue (kAttrTooltip);
609 		if (tooltipAttr)
610 		{
611 			if (!tooltipAttr->empty ())
612 				view->setTooltipText (tooltipAttr->data ());
613 			else
614 				view->setTooltipText (nullptr);
615 		}
616 
617 		const std::string* customViewAttr = attributes.getAttributeValue (kAttrCustomViewName);
618 		if (customViewAttr)
619 			view->setAttribute ('uicv', static_cast<uint32_t> (customViewAttr->size () + 1), customViewAttr->c_str ());
620 
621 		const std::string* subControllerAttr = attributes.getAttributeValue (kAttrSubController);
622 		if (subControllerAttr)
623 			view->setAttribute ('uisc', static_cast<uint32_t> (subControllerAttr->size () + 1), subControllerAttr->c_str ());
624 
625 		double opacity;
626 		if (attributes.getDoubleAttribute (kAttrOpacity, opacity))
627 			view->setAlphaValue (static_cast<float>(opacity));
628 
629 		return true;
630 	}
getAttributeNames(std::list<std::string> & attributeNames) const631 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
632 	{
633 		attributeNames.emplace_back (kAttrOrigin);
634 		attributeNames.emplace_back (kAttrSize);
635 		attributeNames.emplace_back (kAttrOpacity);
636 		attributeNames.emplace_back (kAttrTransparent);
637 		attributeNames.emplace_back (kAttrMouseEnabled);
638 		attributeNames.emplace_back (kAttrWantsFocus);
639 		attributeNames.emplace_back (kAttrBitmap);
640 		attributeNames.emplace_back (kAttrDisabledBitmap);
641 		attributeNames.emplace_back (kAttrAutosize);
642 		attributeNames.emplace_back (kAttrTooltip);
643 		attributeNames.emplace_back (kAttrCustomViewName);
644 		attributeNames.emplace_back (kAttrSubController);
645 		return true;
646 	}
getAttributeType(const std::string & attributeName) const647 	AttrType getAttributeType (const std::string& attributeName) const override
648 	{
649 		if (attributeName == kAttrOrigin) return kPointType;
650 		else if (attributeName == kAttrSize) return kPointType;
651 		else if (attributeName == kAttrOpacity) return kFloatType;
652 		else if (attributeName == kAttrTransparent) return kBooleanType;
653 		else if (attributeName == kAttrMouseEnabled) return kBooleanType;
654 		else if (attributeName == kAttrWantsFocus) return kBooleanType;
655 		else if (attributeName == kAttrBitmap) return kBitmapType;
656 		else if (attributeName == kAttrDisabledBitmap) return kBitmapType;
657 		else if (attributeName == kAttrAutosize) return kStringType;
658 		else if (attributeName == kAttrTooltip) return kStringType;
659 		else if (attributeName == kAttrCustomViewName) return kStringType;
660 		else if (attributeName == kAttrSubController) return kStringType;
661 		return kUnknownType;
662 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const663 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
664 	{
665 		if (attributeName == kAttrOrigin)
666 		{
667 			pointToString (view->getViewSize ().getTopLeft (), stringValue);
668 			return true;
669 		}
670 		else if (attributeName == kAttrSize)
671 		{
672 			pointToString (view->getViewSize ().getSize (), stringValue);
673 			return true;
674 		}
675 		else if (attributeName == kAttrOpacity)
676 		{
677 			stringValue = numberToString (view->getAlphaValue ());
678 			return true;
679 		}
680 		else if (attributeName == kAttrTransparent)
681 		{
682 			stringValue = view->getTransparency () ? strTrue : strFalse;
683 			return true;
684 		}
685 		else if (attributeName == kAttrMouseEnabled)
686 		{
687 			stringValue = view->getMouseEnabled () ? strTrue : strFalse;
688 			return true;
689 		}
690 		else if (attributeName == kAttrWantsFocus)
691 		{
692 			stringValue = view->wantsFocus () ? strTrue : strFalse;
693 			return true;
694 		}
695 		else if (attributeName == kAttrBitmap)
696 		{
697 			CBitmap* bitmap = view->getBackground ();
698 			if (bitmap)
699 				bitmapToString (bitmap, stringValue, desc);
700 			else
701 				stringValue = "";
702 			return true;
703 		}
704 		else if (attributeName == kAttrDisabledBitmap)
705 		{
706 			CBitmap* bitmap = view->getDisabledBackground ();
707 			if (bitmap)
708 				bitmapToString (bitmap, stringValue, desc);
709 			else
710 				stringValue = "";
711 			return true;
712 		}
713 		else if (attributeName == kAttrAutosize)
714 		{
715 			std::stringstream stream;
716 			int32_t autosize = view->getAutosizeFlags ();
717 			if (autosize == 0)
718 				return true;
719 			if (autosize & kAutosizeLeft)
720 				stream << "left ";
721 			if (autosize & kAutosizeRight)
722 				stream << "right ";
723 			if (autosize & kAutosizeTop)
724 				stream << "top ";
725 			if (autosize & kAutosizeBottom)
726 				stream << "bottom ";
727 			if (autosize & kAutosizeRow)
728 				stream << "row ";
729 			if (autosize & kAutosizeColumn)
730 				stream << "column ";
731 			stringValue = stream.str ();
732 			return true;
733 		}
734 		else if (attributeName == kAttrTooltip)
735 		{
736 			return getViewAttributeString (view, kCViewTooltipAttribute, stringValue);
737 		}
738 		else if (attributeName == kAttrCustomViewName)
739 		{
740 			return getViewAttributeString (view, 'uicv', stringValue);
741 		}
742 		else if (attributeName == kAttrSubController)
743 		{
744 			return getViewAttributeString (view, 'uisc', stringValue);
745 		}
746 		return false;
747 	}
getAttributeValueRange(const std::string & attributeName,double & minValue,double & maxValue) const748 	bool getAttributeValueRange (const std::string& attributeName, double& minValue, double &maxValue) const override
749 	{
750 		if (attributeName == kAttrOpacity)
751 		{
752 			minValue = 0.;
753 			maxValue = 1.;
754 			return true;
755 		}
756 		return false;
757 	}
758 private:
getViewAttributeString(CView * view,const CViewAttributeID attrID,std::string & value)759 	static bool getViewAttributeString (CView* view, const CViewAttributeID attrID, std::string& value)
760 	{
761 		uint32_t attrSize = 0;
762 		if (view->getAttributeSize (attrID, attrSize))
763 		{
764 			char* cstr = new char [attrSize+1];
765 			if (view->getAttribute (attrID, attrSize, cstr, attrSize))
766 				value = cstr;
767 			else
768 				value = "";
769 			delete [] cstr;
770 			return true;
771 		}
772 		return false;
773 	}
774 };
775 CViewCreator __gCViewCreator;
776 
777 //-----------------------------------------------------------------------------
778 class CViewContainerCreator : public ViewCreatorAdapter
779 {
780 public:
781 	std::string kStroked = "stroked";
782 	std::string kFilledAndStroked = "filled and stroked";
783 	std::string kFilled = "filled";
784 
CViewContainerCreator()785 	CViewContainerCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const786 	IdStringPtr getViewName () const override { return kCViewContainer; }
getBaseViewName() const787 	IdStringPtr getBaseViewName () const override { return kCView; }
getDisplayName() const788 	UTF8StringPtr getDisplayName () const override { return "View Container"; }
create(const UIAttributes & attributes,const IUIDescription * description) const789 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CViewContainer (CRect (0, 0, 100, 100)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const790 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
791 	{
792 		CViewContainer* viewContainer = view->asViewContainer ();
793 		if (viewContainer == nullptr)
794 			return false;
795 		CColor backColor;
796 		if (stringToColor (attributes.getAttributeValue (kAttrBackgroundColor), backColor, description))
797 			viewContainer->setBackgroundColor (backColor);
798 		const std::string* attr = attributes.getAttributeValue (kAttrBackgroundColorDrawStyle);
799 		if (attr)
800 		{
801 			CDrawStyle drawStyle = kDrawFilledAndStroked;
802 			if (*attr == kStroked)
803 			{
804 				drawStyle = kDrawStroked;
805 			}
806 			else if (*attr == kFilled)
807 			{
808 				drawStyle = kDrawFilled;
809 			}
810 			viewContainer->setBackgroundColorDrawStyle (drawStyle);
811 		}
812 		return true;
813 	}
getAttributeNames(std::list<std::string> & attributeNames) const814 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
815 	{
816 		attributeNames.emplace_back (kAttrBackgroundColor);
817 		attributeNames.emplace_back (kAttrBackgroundColorDrawStyle);
818 		return true;
819 	}
getAttributeType(const std::string & attributeName) const820 	AttrType getAttributeType (const std::string& attributeName) const override
821 	{
822 		if (attributeName == kAttrBackgroundColor) return kColorType;
823 		if (attributeName == kAttrBackgroundColorDrawStyle) return kListType;
824 		return kUnknownType;
825 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const826 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
827 	{
828 		CViewContainer* vc = view->asViewContainer ();
829 		if (vc == nullptr)
830 			return false;
831 		if (attributeName == kAttrBackgroundColor)
832 		{
833 			colorToString (vc->getBackgroundColor (), stringValue, desc);
834 			return true;
835 		}
836 		if (attributeName == kAttrBackgroundColorDrawStyle)
837 		{
838 			switch (vc->getBackgroundColorDrawStyle ())
839 			{
840 				case kDrawStroked: stringValue = kStroked; break;
841 				case kDrawFilledAndStroked: stringValue = kFilledAndStroked; break;
842 				case kDrawFilled: stringValue = kFilled; break;
843 			}
844 			return true;
845 		}
846 		return false;
847 	}
848 
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const849 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
850 	{
851 		if (attributeName == kAttrBackgroundColorDrawStyle)
852 		{
853 			values.emplace_back (&kStroked);
854 			values.emplace_back (&kFilledAndStroked);
855 			values.emplace_back (&kFilled);
856 			return true;
857 		}
858 		return false;
859 	}
860 
861 };
862 CViewContainerCreator __CViewContainerCreator;
863 
864 //-----------------------------------------------------------------------------
865 class CLayeredViewContainerCreator : public ViewCreatorAdapter
866 {
867 public:
CLayeredViewContainerCreator()868 	CLayeredViewContainerCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const869 	IdStringPtr getViewName () const override { return kCLayeredViewContainer; }
getBaseViewName() const870 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const871 	UTF8StringPtr getDisplayName () const override { return "Layered View Container"; }
create(const UIAttributes & attributes,const IUIDescription * description) const872 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CLayeredViewContainer (CRect (0, 0, 100, 100)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const873 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
874 	{
875 		auto* lvc = dynamic_cast<CLayeredViewContainer*>(view);
876 		if (lvc == nullptr)
877 			return false;
878 		int32_t zIndex;
879 		if (attributes.getIntegerAttribute (kAttrZIndex, zIndex))
880 			lvc->setZIndex (static_cast<uint32_t>(zIndex));
881 		return true;
882 	}
getAttributeNames(std::list<std::string> & attributeNames) const883 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
884 	{
885 		attributeNames.emplace_back (kAttrZIndex);
886 		return true;
887 	}
getAttributeType(const std::string & attributeName) const888 	AttrType getAttributeType (const std::string& attributeName) const override
889 	{
890 		if (attributeName == kAttrZIndex) return kIntegerType;
891 		return kUnknownType;
892 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const893 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
894 	{
895 		auto* lvc = dynamic_cast<CLayeredViewContainer*>(view);
896 		if (lvc == nullptr)
897 			return false;
898 		if (attributeName == kAttrZIndex)
899 		{
900 			stringValue = numberToString (static_cast<int32_t>(lvc->getZIndex ()));
901 			return true;
902 		}
903 		return false;
904 	}
905 };
906 CLayeredViewContainerCreator __CLayeredViewContainerCreator;
907 
908 //-----------------------------------------------------------------------------
909 class CRowColumnViewCreator : public ViewCreatorAdapter
910 {
911 public:
912 	std::string kLeftTop = "left-top";
913 	std::string kStretch = "stretch";
914 	std::string kCenter = strCenter;
915 	std::string kRightBottom = "right-bottom";
916 
CRowColumnViewCreator()917 	CRowColumnViewCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const918 	IdStringPtr getViewName () const override { return kCRowColumnView; }
getBaseViewName() const919 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const920 	UTF8StringPtr getDisplayName () const override { return "Row Column View Container"; }
create(const UIAttributes & attributes,const IUIDescription * description) const921 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CRowColumnView (CRect (0, 0, 100, 100)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const922 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
923 	{
924 		auto* rcv = dynamic_cast<CRowColumnView*> (view);
925 		if (rcv == nullptr)
926 			return false;
927 		const std::string* attr = attributes.getAttributeValue (kAttrRowStyle);
928 		if (attr)
929 			rcv->setStyle (*attr == strTrue ? CRowColumnView::kRowStyle : CRowColumnView::kColumnStyle);
930 		attr = attributes.getAttributeValue (kAttrSpacing);
931 		if (attr)
932 		{
933 			CCoord spacing = UTF8StringView (attr->c_str ()).toDouble ();
934 			rcv->setSpacing (spacing);
935 		}
936 		CRect margin;
937 		if (attributes.getRectAttribute (kAttrMargin, margin))
938 			rcv->setMargin (margin);
939 		attr = attributes.getAttributeValue (kAttrAnimateViewResizing);
940 		if (attr)
941 			rcv->setAnimateViewResizing (*attr == strTrue ? true : false);
942 		attr = attributes.getAttributeValue (kAttrHideClippedSubviews);
943 		if (attr)
944 			rcv->setHideClippedSubviews (*attr == strTrue ? true : false);
945 		attr = attributes.getAttributeValue (kAttrEqualSizeLayout);
946 		if (attr)
947 		{
948 			if (*attr == kStretch)
949 				rcv->setLayoutStyle (CRowColumnView::kStretchEqualy);
950 			else if (*attr == kCenter)
951 				rcv->setLayoutStyle (CRowColumnView::kCenterEqualy);
952 			else if (*attr == kRightBottom)
953 				rcv->setLayoutStyle (CRowColumnView::kRightBottomEqualy);
954 			else
955 				rcv->setLayoutStyle (CRowColumnView::kLeftTopEqualy);
956 		}
957 		attr = attributes.getAttributeValue (kAttrViewResizeAnimationTime);
958 		if (attr)
959 		{
960 			uint32_t time = (uint32_t)strtol (attr->c_str(), nullptr, 10);
961 			rcv->setViewResizeAnimationTime (time);
962 		}
963 		return true;
964 	}
getAttributeNames(std::list<std::string> & attributeNames) const965 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
966 	{
967 		attributeNames.emplace_back (kAttrRowStyle);
968 		attributeNames.emplace_back (kAttrSpacing);
969 		attributeNames.emplace_back (kAttrMargin);
970 		attributeNames.emplace_back (kAttrEqualSizeLayout);
971 		attributeNames.emplace_back (kAttrHideClippedSubviews);
972 		attributeNames.emplace_back (kAttrAnimateViewResizing);
973 		attributeNames.emplace_back (kAttrViewResizeAnimationTime);
974 		return true;
975 	}
getAttributeType(const std::string & attributeName) const976 	AttrType getAttributeType (const std::string& attributeName) const override
977 	{
978 		if (attributeName == kAttrRowStyle) return kBooleanType;
979 		if (attributeName == kAttrSpacing) return kIntegerType;
980 		if (attributeName == kAttrMargin) return kRectType;
981 		if (attributeName == kAttrEqualSizeLayout) return kListType;
982 		if (attributeName == kAttrHideClippedSubviews) return kBooleanType;
983 		if (attributeName == kAttrAnimateViewResizing) return kBooleanType;
984 		if (attributeName == kAttrViewResizeAnimationTime) return kIntegerType;
985 		return kUnknownType;
986 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const987 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
988 	{
989 		auto* rcv = dynamic_cast<CRowColumnView*> (view);
990 		if (rcv == nullptr)
991 			return false;
992 		if (attributeName == kAttrRowStyle)
993 		{
994 			stringValue = rcv->getStyle () == CRowColumnView::kRowStyle ? strTrue : strFalse;
995 			return true;
996 		}
997 		if (attributeName == kAttrAnimateViewResizing)
998 		{
999 			stringValue = rcv->isAnimateViewResizing () ? strTrue : strFalse;
1000 			return true;
1001 		}
1002 		if (attributeName == kAttrHideClippedSubviews)
1003 		{
1004 			stringValue = rcv->hideClippedSubviews () ? strTrue : strFalse;
1005 			return true;
1006 		}
1007 		if (attributeName == kAttrSpacing)
1008 		{
1009 			stringValue = numberToString ((int32_t)rcv->getSpacing ());
1010 			return true;
1011 		}
1012 		if (attributeName == kAttrViewResizeAnimationTime)
1013 		{
1014 			stringValue = numberToString (rcv->getViewResizeAnimationTime ());
1015 			return true;
1016 		}
1017 		if (attributeName == kAttrMargin)
1018 		{
1019 			const CRect& margin = rcv->getMargin ();
1020 			std::stringstream str;
1021 			str << (int32_t)margin.left;
1022 			str << ",";
1023 			str << (int32_t)margin.top;
1024 			str << ",";
1025 			str << (int32_t)margin.right;
1026 			str << ",";
1027 			str << (int32_t)margin.bottom;
1028 			stringValue = str.str ();
1029 			return true;
1030 		}
1031 		if (attributeName == kAttrEqualSizeLayout)
1032 		{
1033 			switch (rcv->getLayoutStyle ())
1034 			{
1035 				case CRowColumnView::kLeftTopEqualy: stringValue = kLeftTop; break;
1036 				case CRowColumnView::kStretchEqualy: stringValue = kStretch; break;
1037 				case CRowColumnView::kCenterEqualy: stringValue = kCenter; break;
1038 				case CRowColumnView::kRightBottomEqualy: stringValue = kRightBottom; break;
1039 			}
1040 			return true;
1041 		}
1042 		return false;
1043 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const1044 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
1045 	{
1046 		if (attributeName == kAttrEqualSizeLayout)
1047 		{
1048 			values.emplace_back (&kLeftTop);
1049 			values.emplace_back (&kStretch);
1050 			values.emplace_back (&kCenter);
1051 			values.emplace_back (&kRightBottom);
1052 			return true;
1053 		}
1054 		return false;
1055 	}
1056 
1057 };
1058 CRowColumnViewCreator __CRowColumnViewCreator;
1059 
1060 //-----------------------------------------------------------------------------
1061 class CScrollViewCreator : public ViewCreatorAdapter
1062 {
1063 public:
CScrollViewCreator()1064 	CScrollViewCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1065 	IdStringPtr getViewName () const override { return kCScrollView; }
getBaseViewName() const1066 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const1067 	UTF8StringPtr getDisplayName () const override { return "Scroll View"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1068 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CScrollView (CRect (0, 0, 100, 100), CRect (0, 0, 200, 200), CScrollView::kHorizontalScrollbar|CScrollView::kVerticalScrollbar); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1069 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1070 	{
1071 		auto* scrollView = dynamic_cast<CScrollView*> (view);
1072 		if (scrollView == nullptr)
1073 			return false;
1074 
1075 		CPoint p;
1076 		if (attributes.getPointAttribute (kAttrContainerSize, p))
1077 		{
1078 			CRect r;
1079 			r.setSize (p);
1080 			scrollView->setContainerSize (r);
1081 		}
1082 
1083 		int32_t style = scrollView->getStyle ();
1084 		applyStyleMask (attributes.getAttributeValue (kAttrHorizontalScrollbar), CScrollView::kHorizontalScrollbar, style);
1085 		applyStyleMask (attributes.getAttributeValue (kAttrVerticalScrollbar), CScrollView::kVerticalScrollbar, style);
1086 		applyStyleMask (attributes.getAttributeValue (kAttrAutoDragScrolling), CScrollView::kAutoDragScrolling, style);
1087 		const std::string* attr = attributes.getAttributeValue (kAttrBordered);
1088 		if (attr)
1089 		{
1090 			setBit (style, CScrollView::kDontDrawFrame, *attr != strTrue);
1091 		}
1092 		applyStyleMask (attributes.getAttributeValue (kAttrOverlayScrollbars), CScrollView::kOverlayScrollbars, style);
1093 		applyStyleMask (attributes.getAttributeValue (kAttrFollowFocusView), CScrollView::kFollowFocusView, style);
1094 		applyStyleMask (attributes.getAttributeValue (kAttrAutoHideScrollbars), CScrollView::kAutoHideScrollbars, style);
1095 		scrollView->setStyle (style);
1096 		CColor color;
1097 		CScrollbar* vscrollbar = scrollView->getVerticalScrollbar ();
1098 		CScrollbar* hscrollbar = scrollView->getHorizontalScrollbar ();
1099 		if (stringToColor (attributes.getAttributeValue (kAttrScrollbarBackgroundColor), color, description))
1100 		{
1101 			if (vscrollbar) vscrollbar->setBackgroundColor (color);
1102 			if (hscrollbar) hscrollbar->setBackgroundColor (color);
1103 		}
1104 		if (stringToColor (attributes.getAttributeValue (kAttrScrollbarFrameColor), color, description))
1105 		{
1106 			if (vscrollbar) vscrollbar->setFrameColor (color);
1107 			if (hscrollbar) hscrollbar->setFrameColor (color);
1108 		}
1109 		if (stringToColor (attributes.getAttributeValue (kAttrScrollbarScrollerColor), color, description))
1110 		{
1111 			if (vscrollbar) vscrollbar->setScrollerColor (color);
1112 			if (hscrollbar) hscrollbar->setScrollerColor (color);
1113 		}
1114 		CCoord width;
1115 		if (attributes.getDoubleAttribute (kAttrScrollbarWidth, width))
1116 			scrollView->setScrollbarWidth (width);
1117 		return true;
1118 	}
getAttributeNames(std::list<std::string> & attributeNames) const1119 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1120 	{
1121 		attributeNames.emplace_back (kAttrContainerSize);
1122 		attributeNames.emplace_back (kAttrScrollbarBackgroundColor);
1123 		attributeNames.emplace_back (kAttrScrollbarFrameColor);
1124 		attributeNames.emplace_back (kAttrScrollbarScrollerColor);
1125 		attributeNames.emplace_back (kAttrHorizontalScrollbar);
1126 		attributeNames.emplace_back (kAttrVerticalScrollbar);
1127 		attributeNames.emplace_back (kAttrAutoHideScrollbars);
1128 		attributeNames.emplace_back (kAttrAutoDragScrolling);
1129 		attributeNames.emplace_back (kAttrOverlayScrollbars);
1130 		attributeNames.emplace_back (kAttrScrollbarWidth);
1131 		attributeNames.emplace_back (kAttrBordered);
1132 		attributeNames.emplace_back (kAttrFollowFocusView);
1133 		return true;
1134 	}
getAttributeType(const std::string & attributeName) const1135 	AttrType getAttributeType (const std::string& attributeName) const override
1136 	{
1137 		if (attributeName == kAttrContainerSize) return kPointType;
1138 		if (attributeName == kAttrScrollbarBackgroundColor) return kColorType;
1139 		if (attributeName == kAttrScrollbarFrameColor) return kColorType;
1140 		if (attributeName == kAttrScrollbarScrollerColor) return kColorType;
1141 		if (attributeName == kAttrHorizontalScrollbar) return kBooleanType;
1142 		if (attributeName == kAttrVerticalScrollbar) return kBooleanType;
1143 		if (attributeName == kAttrAutoHideScrollbars) return kBooleanType;
1144 		if (attributeName == kAttrAutoDragScrolling) return kBooleanType;
1145 		if (attributeName == kAttrOverlayScrollbars) return kBooleanType;
1146 		if (attributeName == kAttrScrollbarWidth) return kIntegerType;
1147 		if (attributeName == kAttrBordered) return kBooleanType;
1148 		if (attributeName == kAttrFollowFocusView) return kBooleanType;
1149 		return kUnknownType;
1150 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1151 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1152 	{
1153 		auto* sc = dynamic_cast<CScrollView*> (view);
1154 		if (sc == nullptr)
1155 			return false;
1156 		if (attributeName == kAttrContainerSize)
1157 		{
1158 			pointToString (sc->getContainerSize ().getSize (), stringValue);
1159 			return true;
1160 		}
1161 		if (attributeName == kAttrScrollbarWidth)
1162 		{
1163 			stringValue = numberToString (sc->getScrollbarWidth ());
1164 			return true;
1165 		}
1166 		CScrollbar* scrollbar = sc->getVerticalScrollbar ();
1167 		if (!scrollbar)
1168 			scrollbar = sc->getHorizontalScrollbar ();
1169 		if (scrollbar)
1170 		{
1171 			if (attributeName == kAttrScrollbarBackgroundColor)
1172 			{
1173 				colorToString (scrollbar->getBackgroundColor (), stringValue, desc);
1174 				return true;
1175 			}
1176 			if (attributeName == kAttrScrollbarFrameColor)
1177 			{
1178 				colorToString (scrollbar->getFrameColor (), stringValue, desc);
1179 				return true;
1180 			}
1181 			if (attributeName == kAttrScrollbarScrollerColor)
1182 			{
1183 				colorToString (scrollbar->getScrollerColor (), stringValue, desc);
1184 				return true;
1185 			}
1186 		}
1187 		if (attributeName == kAttrHorizontalScrollbar)
1188 		{
1189 			stringValue = sc->getStyle () & CScrollView::kHorizontalScrollbar ? strTrue : strFalse;
1190 			return true;
1191 		}
1192 		if (attributeName == kAttrVerticalScrollbar)
1193 		{
1194 			stringValue = sc->getStyle () & CScrollView::kVerticalScrollbar ? strTrue : strFalse;
1195 			return true;
1196 		}
1197 		if (attributeName == kAttrAutoHideScrollbars)
1198 		{
1199 			stringValue = sc->getStyle () & CScrollView::kAutoHideScrollbars ? strTrue : strFalse;
1200 			return true;
1201 		}
1202 		if (attributeName == kAttrAutoDragScrolling)
1203 		{
1204 			stringValue = sc->getStyle () & CScrollView::kAutoDragScrolling ? strTrue : strFalse;
1205 			return true;
1206 		}
1207 		if (attributeName == kAttrBordered)
1208 		{
1209 			stringValue = sc->getStyle () & CScrollView::kDontDrawFrame ? strFalse : strTrue;
1210 			return true;
1211 		}
1212 		if (attributeName == kAttrOverlayScrollbars)
1213 		{
1214 			stringValue = sc->getStyle () & CScrollView::kOverlayScrollbars ? strTrue : strFalse;
1215 			return true;
1216 		}
1217 		if (attributeName == kAttrFollowFocusView)
1218 		{
1219 			stringValue = sc->getStyle () & CScrollView::kFollowFocusView ? strTrue : strFalse;
1220 			return true;
1221 		}
1222 		return false;
1223 	}
1224 
1225 };
1226 CScrollViewCreator __CScrollViewCreator;
1227 
1228 //-----------------------------------------------------------------------------
1229 class CControlCreator : public ViewCreatorAdapter
1230 {
1231 protected:
1232 	class DummyControl : public CControl
1233 	{
1234 	public:
DummyControl()1235 		DummyControl () : CControl (CRect (0, 0, 40, 40), nullptr, -1) {}
draw(CDrawContext * pContext)1236 		void draw (CDrawContext* pContext) override { CView::draw (pContext); }
1237 
1238 		CLASS_METHODS(DummyControl, CControl)
1239 	};
1240 public:
CControlCreator()1241 	CControlCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1242 	IdStringPtr getViewName () const override { return kCControl; }
getBaseViewName() const1243 	IdStringPtr getBaseViewName () const override { return kCView; }
getDisplayName() const1244 	UTF8StringPtr getDisplayName () const override { return "Control"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1245 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new DummyControl (); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1246 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1247 	{
1248 		auto* control = dynamic_cast<CControl*> (view);
1249 		if (control == nullptr)
1250 			return false;
1251 
1252 		double value;
1253 		if (attributes.getDoubleAttribute (kAttrDefaultValue, value))
1254 			control->setDefaultValue (static_cast<float> (value));
1255 		if (attributes.getDoubleAttribute (kAttrMinValue, value))
1256 			control->setMin (static_cast<float> (value));
1257 		if (attributes.getDoubleAttribute (kAttrMaxValue, value))
1258 			control->setMax (static_cast<float> (value));
1259 		if (attributes.getDoubleAttribute (kAttrWheelIncValue, value))
1260 			control->setWheelInc (static_cast<float> (value));
1261 
1262 		const std::string* controlTagAttr = attributes.getAttributeValue (kAttrControlTag);
1263 		if (controlTagAttr)
1264 		{
1265 			if (controlTagAttr->length () == 0)
1266 			{
1267 				control->setTag (-1);
1268 				control->setListener (nullptr);
1269 			}
1270 			else
1271 			{
1272 				int32_t tag = description->getTagForName (controlTagAttr->c_str ());
1273 				if (tag != -1)
1274 				{
1275 					control->setListener (description->getControlListener (controlTagAttr->c_str ()));
1276 					control->setTag (tag);
1277 				}
1278 				else
1279 				{
1280 					char* endPtr = nullptr;
1281 					tag = (int32_t)strtol (controlTagAttr->c_str (), &endPtr, 10);
1282 					if (endPtr != controlTagAttr->c_str ())
1283 					{
1284 						control->setListener (description->getControlListener (controlTagAttr->c_str ()));
1285 						control->setTag (tag);
1286 					}
1287 				}
1288 			}
1289 		}
1290 
1291 		return true;
1292 	}
getAttributeNames(std::list<std::string> & attributeNames) const1293 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1294 	{
1295 		attributeNames.emplace_back (kAttrControlTag);
1296 		attributeNames.emplace_back (kAttrDefaultValue);
1297 		attributeNames.emplace_back (kAttrMinValue);
1298 		attributeNames.emplace_back (kAttrMaxValue);
1299 		attributeNames.emplace_back (kAttrWheelIncValue);
1300 		return true;
1301 	}
getAttributeType(const std::string & attributeName) const1302 	AttrType getAttributeType (const std::string& attributeName) const override
1303 	{
1304 		if (attributeName == kAttrControlTag) return kTagType;
1305 		else if (attributeName == kAttrDefaultValue) return kFloatType;
1306 		else if (attributeName == kAttrMinValue) return kFloatType;
1307 		else if (attributeName == kAttrMaxValue) return kFloatType;
1308 		else if (attributeName == kAttrWheelIncValue) return kFloatType;
1309 		return kUnknownType;
1310 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1311 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1312 	{
1313 		auto* control = dynamic_cast<CControl*> (view);
1314 		if (control == nullptr)
1315 			return false;
1316 		if (attributeName == kAttrControlTag)
1317 		{
1318 			if (control->getTag () != -1)
1319 			{
1320 				UTF8StringPtr controlTag = desc->lookupControlTagName (control->getTag ());
1321 				if (controlTag)
1322 				{
1323 					stringValue = controlTag;
1324 					return true;
1325 				}
1326 			}
1327 		}
1328 		else if (attributeName == kAttrDefaultValue)
1329 		{
1330 			stringValue = numberToString (control->getDefaultValue ());
1331 			return true;
1332 		}
1333 		else if (attributeName == kAttrMinValue)
1334 		{
1335 			stringValue = numberToString (control->getMin ());
1336 			return true;
1337 		}
1338 		else if (attributeName == kAttrMaxValue)
1339 		{
1340 			stringValue = numberToString (control->getMax ());
1341 			return true;
1342 		}
1343 		else if (attributeName == kAttrWheelIncValue)
1344 		{
1345 			stringValue = numberToString (control->getWheelInc ());
1346 			return true;
1347 		}
1348 		return false;
1349 	}
1350 
1351 };
1352 CControlCreator __gCControlCreator;
1353 
1354 //-----------------------------------------------------------------------------
1355 class COnOffButtonCreator : public ViewCreatorAdapter
1356 {
1357 public:
COnOffButtonCreator()1358 	COnOffButtonCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1359 	IdStringPtr getViewName () const override { return kCOnOffButton; }
getBaseViewName() const1360 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const1361 	UTF8StringPtr getDisplayName () const override { return "OnOff Button"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1362 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new COnOffButton (CRect (0, 0, 20, 20), nullptr, -1, nullptr); }
1363 };
1364 COnOffButtonCreator __gCOnOffButtonCreator;
1365 
1366 //-----------------------------------------------------------------------------
1367 class CCheckBoxCreator : public ViewCreatorAdapter
1368 {
1369 public:
CCheckBoxCreator()1370 	CCheckBoxCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1371 	IdStringPtr getViewName () const override { return kCCheckBox; }
getBaseViewName() const1372 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const1373 	UTF8StringPtr getDisplayName () const override { return "Checkbox"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1374 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CCheckBox (CRect (0, 0, 100, 20), nullptr, -1, "Title"); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1375 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1376 	{
1377 		auto* checkbox = dynamic_cast<CCheckBox*> (view);
1378 		if (!checkbox)
1379 			return false;
1380 
1381 		const std::string* attr = attributes.getAttributeValue (kAttrTitle);
1382 		if (attr)
1383 			checkbox->setTitle (attr->c_str ());
1384 
1385 		attr = attributes.getAttributeValue (kAttrFont);
1386 		if (attr)
1387 		{
1388 			CFontRef font = description->getFont (attr->c_str ());
1389 			if (font)
1390 			{
1391 				checkbox->setFont (font);
1392 			}
1393 		}
1394 
1395 		CColor color;
1396 		if (stringToColor (attributes.getAttributeValue (kAttrFontColor), color, description))
1397 			checkbox->setFontColor (color);
1398 
1399 		if (stringToColor (attributes.getAttributeValue (kAttrBoxframeColor), color, description))
1400 			checkbox->setBoxFrameColor (color);
1401 
1402 		if (stringToColor (attributes.getAttributeValue (kAttrBoxfillColor), color, description))
1403 			checkbox->setBoxFillColor (color);
1404 
1405 		if (stringToColor (attributes.getAttributeValue (kAttrCheckmarkColor), color, description))
1406 			checkbox->setCheckMarkColor (color);
1407 
1408 		int32_t style = checkbox->getStyle ();
1409 		applyStyleMask (attributes.getAttributeValue (kAttrDrawCrossbox), CCheckBox::kDrawCrossBox, style);
1410 		applyStyleMask (attributes.getAttributeValue (kAttrAutosizeToFit), CCheckBox::kAutoSizeToFit, style);
1411 		checkbox->setStyle (style);
1412 
1413 		double dv;
1414 		if (attributes.getDoubleAttribute (kAttrFrameWidth, dv))
1415 			checkbox->setFrameWidth (dv);
1416 		if (attributes.getDoubleAttribute (kAttrRoundRectRadius, dv))
1417 			checkbox->setRoundRectRadius (dv);
1418 		return true;
1419 	}
1420 
getAttributeNames(std::list<std::string> & attributeNames) const1421 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1422 	{
1423 		attributeNames.emplace_back (kAttrTitle);
1424 		attributeNames.emplace_back (kAttrFont);
1425 		attributeNames.emplace_back (kAttrFontColor);
1426 		attributeNames.emplace_back (kAttrBoxframeColor);
1427 		attributeNames.emplace_back (kAttrBoxfillColor);
1428 		attributeNames.emplace_back (kAttrCheckmarkColor);
1429 		attributeNames.emplace_back (kAttrFrameWidth);
1430 		attributeNames.emplace_back (kAttrRoundRectRadius);
1431 		attributeNames.emplace_back (kAttrAutosizeToFit);
1432 		attributeNames.emplace_back (kAttrDrawCrossbox);
1433 		return true;
1434 	}
getAttributeType(const std::string & attributeName) const1435 	AttrType getAttributeType (const std::string& attributeName) const override
1436 	{
1437 		if (attributeName == kAttrTitle) return kStringType;
1438 		else if (attributeName == kAttrFont) return kFontType;
1439 		else if (attributeName == kAttrFontColor) return kColorType;
1440 		else if (attributeName == kAttrBoxframeColor) return kColorType;
1441 		else if (attributeName == kAttrBoxfillColor) return kColorType;
1442 		else if (attributeName == kAttrCheckmarkColor) return kColorType;
1443 		else if (attributeName == kAttrFrameWidth) return kFloatType;
1444 		else if (attributeName == kAttrRoundRectRadius) return kFloatType;
1445 		else if (attributeName == kAttrAutosizeToFit) return kBooleanType;
1446 		else if (attributeName == kAttrDrawCrossbox) return kBooleanType;
1447 		return kUnknownType;
1448 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1449 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1450 	{
1451 		auto* checkbox = dynamic_cast<CCheckBox*> (view);
1452 		if (!checkbox)
1453 			return false;
1454 
1455 		if (attributeName == kAttrTitle)
1456 		{
1457 			stringValue = checkbox->getTitle ().getString ();
1458 			return true;
1459 		}
1460 		else if (attributeName == kAttrFont)
1461 		{
1462 			UTF8StringPtr fontName = desc->lookupFontName (checkbox->getFont ());
1463 			if (fontName)
1464 			{
1465 				stringValue = fontName;
1466 				return true;
1467 			}
1468 			return false;
1469 		}
1470 		else if (attributeName == kAttrFontColor)
1471 		{
1472 			colorToString (checkbox->getFontColor (), stringValue, desc);
1473 			return true;
1474 		}
1475 		else if (attributeName == kAttrBoxframeColor)
1476 		{
1477 			colorToString (checkbox->getBoxFrameColor (), stringValue, desc);
1478 			return true;
1479 		}
1480 		else if (attributeName == kAttrBoxfillColor)
1481 		{
1482 			colorToString (checkbox->getBoxFillColor (), stringValue, desc);
1483 			return true;
1484 		}
1485 		else if (attributeName == kAttrCheckmarkColor)
1486 		{
1487 			colorToString (checkbox->getCheckMarkColor (), stringValue, desc);
1488 			return true;
1489 		}
1490 		else if (attributeName == kAttrAutosizeToFit)
1491 		{
1492 			if (checkbox->getStyle () & CCheckBox::kAutoSizeToFit)
1493 				stringValue = strTrue;
1494 			else
1495 				stringValue = strFalse;
1496 			return true;
1497 		}
1498 		else if (attributeName == kAttrDrawCrossbox)
1499 		{
1500 			if (checkbox->getStyle () & CCheckBox::kDrawCrossBox)
1501 				stringValue = strTrue;
1502 			else
1503 				stringValue = strFalse;
1504 			return true;
1505 		}
1506 		else if (attributeName == kAttrFrameWidth)
1507 		{
1508 			stringValue = numberToString (checkbox->getFrameWidth ());
1509 			return true;
1510 		}
1511 		else if (attributeName == kAttrRoundRectRadius)
1512 		{
1513 			stringValue = numberToString (checkbox->getRoundRectRadius ());
1514 			return true;
1515 		}
1516 		else if (attributeName == kAttrFrameWidth)
1517 		{
1518 			stringValue = numberToString (checkbox->getFrameWidth ());
1519 			return true;
1520 		}
1521 		else if (attributeName == kAttrRoundRectRadius)
1522 		{
1523 			stringValue = numberToString (checkbox->getRoundRectRadius ());
1524 			return true;
1525 		}
1526 		return false;
1527 	}
1528 
1529 };
1530 CCheckBoxCreator __gCCheckBoxCreator;
1531 
1532 //-----------------------------------------------------------------------------
1533 class CParamDisplayCreator : public ViewCreatorAdapter
1534 {
1535 public:
CParamDisplayCreator()1536 	CParamDisplayCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1537 	IdStringPtr getViewName () const override { return kCParamDisplay; }
getBaseViewName() const1538 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const1539 	UTF8StringPtr getDisplayName () const override { return "Parameter Display"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1540 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CParamDisplay (CRect (0, 0, 100, 20)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1541 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1542 	{
1543 		auto* display = dynamic_cast<CParamDisplay*> (view);
1544 		if (!display)
1545 			return false;
1546 
1547 		const std::string* fontAttr = attributes.getAttributeValue (kAttrFont);
1548 		if (fontAttr)
1549 		{
1550 			CFontRef font = description->getFont (fontAttr->c_str ());
1551 			if (font)
1552 			{
1553 				display->setFont (font);
1554 			}
1555 		}
1556 
1557 		CColor color;
1558 		if (stringToColor (attributes.getAttributeValue (kAttrFontColor), color, description))
1559 			display->setFontColor (color);
1560 		if (stringToColor (attributes.getAttributeValue (kAttrBackColor), color, description))
1561 			display->setBackColor (color);
1562 		if (stringToColor (attributes.getAttributeValue (kAttrFrameColor), color, description))
1563 			display->setFrameColor (color);
1564 		if (stringToColor (attributes.getAttributeValue (kAttrShadowColor), color, description))
1565 			display->setShadowColor (color);
1566 
1567 		CPoint p;
1568 		if (attributes.getPointAttribute (kAttrTextInset, p))
1569 			display->setTextInset (p);
1570 		if (attributes.getPointAttribute (kAttrTextShadowOffset, p))
1571 			display->setShadowTextOffset (p);
1572 		if (attributes.getPointAttribute (kAttrBackgroundOffset, p))
1573 			display->setBackOffset (p);
1574 		bool b;
1575 		if (attributes.getBooleanAttribute(kAttrFontAntialias, b))
1576 			display->setAntialias (b);
1577 
1578 		const std::string* textAlignmentAttr = attributes.getAttributeValue (kAttrTextAlignment);
1579 		if (textAlignmentAttr)
1580 		{
1581 			CHoriTxtAlign align = kCenterText;
1582 			if (*textAlignmentAttr == strLeft)
1583 				align = kLeftText;
1584 			else if (*textAlignmentAttr == strRight)
1585 				align = kRightText;
1586 			display->setHoriAlign (align);
1587 		}
1588 		double d;
1589 		if (attributes.getDoubleAttribute(kAttrRoundRectRadius, d))
1590 			display->setRoundRectRadius (d);
1591 		if (attributes.getDoubleAttribute(kAttrFrameWidth, d))
1592 			display->setFrameWidth (d);
1593 		if (attributes.getDoubleAttribute (kAttrTextRotation, d))
1594 			display->setTextRotation (d);
1595 
1596 		int32_t style = display->getStyle ();
1597 		applyStyleMask (attributes.getAttributeValue (kAttrStyle3DIn), CParamDisplay::k3DIn, style);
1598 		applyStyleMask (attributes.getAttributeValue (kAttrStyle3DOut), CParamDisplay::k3DOut, style);
1599 		applyStyleMask (attributes.getAttributeValue (kAttrStyleNoFrame), CParamDisplay::kNoFrame, style);
1600 		applyStyleMask (attributes.getAttributeValue (kAttrStyleNoDraw), CParamDisplay::kNoDrawStyle, style);
1601 		applyStyleMask (attributes.getAttributeValue (kAttrStyleNoText), CParamDisplay::kNoTextStyle, style);
1602 		applyStyleMask (attributes.getAttributeValue (kAttrStyleShadowText), CParamDisplay::kShadowText, style);
1603 		applyStyleMask (attributes.getAttributeValue (kAttrStyleRoundRect), CParamDisplay::kRoundRectStyle, style);
1604 		display->setStyle (style);
1605 
1606 		const std::string* precisionAttr = attributes.getAttributeValue (kAttrValuePrecision);
1607 		if (precisionAttr)
1608 		{
1609 			uint8_t precision = (uint8_t)strtol (precisionAttr->c_str (), nullptr, 10);
1610 			display->setPrecision (precision);
1611 		}
1612 
1613 		return true;
1614 	}
getAttributeNames(std::list<std::string> & attributeNames) const1615 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1616 	{
1617 		attributeNames.emplace_back (kAttrFont);
1618 		attributeNames.emplace_back (kAttrFontColor);
1619 		attributeNames.emplace_back (kAttrBackColor);
1620 		attributeNames.emplace_back (kAttrFrameColor);
1621 		attributeNames.emplace_back (kAttrShadowColor);
1622 		attributeNames.emplace_back (kAttrRoundRectRadius);
1623 		attributeNames.emplace_back (kAttrFrameWidth);
1624 		attributeNames.emplace_back (kAttrTextAlignment);
1625 		attributeNames.emplace_back (kAttrTextInset);
1626 		attributeNames.emplace_back (kAttrTextShadowOffset);
1627 		attributeNames.emplace_back (kAttrValuePrecision);
1628 		attributeNames.emplace_back (kAttrBackgroundOffset);
1629 		attributeNames.emplace_back (kAttrFontAntialias);
1630 		attributeNames.emplace_back (kAttrStyle3DIn);
1631 		attributeNames.emplace_back (kAttrStyle3DOut);
1632 		attributeNames.emplace_back (kAttrStyleNoFrame);
1633 		attributeNames.emplace_back (kAttrStyleNoText);
1634 		attributeNames.emplace_back (kAttrStyleNoDraw);
1635 		attributeNames.emplace_back (kAttrStyleShadowText);
1636 		attributeNames.emplace_back (kAttrStyleRoundRect);
1637 		attributeNames.emplace_back (kAttrTextRotation);
1638 		return true;
1639 	}
getAttributeType(const std::string & attributeName) const1640 	AttrType getAttributeType (const std::string& attributeName) const override
1641 	{
1642 		if (attributeName == kAttrFont) return kFontType;
1643 		else if (attributeName == kAttrFontColor) return kColorType;
1644 		else if (attributeName == kAttrBackColor) return kColorType;
1645 		else if (attributeName == kAttrFrameColor) return kColorType;
1646 		else if (attributeName == kAttrShadowColor) return kColorType;
1647 		else if (attributeName == kAttrFontAntialias) return kBooleanType;
1648 		else if (attributeName == kAttrStyle3DIn)return kBooleanType;
1649 		else if (attributeName == kAttrStyle3DOut) return kBooleanType;
1650 		else if (attributeName == kAttrStyleNoFrame) return kBooleanType;
1651 		else if (attributeName == kAttrStyleNoText) return kBooleanType;
1652 		else if (attributeName == kAttrStyleNoDraw) return kBooleanType;
1653 		else if (attributeName == kAttrStyleShadowText) return kBooleanType;
1654 		else if (attributeName == kAttrStyleRoundRect) return kBooleanType;
1655 		else if (attributeName == kAttrRoundRectRadius) return kFloatType;
1656 		else if (attributeName == kAttrFrameWidth) return kFloatType;
1657 		else if (attributeName == kAttrTextAlignment) return kStringType;
1658 		else if (attributeName == kAttrTextInset) return kPointType;
1659 		else if (attributeName == kAttrTextShadowOffset) return kPointType;
1660 		else if (attributeName == kAttrValuePrecision) return kIntegerType;
1661 		else if (attributeName == kAttrTextRotation) return kFloatType;
1662 		else if (attributeName == kAttrBackgroundOffset) return kPointType;
1663 		return kUnknownType;
1664 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1665 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1666 	{
1667 		auto* pd = dynamic_cast<CParamDisplay*> (view);
1668 		if (pd == nullptr)
1669 			return false;
1670 		if (attributeName == kAttrFont)
1671 		{
1672 			UTF8StringPtr fontName = desc->lookupFontName (pd->getFont ());
1673 			if (fontName)
1674 			{
1675 				stringValue = fontName;
1676 				return true;
1677 			}
1678 			return false;
1679 		}
1680 		else if (attributeName == kAttrFontColor)
1681 		{
1682 			colorToString (pd->getFontColor (), stringValue, desc);
1683 			return true;
1684 		}
1685 		else if (attributeName == kAttrBackColor)
1686 		{
1687 			colorToString (pd->getBackColor (), stringValue, desc);
1688 			return true;
1689 		}
1690 		else if (attributeName == kAttrFrameColor)
1691 		{
1692 			colorToString (pd->getFrameColor (), stringValue, desc);
1693 			return true;
1694 		}
1695 		else if (attributeName == kAttrShadowColor)
1696 		{
1697 			colorToString (pd->getShadowColor (), stringValue, desc);
1698 			return true;
1699 		}
1700 		else if (attributeName == kAttrTextInset)
1701 		{
1702 			pointToString (pd->getTextInset (), stringValue);
1703 			return true;
1704 		}
1705 		else if (attributeName == kAttrTextShadowOffset)
1706 		{
1707 			pointToString (pd->getShadowTextOffset (), stringValue);
1708 			return true;
1709 		}
1710 		else if (attributeName == kAttrFontAntialias)
1711 		{
1712 			stringValue = pd->getAntialias () ? strTrue : strFalse;
1713 			return true;
1714 		}
1715 		else if (attributeName == kAttrStyle3DIn)
1716 		{
1717 			stringValue = pd->getStyle () & CParamDisplay::k3DIn ? strTrue : strFalse;
1718 			return true;
1719 		}
1720 		else if (attributeName == kAttrStyle3DOut)
1721 		{
1722 			stringValue = pd->getStyle () & CParamDisplay::k3DOut ? strTrue : strFalse;
1723 			return true;
1724 		}
1725 		else if (attributeName == kAttrStyleNoFrame)
1726 		{
1727 			stringValue = pd->getStyle () & CParamDisplay::kNoFrame ? strTrue : strFalse;
1728 			return true;
1729 		}
1730 		else if (attributeName == kAttrStyleNoText)
1731 		{
1732 			stringValue = pd->getStyle () & CParamDisplay::kNoTextStyle ? strTrue : strFalse;
1733 			return true;
1734 		}
1735 		else if (attributeName == kAttrStyleNoDraw)
1736 		{
1737 			stringValue = pd->getStyle () & CParamDisplay::kNoDrawStyle ? strTrue : strFalse;
1738 			return true;
1739 		}
1740 		else if (attributeName == kAttrStyleShadowText)
1741 		{
1742 			stringValue = pd->getStyle () & CParamDisplay::kShadowText ? strTrue : strFalse;
1743 			return true;
1744 		}
1745 		else if (attributeName == kAttrStyleRoundRect)
1746 		{
1747 			stringValue = pd->getStyle () & CParamDisplay::kRoundRectStyle ? strTrue : strFalse;
1748 			return true;
1749 		}
1750 		else if (attributeName == kAttrRoundRectRadius)
1751 		{
1752 			stringValue = numberToString (pd->getRoundRectRadius ());
1753 			return true;
1754 		}
1755 		else if (attributeName == kAttrFrameWidth)
1756 		{
1757 			stringValue = numberToString (pd->getFrameWidth ());
1758 			return true;
1759 		}
1760 		else if (attributeName == kAttrTextAlignment)
1761 		{
1762 			CHoriTxtAlign align = pd->getHoriAlign ();
1763 			switch (align)
1764 			{
1765 				case kLeftText: stringValue = strLeft; break;
1766 				case kRightText: stringValue = strRight; break;
1767 				case kCenterText: stringValue = strCenter; break;
1768 			}
1769 			return true;
1770 		}
1771 		else if (attributeName == kAttrValuePrecision)
1772 		{
1773 			stringValue = numberToString ((uint32_t)pd->getPrecision ());
1774 			return true;
1775 		}
1776 		else if (attributeName == kAttrTextRotation)
1777 		{
1778 			stringValue = numberToString (pd->getTextRotation ());
1779 			return true;
1780 		}
1781 		else if (attributeName == kAttrBackgroundOffset)
1782 		{
1783 			pointToString (pd->getBackOffset (), stringValue);
1784 			return true;
1785 		}
1786 		return false;
1787 	}
getAttributeValueRange(const std::string & attributeName,double & minValue,double & maxValue) const1788 	bool getAttributeValueRange (const std::string& attributeName, double& minValue, double &maxValue) const override
1789 	{
1790 		if (attributeName == kAttrTextRotation)
1791 		{
1792 			minValue = 0.;
1793 			maxValue = 360.;
1794 			return true;
1795 		}
1796 		return false;
1797 	}
1798 
1799 };
1800 CParamDisplayCreator __gCParamDisplayCreator;
1801 
1802 //-----------------------------------------------------------------------------
1803 class COptionMenuCreator : public ViewCreatorAdapter
1804 {
1805 public:
COptionMenuCreator()1806 	COptionMenuCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1807 	IdStringPtr getViewName () const override { return kCOptionMenu; }
getBaseViewName() const1808 	IdStringPtr getBaseViewName () const override { return kCParamDisplay; }
getDisplayName() const1809 	UTF8StringPtr getDisplayName () const override { return "Option Menu"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1810 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new COptionMenu (CRect (0, 0, 100, 20), nullptr, -1); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1811 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1812 	{
1813 		auto* menu = dynamic_cast<COptionMenu*> (view);
1814 		if (!menu)
1815 			return false;
1816 
1817 		int32_t style = menu->getStyle ();
1818 		applyStyleMask (attributes.getAttributeValue (kAttrMenuPopupStyle), COptionMenu::kPopupStyle, style);
1819 		applyStyleMask (attributes.getAttributeValue (kAttrMenuCheckStyle), COptionMenu::kCheckStyle, style);
1820 		menu->setStyle (style);
1821 
1822 		return true;
1823 	}
getAttributeNames(std::list<std::string> & attributeNames) const1824 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1825 	{
1826 		attributeNames.emplace_back (kAttrMenuPopupStyle);
1827 		attributeNames.emplace_back (kAttrMenuCheckStyle);
1828 		return true;
1829 	}
getAttributeType(const std::string & attributeName) const1830 	AttrType getAttributeType (const std::string& attributeName) const override
1831 	{
1832 		if (attributeName == kAttrMenuPopupStyle) return kBooleanType;
1833 		if (attributeName == kAttrMenuCheckStyle) return kBooleanType;
1834 		return kUnknownType;
1835 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1836 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1837 	{
1838 		auto* menu = dynamic_cast<COptionMenu*> (view);
1839 		if (!menu)
1840 			return false;
1841 		if (attributeName == kAttrMenuPopupStyle)
1842 		{
1843 			stringValue = (menu->getStyle () & COptionMenu::kPopupStyle) ? strTrue : strFalse;
1844 			return true;
1845 		}
1846 		if (attributeName == kAttrMenuCheckStyle)
1847 		{
1848 			stringValue = (menu->getStyle () & COptionMenu::kCheckStyle) ? strTrue : strFalse;
1849 			return true;
1850 		}
1851 		return false;
1852 	}
1853 
1854 };
1855 COptionMenuCreator __gCOptionMenuCreator;
1856 
1857 //-----------------------------------------------------------------------------
1858 class CTextLabelCreator : public ViewCreatorAdapter
1859 {
1860 public:
CTextLabelCreator()1861 	CTextLabelCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1862 	IdStringPtr getViewName () const override { return kCTextLabel; }
getBaseViewName() const1863 	IdStringPtr getBaseViewName () const override { return kCParamDisplay; }
getDisplayName() const1864 	UTF8StringPtr getDisplayName () const override { return "Label"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1865 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CTextLabel (CRect (0, 0, 100, 20)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1866 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1867 	{
1868 		auto* label = dynamic_cast<CTextLabel*> (view);
1869 		if (!label)
1870 			return false;
1871 
1872 		const std::string* attr = attributes.getAttributeValue (kAttrTitle);
1873 		if (attr)
1874 		{
1875 			auto index = attr->find ("\\n");
1876 			if (index != std::string::npos)
1877 			{
1878 				auto str = *attr;
1879 				while (index != std::string::npos)
1880 				{
1881 					str.replace (index, 2, "\n");
1882 					index = str.find ("\\n");
1883 				}
1884 				label->setText (UTF8String (std::move (str)));
1885 			}
1886 			else
1887 				label->setText (UTF8String (*attr));
1888 		}
1889 		attr = attributes.getAttributeValue (kAttrTruncateMode);
1890 		if (attr)
1891 		{
1892 			if (*attr == strHead)
1893 				label->setTextTruncateMode (CTextLabel::kTruncateHead);
1894 			else if (*attr == strTail)
1895 				label->setTextTruncateMode (CTextLabel::kTruncateTail);
1896 			else
1897 				label->setTextTruncateMode (CTextLabel::kTruncateNone);
1898 		}
1899 
1900 		return true;
1901 	}
getAttributeNames(std::list<std::string> & attributeNames) const1902 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1903 	{
1904 		attributeNames.emplace_back (kAttrTitle);
1905 		attributeNames.emplace_back (kAttrTruncateMode);
1906 		return true;
1907 	}
getAttributeType(const std::string & attributeName) const1908 	AttrType getAttributeType (const std::string& attributeName) const override
1909 	{
1910 		if (attributeName == kAttrTitle) return kStringType;
1911 		if (attributeName == kAttrTruncateMode) return kListType;
1912 		return kUnknownType;
1913 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const1914 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
1915 	{
1916 		auto* label = dynamic_cast<CTextLabel*> (view);
1917 		if (!label)
1918 			return false;
1919 		if (attributeName == kAttrTitle)
1920 		{
1921 			stringValue = label->getText ().getString ();
1922 			auto index = stringValue.find ("\n");
1923 			while (index != std::string::npos)
1924 			{
1925 				stringValue.replace (index, 1, "\\n");
1926 				index = stringValue.find ("\n");
1927 			}
1928 			return true;
1929 		}
1930 		else if (attributeName == kAttrTruncateMode)
1931 		{
1932 			switch (label->getTextTruncateMode ())
1933 			{
1934 				case CTextLabel::kTruncateHead: stringValue = strHead; break;
1935 				case CTextLabel::kTruncateTail: stringValue = strTail; break;
1936 				case CTextLabel::kTruncateNone: stringValue = ""; break;
1937 			}
1938 			return true;
1939 		}
1940 		return false;
1941 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const1942 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
1943 	{
1944 		if (attributeName == kAttrTruncateMode)
1945 		{
1946 			return getStandardAttributeListValues (kAttrTruncateMode, values);
1947 		}
1948 		return false;
1949 	}
1950 
1951 };
1952 CTextLabelCreator __gCTextLabelCreator;
1953 
1954 //-----------------------------------------------------------------------------
1955 class CMultiLineTextLabelCreator : public ViewCreatorAdapter
1956 {
1957 public:
1958 	std::string kClip = "clip";
1959 	std::string kTruncate = "truncate";
1960 	std::string kWrap = "wrap";
1961 
CMultiLineTextLabelCreator()1962 	CMultiLineTextLabelCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const1963 	IdStringPtr getViewName () const override { return kCMultiLineTextLabel; }
getBaseViewName() const1964 	IdStringPtr getBaseViewName () const override { return kCTextLabel; }
getDisplayName() const1965 	UTF8StringPtr getDisplayName () const override { return "Multiline Label"; }
create(const UIAttributes & attributes,const IUIDescription * description) const1966 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CMultiLineTextLabel (CRect (0, 0, 100, 20)); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const1967 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
1968 	{
1969 		auto label = dynamic_cast<CMultiLineTextLabel*> (view);
1970 		if (!label)
1971 			return false;
1972 
1973 		auto attr = attributes.getAttributeValue (kAttrLineLayout);
1974 		if (attr)
1975 		{
1976 			if (*attr == kTruncate)
1977 				label->setLineLayout (CMultiLineTextLabel::LineLayout::truncate);
1978 			else if (*attr == kWrap)
1979 				label->setLineLayout (CMultiLineTextLabel::LineLayout::wrap);
1980 			else
1981 				label->setLineLayout (CMultiLineTextLabel::LineLayout::clip);
1982 		}
1983 		bool autoHeight;
1984 		if (attributes.getBooleanAttribute (kAttrAutoHeight, autoHeight))
1985 			label->setAutoHeight (autoHeight);
1986 
1987 		return true;
1988 	}
getAttributeNames(std::list<std::string> & attributeNames) const1989 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
1990 	{
1991 		attributeNames.emplace_back (kAttrLineLayout);
1992 		attributeNames.emplace_back (kAttrAutoHeight);
1993 		return true;
1994 	}
getAttributeType(const std::string & attributeName) const1995 	AttrType getAttributeType (const std::string& attributeName) const override
1996 	{
1997 		if (attributeName == kAttrLineLayout) return kListType;
1998 		if (attributeName == kAttrAutoHeight) return kBooleanType;
1999 		return kUnknownType;
2000 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2001 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2002 	{
2003 		auto label = dynamic_cast<CMultiLineTextLabel*> (view);
2004 		if (!label)
2005 			return false;
2006 		if (attributeName == kAttrLineLayout)
2007 		{
2008 			switch (label->getLineLayout ())
2009 			{
2010 				case CMultiLineTextLabel::LineLayout::truncate: stringValue = kTruncate; break;
2011 				case CMultiLineTextLabel::LineLayout::wrap: stringValue = kWrap; break;
2012 				case CMultiLineTextLabel::LineLayout::clip: stringValue = kClip; break;
2013 			}
2014 			return true;
2015 		}
2016 		else if (attributeName == kAttrAutoHeight)
2017 		{
2018 			stringValue = label->getAutoHeight () ? strTrue : strFalse;
2019 			return true;
2020 		}
2021 
2022 		return false;
2023 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const2024 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
2025 	{
2026 		if (attributeName == kAttrLineLayout)
2027 		{
2028 			values.emplace_back (&kClip);
2029 			values.emplace_back (&kTruncate);
2030 			values.emplace_back (&kWrap);
2031 			return true;
2032 		}
2033 		return false;
2034 	}
2035 
2036 };
2037 CMultiLineTextLabelCreator __gCMultiLineTextLabelCreator;
2038 
2039 //-----------------------------------------------------------------------------
2040 class CTextEditCreator : public ViewCreatorAdapter
2041 {
2042 public:
CTextEditCreator()2043 	CTextEditCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const2044 	IdStringPtr getViewName () const override { return kCTextEdit; }
getBaseViewName() const2045 	IdStringPtr getBaseViewName () const override { return kCTextLabel; }
getDisplayName() const2046 	UTF8StringPtr getDisplayName () const override { return "Text Edit"; }
create(const UIAttributes & attributes,const IUIDescription * description) const2047 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CTextEdit (CRect (0, 0, 100, 20), nullptr, -1); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2048 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2049 	{
2050 		auto* label = dynamic_cast<CTextEdit*> (view);
2051 		if (!label)
2052 			return false;
2053 
2054 		bool b;
2055 		if (attributes.getBooleanAttribute (kAttrSecureStyle, b))
2056 			label->setSecureStyle (b);
2057 		if (attributes.getBooleanAttribute (kAttrImmediateTextChange, b))
2058 			label->setImmediateTextChange (b);
2059 
2060 		int32_t style = label->getStyle ();
2061 		applyStyleMask (attributes.getAttributeValue (kAttrStyleDoubleClick), CTextEdit::kDoubleClickStyle, style);
2062 		label->setStyle (style);
2063 
2064 		if (auto placeholder = attributes.getAttributeValue (kAttrPlaceholderTitle))
2065 			label->setPlaceholderString (placeholder->c_str ());
2066 
2067 		return true;
2068 	}
getAttributeNames(std::list<std::string> & attributeNames) const2069 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
2070 	{
2071 		attributeNames.emplace_back (kAttrSecureStyle);
2072 		attributeNames.emplace_back (kAttrImmediateTextChange);
2073 		attributeNames.emplace_back (kAttrStyleDoubleClick);
2074 		attributeNames.emplace_back (kAttrPlaceholderTitle);
2075 		return true;
2076 	}
getAttributeType(const std::string & attributeName) const2077 	AttrType getAttributeType (const std::string& attributeName) const override
2078 	{
2079 		if (attributeName == kAttrSecureStyle) return kBooleanType;
2080 		if (attributeName == kAttrImmediateTextChange) return kBooleanType;
2081 		if (attributeName == kAttrStyleDoubleClick) return kBooleanType;
2082 		if (attributeName == kAttrPlaceholderTitle) return kStringType;
2083 		return kUnknownType;
2084 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2085 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2086 	{
2087 		auto* label = dynamic_cast<CTextEdit*> (view);
2088 		if (!label)
2089 			return false;
2090 		if (attributeName == kAttrSecureStyle)
2091 		{
2092 			stringValue = label->getSecureStyle () ? strTrue : strFalse;
2093 			return true;
2094 		}
2095 		if (attributeName == kAttrImmediateTextChange)
2096 		{
2097 			stringValue = label->getImmediateTextChange () ? strTrue : strFalse;
2098 			return true;
2099 		}
2100 		if (attributeName == kAttrStyleDoubleClick)
2101 		{
2102 			stringValue = label->getStyle () & CTextEdit::kDoubleClickStyle ? strTrue : strFalse;
2103 			return true;
2104 		}
2105 		if (attributeName == kAttrPlaceholderTitle)
2106 		{
2107 			stringValue = label->getPlaceholderString ().getString ();
2108 			return true;
2109 		}
2110 
2111 		return false;
2112 	}
2113 
2114 };
2115 CTextEditCreator __gCTextEditCreator;
2116 
2117 //------------------------------------------------------------------------
2118 class CSearchTextEditCreator : public ViewCreatorAdapter
2119 {
2120 public:
CSearchTextEditCreator()2121 	CSearchTextEditCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const2122 	IdStringPtr getViewName () const override { return kCSearchTextEdit; }
getBaseViewName() const2123 	IdStringPtr getBaseViewName () const override { return kCTextEdit; }
getDisplayName() const2124 	UTF8StringPtr getDisplayName () const override { return "Search Text Edit"; }
create(const UIAttributes & attributes,const IUIDescription * description) const2125 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
2126 	{
2127 		return new CSearchTextEdit (CRect (0, 0, 100, 20), nullptr, -1);
2128 	}
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2129 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2130 	{
2131 		auto ste = dynamic_cast<CSearchTextEdit*>(view);
2132 		if (!ste)
2133 			return false;
2134 		CPoint p;
2135 		if (attributes.getPointAttribute (kAttrClearMarkInset, p))
2136 			ste->setClearMarkInset (p);
2137 		return true;
2138 	}
getAttributeNames(std::list<std::string> & attributeNames) const2139 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
2140 	{
2141 		attributeNames.emplace_back (kAttrClearMarkInset);
2142 		return true;
2143 	}
getAttributeType(const std::string & attributeName) const2144 	AttrType getAttributeType (const std::string& attributeName) const override
2145 	{
2146 		if (attributeName == kAttrClearMarkInset)
2147 			return kPointType;
2148 		return kUnknownType;
2149 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2150 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2151 	{
2152 		auto ste = dynamic_cast<CSearchTextEdit*>(view);
2153 		if (!ste)
2154 			return false;
2155 		if (attributeName == kAttrClearMarkInset)
2156 		{
2157 			pointToString (ste->getClearMarkInset (), stringValue);
2158 			return true;
2159 		}
2160 		return false;
2161 	}
2162 };
2163 CSearchTextEditCreator __gCSearchTextEditCreator;
2164 
2165 //-----------------------------------------------------------------------------
2166 class CTextButtonCreator : public ViewCreatorAdapter
2167 {
2168 public:
2169 	std::array<std::string, 4> positionsStrings = {
2170 	    {strLeft, "center above text", "center below text", strRight}};
2171 
CTextButtonCreator()2172 	CTextButtonCreator () { UIViewFactory::registerViewCreator (*this); vstgui_assert (positionsStrings.size () == CDrawMethods::kIconRight + 1); }
getViewName() const2173 	IdStringPtr getViewName () const override { return kCTextButton; }
getBaseViewName() const2174 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const2175 	UTF8StringPtr getDisplayName () const override { return "Text Button"; }
create(const UIAttributes & attributes,const IUIDescription * description) const2176 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
2177 	{
2178 		CTextButton* button = new CTextButton (CRect (0, 0, 100, 20), nullptr, -1, "");
2179 		if (!description->lookupGradientName (button->getGradient ()))
2180 			addGradientToUIDescription (description, button->getGradient (), "Default TextButton Gradient");
2181 		if (!description->lookupGradientName (button->getGradientHighlighted ()))
2182 			addGradientToUIDescription (description, button->getGradientHighlighted (), "Default TextButton Gradient Highlighted");
2183 		return button;
2184 	}
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2185 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2186 	{
2187 		auto* button = dynamic_cast<CTextButton*> (view);
2188 		if (!button)
2189 			return false;
2190 
2191 		const std::string* attr = attributes.getAttributeValue (kAttrTitle);
2192 		if (attr)
2193 			button->setTitle (attr->c_str ());
2194 
2195 		attr = attributes.getAttributeValue (kAttrFont);
2196 		if (attr)
2197 		{
2198 			CFontRef font = description->getFont (attr->c_str ());
2199 			if (font)
2200 			{
2201 				button->setFont (font);
2202 			}
2203 		}
2204 
2205 		CColor color;
2206 		if (stringToColor (attributes.getAttributeValue (kAttrTextColor), color, description))
2207 			button->setTextColor (color);
2208 		if (stringToColor (attributes.getAttributeValue (kAttrTextColorHighlighted), color, description))
2209 			button->setTextColorHighlighted (color);
2210 		if (stringToColor (attributes.getAttributeValue (kAttrFrameColor), color, description))
2211 			button->setFrameColor (color);
2212 		if (stringToColor (attributes.getAttributeValue (kAttrFrameColorHighlighted), color, description))
2213 			button->setFrameColorHighlighted (color);
2214 
2215 		double d;
2216 		if (attributes.getDoubleAttribute (kAttrFrameWidth, d))
2217 			button->setFrameWidth (d);
2218 		if (attributes.getDoubleAttribute (kAttrRoundRadius, d))
2219 			button->setRoundRadius (d);
2220 		if (attributes.getDoubleAttribute (kAttrIconTextMargin, d))
2221 			button->setTextMargin (d);
2222 
2223 		attr = attributes.getAttributeValue (kAttrKickStyle);
2224 		if (attr)
2225 		{
2226 			button->setStyle (*attr == strTrue ? CTextButton::kKickStyle : CTextButton::kOnOffStyle);
2227 		}
2228 
2229 		CBitmap* bitmap;
2230 		if (stringToBitmap (attributes.getAttributeValue (kAttrIcon), bitmap, description))
2231 			button->setIcon (bitmap);
2232 		if (stringToBitmap (attributes.getAttributeValue (kAttrIconHighlighted), bitmap, description))
2233 			button->setIconHighlighted (bitmap);
2234 
2235 		attr = attributes.getAttributeValue (kAttrIconPosition);
2236 		if (attr)
2237 		{
2238 			auto it = std::find (positionsStrings.begin (), positionsStrings.end (), *attr);
2239 			if (it != positionsStrings.end ())
2240 			{
2241 				auto pos = std::distance (positionsStrings.begin (), it);
2242 				button->setIconPosition (static_cast<CDrawMethods::IconPosition> (pos));
2243 			}
2244 		}
2245 		attr = attributes.getAttributeValue (kAttrTextAlignment);
2246 		if (attr)
2247 		{
2248 			CHoriTxtAlign align = kCenterText;
2249 			if (*attr == strLeft)
2250 				align = kLeftText;
2251 			else if (*attr == strRight)
2252 				align = kRightText;
2253 			button->setTextAlignment (align);
2254 		}
2255 		const std::string* gradientName = attributes.getAttributeValue (kAttrGradient);
2256 		if (gradientName)
2257 			button->setGradient (description->getGradient (gradientName->c_str ()));
2258 		const std::string* gradientHighlightedName = attributes.getAttributeValue (kAttrGradientHighlighted);
2259 		if (gradientHighlightedName)
2260 			button->setGradientHighlighted (description->getGradient (gradientHighlightedName->c_str ()));
2261 
2262 		if (gradientName == nullptr && gradientHighlightedName == nullptr)
2263 		{
2264 			bool hasOldGradient = true;
2265 			CColor startColor, highlightedStartColor, endColor, highlightedEndColor;
2266 			if (!stringToColor (attributes.getAttributeValue (kAttrGradientStartColor), startColor, description))
2267 				hasOldGradient = false;
2268 			if (hasOldGradient && !stringToColor (attributes.getAttributeValue (kAttrGradientStartColorHighlighted), highlightedStartColor, description))
2269 				hasOldGradient = false;
2270 			if (hasOldGradient && !stringToColor (attributes.getAttributeValue (kAttrGradientEndColor), endColor, description))
2271 				hasOldGradient = false;
2272 			if (hasOldGradient && !stringToColor (attributes.getAttributeValue (kAttrGradientEndColorHighlighted), highlightedEndColor, description))
2273 				hasOldGradient = false;
2274 			if (hasOldGradient)
2275 			{
2276 				SharedPointer<CGradient> gradient = owned (CGradient::create (0, 1, startColor, endColor));
2277 				button->setGradient (gradient);
2278 				addGradientToUIDescription (description, gradient, "TextButton");
2279 				gradient = owned (CGradient::create (0, 1, highlightedStartColor, highlightedEndColor));
2280 				button->setGradientHighlighted (gradient);
2281 				addGradientToUIDescription (description, gradient, "TextButton Highlighted");
2282 			}
2283 		}
2284 
2285 		return true;
2286 	}
getAttributeNames(std::list<std::string> & attributeNames) const2287 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
2288 	{
2289 		attributeNames.emplace_back (kAttrKickStyle);
2290 		attributeNames.emplace_back (kAttrTitle);
2291 		attributeNames.emplace_back (kAttrFont);
2292 		attributeNames.emplace_back (kAttrTextColor);
2293 		attributeNames.emplace_back (kAttrTextColorHighlighted);
2294 		attributeNames.emplace_back (kAttrGradient);
2295 		attributeNames.emplace_back (kAttrGradientHighlighted);
2296 		attributeNames.emplace_back (kAttrFrameColor);
2297 		attributeNames.emplace_back (kAttrFrameColorHighlighted);
2298 		attributeNames.emplace_back (kAttrRoundRadius);
2299 		attributeNames.emplace_back (kAttrFrameWidth);
2300 		attributeNames.emplace_back (kAttrIconTextMargin);
2301 		attributeNames.emplace_back (kAttrTextAlignment);
2302 		attributeNames.emplace_back (kAttrIcon);
2303 		attributeNames.emplace_back (kAttrIconHighlighted);
2304 		attributeNames.emplace_back (kAttrIconPosition);
2305 		return true;
2306 	}
getAttributeType(const std::string & attributeName) const2307 	AttrType getAttributeType (const std::string& attributeName) const override
2308 	{
2309 		if (attributeName == kAttrTitle) return kStringType;
2310 		if (attributeName == kAttrFont) return kFontType;
2311 		if (attributeName == kAttrTextColor) return kColorType;
2312 		if (attributeName == kAttrTextColorHighlighted) return kColorType;
2313 		if (attributeName == kAttrGradient) return kGradientType;
2314 		if (attributeName == kAttrGradientHighlighted) return kGradientType;
2315 		if (attributeName == kAttrFrameColor) return kColorType;
2316 		if (attributeName == kAttrFrameColorHighlighted) return kColorType;
2317 		if (attributeName == kAttrFrameWidth) return kFloatType;
2318 		if (attributeName == kAttrRoundRadius) return kFloatType;
2319 		if (attributeName == kAttrKickStyle) return kBooleanType;
2320 		if (attributeName == kAttrIcon) return kBitmapType;
2321 		if (attributeName == kAttrIconHighlighted) return kBitmapType;
2322 		if (attributeName == kAttrIconPosition) return kListType;
2323 		if (attributeName == kAttrIconTextMargin) return kFloatType;
2324 		if (attributeName == kAttrTextAlignment) return kStringType;
2325 		return kUnknownType;
2326 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const2327 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
2328 	{
2329 		if (attributeName == kAttrIconPosition)
2330 		{
2331 			for (const auto& s : positionsStrings)
2332 				values.emplace_back (&s);
2333 			return true;
2334 		}
2335 		return false;
2336 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2337 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2338 	{
2339 		auto* button = dynamic_cast<CTextButton*> (view);
2340 		if (!button)
2341 			return false;
2342 		if (attributeName == kAttrTitle)
2343 		{
2344 			stringValue = button->getTitle ().getString ();
2345 			return true;
2346 		}
2347 		else if (attributeName == kAttrFont)
2348 		{
2349 			UTF8StringPtr fontName = desc->lookupFontName (button->getFont ());
2350 			if (fontName)
2351 			{
2352 				stringValue = fontName;
2353 				return true;
2354 			}
2355 			return false;
2356 		}
2357 		else if (attributeName == kAttrTextColor)
2358 		{
2359 			colorToString (button->getTextColor (), stringValue, desc);
2360 			return true;
2361 		}
2362 		else if (attributeName == kAttrTextColorHighlighted)
2363 		{
2364 			colorToString (button->getTextColorHighlighted (), stringValue, desc);
2365 			return true;
2366 		}
2367 		else if (attributeName == kAttrFrameColor)
2368 		{
2369 			colorToString (button->getFrameColor (), stringValue, desc);
2370 			return true;
2371 		}
2372 		else if (attributeName == kAttrFrameColorHighlighted)
2373 		{
2374 			colorToString (button->getFrameColorHighlighted (), stringValue, desc);
2375 			return true;
2376 		}
2377 		else if (attributeName == kAttrFrameWidth)
2378 		{
2379 			stringValue = numberToString (button->getFrameWidth ());
2380 			return true;
2381 		}
2382 		else if (attributeName == kAttrRoundRadius)
2383 		{
2384 			stringValue = numberToString (button->getRoundRadius ());
2385 			return true;
2386 		}
2387 		else if (attributeName == kAttrKickStyle)
2388 		{
2389 			stringValue = button->getStyle() == CTextButton::kKickStyle ? strTrue : strFalse;
2390 			return true;
2391 		}
2392 		else if (attributeName == kAttrIcon)
2393 		{
2394 			CBitmap* bitmap = button->getIcon ();
2395 			if (bitmap)
2396 			{
2397 				return bitmapToString (bitmap, stringValue, desc);
2398 			}
2399 		}
2400 		else if (attributeName == kAttrIconHighlighted)
2401 		{
2402 			CBitmap* bitmap = button->getIconHighlighted ();
2403 			if (bitmap)
2404 			{
2405 				return bitmapToString (bitmap, stringValue, desc);
2406 			}
2407 		}
2408 		else if (attributeName == kAttrIconPosition)
2409 		{
2410 			auto pos = button->getIconPosition ();
2411 			vstgui_assert (pos < positionsStrings.size ());
2412 			stringValue = positionsStrings[pos];
2413 			return true;
2414 		}
2415 		else if (attributeName == kAttrIconTextMargin)
2416 		{
2417 			stringValue = numberToString (button->getTextMargin ());
2418 			return true;
2419 		}
2420 		else if (attributeName == kAttrTextAlignment)
2421 		{
2422 			CHoriTxtAlign align = button->getTextAlignment ();
2423 			switch (align)
2424 			{
2425 				case kLeftText: stringValue = strLeft; break;
2426 				case kRightText: stringValue = strRight; break;
2427 				case kCenterText: stringValue = strCenter; break;
2428 			}
2429 			return true;
2430 		}
2431 		else if (attributeName == kAttrGradient)
2432 		{
2433 			CGradient* gradient = button->getGradient ();
2434 			UTF8StringPtr gradientName = gradient ? desc->lookupGradientName (gradient) : nullptr;
2435 			stringValue = gradientName ? gradientName : "";
2436 			return true;
2437 		}
2438 		else if (attributeName == kAttrGradientHighlighted)
2439 		{
2440 			CGradient* gradient = button->getGradientHighlighted ();
2441 			UTF8StringPtr gradientName = gradient ? desc->lookupGradientName (gradient) : nullptr;
2442 			stringValue = gradientName ? gradientName : "";
2443 			return true;
2444 		}
2445 		return false;
2446 	}
2447 
2448 };
2449 CTextButtonCreator __gCTextButtonCreator;
2450 
2451 //-----------------------------------------------------------------------------
2452 class CSegmentButtonCreator : public ViewCreatorAdapter
2453 {
2454 public:
2455 	std::string SelectionModeSingle = "Single";
2456 	std::string SelectionModeMultiple = "Multiple";
2457 
CSegmentButtonCreator()2458 	CSegmentButtonCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const2459 	IdStringPtr getViewName () const override { return kCSegmentButton; }
getBaseViewName() const2460 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const2461 	UTF8StringPtr getDisplayName () const override { return "Segment Button"; }
create(const UIAttributes & attributes,const IUIDescription * description) const2462 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
2463 	{
2464 		CSegmentButton* button = new CSegmentButton (CRect (0, 0, 200, 20));
2465 		updateSegmentCount (button, 4);
2466 		return button;
2467 	}
updateSegmentCount(CSegmentButton * button,uint32_t numSegments) const2468 	void updateSegmentCount (CSegmentButton* button, uint32_t numSegments) const
2469 	{
2470 		if (button->getSegments ().size () != numSegments)
2471 		{
2472 			button->removeAllSegments ();
2473 			for (uint32_t i = 0; i < numSegments; i++)
2474 			{
2475 				std::stringstream str;
2476 				str << "Segment ";
2477 				str << i + 1;
2478 				CSegmentButton::Segment seg;
2479 				seg.name = str.str ().c_str ();
2480 				button->addSegment (std::move (seg));
2481 			}
2482 		}
2483 	}
updateSegments(CSegmentButton * button,const UIAttributes::StringArray & names) const2484 	void updateSegments (CSegmentButton* button, const UIAttributes::StringArray& names) const
2485 	{
2486 		button->removeAllSegments ();
2487 		for (const auto& name : names)
2488 		{
2489 			CSegmentButton::Segment segment;
2490 			segment.name = name.c_str ();
2491 			button->addSegment (std::move (segment));
2492 		}
2493 	}
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2494 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2495 	{
2496 		auto* button = dynamic_cast<CSegmentButton*> (view);
2497 		if (!button)
2498 			return false;
2499 
2500 		const std::string* attr = attributes.getAttributeValue (kAttrFont);
2501 		if (attr)
2502 		{
2503 			CFontRef font = description->getFont (attr->c_str ());
2504 			if (font)
2505 			{
2506 				button->setFont (font);
2507 			}
2508 		}
2509 
2510 		attr = attributes.getAttributeValue (kAttrStyle);
2511 		if (attr)
2512 			button->setStyle (*attr == strHorizontal ? CSegmentButton::Style::kHorizontal : CSegmentButton::Style::kVertical);
2513 
2514 		CColor color;
2515 		if (stringToColor (attributes.getAttributeValue (kAttrTextColor), color, description))
2516 			button->setTextColor (color);
2517 		if (stringToColor (attributes.getAttributeValue (kAttrTextColorHighlighted), color, description))
2518 			button->setTextColorHighlighted (color);
2519 		if (stringToColor (attributes.getAttributeValue (kAttrFrameColor), color, description))
2520 			button->setFrameColor (color);
2521 
2522 		double d;
2523 		if (attributes.getDoubleAttribute (kAttrFrameWidth, d))
2524 			button->setFrameWidth (d);
2525 		if (attributes.getDoubleAttribute (kAttrRoundRadius, d))
2526 			button->setRoundRadius (d);
2527 		if (attributes.getDoubleAttribute (kAttrIconTextMargin, d))
2528 			button->setTextMargin (d);
2529 
2530 		attr = attributes.getAttributeValue (kAttrTextAlignment);
2531 		if (attr)
2532 		{
2533 			CHoriTxtAlign align = kCenterText;
2534 			if (*attr == strLeft)
2535 				align = kLeftText;
2536 			else if (*attr == strRight)
2537 				align = kRightText;
2538 			button->setTextAlignment (align);
2539 		}
2540 		const std::string* gradientName = attributes.getAttributeValue (kAttrGradient);
2541 		if (gradientName)
2542 			button->setGradient (description->getGradient (gradientName->c_str ()));
2543 		const std::string* gradientHighlightedName = attributes.getAttributeValue (kAttrGradientHighlighted);
2544 		if (gradientHighlightedName)
2545 			button->setGradientHighlighted (description->getGradient (gradientHighlightedName->c_str ()));
2546 
2547 		UIAttributes::StringArray segmentNames;
2548 		if (attributes.getStringArrayAttribute (kAttrSegmentNames, segmentNames))
2549 			updateSegments (button, segmentNames);
2550 
2551 		attr = attributes.getAttributeValue (kAttrTruncateMode);
2552 		if (attr)
2553 		{
2554 			if (*attr == strHead)
2555 				button->setTextTruncateMode (CDrawMethods::kTextTruncateHead);
2556 			else if (*attr == strTail)
2557 				button->setTextTruncateMode (CDrawMethods::kTextTruncateTail);
2558 			else
2559 				button->setTextTruncateMode (CDrawMethods::kTextTruncateNone);
2560 		}
2561 		attr = attributes.getAttributeValue (kAttrSelectionMode);
2562 		if (attr)
2563 		{
2564 			if (*attr == SelectionModeSingle)
2565 				button->setSelectionMode (CSegmentButton::SelectionMode::kSingle);
2566 			else if (*attr == SelectionModeMultiple)
2567 				button->setSelectionMode (CSegmentButton::SelectionMode::kMultiple);
2568 		}
2569 		return true;
2570 	}
getAttributeNames(std::list<std::string> & attributeNames) const2571 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
2572 	{
2573 		attributeNames.emplace_back (kAttrStyle);
2574 		attributeNames.emplace_back (kAttrSelectionMode);
2575 		attributeNames.emplace_back (kAttrSegmentNames);
2576 		attributeNames.emplace_back (kAttrFont);
2577 		attributeNames.emplace_back (kAttrTextColor);
2578 		attributeNames.emplace_back (kAttrTextColorHighlighted);
2579 		attributeNames.emplace_back (kAttrGradient);
2580 		attributeNames.emplace_back (kAttrGradientHighlighted);
2581 		attributeNames.emplace_back (kAttrFrameColor);
2582 		attributeNames.emplace_back (kAttrRoundRadius);
2583 		attributeNames.emplace_back (kAttrFrameWidth);
2584 		attributeNames.emplace_back (kAttrIconTextMargin);
2585 		attributeNames.emplace_back (kAttrTextAlignment);
2586 		attributeNames.emplace_back (kAttrTruncateMode);
2587 		return true;
2588 	}
getAttributeType(const std::string & attributeName) const2589 	AttrType getAttributeType (const std::string& attributeName) const override
2590 	{
2591 		if (attributeName == kAttrStyle) return kListType;
2592 		if (attributeName == kAttrSelectionMode) return kListType;
2593 		if (attributeName == kAttrSegmentNames) return kStringType;
2594 		if (attributeName == kAttrFont) return kFontType;
2595 		if (attributeName == kAttrTextColor) return kColorType;
2596 		if (attributeName == kAttrTextColorHighlighted) return kColorType;
2597 		if (attributeName == kAttrGradient) return kGradientType;
2598 		if (attributeName == kAttrGradientHighlighted) return kGradientType;
2599 		if (attributeName == kAttrFrameColor) return kColorType;
2600 		if (attributeName == kAttrFrameWidth) return kFloatType;
2601 		if (attributeName == kAttrRoundRadius) return kFloatType;
2602 		if (attributeName == kAttrIconTextMargin) return kFloatType;
2603 		if (attributeName == kAttrTextAlignment) return kStringType;
2604 		if (attributeName == kAttrTruncateMode) return kListType;
2605 		return kUnknownType;
2606 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const2607 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
2608 	{
2609 		if (attributeName == kAttrStyle)
2610 		{
2611 			return getStandardAttributeListValues (kAttrOrientation, values);
2612 		}
2613 		else if (attributeName == kAttrSelectionMode)
2614 		{
2615 			values.push_back (&SelectionModeSingle);
2616 			values.push_back (&SelectionModeMultiple);
2617 			return true;
2618 		}
2619 		else if (attributeName == kAttrTruncateMode)
2620 		{
2621 			return getStandardAttributeListValues (kAttrTruncateMode, values);
2622 		}
2623 		return false;
2624 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2625 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2626 	{
2627 		auto* button = dynamic_cast<CSegmentButton*> (view);
2628 		if (!button)
2629 			return false;
2630 		if (attributeName == kAttrFont)
2631 		{
2632 			UTF8StringPtr fontName = desc->lookupFontName (button->getFont ());
2633 			if (fontName)
2634 			{
2635 				stringValue = fontName;
2636 				return true;
2637 			}
2638 			return false;
2639 		}
2640 		else if (attributeName == kAttrSegmentNames)
2641 		{
2642 			const CSegmentButton::Segments& segments = button->getSegments ();
2643 			UIAttributes::StringArray stringArray;
2644 			for (const auto& segment : segments)
2645 				stringArray.emplace_back (segment.name.getString ());
2646 			stringValue = UIAttributes::createStringArrayValue (stringArray);
2647 			return true;
2648 		}
2649 		else if (attributeName == kAttrTextColor)
2650 		{
2651 			colorToString (button->getTextColor (), stringValue, desc);
2652 			return true;
2653 		}
2654 		else if (attributeName == kAttrTextColorHighlighted)
2655 		{
2656 			colorToString (button->getTextColorHighlighted (), stringValue, desc);
2657 			return true;
2658 		}
2659 		else if (attributeName == kAttrFrameColor)
2660 		{
2661 			colorToString (button->getFrameColor (), stringValue, desc);
2662 			return true;
2663 		}
2664 		else if (attributeName == kAttrFrameWidth)
2665 		{
2666 			stringValue = numberToString (button->getFrameWidth ());
2667 			return true;
2668 		}
2669 		else if (attributeName == kAttrRoundRadius)
2670 		{
2671 			stringValue = numberToString (button->getRoundRadius ());
2672 			return true;
2673 		}
2674 		else if (attributeName == kAttrStyle)
2675 		{
2676 			stringValue = button->getStyle () == CSegmentButton::Style::kHorizontal ? strHorizontal :
2677 			                                                                          strVertical;
2678 			return true;
2679 		}
2680 		else if (attributeName == kAttrIconTextMargin)
2681 		{
2682 			stringValue = numberToString (button->getTextMargin ());
2683 			return true;
2684 		}
2685 		else if (attributeName == kAttrTextAlignment)
2686 		{
2687 			CHoriTxtAlign align = button->getTextAlignment ();
2688 			switch (align)
2689 			{
2690 				case kLeftText: stringValue = strLeft; break;
2691 				case kRightText: stringValue = strRight; break;
2692 				case kCenterText: stringValue = strCenter; break;
2693 			}
2694 			return true;
2695 		}
2696 		else if (attributeName == kAttrGradient)
2697 		{
2698 			CGradient* gradient = button->getGradient ();
2699 			if (gradient)
2700 			{
2701 				UTF8StringPtr gradientName = desc->lookupGradientName (gradient);
2702 				stringValue = gradientName ? gradientName : "";
2703 			}
2704 			return true;
2705 		}
2706 		else if (attributeName == kAttrGradientHighlighted)
2707 		{
2708 			CGradient* gradient = button->getGradientHighlighted ();
2709 			if (gradient)
2710 			{
2711 				UTF8StringPtr gradientName = desc->lookupGradientName (gradient);
2712 				stringValue = gradientName ? gradientName : "";
2713 			}
2714 			return true;
2715 		}
2716 		else if (attributeName == kAttrTruncateMode)
2717 		{
2718 			switch (button->getTextTruncateMode ())
2719 			{
2720 				case CDrawMethods::kTextTruncateHead: stringValue = strHead; break;
2721 				case CDrawMethods::kTextTruncateTail: stringValue = strTail; break;
2722 				case CDrawMethods::kTextTruncateNone: stringValue = ""; break;
2723 			}
2724 			return true;
2725 		}
2726 		else if (attributeName == kAttrSelectionMode)
2727 		{
2728 			switch (button->getSelectionMode ())
2729 			{
2730 				case CSegmentButton::SelectionMode::kSingle:
2731 				{
2732 					stringValue = SelectionModeSingle;
2733 					break;
2734 				}
2735 				case CSegmentButton::SelectionMode::kMultiple:
2736 				{
2737 					stringValue = SelectionModeMultiple;
2738 					break;
2739 				}
2740 			}
2741 			return true;
2742 		}
2743 		return false;
2744 	}
2745 
2746 };
2747 CSegmentButtonCreator __gCSegmentButtonCreator;
2748 
2749 //-----------------------------------------------------------------------------
2750 class CKnobCreator : public ViewCreatorAdapter
2751 {
2752 public:
CKnobCreator()2753 	CKnobCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const2754 	IdStringPtr getViewName () const override { return kCKnob; }
getBaseViewName() const2755 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const2756 	UTF8StringPtr getDisplayName () const override { return "Knob"; }
create(const UIAttributes & attributes,const IUIDescription * description) const2757 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CKnob (CRect (0, 0, 0, 0), nullptr, -1, nullptr, nullptr); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2758 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2759 	{
2760 		auto* knob = dynamic_cast<CKnob*> (view);
2761 		if (!knob)
2762 			return false;
2763 
2764 		double d;
2765 		if (attributes.getDoubleAttribute (kAttrAngleStart, d))
2766 		{
2767 			// convert from degree
2768 			d = d / 180.f * (float)Constants::pi;
2769 			knob->setStartAngle (static_cast<float>(d));
2770 		}
2771 		if (attributes.getDoubleAttribute (kAttrAngleRange, d))
2772 		{
2773 			// convert from degree
2774 			d = d / 180.f * (float)Constants::pi;
2775 			knob->setRangeAngle (static_cast<float>(d));
2776 		}
2777 		if (attributes.getDoubleAttribute (kAttrValueInset, d))
2778 			knob->setInsetValue (d);
2779 		if (attributes.getDoubleAttribute (kAttrCoronaInset, d))
2780 			knob->setCoronaInset (d);
2781 		if (attributes.getDoubleAttribute (kAttrZoomFactor, d))
2782 			knob->setZoomFactor (static_cast<float>(d));
2783 		if (attributes.getDoubleAttribute (kAttrHandleLineWidth, d))
2784 			knob->setHandleLineWidth (d);
2785 		if (attributes.getDoubleAttribute (kAttrCoronaOutlineWidthAdd, d))
2786 			knob->setCoronaOutlineWidthAdd (d);
2787 
2788 		CColor color;
2789 		if (stringToColor (attributes.getAttributeValue (kAttrCoronaColor), color, description))
2790 			knob->setCoronaColor (color);
2791 		if (stringToColor (attributes.getAttributeValue (kAttrHandleShadowColor), color, description))
2792 			knob->setColorShadowHandle (color);
2793 		if (stringToColor (attributes.getAttributeValue (kAttrHandleColor), color, description))
2794 			knob->setColorHandle (color);
2795 
2796 		CBitmap* bitmap;
2797 		if (stringToBitmap (attributes.getAttributeValue (kAttrHandleBitmap), bitmap, description))
2798 			knob->setHandleBitmap (bitmap);
2799 
2800 		int32_t drawStyle = knob->getDrawStyle ();
2801 		applyStyleMask (attributes.getAttributeValue (kAttrCircleDrawing), CKnob::kHandleCircleDrawing, drawStyle);
2802 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaDrawing), CKnob::kCoronaDrawing, drawStyle);
2803 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaFromCenter), CKnob::kCoronaFromCenter, drawStyle);
2804 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaInverted), CKnob::kCoronaInverted, drawStyle);
2805 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaDashDot), CKnob::kCoronaLineDashDot, drawStyle);
2806 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaOutline), CKnob::kCoronaOutline, drawStyle);
2807 		applyStyleMask (attributes.getAttributeValue (kAttrCoronaLineCapButt), CKnob::kCoronaLineCapButt, drawStyle);
2808 		applyStyleMask (attributes.getAttributeValue (kAttrSkipHandleDrawing), CKnob::kSkipHandleDrawing, drawStyle);
2809 		knob->setDrawStyle (drawStyle);
2810 		return true;
2811 	}
getAttributeNames(std::list<std::string> & attributeNames) const2812 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
2813 	{
2814 		attributeNames.emplace_back (kAttrAngleStart);
2815 		attributeNames.emplace_back (kAttrAngleRange);
2816 		attributeNames.emplace_back (kAttrValueInset);
2817 		attributeNames.emplace_back (kAttrZoomFactor);
2818 		attributeNames.emplace_back (kAttrCircleDrawing);
2819 		attributeNames.emplace_back (kAttrCoronaDrawing);
2820 		attributeNames.emplace_back (kAttrCoronaOutline);
2821 		attributeNames.emplace_back (kAttrCoronaFromCenter);
2822 		attributeNames.emplace_back (kAttrCoronaInverted);
2823 		attributeNames.emplace_back (kAttrCoronaDashDot);
2824 		attributeNames.emplace_back (kAttrCoronaLineCapButt);
2825 		attributeNames.emplace_back (kAttrSkipHandleDrawing);
2826 		attributeNames.emplace_back (kAttrCoronaInset);
2827 		attributeNames.emplace_back (kAttrCoronaColor);
2828 		attributeNames.emplace_back (kAttrHandleShadowColor);
2829 		attributeNames.emplace_back (kAttrHandleColor);
2830 		attributeNames.emplace_back (kAttrHandleLineWidth);
2831 		attributeNames.emplace_back (kAttrCoronaOutlineWidthAdd);
2832 		attributeNames.emplace_back (kAttrHandleBitmap);
2833 		return true;
2834 	}
getAttributeType(const std::string & attributeName) const2835 	AttrType getAttributeType (const std::string& attributeName) const override
2836 	{
2837 		if (attributeName == kAttrAngleStart) return kFloatType;
2838 		else if (attributeName == kAttrAngleRange) return kFloatType;
2839 		else if (attributeName == kAttrValueInset) return kFloatType;
2840 		else if (attributeName == kAttrZoomFactor) return kFloatType;
2841 		else if (attributeName == kAttrCircleDrawing) return kBooleanType;
2842 		else if (attributeName == kAttrCoronaDrawing) return kBooleanType;
2843 		else if (attributeName == kAttrCoronaOutline) return kBooleanType;
2844 		else if (attributeName == kAttrCoronaFromCenter) return kBooleanType;
2845 		else if (attributeName == kAttrCoronaInverted) return kBooleanType;
2846 		else if (attributeName == kAttrCoronaDashDot) return kBooleanType;
2847 		else if (attributeName == kAttrCoronaLineCapButt) return kBooleanType;
2848 		else if (attributeName == kAttrSkipHandleDrawing) return kBooleanType;
2849 		else if (attributeName == kAttrCoronaInset) return kFloatType;
2850 		else if (attributeName == kAttrCoronaColor) return kColorType;
2851 		else if (attributeName == kAttrHandleShadowColor) return kColorType;
2852 		else if (attributeName == kAttrHandleColor) return kColorType;
2853 		else if (attributeName == kAttrHandleLineWidth) return kFloatType;
2854 		else if (attributeName == kAttrCoronaOutlineWidthAdd) return kFloatType;
2855 		else if (attributeName == kAttrHandleBitmap) return kBitmapType;
2856 		return kUnknownType;
2857 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const2858 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
2859 	{
2860 		auto* knob = dynamic_cast<CKnob*> (view);
2861 		if (!knob)
2862 			return false;
2863 
2864 		if (attributeName == kAttrAngleStart)
2865 		{
2866 			stringValue = numberToString ((knob->getStartAngle () / Constants::pi * 180.));
2867 			return true;
2868 		}
2869 		else if (attributeName == kAttrAngleRange)
2870 		{
2871 			stringValue = numberToString ((knob->getRangeAngle () / Constants::pi * 180.));
2872 			return true;
2873 		}
2874 		else if (attributeName == kAttrValueInset)
2875 		{
2876 			stringValue = numberToString (knob->getInsetValue ());
2877 			return true;
2878 		}
2879 		else if (attributeName == kAttrCoronaInset)
2880 		{
2881 			stringValue = numberToString (knob->getCoronaInset ());
2882 			return true;
2883 		}
2884 		else if (attributeName == kAttrZoomFactor)
2885 		{
2886 			stringValue = numberToString (knob->getZoomFactor ());
2887 			return true;
2888 		}
2889 		else if (attributeName == kAttrHandleLineWidth)
2890 		{
2891 			stringValue = numberToString (knob->getHandleLineWidth ());
2892 			return true;
2893 		}
2894 		else if (attributeName == kAttrCoronaOutlineWidthAdd)
2895 		{
2896 			stringValue = numberToString (knob->getCoronaOutlineWidthAdd ());
2897 			return true;
2898 		}
2899 		else if (attributeName == kAttrCoronaColor)
2900 		{
2901 			colorToString (knob->getCoronaColor (), stringValue, desc);
2902 			return true;
2903 		}
2904 		else if (attributeName == kAttrHandleShadowColor)
2905 		{
2906 			colorToString (knob->getColorShadowHandle (), stringValue, desc);
2907 			return true;
2908 		}
2909 		else if (attributeName == kAttrHandleColor)
2910 		{
2911 			colorToString (knob->getColorHandle (), stringValue, desc);
2912 			return true;
2913 		}
2914 		else if (attributeName == kAttrHandleBitmap)
2915 		{
2916 			CBitmap* bitmap = knob->getHandleBitmap ();
2917 			if (bitmap)
2918 			{
2919 				return bitmapToString (bitmap, stringValue, desc);
2920 			}
2921 		}
2922 		else if (attributeName == kAttrCircleDrawing)
2923 		{
2924 			if (knob->getDrawStyle () & CKnob::kHandleCircleDrawing)
2925 				stringValue = strTrue;
2926 			else
2927 				stringValue = strFalse;
2928 			return true;
2929 		}
2930 		else if (attributeName == kAttrCoronaDrawing)
2931 		{
2932 			if (knob->getDrawStyle () & CKnob::kCoronaDrawing)
2933 				stringValue = strTrue;
2934 			else
2935 				stringValue = strFalse;
2936 			return true;
2937 		}
2938 		else if (attributeName == kAttrCoronaFromCenter)
2939 		{
2940 			if (knob->getDrawStyle () & CKnob::kCoronaFromCenter)
2941 				stringValue = strTrue;
2942 			else
2943 				stringValue = strFalse;
2944 			return true;
2945 		}
2946 		else if (attributeName == kAttrCoronaInverted)
2947 		{
2948 			if (knob->getDrawStyle () & CKnob::kCoronaInverted)
2949 				stringValue = strTrue;
2950 			else
2951 				stringValue = strFalse;
2952 			return true;
2953 		}
2954 		else if (attributeName == kAttrCoronaDashDot)
2955 		{
2956 			if (knob->getDrawStyle () & CKnob::kCoronaLineDashDot)
2957 				stringValue = strTrue;
2958 			else
2959 				stringValue = strFalse;
2960 			return true;
2961 		}
2962 		else if (attributeName == kAttrCoronaOutline)
2963 		{
2964 			if (knob->getDrawStyle () & CKnob::kCoronaOutline)
2965 				stringValue = strTrue;
2966 			else
2967 				stringValue = strFalse;
2968 			return true;
2969 		}
2970 		else if (attributeName == kAttrCoronaLineCapButt)
2971 		{
2972 			if (knob->getDrawStyle () & CKnob::kCoronaLineCapButt)
2973 				stringValue = strTrue;
2974 			else
2975 				stringValue = strFalse;
2976 			return true;
2977 		}
2978 		else if (attributeName == kAttrSkipHandleDrawing)
2979 		{
2980 			if (knob->getDrawStyle () & CKnob::kSkipHandleDrawing)
2981 				stringValue = strTrue;
2982 			else
2983 				stringValue = strFalse;
2984 			return true;
2985 		}
2986 		return false;
2987 	}
2988 
2989 };
2990 CKnobCreator __CKnobCreator;
2991 
2992 //-----------------------------------------------------------------------------
2993 class IMultiBitmapControlCreator : public ViewCreatorAdapter
2994 {
2995 public:
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const2996 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
2997 	{
2998 		auto* multiBitmapControl = dynamic_cast<IMultiBitmapControl*> (view);
2999 		if (!multiBitmapControl)
3000 			return false;
3001 
3002 		int32_t value;
3003 		if (attributes.getIntegerAttribute (kAttrHeightOfOneImage, value))
3004 			multiBitmapControl->setHeightOfOneImage (value);
3005 		else
3006 			multiBitmapControl->autoComputeHeightOfOneImage ();
3007 
3008 		if (attributes.getIntegerAttribute (kAttrSubPixmaps, value))
3009 			multiBitmapControl->setNumSubPixmaps (value);
3010 		return true;
3011 	}
getAttributeNames(std::list<std::string> & attributeNames) const3012 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3013 	{
3014 		attributeNames.emplace_back (kAttrHeightOfOneImage);
3015 		attributeNames.emplace_back (kAttrSubPixmaps);
3016 		return true;
3017 	}
getAttributeType(const std::string & attributeName) const3018 	AttrType getAttributeType (const std::string& attributeName) const override
3019 	{
3020 		if (attributeName == kAttrHeightOfOneImage) return kIntegerType;
3021 		if (attributeName == kAttrSubPixmaps) return kIntegerType;
3022 		return kUnknownType;
3023 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3024 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3025 	{
3026 		auto* multiBitmapControl = dynamic_cast<IMultiBitmapControl*> (view);
3027 		if (!multiBitmapControl)
3028 			return false;
3029 
3030 		if (attributeName == kAttrHeightOfOneImage)
3031 		{
3032 			stringValue = numberToString ((int32_t)multiBitmapControl->getHeightOfOneImage ());
3033 			return true;
3034 		}
3035 		if (attributeName == kAttrSubPixmaps)
3036 		{
3037 			stringValue = numberToString (multiBitmapControl->getNumSubPixmaps ());
3038 			return true;
3039 		}
3040 		return false;
3041 	}
3042 
3043 };
3044 
3045 //-----------------------------------------------------------------------------
3046 class CAnimKnobCreator : public IMultiBitmapControlCreator
3047 {
3048 public:
CAnimKnobCreator()3049 	CAnimKnobCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3050 	IdStringPtr getViewName () const override { return kCAnimKnob; }
getBaseViewName() const3051 	IdStringPtr getBaseViewName () const override { return kCKnob; }
getDisplayName() const3052 	UTF8StringPtr getDisplayName () const override { return "Animation Knob"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3053 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CAnimKnob (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3054 
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3055 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3056 	{
3057 		auto* animKnob = dynamic_cast<CAnimKnob*> (view);
3058 		if (!animKnob)
3059 			return false;
3060 
3061 		bool b;
3062 		if (attributes.getBooleanAttribute(kAttrInverseBitmap, b))
3063 		{
3064 			animKnob->setInverseBitmap (b);
3065 		}
3066 
3067 		return IMultiBitmapControlCreator::apply (view, attributes, description);
3068 	}
getAttributeNames(std::list<std::string> & attributeNames) const3069 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3070 	{
3071 		attributeNames.emplace_back (kAttrInverseBitmap);
3072 		return IMultiBitmapControlCreator::getAttributeNames (attributeNames);
3073 	}
getAttributeType(const std::string & attributeName) const3074 	AttrType getAttributeType (const std::string& attributeName) const override
3075 	{
3076 		if (attributeName == kAttrInverseBitmap) return kBooleanType;
3077 		return IMultiBitmapControlCreator::getAttributeType (attributeName);
3078 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3079 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3080 	{
3081 		auto* animKnob = dynamic_cast<CAnimKnob*> (view);
3082 		if (!animKnob)
3083 			return false;
3084 
3085 		if (attributeName == kAttrInverseBitmap)
3086 		{
3087 			stringValue = animKnob->getInverseBitmap() ? strTrue : strFalse;
3088 			return true;
3089 		}
3090 		return IMultiBitmapControlCreator::getAttributeValue (view, attributeName, stringValue, desc);
3091 	}
3092 };
3093 CAnimKnobCreator __gCAnimKnobCreator;
3094 
3095 //-----------------------------------------------------------------------------
3096 class CSwitchBaseCreator : public IMultiBitmapControlCreator
3097 {
3098 public:
getAttributeNames(std::list<std::string> & attributeNames) const3099 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3100 	{
3101 		attributeNames.emplace_back (kAttrInverseBitmap);
3102 		return IMultiBitmapControlCreator::getAttributeNames (attributeNames);
3103 	}
getAttributeType(const std::string & attributeName) const3104 	AttrType getAttributeType (const std::string& attributeName) const override
3105 	{
3106 		if (attributeName == kAttrInverseBitmap) return kBooleanType;
3107 		return IMultiBitmapControlCreator::getAttributeType (attributeName);
3108 	}
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3109 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3110 	{
3111 		auto control = dynamic_cast<CSwitchBase*> (view);
3112 		if (!control)
3113 			return false;
3114 
3115 		bool b;
3116 		if (attributes.getBooleanAttribute (kAttrInverseBitmap, b))
3117 		{
3118 			control->setInverseBitmap (b);
3119 		}
3120 
3121 		return IMultiBitmapControlCreator::apply (view, attributes, description);
3122 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3123 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3124 	{
3125 		auto control = dynamic_cast<CSwitchBase*> (view);
3126 		if (!control)
3127 			return false;
3128 
3129 		if (attributeName == kAttrInverseBitmap)
3130 		{
3131 			stringValue = control->getInverseBitmap() ? strTrue : strFalse;
3132 			return true;
3133 		}
3134 		return IMultiBitmapControlCreator::getAttributeValue (view, attributeName, stringValue, desc);
3135 	}
3136 };
3137 
3138 //-----------------------------------------------------------------------------
3139 class CVerticalSwitchCreator : public CSwitchBaseCreator
3140 {
3141 public:
CVerticalSwitchCreator()3142 	CVerticalSwitchCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3143 	IdStringPtr getViewName () const override { return kCVerticalSwitch; }
getBaseViewName() const3144 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3145 	UTF8StringPtr getDisplayName () const override { return "Vertical Switch"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3146 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CVerticalSwitch (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3147 };
3148 CVerticalSwitchCreator __gCVerticalSwitchCreator;
3149 
3150 //-----------------------------------------------------------------------------
3151 class CHorizontalSwitchCreator : public CSwitchBaseCreator
3152 {
3153 public:
CHorizontalSwitchCreator()3154 	CHorizontalSwitchCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3155 	IdStringPtr getViewName () const override { return kCHorizontalSwitch; }
getBaseViewName() const3156 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3157 	UTF8StringPtr getDisplayName () const override { return "Horizontal Switch"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3158 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CHorizontalSwitch (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3159 };
3160 CHorizontalSwitchCreator __gCHorizontalSwitchCreator;
3161 
3162 //-----------------------------------------------------------------------------
3163 class CRockerSwitchCreator : public IMultiBitmapControlCreator
3164 {
3165 public:
CRockerSwitchCreator()3166 	CRockerSwitchCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3167 	IdStringPtr getViewName () const override { return kCRockerSwitch; }
getBaseViewName() const3168 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3169 	UTF8StringPtr getDisplayName () const override { return "Rocker Switch"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3170 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CRockerSwitch (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3171 };
3172 CRockerSwitchCreator __gCRockerSwitchCreator;
3173 
3174 //-----------------------------------------------------------------------------
3175 class CMovieBitmapCreator : public IMultiBitmapControlCreator
3176 {
3177 public:
CMovieBitmapCreator()3178 	CMovieBitmapCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3179 	IdStringPtr getViewName () const override { return kCMovieBitmap; }
getBaseViewName() const3180 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3181 	UTF8StringPtr getDisplayName () const override { return "Movie Bitmap"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3182 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CMovieBitmap (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3183 };
3184 CMovieBitmapCreator __gCMovieBitmapCreator;
3185 
3186 //-----------------------------------------------------------------------------
3187 class CMovieButtonCreator : public IMultiBitmapControlCreator
3188 {
3189 public:
CMovieButtonCreator()3190 	CMovieButtonCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3191 	IdStringPtr getViewName () const override { return kCMovieButton; }
getBaseViewName() const3192 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3193 	UTF8StringPtr getDisplayName () const override { return "Movie Button"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3194 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CMovieButton (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3195 };
3196 CMovieButtonCreator __gCMovieButtonCreator;
3197 
3198 //-----------------------------------------------------------------------------
3199 class CKickButtonCreator : public IMultiBitmapControlCreator
3200 {
3201 public:
CKickButtonCreator()3202 	CKickButtonCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3203 	IdStringPtr getViewName () const override { return kCKickButton; }
getBaseViewName() const3204 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3205 	UTF8StringPtr getDisplayName () const override { return "Kick Button"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3206 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CKickButton (CRect (0, 0, 0, 0), nullptr, -1, nullptr); }
3207 };
3208 CKickButtonCreator __gCKickButtonCreator;
3209 
3210 //-----------------------------------------------------------------------------
3211 class CSliderCreator : public ViewCreatorAdapter
3212 {
3213 public:
3214 	std::string kTouch = "touch";
3215 	std::string kRelativeTouch = "relative touch";
3216 	std::string kFreeClick = "free click";
3217 	std::string kRamp = "ramp";
3218 	std::string kUseGlobal = "use global";
3219 
CSliderCreator()3220 	CSliderCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3221 	IdStringPtr getViewName () const override { return kCSlider; }
getBaseViewName() const3222 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3223 	UTF8StringPtr getDisplayName () const override { return "Slider"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3224 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CSlider (CRect (0, 0, 0, 0), nullptr, -1, 0, 0, nullptr, nullptr); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3225 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3226 	{
3227 		auto* slider = dynamic_cast<CSlider*> (view);
3228 		if (!slider)
3229 			return false;
3230 
3231 		// support old attribute name and convert it
3232 		const std::string* freeClickAttr = attributes.getAttributeValue ("free-click");
3233 		if (freeClickAttr)
3234 		{
3235 			slider->setSliderMode (*freeClickAttr == strTrue ? CSliderMode::FreeClick : CSliderMode::Touch);
3236 		}
3237 
3238 		const std::string* modeAttr = attributes.getAttributeValue (kAttrMode);
3239 		if (modeAttr)
3240 		{
3241 			if (*modeAttr == kTouch)
3242 				slider->setSliderMode (CSliderMode::Touch);
3243 			else if (*modeAttr == kRelativeTouch)
3244 				slider->setSliderMode (CSliderMode::RelativeTouch);
3245 			else if (*modeAttr == kFreeClick)
3246 				slider->setSliderMode (CSliderMode::FreeClick);
3247 			else if (*modeAttr == kRamp)
3248 				slider->setSliderMode (CSliderMode::Ramp);
3249 			else if (*modeAttr == kUseGlobal)
3250 				slider->setSliderMode (CSliderMode::UseGlobal);
3251 		}
3252 		CBitmap* bitmap;
3253 		if (stringToBitmap (attributes.getAttributeValue (kAttrHandleBitmap), bitmap, description))
3254 			slider->setHandle (bitmap);
3255 
3256 		CPoint p;
3257 		if (attributes.getPointAttribute (kAttrHandleOffset, p))
3258 			slider->setOffsetHandle (p);
3259 		if (attributes.getPointAttribute (kAttrBitmapOffset, p))
3260 			slider->setOffset (p);
3261 
3262 		double d;
3263 		if (attributes.getDoubleAttribute (kAttrZoomFactor, d))
3264 			slider->setZoomFactor (static_cast<float>(d));
3265 
3266 		const std::string* orientationAttr = attributes.getAttributeValue (kAttrOrientation);
3267 		if (orientationAttr)
3268 		{
3269 			int32_t style = slider->getStyle ();
3270 			if (*orientationAttr == strVertical)
3271 			{
3272 				setBit (style, CSlider::kHorizontal, false);
3273 				setBit (style, CSlider::kVertical, true);
3274 			}
3275 			else
3276 			{
3277 				setBit (style, CSlider::kVertical, false);
3278 				setBit (style, CSlider::kHorizontal, true);
3279 			}
3280 			slider->setStyle (style);
3281 		}
3282 		const std::string* reverseOrientationAttr = attributes.getAttributeValue (kAttrReverseOrientation);
3283 		if (reverseOrientationAttr)
3284 		{
3285 			int32_t style = slider->getStyle ();
3286 			if (*reverseOrientationAttr == strTrue)
3287 			{
3288 				if (style & CSlider::kVertical)
3289 				{
3290 					setBit (style, CSlider::kBottom, false);
3291 					setBit (style, CSlider::kTop, true);
3292 				}
3293 				else if (style & CSlider::kHorizontal)
3294 				{
3295 					setBit (style, CSlider::kLeft, false);
3296 					setBit (style, CSlider::kRight, true);
3297 				}
3298 			}
3299 			else
3300 			{
3301 				if (style & CSlider::kVertical)
3302 				{
3303 					setBit (style, CSlider::kTop, false);
3304 					setBit (style, CSlider::kBottom, true);
3305 				}
3306 				else if (style & CSlider::kHorizontal)
3307 				{
3308 					setBit (style, CSlider::kRight, false);
3309 					setBit (style, CSlider::kLeft, true);
3310 				}
3311 			}
3312 			slider->setStyle (style);
3313 		}
3314 
3315 		int32_t drawStyle = slider->getDrawStyle ();
3316 		applyStyleMask (attributes.getAttributeValue (kAttrDrawFrame), CSlider::kDrawFrame, drawStyle);
3317 		applyStyleMask (attributes.getAttributeValue (kAttrDrawBack), CSlider::kDrawBack, drawStyle);
3318 		applyStyleMask (attributes.getAttributeValue (kAttrDrawValue), CSlider::kDrawValue, drawStyle);
3319 		applyStyleMask (attributes.getAttributeValue (kAttrDrawValueFromCenter), CSlider::kDrawValueFromCenter, drawStyle);
3320 		applyStyleMask (attributes.getAttributeValue (kAttrDrawValueInverted), CSlider::kDrawInverted, drawStyle);
3321 		slider->setDrawStyle (drawStyle);
3322 
3323 		CCoord lineWidth;
3324 		if (attributes.getDoubleAttribute(kAttrFrameWidth, lineWidth))
3325 			slider->setFrameWidth (lineWidth);
3326 
3327 		CColor color;
3328 		if (stringToColor (attributes.getAttributeValue (kAttrDrawFrameColor), color, description))
3329 			slider->setFrameColor (color);
3330 		if (stringToColor (attributes.getAttributeValue (kAttrDrawBackColor), color, description))
3331 			slider->setBackColor (color);
3332 		if (stringToColor (attributes.getAttributeValue (kAttrDrawValueColor), color, description))
3333 			slider->setValueColor (color);
3334 		return true;
3335 	}
getAttributeNames(std::list<std::string> & attributeNames) const3336 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3337 	{
3338 		attributeNames.emplace_back (kAttrMode);
3339 		attributeNames.emplace_back (kAttrHandleBitmap);
3340 		attributeNames.emplace_back (kAttrHandleOffset);
3341 		attributeNames.emplace_back (kAttrBitmapOffset);
3342 		attributeNames.emplace_back (kAttrZoomFactor);
3343 		attributeNames.emplace_back (kAttrOrientation);
3344 		attributeNames.emplace_back (kAttrReverseOrientation);
3345 		attributeNames.emplace_back (kAttrDrawFrame);
3346 		attributeNames.emplace_back (kAttrDrawBack);
3347 		attributeNames.emplace_back (kAttrDrawValue);
3348 		attributeNames.emplace_back (kAttrDrawValueFromCenter);
3349 		attributeNames.emplace_back (kAttrDrawValueInverted);
3350 		attributeNames.emplace_back (kAttrFrameWidth);
3351 		attributeNames.emplace_back (kAttrDrawFrameColor);
3352 		attributeNames.emplace_back (kAttrDrawBackColor);
3353 		attributeNames.emplace_back (kAttrDrawValueColor);
3354 		return true;
3355 	}
getAttributeType(const std::string & attributeName) const3356 	AttrType getAttributeType (const std::string& attributeName) const override
3357 	{
3358 		if (attributeName == kAttrMode) return kListType;
3359 		if (attributeName == kAttrHandleBitmap) return kBitmapType;
3360 		if (attributeName == kAttrHandleOffset) return kPointType;
3361 		if (attributeName == kAttrBitmapOffset) return kPointType;
3362 		if (attributeName == kAttrZoomFactor) return kFloatType;
3363 		if (attributeName == kAttrOrientation) return kListType;
3364 		if (attributeName == kAttrReverseOrientation) return kBooleanType;
3365 		if (attributeName == kAttrDrawFrame) return kBooleanType;
3366 		if (attributeName == kAttrDrawBack) return kBooleanType;
3367 		if (attributeName == kAttrDrawValue) return kBooleanType;
3368 		if (attributeName == kAttrDrawValueFromCenter) return kBooleanType;
3369 		if (attributeName == kAttrDrawValueInverted) return kBooleanType;
3370 		if (attributeName == kAttrFrameWidth) return kFloatType;
3371 		if (attributeName == kAttrDrawFrameColor) return kColorType;
3372 		if (attributeName == kAttrDrawBackColor) return kColorType;
3373 		if (attributeName == kAttrDrawValueColor) return kColorType;
3374 		return kUnknownType;
3375 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3376 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3377 	{
3378 		auto* slider = dynamic_cast<CSlider*> (view);
3379 		if (!slider)
3380 			return false;
3381 		if (attributeName == kAttrMode)
3382 		{
3383 			switch (slider->getSliderMode ())
3384 			{
3385 				case CSliderMode::Touch:
3386 					stringValue = kTouch; break;
3387 				case CSliderMode::RelativeTouch:
3388 					stringValue = kRelativeTouch; break;
3389 				case CSliderMode::FreeClick:
3390 					stringValue = kFreeClick; break;
3391 				case CSliderMode::Ramp:
3392 					stringValue = kRamp; break;
3393 				case CSliderMode::UseGlobal:
3394 					stringValue = kUseGlobal; break;
3395 			}
3396 			return true;
3397 		}
3398 		else if (attributeName == kAttrHandleBitmap)
3399 		{
3400 			CBitmap* bitmap = slider->getHandle ();
3401 			if (bitmap)
3402 			{
3403 				bitmapToString (bitmap, stringValue, desc);
3404 			}
3405 			return true;
3406 		}
3407 		else if (attributeName == kAttrHandleOffset)
3408 		{
3409 			pointToString (slider->getOffsetHandle (), stringValue);
3410 			return true;
3411 		}
3412 		else if (attributeName == kAttrBitmapOffset)
3413 		{
3414 			pointToString (slider->getOffset (), stringValue);
3415 			return true;
3416 		}
3417 		else if (attributeName == kAttrZoomFactor)
3418 		{
3419 			stringValue = numberToString (slider->getZoomFactor ());
3420 			return true;
3421 		}
3422 		else if (attributeName == kAttrOrientation)
3423 		{
3424 			if (slider->getStyle () & CSlider::kVertical)
3425 				stringValue = strVertical;
3426 			else
3427 				stringValue = strHorizontal;
3428 			return true;
3429 		}
3430 		else if (attributeName == kAttrReverseOrientation)
3431 		{
3432 			int32_t style = slider->getStyle ();
3433 			stringValue = strFalse;
3434 			if (((style & CSlider::kVertical) && (style & CSlider::kTop)) || ((style & CSlider::kHorizontal) && (style & CSlider::kRight)))
3435 				stringValue = strTrue;
3436 			else
3437 				stringValue = strFalse;
3438 			return true;
3439 		}
3440 		else if (attributeName == kAttrDrawFrame)
3441 		{
3442 			if (slider->getDrawStyle () & CSlider::kDrawFrame)
3443 				stringValue = strTrue;
3444 			else
3445 				stringValue = strFalse;
3446 			return true;
3447 		}
3448 		else if (attributeName == kAttrDrawBack)
3449 		{
3450 			if (slider->getDrawStyle () & CSlider::kDrawBack)
3451 				stringValue = strTrue;
3452 			else
3453 				stringValue = strFalse;
3454 			return true;
3455 		}
3456 		else if (attributeName == kAttrDrawValue)
3457 		{
3458 			if (slider->getDrawStyle () & CSlider::kDrawValue)
3459 				stringValue = strTrue;
3460 			else
3461 				stringValue = strFalse;
3462 			return true;
3463 		}
3464 		else if (attributeName == kAttrDrawValueFromCenter)
3465 		{
3466 			if (slider->getDrawStyle () & CSlider::kDrawValueFromCenter)
3467 				stringValue = strTrue;
3468 			else
3469 				stringValue = strFalse;
3470 			return true;
3471 		}
3472 		else if (attributeName == kAttrDrawValueInverted)
3473 		{
3474 			if (slider->getDrawStyle () & CSlider::kDrawInverted)
3475 				stringValue = strTrue;
3476 			else
3477 				stringValue = strFalse;
3478 			return true;
3479 		}
3480 		else if (attributeName == kAttrDrawFrameColor)
3481 		{
3482 			colorToString (slider->getFrameColor (), stringValue, desc);
3483 			return true;
3484 		}
3485 		else if (attributeName == kAttrDrawBackColor)
3486 		{
3487 			colorToString (slider->getBackColor (), stringValue, desc);
3488 			return true;
3489 		}
3490 		else if (attributeName == kAttrDrawValueColor)
3491 		{
3492 			colorToString (slider->getValueColor (), stringValue, desc);
3493 			return true;
3494 		}
3495 		else if (attributeName == kAttrFrameWidth)
3496 		{
3497 			stringValue = numberToString (slider->getFrameWidth ());
3498 			return true;
3499 		}
3500 
3501 		return false;
3502 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const3503 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
3504 	{
3505 		if (attributeName == kAttrOrientation)
3506 		{
3507 			return getStandardAttributeListValues (kAttrOrientation, values);
3508 		}
3509 		if (attributeName == kAttrMode)
3510 		{
3511 			values.emplace_back (&kTouch);
3512 			values.emplace_back (&kRelativeTouch);
3513 			values.emplace_back (&kFreeClick);
3514 			values.emplace_back (&kRamp);
3515 			values.emplace_back (&kUseGlobal);
3516 			return true;
3517 		}
3518 		return false;
3519 	}
3520 
3521 };
3522 CSliderCreator __gCSliderCreator;
3523 
3524 //-----------------------------------------------------------------------------
3525 class CVuMeterCreator : public ViewCreatorAdapter
3526 {
3527 public:
CVuMeterCreator()3528 	CVuMeterCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3529 	IdStringPtr getViewName () const override { return kCVuMeter; }
getBaseViewName() const3530 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3531 	UTF8StringPtr getDisplayName () const override { return "VU Meter"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3532 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CVuMeter (CRect (0, 0, 0, 0), nullptr, nullptr, 100); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3533 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3534 	{
3535 		auto* vuMeter = dynamic_cast<CVuMeter*> (view);
3536 		if (!vuMeter)
3537 			return false;
3538 
3539 		CBitmap* bitmap;
3540 		if (stringToBitmap (attributes.getAttributeValue (kAttrOffBitmap), bitmap, description))
3541 			vuMeter->setOffBitmap (bitmap);
3542 
3543 		const std::string* attr = attributes.getAttributeValue (kAttrOrientation);
3544 		if (attr)
3545 			vuMeter->setStyle (*attr == strVertical ? CVuMeter::kVertical : CVuMeter::kHorizontal);
3546 
3547 		int32_t numLed;
3548 		if (attributes.getIntegerAttribute(kAttrNumLed, numLed))
3549 			vuMeter->setNbLed (numLed);
3550 
3551 		double value;
3552 		if (attributes.getDoubleAttribute(kAttrDecreaseStepValue, value))
3553 			vuMeter->setDecreaseStepValue (static_cast<float>(value));
3554 		return true;
3555 	}
getAttributeNames(std::list<std::string> & attributeNames) const3556 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3557 	{
3558 		attributeNames.emplace_back (kAttrOffBitmap);
3559 		attributeNames.emplace_back (kAttrNumLed);
3560 		attributeNames.emplace_back (kAttrOrientation);
3561 		attributeNames.emplace_back (kAttrDecreaseStepValue);
3562 		return true;
3563 	}
getAttributeType(const std::string & attributeName) const3564 	AttrType getAttributeType (const std::string& attributeName) const override
3565 	{
3566 		if (attributeName == kAttrOffBitmap) return kBitmapType;
3567 		if (attributeName == kAttrNumLed) return kIntegerType;
3568 		if (attributeName == kAttrOrientation) return kListType;
3569 		if (attributeName == kAttrDecreaseStepValue) return kFloatType;
3570 		return kUnknownType;
3571 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3572 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3573 	{
3574 		auto* vuMeter = dynamic_cast<CVuMeter*> (view);
3575 		if (!vuMeter)
3576 			return false;
3577 		if (attributeName == kAttrOffBitmap)
3578 		{
3579 			CBitmap* bitmap = vuMeter->getOffBitmap ();
3580 			if (bitmap)
3581 			{
3582 				bitmapToString (bitmap, stringValue, desc);
3583 			}
3584 			return true;
3585 		}
3586 		else if (attributeName == kAttrOrientation)
3587 		{
3588 			if (vuMeter->getStyle () & CVuMeter::kVertical)
3589 				stringValue = strVertical;
3590 			else
3591 				stringValue = strHorizontal;
3592 			return true;
3593 		}
3594 		else if (attributeName == kAttrNumLed)
3595 		{
3596 			stringValue = numberToString (vuMeter->getNbLed ());
3597 			return true;
3598 		}
3599 		else if (attributeName == kAttrDecreaseStepValue)
3600 		{
3601 			stringValue = numberToString (vuMeter->getDecreaseStepValue ());
3602 			return true;
3603 		}
3604 		return false;
3605 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const3606 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
3607 	{
3608 		if (attributeName == kAttrOrientation)
3609 		{
3610 			return getStandardAttributeListValues (kAttrOrientation, values);
3611 		}
3612 		return false;
3613 	}
3614 
3615 };
3616 CVuMeterCreator __gCVuMeterCreator;
3617 
3618 //-----------------------------------------------------------------------------
3619 class CAnimationSplashScreenCreator : public ViewCreatorAdapter
3620 {
3621 public:
CAnimationSplashScreenCreator()3622 	CAnimationSplashScreenCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3623 	IdStringPtr getViewName () const override { return kCAnimationSplashScreen; }
getBaseViewName() const3624 	IdStringPtr getBaseViewName () const override { return kCControl; }
getDisplayName() const3625 	UTF8StringPtr getDisplayName () const override { return "Animation Splash Screen"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3626 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CAnimationSplashScreen (CRect (0, 0, 0, 0), -1, nullptr, nullptr); }
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3627 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3628 	{
3629 		auto* splashScreen = dynamic_cast<CAnimationSplashScreen*> (view);
3630 		if (!splashScreen)
3631 			return false;
3632 
3633 		CBitmap* bitmap;
3634 		if (stringToBitmap (attributes.getAttributeValue (kAttrSplashBitmap), bitmap, description))
3635 			splashScreen->setSplashBitmap (bitmap);
3636 
3637 		CPoint p;
3638 		if (attributes.getPointAttribute (kAttrSplashOrigin, p))
3639 		{
3640 			CRect size = splashScreen->getSplashRect ();
3641 			size.originize ();
3642 			size.offset (p.x, p.y);
3643 			splashScreen->setSplashRect (size);
3644 		}
3645 		if (attributes.getPointAttribute (kAttrSplashSize, p))
3646 		{
3647 			CRect size = splashScreen->getSplashRect ();
3648 			size.setWidth (p.x);
3649 			size.setHeight (p.y);
3650 			splashScreen->setSplashRect (size);
3651 		}
3652 		int32_t value;
3653 		if (attributes.getIntegerAttribute (kAttrAnimationIndex, value))
3654 			splashScreen->setAnimationIndex (static_cast<uint32_t> (value));
3655 		if (attributes.getIntegerAttribute (kAttrAnimationTime, value))
3656 			splashScreen->setAnimationTime (static_cast<uint32_t> (value));
3657 
3658 		return true;
3659 	}
getAttributeNames(std::list<std::string> & attributeNames) const3660 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3661 	{
3662 		attributeNames.emplace_back (kAttrSplashBitmap);
3663 		attributeNames.emplace_back (kAttrSplashOrigin);
3664 		attributeNames.emplace_back (kAttrSplashSize);
3665 		attributeNames.emplace_back (kAttrAnimationIndex);
3666 		attributeNames.emplace_back (kAttrAnimationTime);
3667 		return true;
3668 	}
getAttributeType(const std::string & attributeName) const3669 	AttrType getAttributeType (const std::string& attributeName) const override
3670 	{
3671 		if (attributeName == kAttrSplashBitmap) return kBitmapType;
3672 		if (attributeName == kAttrSplashOrigin) return kRectType;
3673 		if (attributeName == kAttrSplashSize) return kRectType;
3674 		if (attributeName == kAttrAnimationIndex) return kIntegerType;
3675 		if (attributeName == kAttrAnimationTime) return kIntegerType;
3676 		return kUnknownType;
3677 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3678 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3679 	{
3680 		auto* splashScreen = dynamic_cast<CAnimationSplashScreen*> (view);
3681 		if (!splashScreen)
3682 			return false;
3683 
3684 		if (attributeName == kAttrSplashBitmap)
3685 		{
3686 			CBitmap* bitmap = splashScreen->getSplashBitmap ();
3687 			if (bitmap)
3688 				bitmapToString (bitmap, stringValue, desc);
3689 			else
3690 				stringValue = "";
3691 			return true;
3692 		}
3693 		else if (attributeName == kAttrSplashOrigin)
3694 		{
3695 			pointToString (splashScreen->getSplashRect ().getTopLeft (), stringValue);
3696 			return true;
3697 		}
3698 		else if (attributeName == kAttrSplashSize)
3699 		{
3700 			pointToString (splashScreen->getSplashRect ().getSize (), stringValue);
3701 			return true;
3702 		}
3703 		else if (attributeName == kAttrAnimationIndex)
3704 		{
3705 			stringValue = numberToString (splashScreen->getAnimationIndex ());
3706 			return true;
3707 		}
3708 		else if (attributeName == kAttrAnimationTime)
3709 		{
3710 			stringValue = numberToString (splashScreen->getAnimationTime ());
3711 			return true;
3712 		}
3713 		return false;
3714 	}
3715 
3716 };
3717 CAnimationSplashScreenCreator __gCAnimationSplashScreenCreator;
3718 
3719 //-----------------------------------------------------------------------------
3720 class UIViewSwitchContainerCreator : public ViewCreatorAdapter
3721 {
3722 public:
3723 	std::string kLinear = "linear";
3724 	std::string kEasyIn = "easy-in";
3725 	std::string kEasyOut = "easy-out";
3726 	std::string kEasyInOut = "easy-in-out";
3727 	std::string kEasy = "easy";
3728 
3729 	std::string kFadeInOut = "fade";
3730 	std::string kMoveInOut = "move";
3731 	std::string kPushInOut = "push";
3732 
UIViewSwitchContainerCreator()3733 	UIViewSwitchContainerCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3734 	IdStringPtr getViewName () const override { return kUIViewSwitchContainer; }
getBaseViewName() const3735 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const3736 	UTF8StringPtr getDisplayName () const override { return "View Switch Container"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3737 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
3738 	{
3739 		UIViewSwitchContainer* vsc = new UIViewSwitchContainer (CRect (0, 0, 100, 100));
3740 		new UIDescriptionViewSwitchController (vsc, description, description->getController ());
3741 		return vsc;
3742 	}
3743 
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3744 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3745 	{
3746 		auto* viewSwitch = dynamic_cast<UIViewSwitchContainer*> (view);
3747 		if (!viewSwitch)
3748 			return false;
3749 		const std::string* attr = attributes.getAttributeValue (kAttrTemplateNames);
3750 		if (attr)
3751 		{
3752 			auto* controller = dynamic_cast<UIDescriptionViewSwitchController*> (viewSwitch->getController ());
3753 			if (controller)
3754 			{
3755 				controller->setTemplateNames (attr->c_str ());
3756 			}
3757 		}
3758 		attr = attributes.getAttributeValue (kAttrTemplateSwitchControl);
3759 		if (attr)
3760 		{
3761 			auto* controller = dynamic_cast<UIDescriptionViewSwitchController*> (viewSwitch->getController ());
3762 			if (controller)
3763 			{
3764 				int32_t tag = description->getTagForName (attr->c_str ());
3765 				controller->setSwitchControlTag (tag);
3766 			}
3767 		}
3768 		attr = attributes.getAttributeValue (kAttrAnimationStyle);
3769 		if (attr)
3770 		{
3771 			UIViewSwitchContainer::AnimationStyle style = UIViewSwitchContainer::kFadeInOut;
3772 			if (*attr == kMoveInOut)
3773 				style = UIViewSwitchContainer::kMoveInOut;
3774 			else if (*attr == kPushInOut)
3775 				style = UIViewSwitchContainer::kPushInOut;
3776 			viewSwitch->setAnimationStyle (style);
3777 		}
3778 
3779 		attr = attributes.getAttributeValue (kAttrAnimationTimingFunction);
3780 		if (attr)
3781 		{
3782 			UIViewSwitchContainer::TimingFunction tf = UIViewSwitchContainer::kLinear;
3783 			if (*attr == kEasyIn)
3784 				tf = UIViewSwitchContainer::kEasyIn;
3785 			else if (*attr == kEasyOut)
3786 				tf = UIViewSwitchContainer::kEasyOut;
3787 			else if (*attr == kEasyInOut)
3788 				tf = UIViewSwitchContainer::kEasyInOut;
3789 			else if (*attr == kEasy)
3790 				tf = UIViewSwitchContainer::kEasy;
3791 			viewSwitch->setTimingFunction (tf);
3792 		}
3793 
3794 		int32_t animationTime;
3795 		if (attributes.getIntegerAttribute (kAttrAnimationTime, animationTime))
3796 		{
3797 			viewSwitch->setAnimationTime (static_cast<uint32_t> (animationTime));
3798 		}
3799 		return true;
3800 	}
getAttributeNames(std::list<std::string> & attributeNames) const3801 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3802 	{
3803 		attributeNames.emplace_back (kAttrTemplateNames);
3804 		attributeNames.emplace_back (kAttrTemplateSwitchControl);
3805 		attributeNames.emplace_back (kAttrAnimationStyle);
3806 		attributeNames.emplace_back (kAttrAnimationTimingFunction);
3807 		attributeNames.emplace_back (kAttrAnimationTime);
3808 		return true;
3809 	}
getAttributeType(const std::string & attributeName) const3810 	AttrType getAttributeType (const std::string& attributeName) const override
3811 	{
3812 		if (attributeName == kAttrTemplateNames) return kStringType;
3813 		if (attributeName == kAttrTemplateSwitchControl) return kTagType;
3814 		if (attributeName == kAttrAnimationStyle) return kListType;
3815 		if (attributeName == kAttrAnimationTimingFunction) return kListType;
3816 		if (attributeName == kAttrAnimationTime) return kIntegerType;
3817 		return kUnknownType;
3818 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const3819 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
3820 	{
3821 		auto* viewSwitch = dynamic_cast<UIViewSwitchContainer*> (view);
3822 		if (!viewSwitch)
3823 			return false;
3824 		if (attributeName == kAttrTemplateNames)
3825 		{
3826 			auto* controller = dynamic_cast<UIDescriptionViewSwitchController*> (viewSwitch->getController ());
3827 			if (controller)
3828 			{
3829 				controller->getTemplateNames (stringValue);
3830 				return true;
3831 			}
3832 		}
3833 		else if (attributeName == kAttrTemplateSwitchControl)
3834 		{
3835 			auto* controller = dynamic_cast<UIDescriptionViewSwitchController*> (viewSwitch->getController ());
3836 			if (controller)
3837 			{
3838 				UTF8StringPtr controlTag = desc->lookupControlTagName (controller->getSwitchControlTag ());
3839 				if (controlTag)
3840 				{
3841 					stringValue = controlTag;
3842 					return true;
3843 				}
3844 				return true;
3845 			}
3846 		}
3847 		else if (attributeName == kAttrAnimationTime)
3848 		{
3849 			stringValue = numberToString ((int32_t)viewSwitch->getAnimationTime ());
3850 			return true;
3851 		}
3852 		else if (attributeName == kAttrAnimationStyle)
3853 		{
3854 			switch (viewSwitch->getAnimationStyle ())
3855 			{
3856 				case UIViewSwitchContainer::kFadeInOut:
3857 				{
3858 					stringValue = kFadeInOut;
3859 					return true;
3860 				}
3861 				case UIViewSwitchContainer::kMoveInOut:
3862 				{
3863 					stringValue = kMoveInOut;
3864 					return true;
3865 				}
3866 				case UIViewSwitchContainer::kPushInOut:
3867 				{
3868 					stringValue = kPushInOut;
3869 					return true;
3870 				}
3871 			}
3872 		}
3873 		else if (attributeName == kAttrAnimationTimingFunction)
3874 		{
3875 			switch (viewSwitch->getTimingFunction ())
3876 			{
3877 				case UIViewSwitchContainer::kLinear:
3878 				{
3879 					stringValue = kLinear;
3880 					return true;
3881 				}
3882 				case UIViewSwitchContainer::kEasyIn:
3883 				{
3884 					stringValue = kEasyIn;
3885 					return true;
3886 				}
3887 				case UIViewSwitchContainer::kEasyOut:
3888 				{
3889 					stringValue = kEasyOut;
3890 					return true;
3891 				}
3892 				case UIViewSwitchContainer::kEasyInOut:
3893 				{
3894 					stringValue = kEasyInOut;
3895 					return true;
3896 				}
3897 				case UIViewSwitchContainer::kEasy:
3898 				{
3899 					stringValue = kEasy;
3900 					return true;
3901 				}
3902 			}
3903 		}
3904 		return false;
3905 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const3906 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
3907 	{
3908 		if (attributeName == kAttrAnimationStyle)
3909 		{
3910 			values.emplace_back (&kFadeInOut);
3911 			values.emplace_back (&kMoveInOut);
3912 			values.emplace_back (&kPushInOut);
3913 			return true;
3914 		}
3915 		if (attributeName == kAttrAnimationTimingFunction)
3916 		{
3917 			values.emplace_back (&kLinear);
3918 			values.emplace_back (&kEasyIn);
3919 			values.emplace_back (&kEasyOut);
3920 			values.emplace_back (&kEasyInOut);
3921 			values.emplace_back (&kEasy);
3922 			return true;
3923 		}
3924 		return false;
3925 	}
3926 };
3927 UIViewSwitchContainerCreator __gUIViewSwitchContainerCreator;
3928 
3929 //-----------------------------------------------------------------------------
3930 class CSplitViewCreator : public ViewCreatorAdapter
3931 {
3932 public:
3933 	std::string kFirst = "first";
3934 	std::string kSecond = "second";
3935 	std::string kLast = "last";
3936 	std::string kAll = "all";
3937 
3938 
CSplitViewCreator()3939 	CSplitViewCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const3940 	IdStringPtr getViewName () const override { return kCSplitView; }
getBaseViewName() const3941 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const3942 	UTF8StringPtr getDisplayName () const override { return "Split View"; }
create(const UIAttributes & attributes,const IUIDescription * description) const3943 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CSplitView (CRect (0, 0, 100, 100)); }
3944 
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const3945 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
3946 	{
3947 		auto* splitView = dynamic_cast<CSplitView*> (view);
3948 		if (!splitView)
3949 			return false;
3950 
3951 		int32_t width;
3952 		if (attributes.getIntegerAttribute (kAttrSeparatorWidth, width))
3953 			splitView->setSeparatorWidth (width);
3954 		const std::string* attr = attributes.getAttributeValue (kAttrOrientation);
3955 		if (attr)
3956 		{
3957 			if (*attr == strHorizontal)
3958 			{
3959 				splitView->setStyle (CSplitView::kHorizontal);
3960 			}
3961 			else
3962 			{
3963 				splitView->setStyle (CSplitView::kVertical);
3964 			}
3965 		}
3966 		attr = attributes.getAttributeValue (kAttrResizeMethod);
3967 		if (attr)
3968 		{
3969 			if (*attr == kFirst)
3970 			{
3971 				splitView->setResizeMethod (CSplitView::kResizeFirstView);
3972 			}
3973 			if (*attr == kSecond)
3974 			{
3975 				splitView->setResizeMethod (CSplitView::kResizeSecondView);
3976 			}
3977 			else if (*attr == kLast)
3978 			{
3979 				splitView->setResizeMethod (CSplitView::kResizeLastView);
3980 			}
3981 			else if (*attr == kAll)
3982 			{
3983 				splitView->setResizeMethod (CSplitView::kResizeAllViews);
3984 			}
3985 		}
3986 
3987 		return true;
3988 	}
getAttributeNames(std::list<std::string> & attributeNames) const3989 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
3990 	{
3991 		attributeNames.emplace_back (kAttrOrientation);
3992 		attributeNames.emplace_back (kAttrResizeMethod);
3993 		attributeNames.emplace_back (kAttrSeparatorWidth);
3994 		return true;
3995 	}
getAttributeType(const std::string & attributeName) const3996 	AttrType getAttributeType (const std::string& attributeName) const override
3997 	{
3998 		if (attributeName == kAttrOrientation) return kListType;
3999 		if (attributeName == kAttrResizeMethod) return kListType;
4000 		if (attributeName == kAttrSeparatorWidth) return kIntegerType;
4001 		return kUnknownType;
4002 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const4003 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
4004 	{
4005 		auto* splitView = dynamic_cast<CSplitView*> (view);
4006 		if (!splitView)
4007 			return false;
4008 		if (attributeName == kAttrSeparatorWidth)
4009 		{
4010 			stringValue = numberToString ((int32_t)splitView->getSeparatorWidth ());
4011 			return true;
4012 		}
4013 		if (attributeName == kAttrOrientation)
4014 		{
4015 			stringValue = splitView->getStyle () == CSplitView::kHorizontal ? strHorizontal : strVertical;
4016 			return true;
4017 		}
4018 		if (attributeName == kAttrResizeMethod)
4019 		{
4020 			switch (splitView->getResizeMethod ())
4021 			{
4022 				case CSplitView::kResizeFirstView:
4023 				{
4024 					stringValue = kFirst;
4025 					return true;
4026 				}
4027 				case CSplitView::kResizeSecondView:
4028 				{
4029 					stringValue = kSecond;
4030 					return true;
4031 				}
4032 				case CSplitView::kResizeLastView:
4033 				{
4034 					stringValue = kLast;
4035 					return true;
4036 				}
4037 				case CSplitView::kResizeAllViews:
4038 				{
4039 					stringValue = kAll;
4040 					return true;
4041 				}
4042 			}
4043 		}
4044 		return false;
4045 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const4046 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
4047 	{
4048 		if (attributeName == kAttrOrientation)
4049 		{
4050 			return getStandardAttributeListValues (kAttrOrientation, values);
4051 		}
4052 		else if (attributeName == kAttrResizeMethod)
4053 		{
4054 			values.emplace_back (&kFirst);
4055 			values.emplace_back (&kSecond);
4056 			values.emplace_back (&kLast);
4057 			values.emplace_back (&kAll);
4058 			return true;
4059 		}
4060 		return false;
4061 	}
4062 
4063 };
4064 CSplitViewCreator __gCSplitViewCreator;
4065 
4066 //-----------------------------------------------------------------------------
4067 class CShadowViewContainerCreator : public ViewCreatorAdapter
4068 {
4069 public:
CShadowViewContainerCreator()4070 	CShadowViewContainerCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const4071 	IdStringPtr getViewName () const override { return kCShadowViewContainer; }
getBaseViewName() const4072 	IdStringPtr getBaseViewName () const override { return kCViewContainer; }
getDisplayName() const4073 	UTF8StringPtr getDisplayName () const override { return "Shadow View Container"; }
create(const UIAttributes & attributes,const IUIDescription * description) const4074 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
4075 	{
4076 		return new CShadowViewContainer (CRect (0, 0, 200, 200));
4077 	}
4078 
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const4079 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
4080 	{
4081 		auto* shadowView = dynamic_cast<CShadowViewContainer*> (view);
4082 		if (!shadowView)
4083 			return false;
4084 		double d;
4085 		if (attributes.getDoubleAttribute (kAttrShadowIntensity, d))
4086 			shadowView->setShadowIntensity (static_cast<float> (d));
4087 		if (attributes.getDoubleAttribute (kAttrShadowBlurSize, d))
4088 			shadowView->setShadowBlurSize (d);
4089 		CPoint p;
4090 		if (attributes.getPointAttribute (kAttrShadowOffset, p))
4091 			shadowView->setShadowOffset (p);
4092 		return true;
4093 	}
getAttributeNames(std::list<std::string> & attributeNames) const4094 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
4095 	{
4096 		attributeNames.emplace_back (kAttrShadowIntensity);
4097 		attributeNames.emplace_back (kAttrShadowOffset);
4098 		attributeNames.emplace_back (kAttrShadowBlurSize);
4099 		return true;
4100 	}
getAttributeType(const std::string & attributeName) const4101 	AttrType getAttributeType (const std::string& attributeName) const override
4102 	{
4103 		if (attributeName == kAttrShadowIntensity) return kFloatType;
4104 		if (attributeName == kAttrShadowOffset) return kPointType;
4105 		if (attributeName == kAttrShadowBlurSize) return kFloatType;
4106 		return kUnknownType;
4107 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const4108 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
4109 	{
4110 		auto* shadowView = dynamic_cast<CShadowViewContainer*> (view);
4111 		if (!shadowView)
4112 			return false;
4113 		if (attributeName == kAttrShadowIntensity)
4114 		{
4115 			stringValue = numberToString (shadowView->getShadowIntensity ());
4116 			return true;
4117 		}
4118 		else if (attributeName == kAttrShadowBlurSize)
4119 		{
4120 			stringValue = numberToString (shadowView->getShadowBlurSize ());
4121 			return true;
4122 		}
4123 		else if (attributeName == kAttrShadowOffset)
4124 		{
4125 			pointToString (shadowView->getShadowOffset (), stringValue);
4126 			return true;
4127 		}
4128 		return false;
4129 	}
getAttributeValueRange(const std::string & attributeName,double & minValue,double & maxValue) const4130 	bool getAttributeValueRange (const std::string& attributeName, double& minValue, double &maxValue) const override
4131 	{
4132 		if (attributeName == kAttrShadowBlurSize)
4133 		{
4134 			minValue = 0.8;
4135 			maxValue = 20;
4136 			return true;
4137 		}
4138 		else if (attributeName == kAttrShadowIntensity)
4139 		{
4140 			minValue = 0;
4141 			maxValue = 1;
4142 			return true;
4143 		}
4144 		return false;
4145 	}
4146 };
4147 CShadowViewContainerCreator __gCShadowViewContainerCreator;
4148 
4149 //-----------------------------------------------------------------------------
4150 class CGradientViewCreator : public ViewCreatorAdapter
4151 {
4152 public:
4153 	std::string kLinear = "linear";
4154 	std::string kRadial = "radial";
4155 
CGradientViewCreator()4156 	CGradientViewCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const4157 	IdStringPtr getViewName () const override { return kCGradientView; }
getBaseViewName() const4158 	IdStringPtr getBaseViewName () const override { return kCView; }
getDisplayName() const4159 	UTF8StringPtr getDisplayName () const override { return "Gradient View"; }
create(const UIAttributes & attributes,const IUIDescription * description) const4160 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override
4161 	{
4162 		CGradientView* gradientView = new CGradientView (CRect (0, 0, 100, 100));
4163 		if (description)
4164 		{
4165 			std::list<const std::string*> gradients;
4166 			description->collectGradientNames (gradients);
4167 			if (!gradients.empty ())
4168 			{
4169 				gradientView->setGradient (description->getGradient (gradients.front ()->c_str ()));
4170 			}
4171 		}
4172 		return gradientView;
4173 	}
apply(CView * view,const UIAttributes & attributes,const IUIDescription * description) const4174 	bool apply (CView* view, const UIAttributes& attributes, const IUIDescription* description) const override
4175 	{
4176 		auto* gv = dynamic_cast<CGradientView*> (view);
4177 		if (gv == nullptr)
4178 			return false;
4179 		CColor color;
4180 		if (stringToColor (attributes.getAttributeValue (kAttrFrameColor), color, description))
4181 			gv->setFrameColor (color);
4182 
4183 		double d;
4184 		if (attributes.getDoubleAttribute (kAttrGradientAngle, d))
4185 			gv->setGradientAngle (d);
4186 		if (attributes.getDoubleAttribute (kAttrRoundRectRadius, d))
4187 			gv->setRoundRectRadius (d);
4188 		if (attributes.getDoubleAttribute (kAttrFrameWidth, d))
4189 			gv->setFrameWidth (d);
4190 
4191 		bool b;
4192 		if (attributes.getBooleanAttribute (kAttrDrawAntialiased, b))
4193 			gv->setDrawAntialiased (b);
4194 
4195 		const std::string* attr = attributes.getAttributeValue (kAttrGradientStyle);
4196 		if (attr)
4197 		{
4198 			if (*attr == kRadial)
4199 				gv->setGradientStyle(CGradientView::kRadialGradient);
4200 			else
4201 				gv->setGradientStyle(CGradientView::kLinearGradient);
4202 		}
4203 		CPoint p;
4204 		if (attributes.getPointAttribute (kAttrRadialCenter, p))
4205 			gv->setRadialCenter (p);
4206 		if (attributes.getDoubleAttribute (kAttrRadialRadius, d))
4207 			gv->setRadialRadius (d);
4208 
4209 		attr = attributes.getAttributeValue (kAttrGradient);
4210 		if (attr)
4211 		{
4212 			CGradient* gradient = description->getGradient (attr->c_str ());
4213 			gv->setGradient (gradient);
4214 		}
4215 		else
4216 		{ // support old version
4217 			bool hasOldGradient = true;
4218 			CColor startColor, endColor;
4219 			if (!stringToColor (attributes.getAttributeValue (kAttrGradientStartColor), startColor, description))
4220 				hasOldGradient = false;
4221 			if (hasOldGradient && !stringToColor (attributes.getAttributeValue (kAttrGradientEndColor), endColor, description))
4222 				hasOldGradient = false;
4223 			double startOffset = 0.0, endOffset = 1.0;
4224 			if (hasOldGradient && !attributes.getDoubleAttribute (kAttrGradientStartColorOffset, startOffset))
4225 				hasOldGradient = false;
4226 			if (hasOldGradient && !attributes.getDoubleAttribute (kAttrGradientEndColorOffset, endOffset))
4227 				hasOldGradient = false;
4228 			if (hasOldGradient)
4229 			{
4230 				SharedPointer<CGradient> gradient = owned (CGradient::create (startOffset, 1. - endOffset, startColor, endColor));
4231 				gv->setGradient (gradient);
4232 				addGradientToUIDescription (description, gradient, "GradientView");
4233 			}
4234 		}
4235 		return true;
4236 	}
getAttributeNames(std::list<std::string> & attributeNames) const4237 	bool getAttributeNames (std::list<std::string>& attributeNames) const override
4238 	{
4239 		attributeNames.emplace_back (kAttrGradientStyle);
4240 		attributeNames.emplace_back (kAttrGradient);
4241 		attributeNames.emplace_back (kAttrGradientAngle);
4242 		attributeNames.emplace_back (kAttrRadialCenter);
4243 		attributeNames.emplace_back (kAttrRadialRadius);
4244 		attributeNames.emplace_back (kAttrFrameColor);
4245 		attributeNames.emplace_back (kAttrRoundRectRadius);
4246 		attributeNames.emplace_back (kAttrFrameWidth);
4247 		attributeNames.emplace_back (kAttrDrawAntialiased);
4248 		return true;
4249 	}
getAttributeType(const std::string & attributeName) const4250 	AttrType getAttributeType (const std::string& attributeName) const override
4251 	{
4252 		if (attributeName == kAttrGradientStyle) return kListType;
4253 		if (attributeName == kAttrGradient) return kGradientType;
4254 		if (attributeName == kAttrFrameColor) return kColorType;
4255 		if (attributeName == kAttrGradientAngle) return kFloatType;
4256 		if (attributeName == kAttrRoundRectRadius) return kFloatType;
4257 		if (attributeName == kAttrFrameWidth) return kFloatType;
4258 		if (attributeName == kAttrDrawAntialiased) return kBooleanType;
4259 		if (attributeName == kAttrRadialCenter) return kPointType;
4260 		if (attributeName == kAttrRadialRadius) return kFloatType;
4261 		return kUnknownType;
4262 	}
getAttributeValue(CView * view,const std::string & attributeName,std::string & stringValue,const IUIDescription * desc) const4263 	bool getAttributeValue (CView* view, const std::string& attributeName, std::string& stringValue, const IUIDescription* desc) const override
4264 	{
4265 		auto* gv = dynamic_cast<CGradientView*> (view);
4266 		if (gv == nullptr)
4267 			return false;
4268 		if (attributeName == kAttrFrameColor)
4269 		{
4270 			colorToString (gv->getFrameColor (), stringValue, desc);
4271 			return true;
4272 		}
4273 		if (attributeName == kAttrGradientAngle)
4274 		{
4275 			stringValue = numberToString (gv->getGradientAngle ());
4276 			return true;
4277 		}
4278 		if (attributeName == kAttrRoundRectRadius)
4279 		{
4280 			stringValue = numberToString (gv->getRoundRectRadius ());
4281 			return true;
4282 		}
4283 		if (attributeName == kAttrFrameWidth)
4284 		{
4285 			stringValue = numberToString (gv->getFrameWidth ());
4286 			return true;
4287 		}
4288 		if (attributeName == kAttrDrawAntialiased)
4289 		{
4290 			stringValue = gv->getDrawAntialised () ? strTrue : strFalse;
4291 			return true;
4292 		}
4293 		if (attributeName == kAttrGradientStyle)
4294 		{
4295 			stringValue = gv->getGradientStyle () == CGradientView::kLinearGradient ? kLinear : kRadial;
4296 			return true;
4297 		}
4298 		if (attributeName == kAttrRadialRadius)
4299 		{
4300 			stringValue = numberToString (gv->getRadialRadius ());
4301 			return true;
4302 		}
4303 		if (attributeName == kAttrRadialCenter)
4304 		{
4305 			pointToString (gv->getRadialCenter (), stringValue);
4306 			return true;
4307 		}
4308 		if (attributeName == kAttrGradient)
4309 		{
4310 			CGradient* gradient = gv->getGradient ();
4311 			UTF8StringPtr gradientName = gradient ? desc->lookupGradientName (gradient) : nullptr;
4312 			stringValue = gradientName ? gradientName : "";
4313 			return true;
4314 		}
4315 		return false;
4316 	}
getPossibleListValues(const std::string & attributeName,std::list<const std::string * > & values) const4317 	bool getPossibleListValues (const std::string& attributeName, std::list<const std::string*>& values) const override
4318 	{
4319 		if (attributeName == kAttrGradientStyle)
4320 		{
4321 			values.emplace_back (&kLinear);
4322 			values.emplace_back (&kRadial);
4323 			return true;
4324 		}
4325 		return false;
4326 	}
getAttributeValueRange(const std::string & attributeName,double & minValue,double & maxValue) const4327 	bool getAttributeValueRange (const std::string& attributeName, double& minValue, double &maxValue) const override
4328 	{
4329 		if (attributeName == kAttrGradientAngle)
4330 		{
4331 			minValue = 0.;
4332 			maxValue = 360.;
4333 			return true;
4334 		}
4335 		return false;
4336 	}
4337 
4338 };
4339 CGradientViewCreator __gCGradientViewCreator;
4340 
4341 //-----------------------------------------------------------------------------
4342 class CXYPadCreator : public ViewCreatorAdapter
4343 {
4344 public:
CXYPadCreator()4345 	CXYPadCreator () { UIViewFactory::registerViewCreator (*this); }
getViewName() const4346 	IdStringPtr getViewName () const override { return kCXYPad; }
getBaseViewName() const4347 	IdStringPtr getBaseViewName () const override { return kCParamDisplay; }
getDisplayName() const4348 	UTF8StringPtr getDisplayName () const override { return "XY Pad"; }
create(const UIAttributes & attributes,const IUIDescription * description) const4349 	CView* create (const UIAttributes& attributes, const IUIDescription* description) const override { return new CXYPad (CRect (0, 0, 60, 60)); }
4350 };
4351 CXYPadCreator __gCXYPadCreator;
4352 
4353 //-----------------------------------------------------------------------------
getStandardAttributeListValues(const std::string & attributeName,std::list<const std::string * > & values)4354 static bool getStandardAttributeListValues (const std::string& attributeName, std::list<const std::string*>& values)
4355 {
4356 	if (attributeName == kAttrOrientation)
4357 	{
4358 		static std::string kHorizontal = strHorizontal;
4359 		static std::string kVertical = strVertical;
4360 
4361 		values.emplace_back (&kHorizontal);
4362 		values.emplace_back (&kVertical);
4363 		return true;
4364 	}
4365 	else if (attributeName == kAttrTruncateMode)
4366 	{
4367 		static std::string kNone = strNone;
4368 		static std::string kHead = strHead;
4369 		static std::string kTail = strTail;
4370 
4371 		values.emplace_back (&kNone);
4372 		values.emplace_back (&kHead);
4373 		values.emplace_back (&kTail);
4374 		return true;
4375 	}
4376 	return false;
4377 }
4378 }} // namespace
4379 
4380 /**
4381 @endcond ignore
4382 */
4383