1 // This file is part of VSTGUI. It is subject to the license terms
2 // in the LICENSE file found in the top-level directory of this
3 // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE
4 
5 #include "uieditcontroller.h"
6 
7 #if VSTGUI_LIVE_EDITING
8 
9 #include "uieditview.h"
10 #include "uiattributescontroller.h"
11 #include "uibitmapscontroller.h"
12 #include "uicolorscontroller.h"
13 #include "uigradientscontroller.h"
14 #include "uieditmenucontroller.h"
15 #include "uifontscontroller.h"
16 #include "uigridcontroller.h"
17 #include "uitagscontroller.h"
18 #include "uitemplatecontroller.h"
19 #include "uiviewcreatecontroller.h"
20 #include "uiundomanager.h"
21 #include "uiactions.h"
22 #include "uiselection.h"
23 #include "uidialogcontroller.h"
24 #include "uitemplatesettingscontroller.h"
25 #include "uifocussettingscontroller.h"
26 #include "../cstream.h"
27 #include "../uiattributes.h"
28 #include "../xmlparser.h"
29 #include "../../lib/controls/coptionmenu.h"
30 #include "../../lib/controls/csegmentbutton.h"
31 #include "../../lib/controls/csearchtextedit.h"
32 #include "../../lib/animation/animations.h"
33 #include "../../lib/animation/timingfunctions.h"
34 #include "../../lib/cdropsource.h"
35 #include "../../lib/cgraphicspath.h"
36 #include "../../lib/coffscreencontext.h"
37 #include "../../lib/iviewlistener.h"
38 #include "../../lib/cvstguitimer.h"
39 
40 #include <sstream>
41 #include <algorithm>
42 #include <cassert>
43 #include <array>
44 
45 #if WINDOWS
46 #define snprintf _snprintf
47 #endif
48 
49 namespace VSTGUI {
50 
51 #ifdef HAVE_EDITORUIDESC_H
52 #include "editoruidesc.h"
53 #endif
54 
55 //----------------------------------------------------------------------------------------------------
56 class UIEditControllerDescription
57 {
58 public:
get() const59 	SharedPointer<UIDescription> get () const
60 	{
61 		if (uiDesc == nullptr)
62 		{
63 #ifdef HAVE_EDITORUIDESC_H
64 			Xml::MemoryContentProvider provider (editorUIDesc, strlen (editorUIDesc));
65 			SharedPointer<UIDescription> editorDesc = owned (new UIDescription (&provider));
66 			if (editorDesc->parse ())
67 			{
68 				uiDesc = editorDesc;
69 			}
70 #else
71 			std::string descPath (__FILE__);
72 			unixfyPath (descPath);
73 			if (removeLastPathComponent (descPath))
74 			{
75 				descPath += "/uidescriptioneditor.uidesc";
76 				auto editorDesc = makeOwned<UIDescription> (descPath.c_str ());
77 				if (editorDesc->parse ())
78 				{
79 					uiDesc = std::move (editorDesc);
80 				}
81 				else
82 				{
83 					vstgui_assert (false, "the __FILE__ macro is relative, so it's not possible to find the uidescriptioneditor.uidesc. You can replace the macro with the absolute filename to make this work on your devel machine");
84 				}
85 			}
86 #endif
87 		}
88 		return uiDesc;
89 	}
90 
tryFree()91 	void tryFree ()
92 	{
93 		if (uiDesc->getNbReference () == 1)
94 			uiDesc = nullptr;
95 	}
96 
97 private:
98 	mutable SharedPointer<UIDescription> uiDesc;
99 };
100 
101 static UIEditControllerDescription gUIDescription;
102 
103 //----------------------------------------------------------------------------------------------------
getEditorDescription()104 SharedPointer<UIDescription> UIEditController::getEditorDescription ()
105 {
106 	return gUIDescription.get ();
107 }
108 
109 //----------------------------------------------------------------------------------------------------
setupDataSource(GenericStringListDataBrowserSource * source)110 void UIEditController::setupDataSource (GenericStringListDataBrowserSource* source)
111 {
112 	static CColor selectionColor;
113 	static CColor fontColor;
114 	static CColor rowlineColor;
115 	static CColor rowBackColor;
116 	static CColor rowAlternateBackColor;
117 	static bool once = true;
118 	auto editorDescription = UIEditController::getEditorDescription ();
119 	if (once)
120 	{
121 		editorDescription->getColor ("db.selection", selectionColor);
122 		editorDescription->getColor ("db.font", fontColor);
123 		editorDescription->getColor ("db.row.line", rowlineColor);
124 		editorDescription->getColor ("db.row.back", rowBackColor);
125 		editorDescription->getColor ("db.row.alternate.back", rowAlternateBackColor);
126 		once = false;
127 	}
128 	CFontRef font = editorDescription->getFont ("db.font");
129 	source->setupUI (selectionColor, fontColor, rowlineColor, rowBackColor, rowAlternateBackColor, font);
130 }
131 
132 //-----------------------------------------------------------------------------
std__stringCompare(const std::string * lhs,const std::string * rhs)133 bool UIEditController::std__stringCompare (const std::string* lhs, const std::string* rhs)
134 {
135 	for (std::string::const_iterator it = lhs->begin (), it2 = rhs->begin (); it != lhs->end () && it2 != rhs->end (); it++, it2++)
136 	{
137 		char c1 = static_cast<char> (tolower (*it));
138 		char c2 = static_cast<char> (tolower (*it2));
139 		if (c1 != c2)
140 			return c1 < c2;
141 	}
142 	return false;
143 }
144 
145 const UTF8StringPtr UIEditController::kEncodeBitmapsSettingsKey = "EncodeBitmaps";
146 const UTF8StringPtr UIEditController::kWriteWindowsRCFileSettingsKey = "WriteRCFile";
147 
148 //----------------------------------------------------------------------------------------------------
149 class UIEditControllerShadingView : public CView
150 {
151 public:
UIEditControllerShadingView(bool horizontal,bool drawTopLine=false,bool drawBottomLine=true)152 	UIEditControllerShadingView (bool horizontal, bool drawTopLine = false, bool drawBottomLine = true)
153 	: CView (CRect (0, 0, 0, 0))
154 	, horizontal (horizontal)
155 	, drawTopLine (drawTopLine)
156 	, drawBottomLine (drawBottomLine)
157 	{}
158 
draw(CDrawContext * context)159 	void draw (CDrawContext* context) override
160 	{
161 		drawGradient (context, getViewSize (), horizontal, drawTopLine, drawBottomLine);
162 	}
163 
drawGradient(CDrawContext * context,const CRect & _size,bool horizontal,bool drawTopLine=true,bool drawBottomLine=true)164 	static void drawGradient (CDrawContext* context, const CRect& _size, bool horizontal, bool drawTopLine = true, bool drawBottomLine = true)
165 	{
166 		SharedPointer<CGraphicsPath> path = owned (context->createGraphicsPath ());
167 		if (path)
168 		{
169 			static CColor lineColor = kBlackCColor;
170 			if (lineColor == kBlackCColor)
171 				UIEditController::getEditorDescription ()->getColor ("shading.light.frame", lineColor);
172 
173 			auto lineWidth = 1.;
174 
175 			CRect size (_size);
176 			context->setDrawMode (kAliasing);
177 			context->setLineStyle (kLineSolid);
178 			context->setLineWidth (lineWidth);
179 			context->setFrameColor (lineColor);
180 
181 			CGradient* shading = UIEditController::getEditorDescription ()->getGradient ("shading.light");
182 			if (shading)
183 			{
184 				path->addRect (size);
185 				if (horizontal)
186 				{
187 					context->fillLinearGradient (path, *shading, CPoint (size.left, size.top), CPoint (size.right, size.top));
188 					if (drawBottomLine)
189 						context->drawLine (CPoint (size.left, size.top), CPoint (size.left, size.bottom));
190 					if (drawTopLine)
191 						context->drawLine (CPoint (size.right-lineWidth, size.bottom), CPoint (size.right-lineWidth, size.top));
192 				}
193 				else
194 				{
195 					context->fillLinearGradient (path, *shading, CPoint (size.left, size.top), CPoint (size.left, size.bottom));
196 					if (drawTopLine)
197 						context->drawLine (CPoint (size.left, size.top), CPoint (size.right, size.top));
198 					if (drawBottomLine)
199 						context->drawLine (CPoint (size.right, size.bottom-lineWidth), CPoint (size.left, size.bottom-lineWidth));
200 				}
201 			}
202 		}
203 	}
204 
205 protected:
206 	bool horizontal;
207 	bool drawTopLine;
208 	bool drawBottomLine;
209 };
210 
211 //----------------------------------------------------------------------------------------------------
212 class UIZoomSettingController : public IController,
213                                 public IContextMenuController2,
214                                 public ViewMouseListenerAdapter,
215                                 public ViewListenerAdapter,
216                                 public NonAtomicReferenceCounted
217 {
218 public:
UIZoomSettingController(UIEditController * editController)219 	UIZoomSettingController (UIEditController* editController)
220 	: editController (editController)
221 	{}
222 
~UIZoomSettingController()223 	~UIZoomSettingController () noexcept override
224 	{
225 		if (zoomValueControl)
226 			viewWillDelete (zoomValueControl);
227 	}
228 
restoreSetting(const UIAttributes & attributes)229 	void restoreSetting (const UIAttributes& attributes)
230 	{
231 		double value;
232 		if (attributes.getDoubleAttribute ("EditViewScale", value))
233 		{
234 			if (zoomValueControl)
235 			{
236 				zoomValueControl->setValue (static_cast<float> (value) * 100.f);
237 				valueChanged (zoomValueControl);
238 			}
239 		}
240 	}
241 
storeSetting(UIAttributes & attributes) const242 	void storeSetting (UIAttributes& attributes) const
243 	{
244 		if (zoomValueControl)
245 			attributes.setDoubleAttribute ("EditViewScale", zoomValueControl->getValue () / 100.f);
246 	}
247 
increaseZoom()248 	void increaseZoom ()
249 	{
250 		if (!zoomValueControl)
251 			return;
252 		float add = 10.f;
253 		float current = zoomValueControl->getValue ();
254 		if (current >= 100.f)
255 			add = 50.f;
256 		updateZoom (current + add);
257 	}
258 
decreaseZoom()259 	void decreaseZoom ()
260 	{
261 		if (!zoomValueControl)
262 			return;
263 		float sub = 10.f;
264 		float current = zoomValueControl->getValue ();
265 		if (current >= 150.f)
266 			sub = 50.f;
267 		updateZoom (current - sub);
268 	}
269 
resetZoom()270 	void resetZoom ()
271 	{
272 		if (!zoomValueControl)
273 			return;
274 		updateZoom (100.f);
275 	}
276 
verifyView(CView * view,const UIAttributes & attributes,const IUIDescription * description)277 	CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override
278 	{
279 		if (!zoomValueControl)
280 		{
281 			zoomValueControl = dynamic_cast<CTextEdit*> (view);
282 			if (zoomValueControl)
283 			{
284 				zoomValueControl->setMin (50.f);
285 				zoomValueControl->setMax (1000.f);
286 				zoomValueControl->setStringToValueFunction ([] (UTF8StringPtr txt, float& result, CTextEdit*) {
287 					int32_t intValue = static_cast<int32_t> (strtol (txt, nullptr, 10));
288 					if (intValue > 0)
289 					{
290 						result = static_cast<float> (intValue);
291 						return true;
292 					}
293 
294 					return false;
295 				});
296 				zoomValueControl->setValueToStringFunction ([] (float value, char utf8String[256], CParamDisplay*) {
297 					snprintf (utf8String, 255, "%d %%", static_cast<uint32_t> (value));
298 					return true;
299 				});
300 				zoomValueControl->setValue (100.f);
301 				CFontRef font = description->getFont ("control.font");
302 				CColor fontColor = kWhiteCColor, frameColor = kBlackCColor, backColor = kBlackCColor;
303 				description->getColor ("control.font", fontColor);
304 				description->getColor ("control.frame", frameColor);
305 				description->getColor ("control.back", backColor);
306 				zoomValueControl->setFont (font);
307 				zoomValueControl->setFontColor (fontColor);
308 				zoomValueControl->setBackColor (backColor);
309 				zoomValueControl->setFrameColor (frameColor);
310 				zoomValueControl->setFrameWidth (-1);
311 				zoomValueControl->setTooltipText ("Editor Zoom");
312 				zoomValueControl->registerViewListener (this);
313 				zoomValueControl->registerViewMouseListener (this);
314 				zoomValueControl->setStyle (zoomValueControl->getStyle () | CTextEdit::kDoubleClickStyle);
315 			}
316 		}
317 		return view;
318 	}
319 
valueChanged(CControl * pControl)320 	void valueChanged (CControl* pControl) override
321 	{
322 		if (pControl == zoomValueControl)
323 			editController->onZoomChanged (pControl->getValue () / 100.f);
324 	}
325 
appendContextMenuItems(COptionMenu & contextMenu,CView * view,const CPoint & where)326 	void appendContextMenuItems (COptionMenu& contextMenu, CView* view, const CPoint& where) override
327 	{
328 		if (view == zoomValueControl)
329 		{
330 			for (auto i = 50; i <= 250; i += 25)
331 			{
332 				auto item = new CCommandMenuItem ("Zoom " + toString (i) + "%");
333 				item->setActions ([this, i] (CCommandMenuItem*) {
334 					updateZoom (static_cast<float> (i));
335 				});
336 				if (zoomValueControl->getValue () == static_cast<float> (i))
337 					item->setChecked (true);
338 				contextMenu.addEntry (item);
339 			}
340 		}
341 	}
342 
viewOnMouseDown(CView * view,CPoint pos,CButtonState buttons)343 	CMouseEventResult viewOnMouseDown (CView* view, CPoint pos, CButtonState buttons) override
344 	{
345 		vstgui_assert (view == zoomValueControl);
346 		if (buttons.isDoubleClick ())
347 			popupTimer = nullptr;
348 		else if (buttons.isLeftButton () && buttons.getModifierState () == 0)
349 		{
350 			popupTimer = makeOwned<CVSTGUITimer> ([this] (CVSTGUITimer*) {
351 				popupTimer = nullptr;
352 				auto menu = makeOwned<COptionMenu> ();
353 				menu->setStyle (COptionMenu::kPopupStyle | COptionMenu::kMultipleCheckStyle);
354 				appendContextMenuItems (*menu, zoomValueControl, CPoint ());
355 				menu->popup (zoomValueControl->getFrame (),
356 				             zoomValueControl->translateToGlobal (
357 				                 zoomValueControl->getViewSize ().getTopLeft (), true));
358 			}, 250);
359 		}
360 		return kMouseEventNotHandled;
361 	}
362 
viewWillDelete(CView * view)363 	void viewWillDelete (CView* view) override
364 	{
365 		vstgui_assert (view == zoomValueControl);
366 		view->unregisterViewListener (this);
367 		view->unregisterViewMouseListener (this);
368 		zoomValueControl = nullptr;
369 	}
370 
371 private:
updateZoom(float newZoom)372 	void updateZoom (float newZoom)
373 	{
374 		if (zoomValueControl)
375 		{
376 			zoomValueControl->setValue (newZoom);
377 			valueChanged (zoomValueControl);
378 		}
379 	}
380 
381 	UIEditController* editController{nullptr};
382 	CTextEdit* zoomValueControl{nullptr};
383 	SharedPointer<CVSTGUITimer> popupTimer;
384 };
385 
386 //----------------------------------------------------------------------------------------------------
387 //----------------------------------------------------------------------------------------------------
388 //----------------------------------------------------------------------------------------------------
UIEditController(UIDescription * description)389 UIEditController::UIEditController (UIDescription* description)
390 : editDescription (description)
391 , selection (makeOwned<UISelection> ())
392 , undoManager (makeOwned<UIUndoManager> ())
393 , gridController (makeOwned<UIGridController> (this, description))
394 , editView (nullptr)
395 , templateController (nullptr)
396 , dirty (false)
397 {
398 	editorDesc = getEditorDescription ();
399 	undoManager->registerListener (this);
400 	editDescription->registerListener (this);
401 	menuController = new UIEditMenuController (this, selection, undoManager, editDescription, this);
402 	onTemplatesChanged ();
403 }
404 
405 //----------------------------------------------------------------------------------------------------
~UIEditController()406 UIEditController::~UIEditController ()
407 {
408 	selection->clear ();
409 	if (templateController)
410 		templateController->unregisterListener (this);
411 	undoManager->unregisterListener (this);
412 	editDescription->unregisterListener (this);
413 	editorDesc = nullptr;
414 	templateController = nullptr;
415 	undoManager->clear ();
416 	gUIDescription.tryFree ();
417 }
418 
419 //----------------------------------------------------------------------------------------------------
createEditView()420 CView* UIEditController::createEditView ()
421 {
422 	if (editorDesc->parse ())
423 	{
424 		IController* controller = this;
425 		CView* view = editorDesc->createView ("view", controller);
426 		if (view)
427 		{
428 			view->setAttribute (kCViewControllerAttribute, controller);
429 			CRect r;
430 			if (getSettings ()->getRectAttribute ("EditorSize", r))
431 			{
432 				view->setViewSize (r);
433 				view->setMouseableArea (r);
434 			}
435 			return view;
436 		}
437 	}
438 	return nullptr;
439 }
440 
441 //----------------------------------------------------------------------------------------------------
createView(const UIAttributes & attributes,const IUIDescription * description)442 CView* UIEditController::createView (const UIAttributes& attributes, const IUIDescription* description)
443 {
444 	const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
445 	if (name)
446 	{
447 		if (*name == "UIEditView")
448 		{
449 			vstgui_assert (editView == nullptr);
450 			editView = new UIEditView (CRect (0, 0, 0, 0), editDescription);
451 			editView->setSelection (selection);
452 			editView->setUndoManager (undoManager);
453 			editView->setGridProcessor (gridController);
454 			editView->setupColors (description);
455 			return editView;
456 		}
457 		else if (*name == "ShadingViewHorizontal")
458 		{
459 			return new UIEditControllerShadingView (true);
460 		}
461 		else if (*name == "ShadingViewVertical")
462 		{
463 			return new UIEditControllerShadingView (false);
464 		}
465 		else if (*name == "ShadingViewVerticalTopLine")
466 		{
467 			return new UIEditControllerShadingView (false, true, false);
468 		}
469 	}
470 	return nullptr;
471 }
472 
473 //----------------------------------------------------------------------------------------------------
onZoomChanged(double zoom)474 void UIEditController::onZoomChanged (double zoom)
475 {
476 	if (editView)
477 		editView->setScale (zoom);
478 	if (zoomSettingController)
479 		zoomSettingController->storeSetting (*getSettings ());
480 }
481 
482 enum {
483 	kNotSavedTag = 666,
484 	kEditingTag,
485 	kAutosizeTag,
486 	kBackgroundSelectTag,
487 	kTabSwitchTag = 123456
488 };
489 
490 //----------------------------------------------------------------------------------------------------
createColorBitmap(CPoint size,CColor color)491 static SharedPointer<CBitmap> createColorBitmap (CPoint size, CColor color)
492 {
493 	auto bitmap = makeOwned<CBitmap> (size);
494 	if (auto pixelAccessor = owned (CBitmapPixelAccess::create (bitmap)))
495 	{
496 		for (auto y = 0u; y < static_cast<uint32_t> (size.y); y++)
497 		{
498 			pixelAccessor->setPosition (0, y);
499 			for (auto x = 0u; x < static_cast<uint32_t> (size.x); ++x)
500 			{
501 				pixelAccessor->setColor (color);
502 				++(*pixelAccessor);
503 			}
504 		}
505 	}
506 
507 	return bitmap;
508 }
509 
510 //----------------------------------------------------------------------------------------------------
511 using BackgroundColors = std::array<CColor, 4>;
512 
editViewBackgroundColors()513 static const BackgroundColors& editViewBackgroundColors ()
514 {
515 	static const BackgroundColors colors = {{
516 		{230, 230, 230},
517 		{150, 150, 150},
518 		kWhiteCColor,
519 		kBlackCColor
520 	}};
521 	return colors;
522 }
523 
524 //----------------------------------------------------------------------------------------------------
verifyView(CView * view,const UIAttributes & attributes,const IUIDescription * description)525 CView* UIEditController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
526 {
527 	if (view == editView)
528 	{
529 		editView->setBackgroundColor (editViewBackgroundColors ()[0]);
530 		return view;
531 	}
532 	auto* splitView = dynamic_cast<CSplitView*>(view);
533 	if (splitView)
534 	{
535 		splitViews.emplace_back (splitView);
536 		if (splitViews.size () == 1)
537 		{
538 			CFontRef font = description->getFont ("control.font");
539 			CColor fontColor = kWhiteCColor, frameColor = kBlackCColor, backColor = kBlackCColor;
540 			description->getColor ("control.font", fontColor);
541 			description->getColor ("control.frame", frameColor);
542 			description->getColor ("control.back", backColor);
543 			auto gradient = description->getGradient ("Default TextButton Gradient");
544 			auto gradientHighlighted = description->getGradient ("Default TextButton Gradient Highlighted");
545 
546 			// Add Background Menu
547 			CRect backSelectRect (0., 0., 20. * editViewBackgroundColors ().size (), splitView->getSeparatorWidth ());
548 			backSelectRect.inset (2, 2);
549 			auto backSelectControl = new CSegmentButton (backSelectRect, this, kBackgroundSelectTag);
550 			backSelectControl->setGradient (gradient);
551 			backSelectControl->setGradientHighlighted (gradientHighlighted);
552 			backSelectControl->setFrameColor (frameColor);
553 			backSelectControl->setFrameWidth (-1.);
554 			backSelectControl->setRoundRadius (2.);
555 			auto bitmapSize = splitView->getSeparatorWidth () - 12;
556 			for (auto& color : editViewBackgroundColors ())
557 			{
558 				CSegmentButton::Segment segment {};
559 				segment.iconPosition = CDrawMethods::kIconCenterAbove;
560 				segment.icon = segment.iconHighlighted = createColorBitmap ({bitmapSize, bitmapSize}, color);
561 				backSelectControl->addSegment (std::move (segment));
562 			}
563 			backSelectControl->setTooltipText ("Editor Background Color");
564 			splitView->addViewToSeparator (0, backSelectControl);
565 
566 			// Add Title
567 			CTextLabel* label = new CTextLabel (CRect (0, 0, splitView->getWidth (), splitView->getSeparatorWidth ()), "Templates | View Hierarchy");
568 			label->setTransparency (true);
569 			label->setMouseEnabled (false);
570 			label->setFont (font);
571 			label->setFontColor (kBlackCColor);
572 			label->setAutosizeFlags (kAutosizeAll);
573 			splitView->addViewToSeparator (0, label);
574 
575 			// Add Scale Menu
576 			CRect scaleMenuRect (0, 0, 50, splitView->getSeparatorWidth ());
577 			scaleMenuRect.offset (splitView->getWidth ()-scaleMenuRect.getWidth (), 0);
578 			scaleMenuRect.inset (2, 2);
579 
580 			zoomSettingController = new UIZoomSettingController (this); // not owned, shared with control
581 			auto* textEdit = new CTextEdit (scaleMenuRect, zoomSettingController, 0);
582 			textEdit->setAttribute (kCViewControllerAttribute, zoomSettingController);
583 			CView* zoomView = zoomSettingController->verifyView (textEdit, UIAttributes (), editorDesc);
584 			zoomView->setAutosizeFlags (kAutosizeRight|kAutosizeTop|kAutosizeBottom);
585 			splitView->addViewToSeparator (0, zoomView);
586 			zoomSettingController->restoreSetting (*getSettings ());
587 
588 		}
589 	}
590 	auto* control = dynamic_cast<CControl*>(view);
591 	if (control)
592 	{
593 		switch (control->getTag ())
594 		{
595 			case kNotSavedTag:
596 			{
597 				notSavedControl = control;
598 				notSavedControl->setAlphaValue (dirty ? 1.f : 0.f);
599 				break;
600 			}
601 			case kAutosizeTag:
602 			{
603 				control->setListener (this);
604 				control->setValue (1.);
605 				break;
606 			}
607 			case kEditingTag:
608 			{
609 				enableEditingControl = control;
610 				enableEditingControl->setValue (1.f);
611 				enableEditingControl->setListener (this);
612 				break;
613 			}
614 			case kTabSwitchTag:
615 			{
616 				auto* button = dynamic_cast<CSegmentButton*>(control);
617 				if (button)
618 				{
619 					size_t numSegments = button->getSegments ().size ();
620 					button->setMax (static_cast<float> (numSegments));
621 					tabSwitchControl = button;
622 					int32_t value = 0;
623 					getSettings ()->getIntegerAttribute ("TabSwitchValue", value);
624 					button->setSelectedSegment (static_cast<uint32_t> (value));
625 					static const char* segmentBitmapNames[] = {"segment-views", "segment-tags", "segment-colors", "segment-gradients", "segment-bitmaps", "segment-fonts", nullptr};
626 					size_t segmentBitmapNameIndex = 0;
627 					for (const auto& segment : button->getSegments())
628 					{
629 						if (segmentBitmapNames[segmentBitmapNameIndex])
630 						{
631 							CBitmap* bitmap = editorDesc->getBitmap (segmentBitmapNames[segmentBitmapNameIndex++]);
632 							if (!bitmap)
633 								continue;
634 							segment.icon = bitmap;
635 							segment.iconHighlighted = bitmap;
636 							segment.iconPosition = CDrawMethods::kIconLeft;
637 						}
638 					}
639 				}
640 				break;
641 			}
642 		}
643 	}
644 	return view;
645 }
646 
647 //----------------------------------------------------------------------------------------------------
createSubController(UTF8StringPtr name,const IUIDescription * description)648 IController* UIEditController::createSubController (UTF8StringPtr name, const IUIDescription* description)
649 {
650 	UTF8StringView subControllerName (name);
651 	if (subControllerName == "TemplatesController")
652 	{
653 		vstgui_assert (templateController == nullptr);
654 		templateController = new UITemplateController (this, editDescription, selection, undoManager, this);
655 		templateController->registerListener (this);
656 		return templateController;
657 	}
658 	else if (subControllerName == "MenuController")
659 	{
660 		return menuController;
661 	}
662 	else if (subControllerName == "ViewCreatorController")
663 	{
664 		return new UIViewCreatorController (this, editDescription);
665 	}
666 	else if (subControllerName == "AttributesController")
667 	{
668 		return new UIAttributesController (this, selection, undoManager, editDescription);
669 	}
670 	else if (subControllerName == "TagEditController")
671 	{
672 		return new UITagsController (this, editDescription, this);
673 	}
674 	else if (subControllerName == "ColorEditController")
675 	{
676 		return new UIColorsController (this, editDescription, this);
677 	}
678 	else if (subControllerName == "GradientEditController")
679 	{
680 		return new UIGradientsController (this, editDescription, this);
681 	}
682 	else if (subControllerName == "BitmapEditController")
683 	{
684 		return new UIBitmapsController (this, editDescription, this);
685 	}
686 	else if (subControllerName == "FontEditController")
687 	{
688 		return new UIFontsController (this, editDescription, this);
689 	}
690 	else if (subControllerName == "GridController")
691 	{
692 		gridController->remember ();
693 		return gridController;
694 	}
695 	return nullptr;
696 }
697 
698 //----------------------------------------------------------------------------------------------------
valueChanged(CControl * control)699 void UIEditController::valueChanged (CControl* control)
700 {
701 	if (editView)
702 	{
703 		switch (control->getTag ())
704 		{
705 			case kEditingTag:
706 			{
707 				selection->clear ();
708 				if (auto container = editView->getEditView () ? editView->getEditView ()->asViewContainer () : nullptr)
709 					resetScrollViewOffsets (container);
710 				editView->enableEditing (control->getValue () == control->getMax () ? true : false);
711 				break;
712 			}
713 			case kAutosizeTag:
714 			{
715 				editView->enableAutosizing (control->getValue () == 1.f);
716 				break;
717 			}
718 			case kBackgroundSelectTag:
719 			{
720 				if (auto seg = dynamic_cast<CSegmentButton*> (control))
721 				{
722 					CColor color = editViewBackgroundColors ()[seg->getSelectedSegment ()];
723 					editView->setBackgroundColor (color);
724 				}
725 				break;
726 			}
727 			case kTabSwitchTag:
728 			{
729 				getSettings ()->setIntegerAttribute ("TabSwitchValue", static_cast<int32_t> (tabSwitchControl->getValue ()));
730 				break;
731 			}
732 		}
733 	}
734 }
735 
736 //----------------------------------------------------------------------------------------------------
validateCommandMenuItem(CCommandMenuItem * item)737 bool UIEditController::validateCommandMenuItem (CCommandMenuItem* item)
738 {
739 	return validateMenuItem (item) == kMessageNotified;
740 }
741 
742 //----------------------------------------------------------------------------------------------------
onCommandMenuItemSelected(CCommandMenuItem * item)743 bool UIEditController::onCommandMenuItemSelected (CCommandMenuItem* item)
744 {
745 	return onMenuItemSelection (item) == kMessageNotified;
746 }
747 
748 //----------------------------------------------------------------------------------------------------
onUndoManagerChange()749 void UIEditController::onUndoManagerChange ()
750 {
751 	onUndoManagerChanged ();
752 }
753 
754 //----------------------------------------------------------------------------------------------------
onTemplateSelectionChanged()755 void UIEditController::onTemplateSelectionChanged ()
756 {
757 	if (editView && templateController)
758 	{
759 		const auto& name = templateController->getSelectedTemplateName ();
760 		if ((name && *name != editTemplateName) || name == nullptr)
761 		{
762 			if (undoManager->canUndo () && !editTemplateName.empty ())
763 				updateTemplate (editTemplateName.c_str ());
764 			if (name)
765 			{
766 				for (auto& it : templates)
767 				{
768 					if (*name == it.name)
769 					{
770 						CView* view = it.view;
771 						editView->setEditView (view);
772 						templateController->setTemplateView (static_cast<CViewContainer*> (view));
773 						editTemplateName = *templateController->getSelectedTemplateName ();
774 						view->remember ();
775 						break;
776 					}
777 				}
778 			}
779 			else
780 			{
781 				selection->clear ();
782 				editView->setEditView (nullptr);
783 				templateController->setTemplateView (nullptr);
784 				editTemplateName = "";
785 			}
786 		}
787 		if (editView->getEditView ())
788 		{
789 			if (!(selection->first () && editView->getEditView ()->asViewContainer ()->isChild (selection->first (), true)))
790 				selection->setExclusive (editView->getEditView ());
791 		}
792 		else
793 			selection->clear ();
794 	}
795 }
796 
797 //----------------------------------------------------------------------------------------------------
notify(CBaseObject * sender,IdStringPtr message)798 CMessageResult UIEditController::notify (CBaseObject* sender, IdStringPtr message)
799 {
800 	if (message == UIEditView::kMsgAttached)
801 	{
802 		vstgui_assert (editView);
803 		editView->getFrame ()->registerKeyboardHook (this);
804 		return kMessageNotified;
805 	}
806 	else if (message == UIEditView::kMsgRemoved)
807 	{
808 		editView->getFrame ()->unregisterKeyboardHook (this);
809 		beforeSave ();
810 		splitViews.clear ();
811 		getEditorDescription ()->freePlatformResources ();
812 		return kMessageNotified;
813 	}
814 
815 	return kMessageUnknown;
816 }
817 
818 //----------------------------------------------------------------------------------------------------
onUIDescTemplateChanged(UIDescription * desc)819 void UIEditController::onUIDescTemplateChanged (UIDescription* desc)
820 {
821 	onTemplatesChanged ();
822 }
823 
824 //----------------------------------------------------------------------------------------------------
beforeUIDescSave(UIDescription * desc)825 void UIEditController::beforeUIDescSave (UIDescription* desc)
826 {
827 	beforeSave ();
828 }
829 
830 //----------------------------------------------------------------------------------------------------
doUIDescTemplateUpdate(UIDescription * desc,UTF8StringPtr name)831 bool UIEditController::doUIDescTemplateUpdate (UIDescription* desc, UTF8StringPtr name)
832 {
833 	if (onlyTemplateToUpdateName.empty ())
834 		return true;
835 	return onlyTemplateToUpdateName == name;
836 }
837 
838 //----------------------------------------------------------------------------------------------------
beforeSave()839 void UIEditController::beforeSave ()
840 {
841 	if (editView && editView->getEditView ())
842 	{
843 		if (undoManager->canUndo ())
844 		{
845 			if (!editTemplateName.empty ())
846 				updateTemplate (editTemplateName.c_str ());
847 			for (std::vector<Template>::const_iterator it = templates.begin (); it != templates.end (); it++)
848 			{
849 				onlyTemplateToUpdateName = it->name;
850 				updateTemplate (it);
851 			}
852 			onlyTemplateToUpdateName.clear ();
853 		}
854 		for (auto& splitView : splitViews)
855 			splitView->storeViewSizes ();
856 
857 		getSettings ()->setIntegerAttribute ("Version", 1);
858 		// find the view of this controller
859 		auto container = editView->getParentView ()->asViewContainer ();
860 		while (container && container != container->getFrame ())
861 		{
862 			if (getViewController (container, false) == this)
863 			{
864 				getSettings ()->setRectAttribute ("EditorSize", container->getViewSize ());
865 				break;
866 			}
867 			container = container->getParentView () ? container->getParentView ()->asViewContainer () : nullptr;
868 		}
869 		undoManager->markSavePosition ();
870 		if (zoomSettingController)
871 			zoomSettingController->storeSetting (*getSettings ());
872 		setDirty (false);
873 	}
874 }
875 
876 //----------------------------------------------------------------------------------------------------
doCopy(bool cut)877 void UIEditController::doCopy (bool cut)
878 {
879 	if (!editTemplateName.empty ())
880 		updateTemplate (editTemplateName.c_str ());
881 	CMemoryStream stream (1024, 1024, false);
882 	selection->store (stream, editDescription);
883 	auto dataSource = CDropSource::create (stream.getBuffer (), static_cast<uint32_t> (stream.tell ()), IDataPackage::kText);
884 	editView->getFrame ()->setClipboard (dataSource);
885 	if (cut)
886 		undoManager->pushAndPerform (new DeleteOperation (selection));
887 }
888 
889 //----------------------------------------------------------------------------------------------------
addSelectionToCurrentView(UISelection * copySelection)890 void UIEditController::addSelectionToCurrentView (UISelection* copySelection)
891 {
892 	if (selection->total () == 0)
893 		return;
894 	CPoint offset;
895 	CViewContainer* container = selection->first ()->asViewContainer ();
896 	if (container == nullptr)
897 	{
898 		container = selection->first ()->getParentView ()->asViewContainer ();
899 		offset = selection->first ()->getViewSize ().getTopLeft ();
900 		offset.offset (gridController->getSize ().x, gridController->getSize ().y);
901 	}
902 	IAction* action = new ViewCopyOperation (copySelection, selection, container, offset, editDescription);
903 	undoManager->pushAndPerform (action);
904 	if (!editTemplateName.empty ())
905 		updateTemplate (editTemplateName.c_str ());
906 }
907 
908 //----------------------------------------------------------------------------------------------------
doPaste()909 void UIEditController::doPaste ()
910 {
911 	if (auto clipboard = editView->getFrame ()->getClipboard ())
912 	{
913 		if (clipboard->getDataType (0) == IDataPackage::kText)
914 		{
915 			const void* data;
916 			IDataPackage::Type type;
917 			uint32_t size = clipboard->getData (0, data, type);
918 			if (size > 0)
919 			{
920 				CMemoryStream stream ((const int8_t*)data, size, false);
921 				auto* copySelection = new UISelection ();
922 				if (copySelection->restore (stream, editDescription))
923 				{
924 					addSelectionToCurrentView (copySelection);
925 				}
926 				copySelection->forget ();
927 			}
928 		}
929 	}
930 }
931 
932 //----------------------------------------------------------------------------------------------------
showTemplateSettings()933 void UIEditController::showTemplateSettings ()
934 {
935 	if (undoManager->canUndo () && !editTemplateName.empty ())
936 	{
937 		updateTemplate (editTemplateName.c_str ());
938 	}
939 	auto dc = new UIDialogController (this, editView->getFrame ());
940 	auto tsController =
941 	    makeOwned<UITemplateSettingsController> (editTemplateName, editDescription, this);
942 	dc->run ("template.settings", "Template Settings", "OK", "Cancel", tsController, editorDesc);
943 }
944 
945 //----------------------------------------------------------------------------------------------------
showFocusSettings()946 void UIEditController::showFocusSettings ()
947 {
948 	auto dc = new UIDialogController (this, editView->getFrame ());
949 	auto fsController = makeOwned<UIFocusSettingsController> (editDescription, this);
950 	dc->run ("focus.settings", "Focus Drawing Settings", "OK", "Cancel", fsController, editorDesc);
951 }
952 
953 //----------------------------------------------------------------------------------------------------
toggleBoolAttribute(UIAttributes * attributes,UTF8StringPtr key)954 static void toggleBoolAttribute (UIAttributes* attributes, UTF8StringPtr key)
955 {
956 	if (attributes)
957 	{
958 		bool val = false;
959 		attributes->getBooleanAttribute (key, val);
960 		attributes->setBooleanAttribute (key, !val);
961 	}
962 }
963 
964 //----------------------------------------------------------------------------------------------------
onMenuItemSelection(CCommandMenuItem * item)965 CMessageResult UIEditController::onMenuItemSelection (CCommandMenuItem* item)
966 {
967 	UTF8StringView cmdCategory (item->getCommandCategory ());
968 	UTF8StringView cmdName (item->getCommandName ());
969 
970 	if (cmdCategory == "Edit")
971 	{
972 		if (cmdName == "Copy")
973 		{
974 			doCopy (false);
975 			return kMessageNotified;
976 		}
977 		else if (cmdName == "Cut")
978 		{
979 			doCopy (true);
980 			return kMessageNotified;
981 		}
982 		else if (cmdName == "Paste")
983 		{
984 			doPaste ();
985 			return kMessageNotified;
986 		}
987 		else if (cmdName == "Template Settings...")
988 		{
989 			showTemplateSettings ();
990 			return kMessageNotified;
991 		}
992 		else if (cmdName == "Focus Drawing Settings...")
993 		{
994 			showFocusSettings ();
995 			return kMessageNotified;
996 		}
997 	}
998 	else if (cmdCategory == "File")
999 	{
1000 		if (cmdName == "Encode Bitmaps in XML")
1001 		{
1002 			toggleBoolAttribute (getSettings (), kEncodeBitmapsSettingsKey);
1003 			return kMessageNotified;
1004 		}
1005 		else if (cmdName == "Write Windows RC File on Save")
1006 		{
1007 			toggleBoolAttribute (getSettings (), kWriteWindowsRCFileSettingsKey);
1008 			return kMessageNotified;
1009 		}
1010 	}
1011 	else if (cmdCategory == "SelectionMoveByGrid")
1012 	{
1013 		if (doSelectionMove (item->getCommandName (), true))
1014 			return kMessageNotified;
1015 	}
1016 	else if (cmdCategory == "SelectionSizeByGrid")
1017 	{
1018 		if (doSelectionSize (item->getCommandName (), true))
1019 			return kMessageNotified;
1020 	}
1021 	else if (cmdCategory == "SelectionMoveByPixel")
1022 	{
1023 		if (doSelectionMove (item->getCommandName (), false))
1024 			return kMessageNotified;
1025 	}
1026 	else if (cmdCategory == "SelectionSizeByPixel")
1027 	{
1028 		if (doSelectionSize (item->getCommandName (), false))
1029 			return kMessageNotified;
1030 	}
1031 	else if (cmdCategory == "SelectionZOrder")
1032 	{
1033 		bool lower = cmdName == "Lower" ? true : false;
1034 		if (doZOrderAction (lower))
1035 			return kMessageNotified;
1036 
1037 	}
1038 	else if (cmdCategory == "Selection")
1039 	{
1040 		if (cmdName == "Select All Children")
1041 		{
1042 			doSelectAllChildren ();
1043 			return kMessageNotified;
1044 		}
1045 		if (cmdName == "Select Parent(s)")
1046 		{
1047 			doSelectParents ();
1048 			return kMessageNotified;
1049 		}
1050 		if (cmdName == "Select View in Hierarchy Browser")
1051 		{
1052 			doSelectViewInHierarchyBrowser (selection->first ());
1053 			return kMessageNotified;
1054 		}
1055 	}
1056 	else if (cmdCategory == "Zoom")
1057 	{
1058 		if (cmdName == "Zoom In")
1059 		{
1060 			zoomSettingController->increaseZoom ();
1061 			return kMessageNotified;
1062 		}
1063 		else if (cmdName == "Zoom Out")
1064 		{
1065 			zoomSettingController->decreaseZoom ();
1066 			return kMessageNotified;
1067 		}
1068 		else if (cmdName == "Zoom 100%")
1069 		{
1070 			zoomSettingController->resetZoom ();
1071 			return kMessageNotified;
1072 		}
1073 	}
1074 	return kMessageUnknown;
1075 }
1076 
1077 //----------------------------------------------------------------------------------------------------
validateMenuItem(CCommandMenuItem * item)1078 CMessageResult UIEditController::validateMenuItem (CCommandMenuItem* item)
1079 {
1080 	UTF8StringView cmdCategory (item->getCommandCategory ());
1081 	UTF8StringView cmdName (item->getCommandName ());
1082 
1083 	if (cmdCategory == "Edit")
1084 	{
1085 		if (cmdName == "Template Settings...")
1086 		{
1087 			item->setEnabled (editTemplateName.empty () ? false : true);
1088 			return kMessageNotified;
1089 		}
1090 		else if (cmdName == "Copy" || cmdName == "Cut")
1091 		{
1092 			if (editView && selection->first () && selection->contains (editView->getEditView ()) == false)
1093 				item->setEnabled (true);
1094 			else
1095 				item->setEnabled (false);
1096 			return kMessageNotified;
1097 		}
1098 		else if (cmdName == "Paste")
1099 		{
1100 			item->setEnabled (false);
1101 			if (editView && selection->first ())
1102 			{
1103 				if (auto clipboard = editView->getFrame ()->getClipboard ())
1104 				{
1105 					if (clipboard->getDataType (0) == IDataPackage::kText)
1106 						item->setEnabled (true);
1107 				}
1108 			}
1109 			return kMessageNotified;
1110 		}
1111 	}
1112 	else if (cmdCategory == "File")
1113 	{
1114 		if (cmdName == "Encode Bitmaps in XML")
1115 		{
1116 			auto attr = getSettings ();
1117 			bool encodeBitmaps = false;
1118 			if (attr && attr->getBooleanAttribute (kEncodeBitmapsSettingsKey, encodeBitmaps))
1119 			{
1120 				item->setChecked (encodeBitmaps);
1121 			}
1122 			return kMessageNotified;
1123 		}
1124 		else if (cmdName == "Write Windows RC File on Save")
1125 		{
1126 			auto attr = getSettings ();
1127 			bool encodeBitmaps = false;
1128 			if (attr && attr->getBooleanAttribute (kWriteWindowsRCFileSettingsKey, encodeBitmaps))
1129 			{
1130 				item->setChecked (encodeBitmaps);
1131 			}
1132 			return kMessageNotified;
1133 		}
1134 	}
1135 	else if (cmdCategory == "SelectionMoveByGrid"
1136 			 || cmdCategory == "SelectionSizeByGrid"
1137 			 || cmdCategory == "SelectionMoveByPixel"
1138 			 || cmdCategory == "SelectionSizeByPixel"
1139 		)
1140 	{
1141 		bool enableItem = selection->first () ? true : false;
1142 		if (enableItem && cmdCategory.contains ("Size") == false)
1143 		{
1144 			if (selection->contains (editView->getEditView ()))
1145 				enableItem = false;
1146 		}
1147 		item->setEnabled (enableItem);
1148 		return kMessageNotified;
1149 	}
1150 	else if (cmdCategory == "SelectionZOrder")
1151 	{
1152 		bool enableItem = selection->total () == 1;
1153 		if (enableItem)
1154 		{
1155 			bool lower = cmdName == "Lower" ? true : false;
1156 			CView* view = selection->first ();
1157 			if (auto parent = view->getParentView ()->asViewContainer ())
1158 			{
1159 				if (lower)
1160 				{
1161 					ViewIterator it (parent);
1162 					if (*it == view)
1163 						enableItem = false;
1164 				}
1165 				else
1166 				{
1167 					ReverseViewIterator it (parent);
1168 					if (*it == view)
1169 						enableItem = false;
1170 				}
1171 			}
1172 		}
1173 		item->setEnabled (enableItem);
1174 		return kMessageNotified;
1175 	}
1176 	else if (cmdCategory == "Selection")
1177 	{
1178 		if (cmdName == "Select All Children")
1179 		{
1180 			bool enable = selection->total () == 1 && selection->first () &&
1181 			              selection->first ()->asViewContainer ();
1182 			item->setEnabled (enable);
1183 			return kMessageNotified;
1184 		}
1185 		if (cmdName == "Select Parent(s)")
1186 		{
1187 			bool enable =
1188 			    selection->total () > 0 && selection->first () != editView->getEditView ();
1189 			item->setEnabled (enable);
1190 			item->setTitle (selection->total () > 1 ? "Select Parents" : "Select Parent");
1191 			return kMessageNotified;
1192 		}
1193 		if (cmdName == "Select View in Hierarchy Browser")
1194 		{
1195 			item->setEnabled (selection->total () == 1);
1196 			return kMessageNotified;
1197 		}
1198 	}
1199 	return kMessageUnknown;
1200 }
1201 
1202 //----------------------------------------------------------------------------------------------------
doSelectionMove(const UTF8String & commandName,bool useGrid) const1203 bool UIEditController::doSelectionMove (const UTF8String& commandName, bool useGrid) const
1204 {
1205 	CPoint diff;
1206 	if (commandName == "Move Up")
1207 		diff.y = -(useGrid ? gridController->getSize ().y : 1);
1208 	else if (commandName == "Move Down")
1209 		diff.y = (useGrid ? gridController->getSize ().y : 1);
1210 	else if (commandName == "Move Left")
1211 		diff.x = -(useGrid ? gridController->getSize ().x : 1);
1212 	else if (commandName == "Move Right")
1213 		diff.x = (useGrid ? gridController->getSize ().x : 1);
1214 	if (diff.x != 0 || diff.y != 0)
1215 	{
1216 		editView->doKeyMove (diff);
1217 		return true;
1218 	}
1219 	return false;
1220 }
1221 
1222 //----------------------------------------------------------------------------------------------------
doSelectionSize(const UTF8String & commandName,bool useGrid) const1223 bool UIEditController::doSelectionSize (const UTF8String& commandName, bool useGrid) const
1224 {
1225 	CPoint diff;
1226 	if (commandName == "Increase Size Width")
1227 		diff.x = (useGrid ? gridController->getSize ().x : 1);
1228 	else if (commandName == "Increase Size Height")
1229 		diff.y = (useGrid ? gridController->getSize ().y : 1);
1230 	else if (commandName == "Decrease Size Width")
1231 		diff.x = -(useGrid ? gridController->getSize ().x : 1);
1232 	else if (commandName == "Decrease Size Height")
1233 		diff.y = -(useGrid ? gridController->getSize ().y : 1);
1234 	if (diff.x != 0 || diff.y != 0)
1235 	{
1236 		editView->doKeySize (diff);
1237 		return true;
1238 	}
1239 	return false;
1240 }
1241 
1242 //----------------------------------------------------------------------------------------------------
doZOrderAction(bool lower)1243 bool UIEditController::doZOrderAction (bool lower)
1244 {
1245 	if (selection->total () == 1)
1246 	{
1247 		CView* view = selection->first ();
1248 		undoManager->pushAndPerform (
1249 		    new HierarchyMoveViewOperation (view, selection, lower ? -1 : 1));
1250 		return true;
1251 	}
1252 	return false;
1253 }
1254 
1255 //----------------------------------------------------------------------------------------------------
doSelectAllChildren()1256 void UIEditController::doSelectAllChildren ()
1257 {
1258 	UISelection::DeferChange dc (*selection);
1259 	CViewContainer* container = selection->first ()->asViewContainer ();
1260 	selection->clear ();
1261 	auto factory = static_cast<const UIViewFactory*> (editDescription->getViewFactory ());
1262 	container->forEachChild ([&] (CView* view) {
1263 		if (factory->getViewName (view))
1264 			selection->add (view);
1265 	});
1266 }
1267 
1268 //----------------------------------------------------------------------------------------------------
doSelectParents()1269 void UIEditController::doSelectParents ()
1270 {
1271 	UISelection::DeferChange dc (*selection);
1272 	std::vector<CView*> parents;
1273 	auto factory = static_cast<const UIViewFactory*> (editDescription->getViewFactory ());
1274 	for (auto& view : *selection)
1275 	{
1276 		if (auto parent = view->getParentView ())
1277 		{
1278 			while (factory->getViewName (parent) == nullptr)
1279 			{
1280 				parent = parent->getParentView ();
1281 			}
1282 			if (parent && std::find (parents.begin (), parents.end (), parent) == parents.end ())
1283 				parents.emplace_back (parent);
1284 		}
1285 	}
1286 	selection->clear ();
1287 	for (auto& parent : parents)
1288 		selection->add (parent);
1289 }
1290 
1291 //----------------------------------------------------------------------------------------------------
doSelectViewInHierarchyBrowser(CView * view)1292 void UIEditController::doSelectViewInHierarchyBrowser (CView* view)
1293 {
1294 	templateController->navigateTo (view);
1295 }
1296 
1297 //----------------------------------------------------------------------------------------------------
onUndoManagerChanged()1298 void UIEditController::onUndoManagerChanged ()
1299 {
1300 	if (undoManager->isSavePosition ())
1301 	{
1302 		updateTemplate (editTemplateName.data ());
1303 		setDirty (false);
1304 	}
1305 	else
1306 		setDirty (true);
1307 	CView* view = selection->first ();
1308 	if (view)
1309 	{
1310 		if (auto templateView = editView->getEditView () ? editView->getEditView ()->asViewContainer () : nullptr)
1311 		{
1312 			if (view == templateView || templateView->isChild (view, true))
1313 			{
1314 				return;
1315 			}
1316 		}
1317 		for (auto& it : templates)
1318 		{
1319 			CViewContainer* container = it.view->asViewContainer ();
1320 			if (container && (view == container || container->isChild (view, true)))
1321 			{
1322 				templateController->selectTemplate (it.name.c_str ());
1323 				return;
1324 			}
1325 		}
1326 		selection->clear ();
1327 	}
1328 }
1329 
1330 //----------------------------------------------------------------------------------------------------
resetScrollViewOffsets(CViewContainer * view)1331 void UIEditController::resetScrollViewOffsets (CViewContainer* view)
1332 {
1333 	view->forEachChild ([&] (CView* view) {
1334 		auto* scrollView = dynamic_cast<CScrollView*>(view);
1335 		if (scrollView)
1336 		{
1337 			scrollView->resetScrollOffset ();
1338 		}
1339 		if (auto container = view->asViewContainer ())
1340 			resetScrollViewOffsets (container);
1341 	});
1342 }
1343 
1344 //----------------------------------------------------------------------------------------------------
onKeyDown(const VstKeyCode & code,CFrame * frame)1345 int32_t UIEditController::onKeyDown (const VstKeyCode& code, CFrame* frame)
1346 {
1347 	if (frame->getModalView () == nullptr)
1348 	{
1349 		if (frame->getFocusView ())
1350 		{
1351 			auto* edit = dynamic_cast<CTextEdit*>(frame->getFocusView ());
1352 			if (edit && edit->getPlatformTextEdit ())
1353 				return -1;
1354 		}
1355 		return menuController->processKeyCommand (code);
1356 	}
1357 	return -1;
1358 }
1359 
1360 //----------------------------------------------------------------------------------------------------
onKeyUp(const VstKeyCode & code,CFrame * frame)1361 int32_t UIEditController::onKeyUp (const VstKeyCode& code, CFrame* frame)
1362 {
1363 	return -1;
1364 }
1365 
1366 //----------------------------------------------------------------------------------------------------
getSettings()1367 SharedPointer<UIAttributes> UIEditController::getSettings ()
1368 {
1369 	return editDescription->getCustomAttributes ("UIEditController", true);
1370 }
1371 
1372 //----------------------------------------------------------------------------------------------------
getSaveOptions()1373 int32_t UIEditController::getSaveOptions ()
1374 {
1375 	int32_t flags = 0;
1376 	auto attributes = getSettings ();
1377 	bool val;
1378 	if (attributes->getBooleanAttribute (UIEditController::kEncodeBitmapsSettingsKey, val) && val == true)
1379 	{
1380 		flags |= UIDescription::kWriteImagesIntoXMLFile;
1381 	}
1382 	if (attributes->getBooleanAttribute (UIEditController::kWriteWindowsRCFileSettingsKey, val) && val == true)
1383 	{
1384 		flags |= UIDescription::kWriteWindowsResourceFile;
1385 	}
1386 	return flags;
1387 }
1388 
1389 //----------------------------------------------------------------------------------------------------
getSplitViewIndex(CSplitView * splitView)1390 int32_t UIEditController::getSplitViewIndex (CSplitView* splitView)
1391 {
1392 	int32_t index = 0;
1393 	for (auto& sv : splitViews)
1394 	{
1395 		if (sv == splitView)
1396 			return index;
1397 		index++;
1398 	}
1399 	return -1;
1400 }
1401 
1402 //----------------------------------------------------------------------------------------------------
getSplitViewSizeConstraint(int32_t index,CCoord & minSize,CCoord & maxSize,CSplitView * splitView)1403 bool UIEditController::getSplitViewSizeConstraint (int32_t index, CCoord& minSize, CCoord& maxSize, CSplitView* splitView)
1404 {
1405 	return false;
1406 }
1407 
1408 //----------------------------------------------------------------------------------------------------
getSplitViewSeparatorDrawer(CSplitView * splitView)1409 ISplitViewSeparatorDrawer* UIEditController::getSplitViewSeparatorDrawer (CSplitView* splitView)
1410 {
1411 	int32_t si = getSplitViewIndex (splitView);
1412 	if (si >= 0)
1413 	{
1414 		return this;
1415 	}
1416 	return nullptr;
1417 }
1418 
1419 //----------------------------------------------------------------------------------------------------
storeViewSize(int32_t index,const CCoord & size,CSplitView * splitView)1420 bool UIEditController::storeViewSize (int32_t index, const CCoord& size, CSplitView* splitView)
1421 {
1422 	int32_t si = getSplitViewIndex (splitView);
1423 	if (si >= 0)
1424 	{
1425 		std::stringstream str;
1426 		str << "SplitViewSize_";
1427 		str << si;
1428 		str << "_";
1429 		str << index;
1430 		double value;
1431 		if (splitView->getStyle () == CSplitView::kHorizontal)
1432 			value = size / splitView->getWidth ();
1433 		else
1434 			value = size / splitView->getHeight ();
1435 		getSettings ()->setDoubleAttribute (str.str (), value);
1436 		return true;
1437 	}
1438 	return false;
1439 }
1440 
1441 //----------------------------------------------------------------------------------------------------
restoreViewSize(int32_t index,CCoord & size,CSplitView * splitView)1442 bool UIEditController::restoreViewSize (int32_t index, CCoord& size, CSplitView* splitView)
1443 {
1444 	int32_t version = 0;
1445 	getSettings ()->getIntegerAttribute ("Version", version);
1446 	if (version == 0)
1447 		return false;
1448 	int32_t si = getSplitViewIndex (splitView);
1449 	if (si >= 0)
1450 	{
1451 		std::stringstream str;
1452 		str << "SplitViewSize_";
1453 		str << si;
1454 		str << "_";
1455 		str << index;
1456 		double value;
1457 		if (getSettings ()->getDoubleAttribute (str.str ().c_str (), value))
1458 		{
1459 			if (splitView->getStyle () == CSplitView::kHorizontal)
1460 				value = floor (splitView->getWidth () * value + 0.5);
1461 			else
1462 				value = floor (splitView->getHeight () * value + 0.5);
1463 			size = value;
1464 			return true;
1465 		}
1466 	}
1467 	return false;
1468 }
1469 
1470 //----------------------------------------------------------------------------------------------------
drawSplitViewSeparator(CDrawContext * context,const CRect & size,int32_t flags,int32_t index,CSplitView * splitView)1471 void UIEditController::drawSplitViewSeparator (CDrawContext* context, const CRect& size, int32_t flags, int32_t index, CSplitView* splitView)
1472 {
1473 	if (splitView->getStyle () == CSplitView::kHorizontal)
1474 	{
1475 		UIEditControllerShadingView::drawGradient (context, size, true);
1476 	}
1477 	else
1478 	{
1479 		UIEditControllerShadingView::drawGradient (context, size, false);
1480 	}
1481 }
1482 
1483 //----------------------------------------------------------------------------------------------------
setDirty(bool state)1484 void UIEditController::setDirty (bool state)
1485 {
1486 	if (dirty != state)
1487 	{
1488 		dirty = state;
1489 		if (notSavedControl && notSavedControl->isAttached ())
1490 		{
1491 			notSavedControl->invalid ();
1492 			notSavedControl->addAnimation ("AlphaValueAnimation", new Animation::AlphaValueAnimation (dirty ? 1.f : 0.f), new Animation::LinearTimingFunction (80));
1493 		}
1494 	}
1495 }
1496 
1497 //----------------------------------------------------------------------------------------------------
performAction(IAction * action)1498 void UIEditController::performAction (IAction* action)
1499 {
1500 	undoManager->pushAndPerform (action);
1501 }
1502 
1503 //----------------------------------------------------------------------------------------------------
beginGroupAction(UTF8StringPtr name)1504 void UIEditController::beginGroupAction (UTF8StringPtr name)
1505 {
1506 	undoManager->startGroupAction (name);
1507 }
1508 
1509 //----------------------------------------------------------------------------------------------------
finishGroupAction()1510 void UIEditController::finishGroupAction ()
1511 {
1512 	undoManager->endGroupAction ();
1513 }
1514 
1515 //----------------------------------------------------------------------------------------------------
performChangeFocusDrawingSettings(const FocusDrawingSettings & newSettings)1516 void UIEditController::performChangeFocusDrawingSettings (const FocusDrawingSettings& newSettings)
1517 {
1518 	undoManager->pushAndPerform (new ChangeFocusDrawingAction (editDescription, newSettings));
1519 }
1520 
1521 //----------------------------------------------------------------------------------------------------
getTemplateViews(std::list<CView * > & views) const1522 void UIEditController::getTemplateViews (std::list<CView*>& views) const
1523 {
1524 	for (const auto& templateDesc : templates)
1525 		views.emplace_back (templateDesc.view);
1526 }
1527 
1528 //----------------------------------------------------------------------------------------------------
performColorChange(UTF8StringPtr colorName,const CColor & newColor,bool remove)1529 void UIEditController::performColorChange (UTF8StringPtr colorName, const CColor& newColor, bool remove)
1530 {
1531 	std::list<CView*> views;
1532 	getTemplateViews (views);
1533 
1534 	auto* action = new ColorChangeAction (editDescription, colorName, newColor, remove, true);
1535 	undoManager->startGroupAction (remove ? "Delete Color" : action->isAddColor () ? "Add New Color" : "Change Color");
1536 	undoManager->pushAndPerform (action);
1537 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kColorType, colorName, remove ? "" : colorName));
1538 	undoManager->pushAndPerform (new ColorChangeAction (editDescription, colorName, newColor, remove, false));
1539 	undoManager->endGroupAction ();
1540 }
1541 
1542 //----------------------------------------------------------------------------------------------------
performTagChange(UTF8StringPtr tagName,UTF8StringPtr tagStr,bool remove)1543 void UIEditController::performTagChange (UTF8StringPtr tagName, UTF8StringPtr tagStr, bool remove)
1544 {
1545 	std::list<CView*> views;
1546 	getTemplateViews (views);
1547 
1548 	auto* action = new TagChangeAction (editDescription, tagName, tagStr, remove, true);
1549 	undoManager->startGroupAction (remove ? "Delete Tag" : action->isAddTag () ? "Add New Tag" : "Change Tag");
1550 	undoManager->pushAndPerform (action);
1551 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kTagType, tagName, remove ? "" : tagName));
1552 	undoManager->pushAndPerform (new TagChangeAction (editDescription, tagName, tagStr, remove, false));
1553 	undoManager->endGroupAction ();
1554 }
1555 
1556 //----------------------------------------------------------------------------------------------------
performBitmapChange(UTF8StringPtr bitmapName,UTF8StringPtr bitmapPath,bool remove)1557 void UIEditController::performBitmapChange (UTF8StringPtr bitmapName, UTF8StringPtr bitmapPath, bool remove)
1558 {
1559 	std::list<CView*> views;
1560 	getTemplateViews (views);
1561 
1562 	auto* action = new BitmapChangeAction (editDescription, bitmapName, bitmapPath, remove, true);
1563 	undoManager->startGroupAction (remove ? "Delete Bitmap" : action->isAddBitmap () ? "Add New Bitmap" :"Change Bitmap");
1564 	undoManager->pushAndPerform (action);
1565 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, remove ? "" : bitmapName));
1566 	undoManager->pushAndPerform (new BitmapChangeAction (editDescription, bitmapName, bitmapPath, remove, false));
1567 	undoManager->endGroupAction ();
1568 }
1569 
1570 //------------------------------------------------------------------------
performGradientChange(UTF8StringPtr gradientName,CGradient * newGradient,bool remove)1571 void UIEditController::performGradientChange (UTF8StringPtr gradientName, CGradient* newGradient, bool remove)
1572 {
1573 	std::list<CView*> views;
1574 	getTemplateViews (views);
1575 
1576 	auto* action = new GradientChangeAction (editDescription, gradientName, newGradient, remove, true);
1577 	undoManager->startGroupAction (remove ? "Delete Bitmap" : action->isAddGradient () ? "Add New Gradient" :"Change Gradient");
1578 	undoManager->pushAndPerform (action);
1579 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kGradientType, gradientName, remove ? "" : gradientName));
1580 	undoManager->pushAndPerform (new GradientChangeAction (editDescription, gradientName, newGradient, remove, false));
1581 	undoManager->endGroupAction ();
1582 }
1583 
1584 //----------------------------------------------------------------------------------------------------
performFontChange(UTF8StringPtr fontName,CFontRef newFont,bool remove)1585 void UIEditController::performFontChange (UTF8StringPtr fontName, CFontRef newFont, bool remove)
1586 {
1587 	std::list<CView*> views;
1588 	getTemplateViews (views);
1589 
1590 	auto* action = new FontChangeAction (editDescription, fontName, newFont, remove, true);
1591 	undoManager->startGroupAction (remove ? "Delete Font" : action->isAddFont () ? "Add New Font" : "Change Font");
1592 	undoManager->pushAndPerform (action);
1593 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kFontType, fontName, remove ? "" : fontName));
1594 	undoManager->pushAndPerform (new FontChangeAction (editDescription, fontName, newFont, remove, false));
1595 	undoManager->endGroupAction ();
1596 }
1597 
1598 //----------------------------------------------------------------------------------------------------
performNameChange(UTF8StringPtr oldName,UTF8StringPtr newName,IdStringPtr groupActionName)1599 template<typename NameChangeAction, IViewCreator::AttrType attrType> void UIEditController::performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName, IdStringPtr groupActionName)
1600 {
1601 	std::list<CView*> views;
1602 	getTemplateViews (views);
1603 
1604 	undoManager->startGroupAction (groupActionName);
1605 	undoManager->pushAndPerform (new NameChangeAction (editDescription, oldName, newName, true));
1606 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, attrType, oldName, newName));
1607 	undoManager->pushAndPerform (new NameChangeAction (editDescription, oldName, newName, false));
1608 	undoManager->endGroupAction ();
1609 }
1610 
1611 //----------------------------------------------------------------------------------------------------
performColorNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1612 void UIEditController::performColorNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1613 {
1614 	performNameChange<ColorNameChangeAction, IViewCreator::kColorType> (oldName, newName, "Change Color Name");
1615 }
1616 
1617 //----------------------------------------------------------------------------------------------------
performTagNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1618 void UIEditController::performTagNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1619 {
1620 	performNameChange<TagNameChangeAction, IViewCreator::kTagType> (oldName, newName, "Change Tag Name");
1621 }
1622 
1623 //----------------------------------------------------------------------------------------------------
performFontNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1624 void UIEditController::performFontNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1625 {
1626 	performNameChange<FontNameChangeAction, IViewCreator::kFontType> (oldName, newName, "Change Font Name");
1627 }
1628 
1629 //----------------------------------------------------------------------------------------------------
performGradientNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1630 void UIEditController::performGradientNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1631 {
1632 	performNameChange<GradientNameChangeAction, IViewCreator::kGradientType> (oldName, newName, "Change Gradient Name");
1633 }
1634 
1635 //----------------------------------------------------------------------------------------------------
performBitmapNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1636 void UIEditController::performBitmapNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1637 {
1638 	performNameChange<BitmapNameChangeAction, IViewCreator::kBitmapType> (oldName, newName, "Change Bitmap Name");
1639 }
1640 
1641 //----------------------------------------------------------------------------------------------------
performBitmapNinePartTiledChange(UTF8StringPtr bitmapName,const CRect * offsets)1642 void UIEditController::performBitmapNinePartTiledChange (UTF8StringPtr bitmapName, const CRect* offsets)
1643 {
1644 	std::list<CView*> views;
1645 	getTemplateViews (views);
1646 
1647 	undoManager->startGroupAction ("Change NinePartTiled Bitmap");
1648 	undoManager->pushAndPerform (new NinePartTiledBitmapChangeAction (editDescription, bitmapName, offsets, true));
1649 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, bitmapName));
1650 	undoManager->pushAndPerform (new NinePartTiledBitmapChangeAction (editDescription, bitmapName, offsets, false));
1651 	undoManager->endGroupAction ();
1652 }
1653 
1654 //----------------------------------------------------------------------------------------------------
performBitmapFiltersChange(UTF8StringPtr bitmapName,const std::list<SharedPointer<UIAttributes>> & filterDescription)1655 void UIEditController::performBitmapFiltersChange (UTF8StringPtr bitmapName, const std::list<SharedPointer<UIAttributes> >& filterDescription)
1656 {
1657 	std::list<CView*> views;
1658 	getTemplateViews (views);
1659 
1660 	undoManager->startGroupAction ("Change Bitmap Filter");
1661 	undoManager->pushAndPerform (new BitmapFilterChangeAction (editDescription, bitmapName, filterDescription, true));
1662 	undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, bitmapName));
1663 	undoManager->pushAndPerform (new BitmapFilterChangeAction (editDescription, bitmapName, filterDescription, false));
1664 	undoManager->endGroupAction ();
1665 }
1666 
1667 
1668 //----------------------------------------------------------------------------------------------------
performAlternativeFontChange(UTF8StringPtr fontName,UTF8StringPtr newAlternativeFonts)1669 void UIEditController::performAlternativeFontChange (UTF8StringPtr fontName, UTF8StringPtr newAlternativeFonts)
1670 {
1671 	undoManager->pushAndPerform (new AlternateFontChangeAction (editDescription, fontName, newAlternativeFonts));
1672 }
1673 
1674 //----------------------------------------------------------------------------------------------------
beginLiveColorChange(UTF8StringPtr colorName)1675 void UIEditController::beginLiveColorChange (UTF8StringPtr colorName)
1676 {
1677 	undoManager->startGroupAction ("Change Color");
1678 	CColor color;
1679 	editDescription->getColor(colorName, color);
1680 	performColorChange (colorName, color, false);
1681 }
1682 
1683 //----------------------------------------------------------------------------------------------------
performLiveColorChange(UTF8StringPtr _colorName,const CColor & newColor)1684 void UIEditController::performLiveColorChange (UTF8StringPtr _colorName, const CColor& newColor)
1685 {
1686 	std::string colorName (_colorName);
1687 
1688 	IAction* action =
1689 	    new ColorChangeAction (editDescription, colorName.data (), newColor, false, true);
1690 	action->perform ();
1691 	delete action;
1692 
1693 	std::list<CView*> views;
1694 	getTemplateViews (views);
1695 
1696 	action = new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kColorType,
1697 	                                            colorName.data (), colorName.data ());
1698 	action->perform ();
1699 	delete action;
1700 }
1701 
1702 //----------------------------------------------------------------------------------------------------
endLiveColorChange(UTF8StringPtr colorName)1703 void UIEditController::endLiveColorChange (UTF8StringPtr colorName)
1704 {
1705 	UIDescriptionListenerOff lo (this, editDescription);
1706 	CColor color;
1707 	editDescription->getColor (colorName, color);
1708 	performColorChange (colorName, color, false);
1709 	undoManager->endGroupAction ();
1710 }
1711 
1712 //----------------------------------------------------------------------------------------------------
performTemplateNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1713 void UIEditController::performTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1714 {
1715 	undoManager->pushAndPerform (new TemplateNameChangeAction (editDescription, this, oldName, newName));
1716 }
1717 
1718 //----------------------------------------------------------------------------------------------------
performTemplateMinMaxSizeChange(UTF8StringPtr templateName,CPoint minSize,CPoint maxSize)1719 void UIEditController::performTemplateMinMaxSizeChange (UTF8StringPtr templateName, CPoint minSize, CPoint maxSize)
1720 {
1721 	undoManager->pushAndPerform (
1722 	    new ChangeTemplateMinMaxAction (editDescription, templateName, minSize, maxSize));
1723 }
1724 
1725 //----------------------------------------------------------------------------------------------------
performCreateNewTemplate(UTF8StringPtr name,UTF8StringPtr baseViewClassName)1726 void UIEditController::performCreateNewTemplate (UTF8StringPtr name, UTF8StringPtr baseViewClassName)
1727 {
1728 	undoManager->pushAndPerform (new CreateNewTemplateAction (editDescription, this, name, baseViewClassName));
1729 }
1730 
1731 //----------------------------------------------------------------------------------------------------
performDeleteTemplate(UTF8StringPtr name)1732 void UIEditController::performDeleteTemplate (UTF8StringPtr name)
1733 {
1734 	auto it = std::find (templates.begin (), templates.end (), name);
1735 	if (it != templates.end ())
1736 		undoManager->pushAndPerform (new DeleteTemplateAction (editDescription, this, (*it).view, (*it).name.c_str ()));
1737 }
1738 
1739 //----------------------------------------------------------------------------------------------------
performDuplicateTemplate(UTF8StringPtr name,UTF8StringPtr dupName)1740 void UIEditController::performDuplicateTemplate (UTF8StringPtr name, UTF8StringPtr dupName)
1741 {
1742 	updateTemplate (name);
1743 	UIDescriptionListenerOff lo (this, editDescription);
1744 	undoManager->pushAndPerform (new DuplicateTemplateAction (editDescription, this, name, dupName));
1745 }
1746 
1747 //----------------------------------------------------------------------------------------------------
onTemplateCreation(UTF8StringPtr name,CView * view)1748 void UIEditController::onTemplateCreation (UTF8StringPtr name, CView* view)
1749 {
1750 	auto it = std::find (templates.begin (), templates.end (), name);
1751 	if (it == templates.end ())
1752 		templates.emplace_back (name, view);
1753 	templateController->selectTemplate (name);
1754 }
1755 
1756 //----------------------------------------------------------------------------------------------------
onTemplateNameChange(UTF8StringPtr oldName,UTF8StringPtr newName)1757 void UIEditController::onTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
1758 {
1759 	auto it = std::find (templates.begin (), templates.end (), oldName);
1760 	if (it != templates.end ())
1761 	{
1762 		(*it).name = newName;
1763 	}
1764 }
1765 
1766 //----------------------------------------------------------------------------------------------------
updateTemplate(const std::vector<Template>::const_iterator & it)1767 void UIEditController::updateTemplate (const std::vector<Template>::const_iterator& it)
1768 {
1769 	if (it != templates.end ())
1770 	{
1771 		CView* view = (*it).view;
1772 		if (auto container = view->asViewContainer ())
1773 			resetScrollViewOffsets (container);
1774 		editDescription->updateViewDescription ((*it).name.c_str (), view);
1775 	}
1776 }
1777 
1778 //----------------------------------------------------------------------------------------------------
updateTemplate(UTF8StringPtr name)1779 void UIEditController::updateTemplate (UTF8StringPtr name)
1780 {
1781 	auto it = std::find (templates.begin (), templates.end (), name);
1782 	updateTemplate (it);
1783 }
1784 
1785 //----------------------------------------------------------------------------------------------------
onTemplatesChanged()1786 void UIEditController::onTemplatesChanged ()
1787 {
1788 	std::list<const std::string*> templateNames;
1789 	editDescription->collectTemplateViewNames (templateNames);
1790 	for (auto& it : templateNames)
1791 	{
1792 		if (std::find (templates.begin (), templates.end (), *it) == templates.end ())
1793 		{
1794 			auto view = owned (editDescription->createView (it->c_str (), editDescription->getController ()));
1795 			templates.emplace_back (*it, view);
1796 		}
1797 	}
1798 	for (std::vector<Template>::iterator it = templates.begin (); it != templates.end ();)
1799 	{
1800 		Template& t = (*it);
1801 		bool found = false;
1802 		for (auto& it2 : templateNames)
1803 		{
1804 			if (t.name == *it2)
1805 			{
1806 				found = true;
1807 				it++;
1808 				break;
1809 			}
1810 		}
1811 		if (!found)
1812 		{
1813 			it = templates.erase (it);
1814 		}
1815 	}
1816 }
1817 
1818 //----------------------------------------------------------------------------------------------------
appendContextMenuItems(COptionMenu & contextMenu,CView * view,const CPoint & where)1819 void UIEditController::appendContextMenuItems (COptionMenu& contextMenu, CView* view, const CPoint& where)
1820 {
1821 	auto vc = view->asViewContainer ();
1822 	if (!vc || editView == nullptr)
1823 		return;
1824 	view = vc->getViewAt (where, GetViewOptions ().deep ().includeViewContainer ());
1825 	while (view && view != editView)
1826 	{
1827 		view = view->getParentView ();
1828 	}
1829 	if (view != editView)
1830 		return;
1831 	auto editMenu = getMenuController ()->getEditMenu ();
1832 	for (auto& entry : *editMenu->getItems ())
1833 	{
1834 		if (auto item = entry.cast<CCommandMenuItem> ())
1835 		{
1836 			item->validate ();
1837 		}
1838 		if (!entry->isEnabled ())
1839 			continue;
1840 		entry->remember ();
1841 		contextMenu.addEntry (entry);
1842 	}
1843 }
1844 
1845 } // VSTGUI
1846 
1847 #endif // VSTGUI_LIVE_EDITING
1848