Files
hot-step-cpp-ROCm/engine/vendor/vst3sdk/vstgui4/vstgui/uidescription/editing/uieditcontroller.cpp
T
2026-08-16 18:24:52 +07:00

1989 lines
65 KiB
C++

// 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 <sstream>
#include <algorithm>
#include <cassert>
#include <array>
#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<UIDescription> get () const
{
if (uiDesc == nullptr)
{
#ifdef HAVE_EDITORUIDESC_H
MemoryContentProvider provider (editorUIDesc, strlen (editorUIDesc));
SharedPointer<UIDescription> editorDesc = owned (new UIDescription (&provider));
if (editorDesc->parse ())
{
uiDesc = editorDesc;
}
MemoryContentProvider lightUIProvider (editorUILightDesc, strlen (editorUILightDesc));
SharedPointer<UIDescription> lightUIDesc = owned (new UIDescription (&lightUIProvider));
if (lightUIDesc->parse ())
{
lightResourceDesc = std::move (lightUIDesc);
uiDesc->setSharedResources (lightResourceDesc);
}
MemoryContentProvider darkUIProvider (editorUIDarkDesc, strlen (editorUIDarkDesc));
SharedPointer<UIDescription> 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<UIDescription> (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<UIDescription> (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<UIDescription> (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<UIDescription> uiDesc;
mutable SharedPointer<UIDescription> lightResourceDesc;
mutable SharedPointer<UIDescription> darkResourceDesc;
};
static UIEditControllerDescription gUIDescription;
//----------------------------------------------------------------------------------------------------
SharedPointer<UIDescription> 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<char> (tolower (*it));
char c2 = static_cast<char> (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<CGraphicsPath> 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<float> (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<CTextEdit*> (view);
if (zoomValueControl)
{
zoomValueControl->setMin (50.f);
zoomValueControl->setMax (1000.f);
zoomValueControl->setStringToValueFunction ([] (UTF8StringPtr txt, float& result, CTextEdit*) {
int32_t intValue = static_cast<int32_t> (strtol (txt, nullptr, 10));
if (intValue > 0)
{
result = static_cast<float> (intValue);
return true;
}
return false;
});
zoomValueControl->setValueToStringFunction ([] (float value, char utf8String[256], CParamDisplay*) {
snprintf (utf8String, 255, "%u %%", static_cast<uint32_t> (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<float> (i));
});
if (zoomValueControl->getValue () == static_cast<float> (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<CVSTGUITimer> ([this] (CVSTGUITimer*) {
popupTimer = nullptr;
auto menu = makeOwned<COptionMenu> ();
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<CVSTGUITimer> popupTimer;
};
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------------
UIEditController::UIEditController (UIDescription* description)
: editDescription (description)
, selection (makeOwned<UISelection> ())
, undoManager (makeOwned<UIUndoManager> ())
, gridController (makeOwned<UIGridController> (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<UIEditMenuController> (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<CBitmap> createColorBitmap (CPoint size, CColor color)
{
auto bitmap = makeOwned<CBitmap> (size);
if (auto pixelAccessor = owned (CBitmapPixelAccess::create (bitmap)))
{
for (auto y = 0u; y < static_cast<uint32_t> (size.y); y++)
{
pixelAccessor->setPosition (0, y);
for (auto x = 0u; x < static_cast<uint32_t> (size.x); ++x)
{
pixelAccessor->setColor (color);
++(*pixelAccessor);
}
}
}
return bitmap;
}
//----------------------------------------------------------------------------------------------------
using BackgroundColors = std::array<CColor, 4>;
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<CSplitView*>(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<CControl*>(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<CSegmentButton*>(control);
if (button)
{
size_t numSegments = button->getSegments ().size ();
button->setMax (static_cast<float> (numSegments));
tabSwitchControl = button;
int32_t value = 0;
getSettings ()->getIntegerAttribute ("TabSwitchValue", value);
button->setSelectedSegment (static_cast<uint32_t> (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<CSegmentButton*> (control))
{
auto selectedSegment = seg->getSelectedSegment ();
CColor color = editViewBackgroundColors ()[selectedSegment];
editView->setBackgroundColor (color);
getSettings ()->setIntegerAttribute ("ViewBackground", selectedSegment);
}
break;
}
case kTabSwitchTag:
{
getSettings ()->setIntegerAttribute ("TabSwitchValue", static_cast<int32_t> (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<CViewContainer*> (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<Template>::const_iterator it = templates.begin (); it != templates.end (); it++)
{
onlyTemplateToUpdateName = it->name;
updateTemplate (it);
}
onlyTemplateToUpdateName.clear ();
}
for (auto& splitView : splitViews)
splitView->storeViewSizes ();
getSettings ()->setIntegerAttribute ("Version", 1);
// find the view of this controller
auto container = editView->getParentView ()->asViewContainer ();
while (container && container != container->getFrame ())
{
if (getViewController (container, false) == this)
{
getSettings ()->setRectAttribute ("EditorSize", container->getViewSize ());
break;
}
container = container->getParentView () ? container->getParentView ()->asViewContainer () : nullptr;
}
undoManager->markSavePosition ();
if (zoomSettingController)
zoomSettingController->storeSetting (*getSettings ());
setDirty (false);
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::doCopy (bool cut)
{
if (!editTemplateName.empty ())
updateTemplate (editTemplateName.c_str ());
CMemoryStream stream (1024, 1024, false);
selection->store (stream, editDescription);
auto dataSource = CDropSource::create (stream.getBuffer (), static_cast<uint32_t> (stream.tell ()), IDataPackage::kText);
editView->getFrame ()->setClipboard (dataSource);
if (cut)
undoManager->pushAndPerform (new DeleteOperation (selection));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::addSelectionToCurrentView (UISelection* copySelection)
{
if (selection->total () == 0)
return;
CPoint offset;
CViewContainer* container = selection->first ()->asViewContainer ();
if (container == nullptr)
{
container = selection->first ()->getParentView ()->asViewContainer ();
offset = selection->first ()->getViewSize ().getTopLeft ();
offset.offset (gridController->getSize ().x, gridController->getSize ().y);
}
IAction* action = new ViewCopyOperation (copySelection, selection, container, offset, editDescription);
undoManager->pushAndPerform (action);
if (!editTemplateName.empty ())
updateTemplate (editTemplateName.c_str ());
}
//----------------------------------------------------------------------------------------------------
void UIEditController::doPaste ()
{
if (auto clipboard = editView->getFrame ()->getClipboard ())
{
if (clipboard->getDataType (0) == IDataPackage::kText)
{
const void* data;
IDataPackage::Type type;
uint32_t size = clipboard->getData (0, data, type);
if (size > 0)
{
CMemoryStream stream ((const int8_t*)data, size, false);
auto* copySelection = new UISelection ();
if (copySelection->restore (stream, editDescription))
{
addSelectionToCurrentView (copySelection);
}
copySelection->forget ();
}
}
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::showTemplateSettings ()
{
if (undoManager->canUndo () && !editTemplateName.empty ())
{
updateTemplate (editTemplateName.c_str ());
}
auto dc = new UIDialogController (this, editView->getFrame ());
auto tsController =
makeOwned<UITemplateSettingsController> (editTemplateName, editDescription, this);
dc->run ("template.settings", "Template Settings", "OK", "Cancel", tsController, editorDesc);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::showFocusSettings ()
{
auto dc = new UIDialogController (this, editView->getFrame ());
auto fsController = makeOwned<UIFocusSettingsController> (editDescription, this);
dc->run ("focus.settings", "Focus Drawing Settings", "OK", "Cancel", fsController, editorDesc);
}
//----------------------------------------------------------------------------------------------------
static void toggleBoolAttribute (UIAttributes* attributes, UTF8StringPtr key)
{
if (attributes)
{
bool val = false;
attributes->getBooleanAttribute (key, val);
attributes->setBooleanAttribute (key, !val);
}
}
//----------------------------------------------------------------------------------------------------
CMessageResult UIEditController::onMenuItemSelection (CCommandMenuItem* item)
{
UTF8StringView cmdCategory (item->getCommandCategory ());
UTF8StringView cmdName (item->getCommandName ());
if (cmdCategory == "Edit")
{
if (cmdName == "Copy")
{
doCopy (false);
return kMessageNotified;
}
else if (cmdName == "Cut")
{
doCopy (true);
return kMessageNotified;
}
else if (cmdName == "Paste")
{
doPaste ();
return kMessageNotified;
}
else if (cmdName == "Template Settings...")
{
showTemplateSettings ();
return kMessageNotified;
}
else if (cmdName == "Focus Drawing Settings...")
{
showFocusSettings ();
return kMessageNotified;
}
else if (cmdName == "Toggle UI Theme (Dark/Light)")
{
doChangeTheme (!usesDarkTheme ());
return kMessageNotified;
}
}
else if (cmdCategory == "File")
{
if (cmdName == "Encode Bitmaps in XML")
{
toggleBoolAttribute (getSettings (), kEncodeBitmapsSettingsKey);
return kMessageNotified;
}
else if (cmdName == "Write Windows RC File on Save")
{
toggleBoolAttribute (getSettings (), kWriteWindowsRCFileSettingsKey);
return kMessageNotified;
}
}
else if (cmdCategory == "SelectionMoveByGrid")
{
if (doSelectionMove (item->getCommandName (), true))
return kMessageNotified;
}
else if (cmdCategory == "SelectionSizeByGrid")
{
if (doSelectionSize (item->getCommandName (), true))
return kMessageNotified;
}
else if (cmdCategory == "SelectionMoveByPixel")
{
if (doSelectionMove (item->getCommandName (), false))
return kMessageNotified;
}
else if (cmdCategory == "SelectionSizeByPixel")
{
if (doSelectionSize (item->getCommandName (), false))
return kMessageNotified;
}
else if (cmdCategory == "SelectionZOrder")
{
bool lower = cmdName == "Lower" ? true : false;
if (doZOrderAction (lower))
return kMessageNotified;
}
else if (cmdCategory == "Selection")
{
if (cmdName == "Select All Children")
{
doSelectAllChildren ();
return kMessageNotified;
}
if (cmdName == "Select Parent(s)")
{
doSelectParents ();
return kMessageNotified;
}
if (cmdName == "Select View in Hierarchy Browser")
{
doSelectViewInHierarchyBrowser (selection->first ());
return kMessageNotified;
}
}
else if (cmdCategory == "Zoom")
{
if (cmdName == "Zoom In")
{
zoomSettingController->increaseZoom ();
return kMessageNotified;
}
else if (cmdName == "Zoom Out")
{
zoomSettingController->decreaseZoom ();
return kMessageNotified;
}
else if (cmdName == "Zoom 100%")
{
zoomSettingController->resetZoom ();
return kMessageNotified;
}
}
return kMessageUnknown;
}
//----------------------------------------------------------------------------------------------------
CMessageResult UIEditController::validateMenuItem (CCommandMenuItem* item)
{
UTF8StringView cmdCategory (item->getCommandCategory ());
UTF8StringView cmdName (item->getCommandName ());
if (cmdCategory == "Edit")
{
if (cmdName == "Template Settings...")
{
item->setEnabled (editTemplateName.empty () ? false : true);
return kMessageNotified;
}
else if (cmdName == "Copy" || cmdName == "Cut")
{
if (editView && selection->first () && selection->contains (editView->getEditView ()) == false)
item->setEnabled (true);
else
item->setEnabled (false);
return kMessageNotified;
}
else if (cmdName == "Paste")
{
item->setEnabled (false);
if (editView && selection->first ())
{
if (auto clipboard = editView->getFrame ()->getClipboard ())
{
if (clipboard->getDataType (0) == IDataPackage::kText)
item->setEnabled (true);
}
}
return kMessageNotified;
}
else if (cmdName == "Toggle UI Theme (Dark/Light)")
{
return kMessageNotified;
}
}
else if (cmdCategory == "File")
{
if (cmdName == "Encode Bitmaps in XML")
{
auto attr = getSettings ();
bool encodeBitmaps = false;
if (attr && attr->getBooleanAttribute (kEncodeBitmapsSettingsKey, encodeBitmaps))
{
item->setChecked (encodeBitmaps);
}
return kMessageNotified;
}
else if (cmdName == "Write Windows RC File on Save")
{
auto attr = getSettings ();
bool encodeBitmaps = false;
if (attr && attr->getBooleanAttribute (kWriteWindowsRCFileSettingsKey, encodeBitmaps))
{
item->setChecked (encodeBitmaps);
}
return kMessageNotified;
}
}
else if (cmdCategory == "SelectionMoveByGrid"
|| cmdCategory == "SelectionSizeByGrid"
|| cmdCategory == "SelectionMoveByPixel"
|| cmdCategory == "SelectionSizeByPixel"
)
{
bool enableItem = selection->first () ? true : false;
if (enableItem && cmdCategory.contains ("Size") == false)
{
if (selection->contains (editView->getEditView ()))
enableItem = false;
}
item->setEnabled (enableItem);
return kMessageNotified;
}
else if (cmdCategory == "SelectionZOrder")
{
bool enableItem = selection->total () == 1;
if (enableItem)
{
bool lower = cmdName == "Lower" ? true : false;
CView* view = selection->first ();
if (auto parent = view->getParentView ()->asViewContainer ())
{
if (lower)
{
ViewIterator it (parent);
if (*it == view)
enableItem = false;
}
else
{
ReverseViewIterator it (parent);
if (*it == view)
enableItem = false;
}
}
}
item->setEnabled (enableItem);
return kMessageNotified;
}
else if (cmdCategory == "Selection")
{
if (cmdName == "Select All Children")
{
bool enable = selection->total () == 1 && selection->first () &&
selection->first ()->asViewContainer ();
item->setEnabled (enable);
return kMessageNotified;
}
if (cmdName == "Select Parent(s)")
{
bool enable =
selection->total () > 0 && selection->first () != editView->getEditView ();
item->setEnabled (enable);
item->setTitle (selection->total () > 1 ? "Select Parents" : "Select Parent");
return kMessageNotified;
}
if (cmdName == "Select View in Hierarchy Browser")
{
item->setEnabled (selection->total () == 1);
return kMessageNotified;
}
}
return kMessageUnknown;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::doSelectionMove (const UTF8String& commandName, bool useGrid) const
{
CPoint diff;
if (commandName == "Move Up")
diff.y = -(useGrid ? gridController->getSize ().y : 1);
else if (commandName == "Move Down")
diff.y = (useGrid ? gridController->getSize ().y : 1);
else if (commandName == "Move Left")
diff.x = -(useGrid ? gridController->getSize ().x : 1);
else if (commandName == "Move Right")
diff.x = (useGrid ? gridController->getSize ().x : 1);
if (diff.x != 0 || diff.y != 0)
{
editView->doKeyMove (diff);
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::doSelectionSize (const UTF8String& commandName, bool useGrid) const
{
CPoint diff;
if (commandName == "Increase Size Width")
diff.x = (useGrid ? gridController->getSize ().x : 1);
else if (commandName == "Increase Size Height")
diff.y = (useGrid ? gridController->getSize ().y : 1);
else if (commandName == "Decrease Size Width")
diff.x = -(useGrid ? gridController->getSize ().x : 1);
else if (commandName == "Decrease Size Height")
diff.y = -(useGrid ? gridController->getSize ().y : 1);
if (diff.x != 0 || diff.y != 0)
{
editView->doKeySize (diff);
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::doZOrderAction (bool lower)
{
if (selection->total () == 1)
{
CView* view = selection->first ();
undoManager->pushAndPerform (
new HierarchyMoveViewOperation (view, selection, lower ? -1 : 1));
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
void UIEditController::doSelectAllChildren ()
{
UISelection::DeferChange dc (*selection);
CViewContainer* container = selection->first ()->asViewContainer ();
selection->clear ();
container->forEachChild ([&] (CView* view) {
if (IViewFactory::getViewName (view))
selection->add (view);
});
}
//----------------------------------------------------------------------------------------------------
void UIEditController::doSelectParents ()
{
UISelection::DeferChange dc (*selection);
std::vector<CView*> parents;
for (auto& view : *selection)
{
if (auto parent = view->getParentView ())
{
while (IViewFactory::getViewName (parent) == nullptr)
{
parent = parent->getParentView ();
}
if (parent && std::find (parents.begin (), parents.end (), parent) == parents.end ())
parents.emplace_back (parent);
}
}
selection->clear ();
for (auto& parent : parents)
selection->add (parent);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::doSelectViewInHierarchyBrowser (CView* view)
{
templateController->navigateTo (view);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::onUndoManagerChanged ()
{
if (undoManager->isSavePosition ())
{
updateTemplate (editTemplateName.data ());
setDirty (false);
}
else
setDirty (true);
CView* view = selection->first ();
if (view)
{
if (auto templateView = editView->getEditView () ? editView->getEditView ()->asViewContainer () : nullptr)
{
if (view == templateView || templateView->isChild (view, true))
{
return;
}
}
for (auto& it : templates)
{
CViewContainer* container = it.view->asViewContainer ();
if (container && (view == container || container->isChild (view, true)))
{
templateController->selectTemplate (it.name.c_str ());
return;
}
}
selection->clear ();
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::resetScrollViewOffsets (CViewContainer* view)
{
view->forEachChild ([&] (CView* view) {
auto* scrollView = dynamic_cast<CScrollView*>(view);
if (scrollView)
{
scrollView->resetScrollOffset ();
}
if (auto container = view->asViewContainer ())
resetScrollViewOffsets (container);
});
}
//----------------------------------------------------------------------------------------------------
void UIEditController::onKeyboardEvent (KeyboardEvent& event, CFrame* frame)
{
if (event.type == EventType::KeyUp)
return;
if (frame->getModalView () == nullptr)
{
if (frame->getFocusView ())
{
auto* edit = dynamic_cast<CTextEdit*>(frame->getFocusView ());
if (edit && edit->getPlatformTextEdit ())
return;
}
menuController->processKeyCommand (event);
}
}
//----------------------------------------------------------------------------------------------------
SharedPointer<UIAttributes> UIEditController::getSettings ()
{
return editDescription->getCustomAttributes ("UIEditController", true);
}
//----------------------------------------------------------------------------------------------------
int32_t UIEditController::getSaveOptions ()
{
int32_t flags = 0;
auto attributes = getSettings ();
bool val;
if (attributes->getBooleanAttribute (UIEditController::kEncodeBitmapsSettingsKey, val) && val == true)
{
flags |= UIDescription::kWriteImagesIntoUIDescFile;
}
if (attributes->getBooleanAttribute (UIEditController::kWriteWindowsRCFileSettingsKey, val) && val == true)
{
flags |= UIDescription::kWriteWindowsResourceFile;
}
return flags;
}
//----------------------------------------------------------------------------------------------------
int32_t UIEditController::getSplitViewIndex (CSplitView* splitView)
{
int32_t index = 0;
for (auto& sv : splitViews)
{
if (sv == splitView)
return index;
index++;
}
return -1;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::getSplitViewSizeConstraint (int32_t index, CCoord& minSize, CCoord& maxSize, CSplitView* splitView)
{
return false;
}
//----------------------------------------------------------------------------------------------------
ISplitViewSeparatorDrawer* UIEditController::getSplitViewSeparatorDrawer (CSplitView* splitView)
{
int32_t si = getSplitViewIndex (splitView);
if (si >= 0)
{
return this;
}
return nullptr;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::storeViewSize (int32_t index, const CCoord& size, CSplitView* splitView)
{
int32_t si = getSplitViewIndex (splitView);
if (si >= 0)
{
std::stringstream str;
str << "SplitViewSize_";
str << si;
str << "_";
str << index;
double value;
if (splitView->getStyle () == CSplitView::kHorizontal)
value = size / splitView->getWidth ();
else
value = size / splitView->getHeight ();
getSettings ()->setDoubleAttribute (str.str (), value);
return true;
}
return false;
}
//----------------------------------------------------------------------------------------------------
bool UIEditController::restoreViewSize (int32_t index, CCoord& size, CSplitView* splitView)
{
int32_t version = 0;
getSettings ()->getIntegerAttribute ("Version", version);
if (version == 0)
return false;
int32_t si = getSplitViewIndex (splitView);
if (si >= 0)
{
std::stringstream str;
str << "SplitViewSize_";
str << si;
str << "_";
str << index;
double value;
if (getSettings ()->getDoubleAttribute (str.str ().c_str (), value))
{
if (splitView->getStyle () == CSplitView::kHorizontal)
value = floor (splitView->getWidth () * value + 0.5);
else
value = floor (splitView->getHeight () * value + 0.5);
size = value;
return true;
}
}
return false;
}
//----------------------------------------------------------------------------------------------------
void UIEditController::drawSplitViewSeparator (CDrawContext* context, const CRect& size, int32_t flags, int32_t index, CSplitView* splitView)
{
if (splitView->getStyle () == CSplitView::kHorizontal)
{
UIEditControllerShadingView::drawGradient (context, size, true);
}
else
{
UIEditControllerShadingView::drawGradient (context, size, false);
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::setDirty (bool state)
{
if (dirty != state)
{
dirty = state;
if (notSavedControl && notSavedControl->isAttached ())
{
notSavedControl->invalid ();
notSavedControl->addAnimation ("AlphaValueAnimation", new Animation::AlphaValueAnimation (dirty ? 1.f : 0.f), new Animation::LinearTimingFunction (80));
}
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performAction (IAction* action)
{
undoManager->pushAndPerform (action);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::beginGroupAction (UTF8StringPtr name)
{
undoManager->startGroupAction (name);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::finishGroupAction ()
{
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performChangeFocusDrawingSettings (const FocusDrawingSettings& newSettings)
{
undoManager->pushAndPerform (new ChangeFocusDrawingAction (editDescription, newSettings));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::getTemplateViews (std::list<CView*>& views) const
{
for (const auto& templateDesc : templates)
views.emplace_back (templateDesc.view);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performColorChange (UTF8StringPtr colorName, const CColor& newColor, bool remove)
{
std::list<CView*> views;
getTemplateViews (views);
auto* action = new ColorChangeAction (editDescription, colorName, newColor, remove, true);
undoManager->startGroupAction (remove ? "Delete Color" : action->isAddColor () ? "Add New Color" : "Change Color");
undoManager->pushAndPerform (action);
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kColorType, colorName, remove ? "" : colorName));
undoManager->pushAndPerform (new ColorChangeAction (editDescription, colorName, newColor, remove, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performTagChange (UTF8StringPtr tagName, UTF8StringPtr tagStr, bool remove)
{
std::list<CView*> views;
getTemplateViews (views);
auto* action = new TagChangeAction (editDescription, tagName, tagStr, remove, true);
undoManager->startGroupAction (remove ? "Delete Tag" : action->isAddTag () ? "Add New Tag" : "Change Tag");
undoManager->pushAndPerform (action);
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kTagType, tagName, remove ? "" : tagName));
undoManager->pushAndPerform (new TagChangeAction (editDescription, tagName, tagStr, remove, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performBitmapChange (UTF8StringPtr bitmapName, UTF8StringPtr bitmapPath, bool remove)
{
std::list<CView*> views;
getTemplateViews (views);
auto* action = new BitmapChangeAction (editDescription, bitmapName, bitmapPath, remove, true);
undoManager->startGroupAction (remove ? "Delete Bitmap" : action->isAddBitmap () ? "Add New Bitmap" :"Change Bitmap");
undoManager->pushAndPerform (action);
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, remove ? "" : bitmapName));
undoManager->pushAndPerform (new BitmapChangeAction (editDescription, bitmapName, bitmapPath, remove, false));
undoManager->endGroupAction ();
}
//------------------------------------------------------------------------
void UIEditController::performGradientChange (UTF8StringPtr gradientName, CGradient* newGradient, bool remove)
{
std::list<CView*> views;
getTemplateViews (views);
auto* action = new GradientChangeAction (editDescription, gradientName, newGradient, remove, true);
undoManager->startGroupAction (remove ? "Delete Bitmap" : action->isAddGradient () ? "Add New Gradient" :"Change Gradient");
undoManager->pushAndPerform (action);
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kGradientType, gradientName, remove ? "" : gradientName));
undoManager->pushAndPerform (new GradientChangeAction (editDescription, gradientName, newGradient, remove, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performFontChange (UTF8StringPtr fontName, CFontRef newFont, bool remove)
{
std::list<CView*> views;
getTemplateViews (views);
auto* action = new FontChangeAction (editDescription, fontName, newFont, remove, true);
undoManager->startGroupAction (remove ? "Delete Font" : action->isAddFont () ? "Add New Font" : "Change Font");
undoManager->pushAndPerform (action);
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kFontType, fontName, remove ? "" : fontName));
undoManager->pushAndPerform (new FontChangeAction (editDescription, fontName, newFont, remove, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
template<typename NameChangeAction, IViewCreator::AttrType attrType> void UIEditController::performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName, IdStringPtr groupActionName)
{
std::list<CView*> views;
getTemplateViews (views);
undoManager->startGroupAction (groupActionName);
undoManager->pushAndPerform (new NameChangeAction (editDescription, oldName, newName, true));
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, attrType, oldName, newName));
undoManager->pushAndPerform (new NameChangeAction (editDescription, oldName, newName, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performColorNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
performNameChange<ColorNameChangeAction, IViewCreator::kColorType> (oldName, newName, "Change Color Name");
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performTagNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
performNameChange<TagNameChangeAction, IViewCreator::kTagType> (oldName, newName, "Change Tag Name");
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performFontNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
performNameChange<FontNameChangeAction, IViewCreator::kFontType> (oldName, newName, "Change Font Name");
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performGradientNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
performNameChange<GradientNameChangeAction, IViewCreator::kGradientType> (oldName, newName, "Change Gradient Name");
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performBitmapNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
performNameChange<BitmapNameChangeAction, IViewCreator::kBitmapType> (oldName, newName, "Change Bitmap Name");
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performBitmapMultiFrameChange (UTF8StringPtr bitmapName,
const CMultiFrameBitmapDescription* desc)
{
std::list<CView*> views;
getTemplateViews (views);
undoManager->startGroupAction ("Change MultiFrame Bitmap");
undoManager->pushAndPerform (
new MultiFrameBitmapChangeAction (editDescription, bitmapName, desc, true));
undoManager->pushAndPerform (new MultipleAttributeChangeAction (
editDescription, views, IViewCreator::kBitmapType, bitmapName, bitmapName));
undoManager->pushAndPerform (
new MultiFrameBitmapChangeAction (editDescription, bitmapName, desc, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performBitmapNinePartTiledChange (UTF8StringPtr bitmapName, const CRect* offsets)
{
std::list<CView*> views;
getTemplateViews (views);
undoManager->startGroupAction ("Change NinePartTiled Bitmap");
undoManager->pushAndPerform (new NinePartTiledBitmapChangeAction (editDescription, bitmapName, offsets, true));
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, bitmapName));
undoManager->pushAndPerform (new NinePartTiledBitmapChangeAction (editDescription, bitmapName, offsets, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performBitmapFiltersChange (UTF8StringPtr bitmapName, const std::list<SharedPointer<UIAttributes> >& filterDescription)
{
std::list<CView*> views;
getTemplateViews (views);
undoManager->startGroupAction ("Change Bitmap Filter");
undoManager->pushAndPerform (new BitmapFilterChangeAction (editDescription, bitmapName, filterDescription, true));
undoManager->pushAndPerform (new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kBitmapType, bitmapName, bitmapName));
undoManager->pushAndPerform (new BitmapFilterChangeAction (editDescription, bitmapName, filterDescription, false));
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performAlternativeFontChange (UTF8StringPtr fontName, UTF8StringPtr newAlternativeFonts)
{
undoManager->pushAndPerform (new AlternateFontChangeAction (editDescription, fontName, newAlternativeFonts));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::beginLiveColorChange (UTF8StringPtr colorName)
{
undoManager->startGroupAction ("Change Color");
CColor color;
editDescription->getColor(colorName, color);
performColorChange (colorName, color, false);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performLiveColorChange (UTF8StringPtr _colorName, const CColor& newColor)
{
std::string colorName (_colorName);
IAction* action =
new ColorChangeAction (editDescription, colorName.data (), newColor, false, true);
action->perform ();
delete action;
std::list<CView*> views;
getTemplateViews (views);
action = new MultipleAttributeChangeAction (editDescription, views, IViewCreator::kColorType,
colorName.data (), colorName.data ());
action->perform ();
delete action;
}
//----------------------------------------------------------------------------------------------------
void UIEditController::endLiveColorChange (UTF8StringPtr colorName)
{
UIDescriptionListenerOff lo (this, editDescription);
CColor color;
editDescription->getColor (colorName, color);
performColorChange (colorName, color, false);
undoManager->endGroupAction ();
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
undoManager->pushAndPerform (new TemplateNameChangeAction (editDescription, this, oldName, newName));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performTemplateMinMaxSizeChange (UTF8StringPtr templateName, CPoint minSize, CPoint maxSize)
{
undoManager->pushAndPerform (
new ChangeTemplateMinMaxAction (editDescription, templateName, minSize, maxSize));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performCreateNewTemplate (UTF8StringPtr name, UTF8StringPtr baseViewClassName)
{
undoManager->pushAndPerform (new CreateNewTemplateAction (editDescription, this, name, baseViewClassName));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performDeleteTemplate (UTF8StringPtr name)
{
auto it = std::find (templates.begin (), templates.end (), name);
if (it != templates.end ())
undoManager->pushAndPerform (new DeleteTemplateAction (editDescription, this, (*it).view, (*it).name.c_str ()));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::performDuplicateTemplate (UTF8StringPtr name, UTF8StringPtr dupName)
{
updateTemplate (name);
UIDescriptionListenerOff lo (this, editDescription);
undoManager->pushAndPerform (new DuplicateTemplateAction (editDescription, this, name, dupName));
}
//----------------------------------------------------------------------------------------------------
void UIEditController::onTemplateCreation (UTF8StringPtr name, CView* view)
{
auto it = std::find (templates.begin (), templates.end (), name);
if (it == templates.end ())
templates.emplace_back (name, view);
templateController->selectTemplate (name);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::onTemplateNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
{
auto it = std::find (templates.begin (), templates.end (), oldName);
if (it != templates.end ())
{
(*it).name = newName;
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::updateTemplate (const std::vector<Template>::const_iterator& it)
{
if (it != templates.end ())
{
CView* view = (*it).view;
if (auto container = view->asViewContainer ())
resetScrollViewOffsets (container);
editDescription->updateViewDescription ((*it).name.c_str (), view);
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::updateTemplate (UTF8StringPtr name)
{
auto it = std::find (templates.begin (), templates.end (), name);
updateTemplate (it);
}
//----------------------------------------------------------------------------------------------------
void UIEditController::onTemplatesChanged ()
{
std::list<const std::string*> templateNames;
editDescription->collectTemplateViewNames (templateNames);
for (auto& it : templateNames)
{
if (std::find (templates.begin (), templates.end (), *it) == templates.end ())
{
auto view = owned (editDescription->createView (it->c_str (), editDescription->getController ()));
templates.emplace_back (*it, view);
}
}
for (std::vector<Template>::iterator it = templates.begin (); it != templates.end ();)
{
Template& t = (*it);
bool found = false;
for (auto& it2 : templateNames)
{
if (t.name == *it2)
{
found = true;
it++;
break;
}
}
if (!found)
{
it = templates.erase (it);
}
}
}
//----------------------------------------------------------------------------------------------------
void UIEditController::appendContextMenuItems (COptionMenu& contextMenu, CView* view, const CPoint& where)
{
auto vc = view->asViewContainer ();
if (!vc || editView == nullptr)
return;
view = vc->getViewAt (where, GetViewOptions ().deep ().includeViewContainer ());
while (view && view != editView)
{
view = view->getParentView ();
}
if (view != editView)
return;
auto editMenu = getMenuController ()->getEditMenu ();
for (auto& entry : *editMenu->getItems ())
{
if (auto item = entry.cast<CCommandMenuItem> ())
{
item->validate ();
}
if (!entry->isEnabled ())
continue;
entry->remember ();
contextMenu.addEntry (entry);
}
}
} // VSTGUI
#endif // VSTGUI_LIVE_EDITING