// This file is part of VSTGUI. It is subject to the license terms // in the LICENSE file found in the top-level directory of this // distribution and at http://github.com/steinbergmedia/vstgui/LICENSE #include "uieditcontroller.h" #if VSTGUI_LIVE_EDITING #include "uieditview.h" #include "uiattributescontroller.h" #include "uibitmapscontroller.h" #include "uicolorscontroller.h" #include "uigradientscontroller.h" #include "uieditmenucontroller.h" #include "uifontscontroller.h" #include "uigridcontroller.h" #include "uitagscontroller.h" #include "uitemplatecontroller.h" #include "uiviewcreatecontroller.h" #include "uiundomanager.h" #include "uiactions.h" #include "uiselection.h" #include "uidialogcontroller.h" #include "uitemplatesettingscontroller.h" #include "uifocussettingscontroller.h" #include "../cstream.h" #include "../uiattributes.h" #include "../uicontentprovider.h" #include "../uidescriptionaddonregistry.h" #include "../xmlparser.h" #include "../../lib/controls/coptionmenu.h" #include "../../lib/controls/csegmentbutton.h" #include "../../lib/controls/csearchtextedit.h" #include "../../lib/animation/animations.h" #include "../../lib/animation/timingfunctions.h" #include "../../lib/cdropsource.h" #include "../../lib/cgraphicspath.h" #include "../../lib/coffscreencontext.h" #include "../../lib/iviewlistener.h" #include "../../lib/cvstguitimer.h" #include "../../lib/events.h" #include #include #include #include #if WINDOWS #define snprintf _snprintf #endif namespace VSTGUI { #ifdef HAVE_EDITORUIDESC_H #include "editoruidesc.h" #endif //---------------------------------------------------------------------------------------------------- struct UIEditControllerGlobalResources { CColor dataSourceSelectionColor; CColor dataSourceFontColor; CColor dataSourceRowlineColor; CColor dataSourceRowBackColor; CColor dataSourceRowAlternateBackColor; CColor shadingLineColor; CFontRef dataSourceFont; void init (const IUIDescription& desc) { desc.getColor ("db.selection", dataSourceSelectionColor); desc.getColor ("db.font", dataSourceFontColor); desc.getColor ("db.row.line", dataSourceRowlineColor); desc.getColor ("db.row.back", dataSourceRowBackColor); desc.getColor ("db.row.alternate.back", dataSourceRowAlternateBackColor); desc.getColor ("shading.light.frame", shadingLineColor); dataSourceFont = desc.getFont ("db.font"); } }; static UIEditControllerGlobalResources gUIEditorControllerResources; //---------------------------------------------------------------------------------------------------- class UIEditControllerDescription { public: SharedPointer get () const { if (uiDesc == nullptr) { #ifdef HAVE_EDITORUIDESC_H MemoryContentProvider provider (editorUIDesc, strlen (editorUIDesc)); SharedPointer editorDesc = owned (new UIDescription (&provider)); if (editorDesc->parse ()) { uiDesc = editorDesc; } MemoryContentProvider lightUIProvider (editorUILightDesc, strlen (editorUILightDesc)); SharedPointer lightUIDesc = owned (new UIDescription (&lightUIProvider)); if (lightUIDesc->parse ()) { lightResourceDesc = std::move (lightUIDesc); uiDesc->setSharedResources (lightResourceDesc); } MemoryContentProvider darkUIProvider (editorUIDarkDesc, strlen (editorUIDarkDesc)); SharedPointer darkUIDesc = owned (new UIDescription (&darkUIProvider)); if (darkUIDesc->parse ()) { darkResourceDesc = std::move (darkUIDesc); } #else std::string basePath (__FILE__); unixfyPath (basePath); if (removeLastPathComponent (basePath)) { auto descPath = basePath + "/uidescriptioneditor.uidesc"; auto editorDesc = makeOwned (descPath.data ()); if (editorDesc->parse ()) { uiDesc = std::move (editorDesc); } else { 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"); } descPath = basePath + "/uidescriptioneditor_res_light.uidesc"; auto resDesc = makeOwned (descPath.data ()); if (resDesc->parse ()) { lightResourceDesc = std::move (resDesc); uiDesc->setSharedResources (lightResourceDesc); } else { 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"); } descPath = basePath + "/uidescriptioneditor_res_dark.uidesc"; resDesc = makeOwned (descPath.data ()); if (resDesc->parse ()) { darkResourceDesc = std::move (resDesc); } } #endif gUIEditorControllerResources.init (*uiDesc.get ()); } return uiDesc; } void tryFree () { if (uiDesc->getNbReference () == 1) { uiDesc = nullptr; lightResourceDesc = nullptr; darkResourceDesc = nullptr; } } void setDarkTheme (bool state) { auto res = state ? darkResourceDesc : lightResourceDesc; if (res == nullptr || uiDesc == nullptr) return; uiDesc->setSharedResources (res); gUIEditorControllerResources.init (*uiDesc.get ()); } bool usesDarkTheme () const { return uiDesc ? (uiDesc->getSharedResources () == darkResourceDesc) : false; } private: mutable SharedPointer uiDesc; mutable SharedPointer lightResourceDesc; mutable SharedPointer darkResourceDesc; }; static UIEditControllerDescription gUIDescription; //---------------------------------------------------------------------------------------------------- SharedPointer UIEditController::getEditorDescription () { return gUIDescription.get (); } //---------------------------------------------------------------------------------------------------- void UIEditController::setupDataSource (GenericStringListDataBrowserSource* source) { source->setupUI (gUIEditorControllerResources.dataSourceSelectionColor, gUIEditorControllerResources.dataSourceFontColor, gUIEditorControllerResources.dataSourceRowlineColor, gUIEditorControllerResources.dataSourceRowBackColor, gUIEditorControllerResources.dataSourceRowAlternateBackColor, gUIEditorControllerResources.dataSourceFont); } //---------------------------------------------------------------------------------------------------- void UIEditController::setDarkTheme (bool state) { gUIDescription.setDarkTheme (state); getSettings ()->setAttribute ("UI Theme", usesDarkTheme () ? "Dark" : "Light"); } //---------------------------------------------------------------------------------------------------- bool UIEditController::usesDarkTheme () const { return gUIDescription.usesDarkTheme (); } //------------------------------------------------------------------------ void UIEditController::doChangeTheme (bool dark) { setDarkTheme (dark); if (baseView) { vstgui_assert (templateController); auto templateName = std::move (editTemplateName); templateController->selectTemplate (nullptr); auto viewSize = baseView->getViewSize (); auto parent = baseView->getParentView ()->asViewContainer (); vstgui_assert (parent); remember (); parent->removeView (baseView); editView = nullptr; auto view = createEditView (); view->setViewSize (viewSize); parent->addView (view); templateController->selectTemplate (templateName.data ()); } } //----------------------------------------------------------------------------- bool UIEditController::std__stringCompare (const std::string* lhs, const std::string* rhs) { for (std::string::const_iterator it = lhs->begin (), it2 = rhs->begin (); it != lhs->end () && it2 != rhs->end (); it++, it2++) { char c1 = static_cast (tolower (*it)); char c2 = static_cast (tolower (*it2)); if (c1 != c2) return c1 < c2; } return false; } const UTF8StringPtr UIEditController::kEncodeBitmapsSettingsKey = "EncodeBitmaps"; const UTF8StringPtr UIEditController::kWriteWindowsRCFileSettingsKey = "WriteRCFile"; //---------------------------------------------------------------------------------------------------- class UIEditControllerShadingView : public CView { public: UIEditControllerShadingView (bool horizontal, bool drawTopLine = false, bool drawBottomLine = true) : CView (CRect (0, 0, 0, 0)) , horizontal (horizontal) , drawTopLine (drawTopLine) , drawBottomLine (drawBottomLine) {} void draw (CDrawContext* context) override { drawGradient (context, getViewSize (), horizontal, drawTopLine, drawBottomLine); } static void drawGradient (CDrawContext* context, const CRect& _size, bool horizontal, bool drawTopLine = true, bool drawBottomLine = true) { SharedPointer path = owned (context->createGraphicsPath ()); if (path) { auto lineWidth = 1.; CRect size (_size); context->setDrawMode (kAliasing); context->setLineStyle (kLineSolid); context->setLineWidth (lineWidth); context->setFrameColor (gUIEditorControllerResources.shadingLineColor); CGradient* shading = UIEditController::getEditorDescription ()->getGradient ("shading.light"); if (shading) { path->addRect (size); if (horizontal) { context->fillLinearGradient (path, *shading, CPoint (size.left, size.top), CPoint (size.right, size.top)); if (drawBottomLine) context->drawLine (CPoint (size.left, size.top), CPoint (size.left, size.bottom)); if (drawTopLine) context->drawLine (CPoint (size.right-lineWidth, size.bottom), CPoint (size.right-lineWidth, size.top)); } else { context->fillLinearGradient (path, *shading, CPoint (size.left, size.top), CPoint (size.left, size.bottom)); if (drawTopLine) context->drawLine (CPoint (size.left, size.top), CPoint (size.right, size.top)); if (drawBottomLine) context->drawLine (CPoint (size.right, size.bottom-lineWidth), CPoint (size.left, size.bottom-lineWidth)); } } } } protected: bool horizontal; bool drawTopLine; bool drawBottomLine; }; //---------------------------------------------------------------------------------------------------- class UIZoomSettingController : public IController , public IContextMenuController2 , public ViewListenerAdapter , public ViewEventListenerAdapter , public NonAtomicReferenceCounted { public: UIZoomSettingController (UIEditController* editController) : editController (editController) {} ~UIZoomSettingController () noexcept override { if (zoomValueControl) viewWillDelete (zoomValueControl); } void restoreSetting (const UIAttributes& attributes) { double value; if (attributes.getDoubleAttribute ("EditViewScale", value)) { if (zoomValueControl) { zoomValueControl->setValue (static_cast (value) * 100.f); valueChanged (zoomValueControl); } } } void storeSetting (UIAttributes& attributes) const { if (zoomValueControl) attributes.setDoubleAttribute ("EditViewScale", zoomValueControl->getValue () / 100.f); } void increaseZoom () { if (!zoomValueControl) return; float add = 10.f; float current = zoomValueControl->getValue (); if (current >= 100.f) add = 50.f; updateZoom (current + add); } void decreaseZoom () { if (!zoomValueControl) return; float sub = 10.f; float current = zoomValueControl->getValue (); if (current >= 150.f) sub = 50.f; updateZoom (current - sub); } void resetZoom () { if (!zoomValueControl) return; updateZoom (100.f); } CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override { if (!zoomValueControl) { zoomValueControl = dynamic_cast (view); if (zoomValueControl) { zoomValueControl->setMin (50.f); zoomValueControl->setMax (1000.f); zoomValueControl->setStringToValueFunction ([] (UTF8StringPtr txt, float& result, CTextEdit*) { int32_t intValue = static_cast (strtol (txt, nullptr, 10)); if (intValue > 0) { result = static_cast (intValue); return true; } return false; }); zoomValueControl->setValueToStringFunction ([] (float value, char utf8String[256], CParamDisplay*) { snprintf (utf8String, 255, "%u %%", static_cast (value)); return true; }); zoomValueControl->setValue (100.f); CFontRef font = description->getFont ("control.font"); CColor fontColor = kWhiteCColor, frameColor = kBlackCColor, backColor = kBlackCColor; description->getColor ("control.font", fontColor); description->getColor ("control.frame", frameColor); description->getColor ("control.back", backColor); zoomValueControl->setFont (font); zoomValueControl->setFontColor (fontColor); zoomValueControl->setBackColor (backColor); zoomValueControl->setFrameColor (frameColor); zoomValueControl->setFrameWidth (-1); zoomValueControl->setTooltipText ("Editor Zoom"); zoomValueControl->registerViewListener (this); zoomValueControl->registerViewEventListener (this); zoomValueControl->setStyle (zoomValueControl->getStyle () | CTextEdit::kDoubleClickStyle); } } return view; } void valueChanged (CControl* pControl) override { if (pControl == zoomValueControl) editController->onZoomChanged (pControl->getValue () / 100.f); } void appendContextMenuItems (COptionMenu& contextMenu, CView* view, const CPoint& where) override { if (view == zoomValueControl) { for (auto i = 50; i <= 250; i += 25) { auto item = new CCommandMenuItem ("Zoom " + toString (i) + "%"); item->setActions ([this, i] (CCommandMenuItem*) { updateZoom (static_cast (i)); }); if (zoomValueControl->getValue () == static_cast (i)) item->setChecked (true); contextMenu.addEntry (item); } } } void viewOnEvent (CView* view, Event& event) override { vstgui_assert (view == zoomValueControl); if (event.type != EventType::MouseDown) return; auto& downEvent = castMouseDownEvent (event); if (downEvent.clickCount > 1) popupTimer = nullptr; else if (downEvent.buttonState.isLeft () && downEvent.modifiers.empty ()) { popupTimer = makeOwned ([this] (CVSTGUITimer*) { popupTimer = nullptr; auto menu = makeOwned (); menu->setStyle (COptionMenu::kPopupStyle | COptionMenu::kMultipleCheckStyle); appendContextMenuItems (*menu, zoomValueControl, CPoint ()); menu->popup (zoomValueControl->getFrame (), zoomValueControl->translateToGlobal ( zoomValueControl->getViewSize ().getTopLeft (), true)); }, 250); } } void viewWillDelete (CView* view) override { vstgui_assert (view == zoomValueControl); view->unregisterViewListener (this); view->unregisterViewEventListener (this); zoomValueControl = nullptr; } private: void updateZoom (float newZoom) { if (zoomValueControl) { zoomValueControl->setValue (newZoom); valueChanged (zoomValueControl); } } UIEditController* editController{nullptr}; CTextEdit* zoomValueControl{nullptr}; SharedPointer popupTimer; }; //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------- UIEditController::UIEditController (UIDescription* description) : editDescription (description) , selection (makeOwned ()) , undoManager (makeOwned ()) , gridController (makeOwned (this, description)) , editView (nullptr) , templateController (nullptr) , dirty (false) { UIDescriptionAddOnRegistry::forEach ( [this] (auto& addOn) { addOn.onEditingStart (editDescription); }); editorDesc = getEditorDescription (); undoManager->registerListener (this); editDescription->registerListener (this); menuController = makeOwned (this, selection, undoManager, editDescription, this); onTemplatesChanged (); if (auto theme = getSettings ()->getAttributeValue ("UI Theme")) { if (*theme == "Dark") setDarkTheme (true); else if (*theme == "Light") setDarkTheme (false); } } //---------------------------------------------------------------------------------------------------- UIEditController::~UIEditController () { selection->clear (); if (templateController) templateController->unregisterListener (this); undoManager->unregisterListener (this); editDescription->unregisterListener (this); UIDescriptionAddOnRegistry::forEach ( [this] (auto& addOn) { addOn.onEditingEnd (editDescription); }); editorDesc = nullptr; templateController = nullptr; undoManager->clear (); gUIDescription.tryFree (); } //---------------------------------------------------------------------------------------------------- CView* UIEditController::createEditView () { if (editorDesc->parse ()) { IController* controller = this; CView* view = editorDesc->createView ("view", controller); if (view) { view->setAttribute (kCViewControllerAttribute, controller); CRect r; if (getSettings ()->getRectAttribute ("EditorSize", r)) { view->setViewSize (r); view->setMouseableArea (r); } baseView = view; return view; } } return nullptr; } //---------------------------------------------------------------------------------------------------- CView* UIEditController::createView (const UIAttributes& attributes, const IUIDescription* description) { const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName); if (name) { if (*name == "UIEditView") { vstgui_assert (editView == nullptr); editView = new UIEditView (CRect (0, 0, 0, 0), editDescription); editView->setSelection (selection); editView->setUndoManager (undoManager); editView->setGridProcessor (gridController); editView->setupColors (description); return editView; } else if (*name == "ShadingViewHorizontal") { return new UIEditControllerShadingView (true); } else if (*name == "ShadingViewVertical") { return new UIEditControllerShadingView (false); } else if (*name == "ShadingViewVerticalTopLine") { return new UIEditControllerShadingView (false, true, false); } } return nullptr; } //---------------------------------------------------------------------------------------------------- void UIEditController::onZoomChanged (double zoom) { if (editView) editView->setScale (zoom); if (zoomSettingController) zoomSettingController->storeSetting (*getSettings ()); } enum { kNotSavedTag = 666, kEditingTag, kAutosizeTag, kBackgroundSelectTag, kTabSwitchTag = 123456 }; //---------------------------------------------------------------------------------------------------- static SharedPointer createColorBitmap (CPoint size, CColor color) { auto bitmap = makeOwned (size); if (auto pixelAccessor = owned (CBitmapPixelAccess::create (bitmap))) { for (auto y = 0u; y < static_cast (size.y); y++) { pixelAccessor->setPosition (0, y); for (auto x = 0u; x < static_cast (size.x); ++x) { pixelAccessor->setColor (color); ++(*pixelAccessor); } } } return bitmap; } //---------------------------------------------------------------------------------------------------- using BackgroundColors = std::array; static const BackgroundColors& editViewBackgroundColors () { static const BackgroundColors colors = {{ {230, 230, 230}, {150, 150, 150}, kWhiteCColor, kBlackCColor }}; return colors; } //---------------------------------------------------------------------------------------------------- CView* UIEditController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) { if (view == editView) { editView->setBackgroundColor (editViewBackgroundColors ()[0]); return view; } auto* splitView = dynamic_cast(view); if (splitView) { splitViews.emplace_back (splitView); if (splitViews.size () == 1) { CFontRef font = description->getFont ("control.font"); CColor fontColor = kWhiteCColor, frameColor = kBlackCColor, backColor = kBlackCColor; description->getColor ("control.font", fontColor); description->getColor ("control.frame", frameColor); description->getColor ("control.back", backColor); auto gradient = description->getGradient ("Default TextButton Gradient"); auto gradientHighlighted = description->getGradient ("Default TextButton Gradient Highlighted"); // Add Background Menu CRect backSelectRect (0., 0., 20. * editViewBackgroundColors ().size (), splitView->getSeparatorWidth ()); backSelectRect.inset (2, 2); auto backSelectControl = new CSegmentButton (backSelectRect, this, kBackgroundSelectTag); backSelectControl->setGradient (gradient); backSelectControl->setGradientHighlighted (gradientHighlighted); backSelectControl->setFrameColor (frameColor); backSelectControl->setFrameWidth (-1.); backSelectControl->setRoundRadius (2.); auto bitmapSize = splitView->getSeparatorWidth () - 12; for (auto& color : editViewBackgroundColors ()) { CSegmentButton::Segment segment {}; segment.iconPosition = CDrawMethods::kIconCenterAbove; segment.icon = segment.iconHighlighted = createColorBitmap ({bitmapSize, bitmapSize}, color); backSelectControl->addSegment (std::move (segment)); } backSelectControl->setTooltipText ("Editor Background Color"); splitView->addViewToSeparator (0, backSelectControl); int32_t selectedBackground = 0; if (getSettings ()->getIntegerAttribute ("ViewBackground", selectedBackground)) { backSelectControl->setSelectedSegment (selectedBackground); } // Add Title CColor labelColor = kBlackCColor; description->getColor ("control.font", labelColor); CTextLabel* label = new CTextLabel (CRect (0, 0, splitView->getWidth (), splitView->getSeparatorWidth ()), "Templates | View Hierarchy"); label->setTransparency (true); label->setMouseEnabled (false); label->setFont (font); label->setFontColor (labelColor); label->setAutosizeFlags (kAutosizeAll); splitView->addViewToSeparator (0, label); // Add Scale Menu CRect scaleMenuRect (0, 0, 50, splitView->getSeparatorWidth ()); scaleMenuRect.offset (splitView->getWidth ()-scaleMenuRect.getWidth (), 0); scaleMenuRect.inset (2, 2); zoomSettingController = new UIZoomSettingController (this); // not owned, shared with control auto* textEdit = new CTextEdit (scaleMenuRect, zoomSettingController, 0); textEdit->setAttribute (kCViewControllerAttribute, zoomSettingController); CView* zoomView = zoomSettingController->verifyView (textEdit, UIAttributes (), editorDesc); zoomView->setAutosizeFlags (kAutosizeRight|kAutosizeTop|kAutosizeBottom); splitView->addViewToSeparator (0, zoomView); zoomSettingController->restoreSetting (*getSettings ()); } } auto* control = dynamic_cast(view); if (control) { switch (control->getTag ()) { case kNotSavedTag: { notSavedControl = control; notSavedControl->setAlphaValue (dirty ? 1.f : 0.f); break; } case kAutosizeTag: { control->setListener (this); control->setValue (1.); break; } case kEditingTag: { enableEditingControl = control; enableEditingControl->setValue (1.f); enableEditingControl->setListener (this); break; } case kTabSwitchTag: { auto* button = dynamic_cast(control); if (button) { size_t numSegments = button->getSegments ().size (); button->setMax (static_cast (numSegments)); tabSwitchControl = button; int32_t value = 0; getSettings ()->getIntegerAttribute ("TabSwitchValue", value); button->setSelectedSegment (static_cast (value)); static const char* segmentBitmapNames[] = {"segment-views", "segment-tags", "segment-colors", "segment-gradients", "segment-bitmaps", "segment-fonts", nullptr}; size_t segmentBitmapNameIndex = 0; for (const auto& segment : button->getSegments()) { if (segmentBitmapNames[segmentBitmapNameIndex]) { CBitmap* bitmap = editorDesc->getBitmap (segmentBitmapNames[segmentBitmapNameIndex++]); if (!bitmap) continue; segment.icon = bitmap; segment.iconHighlighted = bitmap; segment.iconPosition = CDrawMethods::kIconLeft; } } } break; } } } return view; } //---------------------------------------------------------------------------------------------------- IController* UIEditController::createSubController (UTF8StringPtr name, const IUIDescription* description) { UTF8StringView subControllerName (name); if (subControllerName == "TemplatesController") { // vstgui_assert (templateController == nullptr); templateController = new UITemplateController (this, editDescription, selection, undoManager, this); templateController->registerListener (this); return templateController; } else if (subControllerName == "MenuController") { menuController->remember (); return menuController; } else if (subControllerName == "ViewCreatorController") { return new UIViewCreatorController (this, editDescription); } else if (subControllerName == "AttributesController") { return new UIAttributesController (this, selection, undoManager, editDescription); } else if (subControllerName == "TagEditController") { return new UITagsController (this, editDescription, this); } else if (subControllerName == "ColorEditController") { return new UIColorsController (this, editDescription, this); } else if (subControllerName == "GradientEditController") { return new UIGradientsController (this, editDescription, this); } else if (subControllerName == "BitmapEditController") { return new UIBitmapsController (this, editDescription, this, undoManager); } else if (subControllerName == "FontEditController") { return new UIFontsController (this, editDescription, this); } else if (subControllerName == "GridController") { gridController->remember (); return gridController; } return nullptr; } //---------------------------------------------------------------------------------------------------- void UIEditController::valueChanged (CControl* control) { if (editView) { switch (control->getTag ()) { case kEditingTag: { selection->clear (); if (auto container = editView->getEditView () ? editView->getEditView ()->asViewContainer () : nullptr) resetScrollViewOffsets (container); editView->enableEditing (control->getValue () == control->getMax () ? true : false); break; } case kAutosizeTag: { editView->enableAutosizing (control->getValue () == 1.f); break; } case kBackgroundSelectTag: { if (auto seg = dynamic_cast (control)) { auto selectedSegment = seg->getSelectedSegment (); CColor color = editViewBackgroundColors ()[selectedSegment]; editView->setBackgroundColor (color); getSettings ()->setIntegerAttribute ("ViewBackground", selectedSegment); } break; } case kTabSwitchTag: { getSettings ()->setIntegerAttribute ("TabSwitchValue", static_cast (tabSwitchControl->getValue ())); break; } } } } //---------------------------------------------------------------------------------------------------- bool UIEditController::validateCommandMenuItem (CCommandMenuItem* item) { return validateMenuItem (item) == kMessageNotified; } //---------------------------------------------------------------------------------------------------- bool UIEditController::onCommandMenuItemSelected (CCommandMenuItem* item) { return onMenuItemSelection (item) == kMessageNotified; } //---------------------------------------------------------------------------------------------------- void UIEditController::onUndoManagerChange () { onUndoManagerChanged (); } //---------------------------------------------------------------------------------------------------- void UIEditController::onTemplateSelectionChanged () { if (editView && templateController) { const auto& name = templateController->getSelectedTemplateName (); if ((name && *name != editTemplateName) || name == nullptr) { if (undoManager->canUndo () && !editTemplateName.empty ()) updateTemplate (editTemplateName.c_str ()); if (name) { for (auto& it : templates) { if (*name == it.name) { CView* view = it.view; editView->setEditView (view); templateController->setTemplateView (static_cast (view)); editTemplateName = *templateController->getSelectedTemplateName (); view->remember (); break; } } } else { selection->clear (); editView->setEditView (nullptr); templateController->setTemplateView (nullptr); editTemplateName = ""; } } if (editView->getEditView ()) { if (!(selection->first () && editView->getEditView ()->asViewContainer ()->isChild (selection->first (), true))) selection->setExclusive (editView->getEditView ()); } else selection->clear (); } } //---------------------------------------------------------------------------------------------------- CMessageResult UIEditController::notify (CBaseObject* sender, IdStringPtr message) { if (message == UIEditView::kMsgAttached) { vstgui_assert (editView); if (editView) editView->getFrame ()->registerKeyboardHook (this); return kMessageNotified; } else if (message == UIEditView::kMsgRemoved) { editView->getFrame ()->unregisterKeyboardHook (this); beforeSave (); splitViews.clear (); getEditorDescription ()->freePlatformResources (); return kMessageNotified; } return kMessageUnknown; } //---------------------------------------------------------------------------------------------------- void UIEditController::onUIDescTemplateChanged (UIDescription* desc) { onTemplatesChanged (); } //---------------------------------------------------------------------------------------------------- void UIEditController::beforeUIDescSave (UIDescription* desc) { beforeSave (); } //---------------------------------------------------------------------------------------------------- bool UIEditController::doUIDescTemplateUpdate (UIDescription* desc, UTF8StringPtr name) { if (onlyTemplateToUpdateName.empty ()) return true; return onlyTemplateToUpdateName == name; } //---------------------------------------------------------------------------------------------------- void UIEditController::beforeSave () { if (editView && editView->getEditView ()) { if (undoManager->canUndo ()) { if (!editTemplateName.empty ()) updateTemplate (editTemplateName.c_str ()); for (std::vector