1458 lines
42 KiB
C++
1458 lines
42 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 "uiattributescontroller.h"
|
|
|
|
#if VSTGUI_LIVE_EDITING
|
|
|
|
#include "uiactions.h"
|
|
#include "uicolor.h"
|
|
#include "uieditcontroller.h"
|
|
#include "uidialogcontroller.h"
|
|
#include "../uiattributes.h"
|
|
#include "../detail/uiviewcreatorattributes.h"
|
|
#include "../../lib/controls/coptionmenu.h"
|
|
#include "../../lib/controls/csearchtextedit.h"
|
|
#include "../../lib/controls/cslider.h"
|
|
#include "../../lib/controls/cbuttons.h"
|
|
#include "../../lib/coffscreencontext.h"
|
|
#include "../../lib/crowcolumnview.h"
|
|
#include "../../lib/iviewlistener.h"
|
|
#include "../../lib/cstring.h"
|
|
#include "../../lib/cgraphicspath.h"
|
|
#include "../../lib/ctexteditor.h"
|
|
#include "../../lib/cvstguitimer.h"
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
|
|
namespace VSTGUI {
|
|
|
|
namespace UIAttributeControllers {
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class Controller : public NonAtomicReferenceCounted, public DelegationController
|
|
{
|
|
public:
|
|
Controller (IController* baseController, const std::string& attrName)
|
|
: DelegationController (baseController), attrName (attrName), differentValues (false) {}
|
|
|
|
const std::string& getAttributeName () const { return attrName; }
|
|
virtual void setValue (const std::string& value) = 0;
|
|
|
|
virtual void hasDifferentValues (bool state) { differentValues = state; }
|
|
bool hasDifferentValues () const { return differentValues; }
|
|
protected:
|
|
IControlListener* getControlListener (UTF8StringPtr controlTagName) override { return this; }
|
|
UIAttributesController* getAttributesController () const { return dynamic_cast<UIAttributesController*> (controller); }
|
|
void performValueChange (UTF8StringPtr value)
|
|
{
|
|
hasDifferentValues (false);
|
|
std::string valueStr = value ? value : "";
|
|
UIAttributesController* attrController = getAttributesController ();
|
|
if (attrController)
|
|
attrController->performAttributeChange (attrName, valueStr);
|
|
}
|
|
std::string attrName;
|
|
bool differentValues;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class TextAlignmentController : public Controller
|
|
{
|
|
public:
|
|
TextAlignmentController (IController* baseController, const std::string& attrName)
|
|
: Controller (baseController, attrName) {}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
auto* control = dynamic_cast<CControl*>(view);
|
|
if (control)
|
|
{
|
|
int32_t tag = control->getTag ();
|
|
if (tag >= kLeftTag && tag <= kRightTag)
|
|
controls[tag] = control;
|
|
}
|
|
return controller->verifyView (view, attributes, description);
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
if (hasDifferentValues ())
|
|
{
|
|
for (int32_t i = kLeftTag; i <= kRightTag; i++)
|
|
{
|
|
controls[i]->setValue (0.f);
|
|
controls[i]->invalid ();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
int32_t alignment = 0;
|
|
if (value == "center")
|
|
alignment = 1;
|
|
else if (value == "right")
|
|
alignment = 2;
|
|
for (int32_t i = kLeftTag; i <= kRightTag; i++)
|
|
{
|
|
controls[i]->setValue (i == alignment ? 1.f : 0.f);
|
|
controls[i]->invalid ();
|
|
}
|
|
}
|
|
}
|
|
|
|
void valueChanged (CControl* control) override
|
|
{
|
|
if (control->getValue () == control->getMax ())
|
|
{
|
|
switch (control->getTag ())
|
|
{
|
|
case kLeftTag:
|
|
{
|
|
performValueChange ("left");
|
|
break;
|
|
}
|
|
case kCenterTag:
|
|
{
|
|
performValueChange ("center");
|
|
break;
|
|
}
|
|
case kRightTag:
|
|
{
|
|
performValueChange ("right");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
control->setValue (control->getMax ());
|
|
control->invalid ();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
enum {
|
|
kLeftTag = 0,
|
|
kCenterTag,
|
|
kRightTag
|
|
};
|
|
|
|
CControl* controls[3];
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class AutosizeController : public Controller
|
|
{
|
|
public:
|
|
AutosizeController (IController* baseController, UISelection* selection, const std::string& attrName)
|
|
: Controller (baseController, attrName), selection (selection) {}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
auto* control = dynamic_cast<CControl*>(view);
|
|
if (control)
|
|
{
|
|
int32_t tag = control->getTag ();
|
|
if (tag >= kLeftTag && tag <= kColTag)
|
|
controls[tag] = control;
|
|
if (tag >= kRowTag && tag <= kColTag)
|
|
{
|
|
for (const auto& selView : *selection)
|
|
{
|
|
if (selView->asViewContainer () == nullptr)
|
|
{
|
|
controls[tag]->setVisible (false);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return controller->verifyView (view, attributes, description);
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
if (hasDifferentValues ())
|
|
{
|
|
for (int32_t i = kLeftTag; i <= kColTag; i++)
|
|
{
|
|
controls[i]->setValue (0.f);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
controls[kLeftTag]->setValue (value.find ("left") == std::string::npos ? controls[kLeftTag]->getMin () : controls[kLeftTag]->getMax ());
|
|
controls[kRightTag]->setValue (value.find ("right") == std::string::npos ? controls[kRightTag]->getMin () : controls[kRightTag]->getMax ());
|
|
controls[kTopTag]->setValue (value.find ("top") == std::string::npos ? controls[kTopTag]->getMin () : controls[kTopTag]->getMax ());
|
|
controls[kBottomTag]->setValue (value.find ("bottom") == std::string::npos ? controls[kBottomTag]->getMin () : controls[kBottomTag]->getMax ());
|
|
controls[kRowTag]->setValue (value.find ("row") == std::string::npos ? controls[kRowTag]->getMin () : controls[kRowTag]->getMax ());
|
|
controls[kColTag]->setValue (value.find ("column") == std::string::npos ? controls[kColTag]->getMin () : controls[kColTag]->getMax ());
|
|
}
|
|
for (int32_t i = kLeftTag; i <= kColTag; i++)
|
|
{
|
|
controls[i]->invalid ();
|
|
}
|
|
}
|
|
|
|
void valueChanged (CControl* control) override
|
|
{
|
|
if (control == controls[kRowTag])
|
|
{
|
|
if (control->getValue () == control->getMax ())
|
|
{
|
|
controls[kColTag]->setValue (control->getMin ());
|
|
}
|
|
}
|
|
else if (control == controls[kColTag])
|
|
{
|
|
if (control->getValue () == control->getMax ())
|
|
{
|
|
controls[kRowTag]->setValue (control->getMin ());
|
|
}
|
|
}
|
|
std::string str;
|
|
if (controls[kLeftTag]->getValue () == controls[kLeftTag]->getMax ())
|
|
str = "left";
|
|
if (controls[kRightTag]->getValue () == controls[kRightTag]->getMax ())
|
|
{
|
|
if (str.empty () == false)
|
|
str += " ";
|
|
str += "right";
|
|
}
|
|
if (controls[kTopTag]->getValue () == controls[kTopTag]->getMax ())
|
|
{
|
|
if (str.empty () == false)
|
|
str += " ";
|
|
str += "top";
|
|
}
|
|
if (controls[kBottomTag]->getValue () == controls[kBottomTag]->getMax ())
|
|
{
|
|
if (str.empty () == false)
|
|
str += " ";
|
|
str += "bottom";
|
|
}
|
|
if (controls[kRowTag]->getValue () == controls[kRowTag]->getMax ())
|
|
{
|
|
if (str.empty () == false)
|
|
str += " ";
|
|
str += "row";
|
|
}
|
|
if (controls[kColTag]->getValue () == controls[kColTag]->getMax ())
|
|
{
|
|
if (str.empty () == false)
|
|
str += " ";
|
|
str += "column";
|
|
}
|
|
performValueChange (str.c_str ());
|
|
}
|
|
|
|
|
|
protected:
|
|
enum {
|
|
kLeftTag = 0,
|
|
kTopTag,
|
|
kRightTag,
|
|
kBottomTag,
|
|
kRowTag,
|
|
kColTag
|
|
};
|
|
|
|
CControl* controls[6];
|
|
SharedPointer<UISelection> selection;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class BooleanController : public Controller
|
|
{
|
|
public:
|
|
BooleanController (IController* baseController, const std::string& attrName)
|
|
: Controller (baseController, attrName), control (nullptr) {}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
if (control == nullptr)
|
|
{
|
|
control = dynamic_cast<CControl*>(view);
|
|
}
|
|
return controller->verifyView (view, attributes, description);
|
|
}
|
|
void valueChanged (CControl* pControl) override
|
|
{
|
|
if (pControl->getValue () == control->getMax ())
|
|
performValueChange ("true");
|
|
else
|
|
performValueChange ("false");
|
|
}
|
|
void setValue (const std::string& value) override
|
|
{
|
|
if (hasDifferentValues())
|
|
{
|
|
control->setValue (control->getMin () + (control->getMax () - control->getMin ()) / 2.f);
|
|
}
|
|
else
|
|
{
|
|
if (value == "true")
|
|
control->setValue (control->getMax ());
|
|
else
|
|
control->setValue (control->getMin ());
|
|
}
|
|
control->invalid ();
|
|
}
|
|
|
|
protected:
|
|
CControl* control;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class TextController : public Controller, public ViewListenerAdapter, public ITextLabelListener
|
|
{
|
|
public:
|
|
TextController (IController* baseController, const std::string& attrName)
|
|
: Controller (baseController, attrName) {}
|
|
|
|
~TextController () override
|
|
{
|
|
if (textLabel)
|
|
{
|
|
textLabel->unregisterViewListener (this);
|
|
textLabel->unregisterTextLabelListener (this);
|
|
}
|
|
}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
if (textLabel == nullptr)
|
|
{
|
|
auto* edit = dynamic_cast<CTextLabel*>(view);
|
|
if (edit)
|
|
{
|
|
textLabel = edit;
|
|
originalTextColor = textLabel->getFontColor ();
|
|
textLabel->registerTextLabelListener (this);
|
|
textLabel->registerViewListener (this);
|
|
}
|
|
}
|
|
return controller->verifyView (view, attributes, description);
|
|
}
|
|
|
|
void controlBeginEdit (VSTGUI::CControl* pControl) override
|
|
{
|
|
Controller::controlBeginEdit (pControl);
|
|
}
|
|
|
|
void controlEndEdit (VSTGUI::CControl* pControl) override
|
|
{
|
|
Controller::controlEndEdit (pControl);
|
|
}
|
|
|
|
void valueChanged (CControl* pControl) override
|
|
{
|
|
if (textLabel == pControl)
|
|
{
|
|
textLabel->setFontColor (originalTextColor);
|
|
performValueChange (textLabel->getText ());
|
|
}
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
if (textLabel)
|
|
{
|
|
if (hasDifferentValues ())
|
|
{
|
|
CColor newColor (originalTextColor);
|
|
newColor.alpha /= 2;
|
|
textLabel->setFontColor (newColor);
|
|
textLabel->setText ("Multiple Values");
|
|
}
|
|
else
|
|
{
|
|
textLabel->setText (value.c_str ());
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void valueDisplayTruncated (UTF8StringPtr txt)
|
|
{
|
|
if (textLabel)
|
|
{
|
|
if (txt && *txt != 0)
|
|
textLabel->setAttribute (kCViewTooltipAttribute, static_cast<uint32_t> (textLabel->getText ().length () + 1), textLabel->getText ().data ());
|
|
else
|
|
textLabel->removeAttribute (kCViewTooltipAttribute);
|
|
}
|
|
|
|
}
|
|
|
|
void viewLostFocus (CView* view) override
|
|
{
|
|
if (view == textLabel)
|
|
{
|
|
SharedPointer<CTextEdit> textEdit = textLabel.cast<CTextEdit> ();
|
|
if (textEdit && textEdit->bWasReturnPressed)
|
|
{
|
|
textEdit->getFrame ()->doAfterEventProcessing ([=] () {
|
|
textEdit->takeFocus ();
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void onTextLabelTruncatedTextChanged (CTextLabel* label) override
|
|
{
|
|
UTF8StringPtr txt = label->getTruncatedText ();
|
|
valueDisplayTruncated (txt);
|
|
}
|
|
|
|
protected:
|
|
SharedPointer<CTextLabel> textLabel;
|
|
CColor originalTextColor;
|
|
};
|
|
|
|
//------------------------------------------------------------------------
|
|
class ScriptController : public TextController,
|
|
public IDialogController,
|
|
public TextEditorControllerAdapter
|
|
{
|
|
public:
|
|
using TextController::TextController;
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes,
|
|
const IUIDescription* description) override
|
|
{
|
|
if (editButton == nullptr)
|
|
{
|
|
auto button = dynamic_cast<CTextButton*> (view);
|
|
if (button)
|
|
editButton = button;
|
|
}
|
|
return TextController::verifyView (view, attributes, description);
|
|
}
|
|
|
|
void valueChanged (CControl* pControl) override
|
|
{
|
|
TextController::valueChanged (pControl);
|
|
if (editButton == pControl && pControl->getValue () == pControl->getMax ())
|
|
{
|
|
auto dc = new UIDialogController (this, editButton->getFrame ());
|
|
dc->run ("scripteditor", "Script Editor", "Close", nullptr, this,
|
|
UIEditController::getEditorDescription (), true);
|
|
}
|
|
}
|
|
|
|
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
if (auto name = attributes.getAttributeValue (IUIDescription::kCustomViewName))
|
|
{
|
|
if (*name == "TextEditor")
|
|
{
|
|
CPoint size;
|
|
attributes.getPointAttribute (UIViewCreator::kAttrSize, size);
|
|
auto view = createNewTextEditor ({0, 0, size.x, size.y}, this);
|
|
if (textEditor)
|
|
{
|
|
ITextEditor::Style style {};
|
|
description->getColor ("control.back", style.backColor);
|
|
description->getColor ("control.font", style.textColor);
|
|
description->getColor ("control.frame", style.selectionBackColor);
|
|
description->getColor ("control.frame", style.lineNumberTextColor);
|
|
description->getColor ("control.frame", style.frameColor);
|
|
if (auto font = description->getFont ("scripteditor.font"))
|
|
{
|
|
style.font = font;
|
|
style.lineNumbersFont = makeOwned<CFontDesc> (*font);
|
|
style.lineNumbersFont->setSize (style.lineNumbersFont->getSize () - 2);
|
|
}
|
|
textEditor->setStyle (style);
|
|
textEditor->setPlainText (textLabel->getText ().getString ());
|
|
}
|
|
return view;
|
|
}
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
void onDialogButton1Clicked (UIDialogController*) override {}
|
|
void onDialogButton2Clicked (UIDialogController*) override {}
|
|
void onDialogShow (UIDialogController*) override {}
|
|
|
|
void onTextEditorCreated (const ITextEditor& te) override
|
|
{
|
|
textEditor = &te;
|
|
Call::later ([This = shared (this)] () {
|
|
if (This->textEditor)
|
|
This->textEditor->handleCommand (ITextEditor::Command::TakeFocus);
|
|
});
|
|
}
|
|
|
|
void onTextEditorDestroyed (const ITextEditor& te) override
|
|
{
|
|
textEditor = nullptr;
|
|
auto text = te.getPlainText ();
|
|
if (text != textLabel->getText ().getString ())
|
|
performValueChange (text.data ());
|
|
te.resetController ();
|
|
}
|
|
|
|
protected:
|
|
SharedPointer<CTextButton> editButton;
|
|
const ITextEditor* textEditor {nullptr};
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class NumberController : public TextController
|
|
{
|
|
public:
|
|
NumberController (IController* baseController, const std::string& attrName)
|
|
: TextController (baseController, attrName)
|
|
{
|
|
}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes,
|
|
const IUIDescription* description) override
|
|
{
|
|
if (slider == nullptr)
|
|
{
|
|
auto* sliderView = dynamic_cast<CSlider*> (view);
|
|
if (sliderView)
|
|
slider = sliderView;
|
|
}
|
|
return TextController::verifyView (view, attributes, description);
|
|
}
|
|
|
|
void controlBeginEdit (VSTGUI::CControl* pControl) override
|
|
{
|
|
if (pControl == slider)
|
|
{
|
|
getAttributesController ()->beginLiveAttributeChange (
|
|
attrName, UIAttributes::doubleToString (slider->getValue ()));
|
|
}
|
|
TextController::controlBeginEdit (pControl);
|
|
}
|
|
|
|
void controlEndEdit (VSTGUI::CControl* pControl) override
|
|
{
|
|
if (pControl == slider)
|
|
{
|
|
getAttributesController ()->endLiveAttributeChange ();
|
|
}
|
|
TextController::controlEndEdit (pControl);
|
|
}
|
|
|
|
void valueChanged (CControl* pControl) override
|
|
{
|
|
TextController::valueChanged (pControl);
|
|
if (slider == pControl)
|
|
{
|
|
performValueChange (UIAttributes::doubleToString (slider->getValue ()).data ());
|
|
}
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
TextController::setValue (value);
|
|
if (slider)
|
|
{
|
|
float floatValue;
|
|
|
|
std::istringstream sstream (value);
|
|
sstream.imbue (std::locale::classic ());
|
|
sstream.precision (40);
|
|
sstream >> floatValue;
|
|
|
|
slider->setValue (floatValue);
|
|
slider->invalid ();
|
|
}
|
|
}
|
|
|
|
protected:
|
|
SharedPointer<CSlider> slider;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class MenuController : public TextController, public OptionMenuListenerAdapter, public CommandMenuItemTargetAdapter
|
|
{
|
|
public:
|
|
MenuController (IController* baseController, const std::string& attrName, UIDescription* description, bool addNoneItem = true, bool sortItems = true)
|
|
: TextController (baseController, attrName), description (description), addNoneItem (addNoneItem), sortItems (sortItems) {}
|
|
|
|
~MenuController () override
|
|
{
|
|
if (menu)
|
|
menu->unregisterOptionMenuListener (this);
|
|
}
|
|
|
|
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription*) override
|
|
{
|
|
if (menu == nullptr)
|
|
{
|
|
menu = dynamic_cast<COptionMenu*>(view);
|
|
if (menu)
|
|
menu->registerOptionMenuListener (this);
|
|
}
|
|
return TextController::verifyView (view, attributes, description);
|
|
}
|
|
|
|
using StringPtrList =std::list<const std::string*>;
|
|
virtual void collectMenuItemNames (StringPtrList& names) = 0;
|
|
virtual void validateMenuEntry (CCommandMenuItem* item) {}
|
|
|
|
virtual void addMenuEntry (const std::string* entryName)
|
|
{
|
|
CCommandMenuItem* item = new CCommandMenuItem (CCommandMenuItem::Desc{entryName->data (), this});
|
|
validateMenuEntry (item);
|
|
menu->addEntry (item);
|
|
if (textLabel->getText () == *entryName)
|
|
{
|
|
int32_t index = menu->getNbEntries () - 1;
|
|
menu->setValue ((float)index);
|
|
menu->setCurrent (index);
|
|
}
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
TextController::setValue (value);
|
|
}
|
|
|
|
void onOptionMenuPrePopup (COptionMenu* optMenu) override
|
|
{
|
|
optMenu->removeAllEntry ();
|
|
if (addNoneItem)
|
|
optMenu->addEntry (new CCommandMenuItem (CCommandMenuItem::Desc{"None", 100, this}));
|
|
StringPtrList names;
|
|
collectMenuItemNames (names);
|
|
if (sortItems)
|
|
names.sort (UIEditController::std__stringCompare);
|
|
if (addNoneItem && !names.empty ())
|
|
optMenu->addSeparator ();
|
|
for (const auto& name : names)
|
|
addMenuEntry (name);
|
|
}
|
|
|
|
bool onCommandMenuItemSelected (CCommandMenuItem* item) override
|
|
{
|
|
performValueChange (item->getTag () == 100 ? UTF8String ("") : item->getTitle ());
|
|
return true;
|
|
}
|
|
|
|
void valueDisplayTruncated (UTF8StringPtr txt) override
|
|
{
|
|
if (textLabel && menu)
|
|
{
|
|
if (txt && *txt != 0)
|
|
menu->setAttribute (kCViewTooltipAttribute, static_cast<uint32_t> (textLabel->getText ().length () + 1), textLabel->getText ().data ());
|
|
else
|
|
menu->removeAttribute (kCViewTooltipAttribute);
|
|
}
|
|
|
|
}
|
|
|
|
protected:
|
|
SharedPointer<UIDescription> description;
|
|
SharedPointer<COptionMenu> menu;
|
|
|
|
bool addNoneItem;
|
|
bool sortItems;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class ColorController : public MenuController
|
|
{
|
|
public:
|
|
ColorController (IController* baseController, const std::string& attrName, UIDescription* description)
|
|
: MenuController (baseController, attrName, description) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
description->collectColorNames (names);
|
|
}
|
|
|
|
void validateMenuEntry (CCommandMenuItem* item) override
|
|
{
|
|
CColor color;
|
|
if (description->getColor (item->getTitle (), color))
|
|
{
|
|
item->setIcon (createColorIcon (color));
|
|
}
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
MenuController::setValue (value);
|
|
if (colorView)
|
|
{
|
|
if (hasDifferentValues ())
|
|
{
|
|
colorView->color = kTransparentCColor;
|
|
}
|
|
else
|
|
{
|
|
CColor color;
|
|
if (description->getColor (value.c_str (), color))
|
|
{
|
|
colorView->color = color;
|
|
}
|
|
else
|
|
{
|
|
colorView->color = kTransparentCColor;
|
|
}
|
|
}
|
|
colorView->invalid ();
|
|
}
|
|
}
|
|
|
|
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
const std::string* attr = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
|
if (attr && *attr == "ColorView")
|
|
{
|
|
colorView = new ColorView ();
|
|
return colorView;
|
|
}
|
|
return nullptr;
|
|
}
|
|
protected:
|
|
class ColorView : public CView
|
|
{
|
|
public:
|
|
ColorView () : CView (CRect (0, 0, 0, 0)) ,color (kTransparentCColor) {}
|
|
void draw (CDrawContext* context) override
|
|
{
|
|
context->setFillColor (color);
|
|
context->setDrawMode (kAliasing);
|
|
context->drawRect (getViewSize (), kDrawFilled);
|
|
}
|
|
CColor color;
|
|
};
|
|
SharedPointer<ColorView> colorView;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class GradientController : public MenuController
|
|
{
|
|
public:
|
|
GradientController (IController* baseController, const std::string& attrName, UIDescription* description)
|
|
: MenuController (baseController, attrName, description) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
description->collectGradientNames (names);
|
|
}
|
|
|
|
void validateMenuEntry (CCommandMenuItem* item) override
|
|
{
|
|
const CCoord size = 15;
|
|
if (CGradient* gradient = description->getGradient (item->getTitle ()))
|
|
{
|
|
if (auto context = COffscreenContext::create ({size, size}))
|
|
{
|
|
context->beginDraw ();
|
|
SharedPointer<CGraphicsPath> path = owned (context->createGraphicsPath ());
|
|
path->addRect (CRect (0, 0, size, size));
|
|
context->fillLinearGradient(path, *gradient, CPoint (0, 0), CPoint (size, 0));
|
|
context->endDraw ();
|
|
item->setIcon (context->getBitmap ());
|
|
}
|
|
}
|
|
}
|
|
|
|
void setValue (const std::string& value) override
|
|
{
|
|
MenuController::setValue (value);
|
|
if (gradientView)
|
|
{
|
|
if (hasDifferentValues ())
|
|
{
|
|
gradientView->gradient = nullptr;
|
|
}
|
|
else
|
|
{
|
|
gradientView->gradient = description->getGradient (value.c_str ());
|
|
}
|
|
gradientView->invalid ();
|
|
}
|
|
}
|
|
|
|
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override
|
|
{
|
|
const std::string* attr = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
|
if (attr && *attr == "GradientView")
|
|
{
|
|
gradientView = new GradientView ();
|
|
return gradientView;
|
|
}
|
|
return nullptr;
|
|
}
|
|
protected:
|
|
class GradientView : public CView
|
|
{
|
|
public:
|
|
GradientView () : CView (CRect (0, 0, 0, 0)) {}
|
|
void draw (CDrawContext* context) override
|
|
{
|
|
if (gradient == nullptr)
|
|
return;
|
|
CRect r = getViewSize ();
|
|
SharedPointer<CGraphicsPath> path = owned (context->createGraphicsPath ());
|
|
path->addRect (r);
|
|
context->fillLinearGradient (path, *gradient, r.getTopLeft (), r.getTopRight ());
|
|
}
|
|
SharedPointer<CGradient> gradient;
|
|
};
|
|
SharedPointer<GradientView> gradientView;
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class TagController : public MenuController
|
|
{
|
|
public:
|
|
TagController (IController* baseController, const std::string& attrName, UIDescription* description)
|
|
: MenuController (baseController, attrName, description, true, false) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
description->collectControlTagNames (names);
|
|
}
|
|
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class BitmapController : public MenuController
|
|
{
|
|
public:
|
|
BitmapController (IController* baseController, const std::string& attrName, UIDescription* description)
|
|
: MenuController (baseController, attrName, description) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
description->collectBitmapNames (names);
|
|
}
|
|
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class FontController : public MenuController
|
|
{
|
|
public:
|
|
FontController (IController* baseController, const std::string& attrName, UIDescription* description)
|
|
: MenuController (baseController, attrName, description) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
description->collectFontNames (names);
|
|
}
|
|
|
|
};
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class ListController : public MenuController
|
|
{
|
|
public:
|
|
ListController (IController* baseController, const std::string& attrName, UIDescription* description, UISelection* selection)
|
|
: MenuController (baseController, attrName, description, false, false), selection (selection) {}
|
|
|
|
void collectMenuItemNames (StringPtrList& names) override
|
|
{
|
|
const auto* viewFactory =
|
|
dynamic_cast<const IViewFactoryEditingSupport*> (description->getViewFactory ());
|
|
if (viewFactory)
|
|
{
|
|
viewFactory->getPossibleAttributeListValues (selection->first (), attrName, names);
|
|
}
|
|
}
|
|
|
|
protected:
|
|
SharedPointer<UISelection> selection;
|
|
};
|
|
|
|
|
|
} // VSTGUI
|
|
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
UIAttributesController::UIAttributesController (IController* baseController, UISelection* selection, UIUndoManager* undoManager, UIDescription* description)
|
|
: DelegationController (baseController)
|
|
, selection (selection)
|
|
, undoManager (undoManager)
|
|
, editDescription (description)
|
|
, liveAction (nullptr)
|
|
, viewNameLabel (nullptr)
|
|
, attributeView (nullptr)
|
|
, currentAttributeName (nullptr)
|
|
{
|
|
selection->registerListener (this);
|
|
undoManager->registerListener (this);
|
|
description->registerListener (this);
|
|
|
|
UIEditController::getEditorDescription ()->getColor ("control.font", attributeNameColor);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
UIAttributesController::~UIAttributesController ()
|
|
{
|
|
if (viewNameLabel)
|
|
viewNameLabel->unregisterViewListener (this);
|
|
if (attributeView)
|
|
attributeView->unregisterViewListener (this);
|
|
selection->unregisterListener (this);
|
|
undoManager->unregisterListener (this);
|
|
editDescription->unregisterListener (this);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::beginLiveAttributeChange (const std::string& name, const std::string& currentValue)
|
|
{
|
|
liveAction = new AttributeChangeAction (editDescription, selection, name, currentValue);
|
|
undoManager->startGroupAction (liveAction->getName ());
|
|
undoManager->pushAndPerform (new AttributeChangeAction (editDescription, selection, name, currentValue));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::endLiveAttributeChange ()
|
|
{
|
|
if (liveAction)
|
|
{
|
|
liveAction->undo ();
|
|
undoManager->pushAndPerform (liveAction);
|
|
liveAction = nullptr;
|
|
undoManager->endGroupAction ();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::performAttributeChange (const std::string& name, const std::string& value)
|
|
{
|
|
IAction* action = new AttributeChangeAction (editDescription, selection, name, value);
|
|
if (liveAction)
|
|
{
|
|
delete liveAction;
|
|
liveAction = action;
|
|
action->perform ();
|
|
}
|
|
else
|
|
undoManager->pushAndPerform (action);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::valueChanged (CControl* control)
|
|
{
|
|
switch (control->getTag ())
|
|
{
|
|
case kSearchFieldTag:
|
|
{
|
|
if (auto sf = dynamic_cast<CSearchTextEdit*> (control))
|
|
{
|
|
filterString = sf->getText ();
|
|
rebuildAttributesView ();
|
|
auto attributes = editDescription->getCustomAttributes ("UIAttributesController", true);
|
|
if (attributes)
|
|
{
|
|
attributes->setAttribute("UIAttributesController", filterString);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
CView* UIAttributesController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
|
{
|
|
if (attributeView == nullptr)
|
|
{
|
|
auto* rcv = dynamic_cast<CRowColumnView*>(view);
|
|
if (rcv)
|
|
{
|
|
attributeView = rcv;
|
|
attributeView->registerViewListener (this);
|
|
}
|
|
}
|
|
if (searchField == nullptr)
|
|
{
|
|
auto* textEdit = dynamic_cast<CTextEdit*>(view);
|
|
if (textEdit && textEdit->getTag () == kSearchFieldTag)
|
|
{
|
|
searchField = textEdit;
|
|
auto attrs = editDescription->getCustomAttributes ("UIAttributesController", true);
|
|
if (attrs)
|
|
{
|
|
const std::string* searchText = attrs->getAttributeValue ("SearchString");
|
|
if (searchText)
|
|
{
|
|
searchField->setText (searchText->c_str ());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (viewNameLabel == nullptr)
|
|
{
|
|
auto* textLabel = dynamic_cast<CTextLabel*>(view);
|
|
if (textLabel && textLabel->getTag () == kViewNameTag)
|
|
{
|
|
viewNameLabel = textLabel;
|
|
viewNameLabel->setText ("No Selection");
|
|
viewNameLabel->registerViewListener (this);
|
|
}
|
|
}
|
|
return DelegationController::verifyView (view, attributes, description);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
IControlListener* UIAttributesController::getControlListener (UTF8StringPtr name)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
IController* UIAttributesController::createSubController (IdStringPtr _name, const IUIDescription* description)
|
|
{
|
|
UTF8StringView name (_name);
|
|
if (currentAttributeName)
|
|
{
|
|
if (name == "TextController")
|
|
{
|
|
return new UIAttributeControllers::TextController (this, *currentAttributeName);
|
|
}
|
|
else if (name == "NumberController")
|
|
{
|
|
return new UIAttributeControllers::NumberController (this, *currentAttributeName);
|
|
}
|
|
else if (name == "BooleanController")
|
|
{
|
|
return new UIAttributeControllers::BooleanController (this, *currentAttributeName);
|
|
}
|
|
else if (name == "ColorController")
|
|
{
|
|
return new UIAttributeControllers::ColorController (this, *currentAttributeName, editDescription);
|
|
}
|
|
else if (name == "GradientController")
|
|
{
|
|
return new UIAttributeControllers::GradientController (this, *currentAttributeName, editDescription);
|
|
}
|
|
else if (name == "TagController")
|
|
{
|
|
return new UIAttributeControllers::TagController (this, *currentAttributeName, editDescription);
|
|
}
|
|
else if (name == "BitmapController")
|
|
{
|
|
return new UIAttributeControllers::BitmapController (this, *currentAttributeName, editDescription);
|
|
}
|
|
else if (name == "FontController")
|
|
{
|
|
return new UIAttributeControllers::FontController (this, *currentAttributeName, editDescription);
|
|
}
|
|
else if (name == "ListController")
|
|
{
|
|
return new UIAttributeControllers::ListController (this, *currentAttributeName, editDescription, selection);
|
|
}
|
|
else if (name == "TextAlignmentController")
|
|
{
|
|
return new UIAttributeControllers::TextAlignmentController (this, *currentAttributeName);
|
|
}
|
|
else if (name == "AutosizeController")
|
|
{
|
|
return new UIAttributeControllers::AutosizeController (this, selection, *currentAttributeName);
|
|
}
|
|
else if (name == "ScriptController")
|
|
{
|
|
return new UIAttributeControllers::ScriptController (this, *currentAttributeName);
|
|
}
|
|
}
|
|
return controller->createSubController (name, description);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescTagChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescColorChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescFontChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescBitmapChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescTemplateChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUIDescGradientChanged (UIDescription* desc)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::selectionDidChange (UISelection*)
|
|
{
|
|
if (!rebuildRequested && attributeView)
|
|
{
|
|
if (auto frame = attributeView->getFrame ())
|
|
{
|
|
if (frame->inEventProcessing ())
|
|
{
|
|
rebuildRequested = true;
|
|
frame->doAfterEventProcessing ([Self = shared (this)] () {
|
|
Self->rebuildAttributesView ();
|
|
Self->rebuildRequested = false;
|
|
});
|
|
}
|
|
}
|
|
if (!rebuildRequested)
|
|
rebuildAttributesView ();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::selectionViewsDidChange (UISelection*)
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::onUndoManagerChange ()
|
|
{
|
|
validateAttributeViews ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::validateAttributeViews ()
|
|
{
|
|
const auto* viewFactory = static_cast<const IViewFactory*> (editDescription->getViewFactory ());
|
|
|
|
for (auto& controller : attributeControllers)
|
|
{
|
|
std::string attrValue;
|
|
bool first = true;
|
|
bool hasDifferentValues = false;
|
|
for (const auto& view : *selection)
|
|
{
|
|
std::string temp;
|
|
viewFactory->getAttributeValue (view, controller->getAttributeName (), temp, editDescription);
|
|
if (temp != attrValue && !first)
|
|
hasDifferentValues = true;
|
|
attrValue = temp;
|
|
first = false;
|
|
}
|
|
controller->hasDifferentValues (hasDifferentValues);
|
|
controller->setValue (attrValue);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
CView* UIAttributesController::createValueViewForAttributeType (const IViewFactory* viewFactory,
|
|
CView* view,
|
|
const std::string& attrName,
|
|
IViewCreator::AttrType attrType)
|
|
{
|
|
auto editorDescription = UIEditController::getEditorDescription ();
|
|
if (!editDescription)
|
|
return nullptr;
|
|
switch (attrType)
|
|
{
|
|
case IViewCreator::kFontType:
|
|
return editorDescription->createView ("attributes.font", this);
|
|
case IViewCreator::kBitmapType:
|
|
return editorDescription->createView ("attributes.bitmap", this);
|
|
case IViewCreator::kTagType:
|
|
return editorDescription->createView ("attributes.tag", this);
|
|
case IViewCreator::kColorType:
|
|
return editorDescription->createView ("attributes.color", this);
|
|
case IViewCreator::kGradientType:
|
|
return editorDescription->createView ("attributes.gradient", this);
|
|
case IViewCreator::kBooleanType:
|
|
return editorDescription->createView ("attributes.boolean", this);
|
|
case IViewCreator::kListType:
|
|
return editorDescription->createView ("attributes.list", this);
|
|
case IViewCreator::kScriptType:
|
|
return editorDescription->createView ("attributes.script", this);
|
|
case IViewCreator::kFloatType:
|
|
case IViewCreator::kIntegerType:
|
|
{
|
|
double minValue, maxValue;
|
|
const auto* viewFactoryEditing =
|
|
dynamic_cast<const IViewFactoryEditingSupport*> (viewFactory);
|
|
if (viewFactoryEditing->getAttributeValueRange (view, attrName, minValue, maxValue))
|
|
{
|
|
CView* valueView = editorDescription->createView ("attributes.number", this);
|
|
if (valueView)
|
|
{
|
|
if (auto container = valueView->asViewContainer ())
|
|
{
|
|
std::vector<CSlider*> sliders;
|
|
if (container->getChildViewsOfType<CSlider> (sliders) == 1)
|
|
{
|
|
sliders[0]->setMin (static_cast<float> (minValue));
|
|
sliders[0]->setMax (static_cast<float> (maxValue));
|
|
}
|
|
}
|
|
return valueView;
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
return editorDescription->createView ("attributes.text", this);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
CView* UIAttributesController::createViewForAttribute (const std::string& attrName)
|
|
{
|
|
const CCoord height = 18;
|
|
const CCoord width = 160;
|
|
const CCoord margin = 2;
|
|
CViewContainer* result = new CViewContainer (CRect (0, 0, width, height+2));
|
|
result->setAutosizeFlags (kAutosizeLeft|kAutosizeRight|kAutosizeColumn);
|
|
result->setTransparency (true);
|
|
|
|
CCoord middle = width/2;
|
|
CTextLabel* label = new CTextLabel (CRect (5, 1, middle - margin, height+1), attrName.c_str ());
|
|
label->setTextTruncateMode (CTextLabel::kTruncateHead);
|
|
label->setTransparency (true);
|
|
label->setHoriAlign (kRightText);
|
|
label->setFontColor (attributeNameColor);
|
|
label->setFont (kNormalFontSmall);
|
|
label->setAutosizeFlags (kAutosizeAll);
|
|
|
|
result->addView (label);
|
|
|
|
bool hasDifferentValues = false;
|
|
|
|
const auto* viewFactory = editDescription->getViewFactory ();
|
|
const auto* viewFactoryEditing = dynamic_cast<const IViewFactoryEditingSupport*> (viewFactory);
|
|
|
|
std::string attrValue;
|
|
bool first = true;
|
|
for (const auto& view : *selection)
|
|
{
|
|
std::string temp;
|
|
viewFactory->getAttributeValue (view, attrName, temp, editDescription);
|
|
if (temp != attrValue && !first)
|
|
hasDifferentValues = true;
|
|
attrValue = temp;
|
|
first = false;
|
|
}
|
|
|
|
CRect r (middle+margin, 1, width-5, height+1);
|
|
CView* valueView = nullptr;
|
|
|
|
if (attrName == "text-alignment")
|
|
{
|
|
valueView = UIEditController::getEditorDescription ()->createView ("attributes.text.alignment", this);
|
|
}
|
|
else if (attrName == "autosize")
|
|
{
|
|
valueView = UIEditController::getEditorDescription ()->createView ("attributes.view.autosize", this);
|
|
}
|
|
|
|
if (valueView == nullptr)
|
|
{
|
|
CView* firstView = selection->first ();
|
|
auto attrType = viewFactoryEditing->getAttributeType (firstView, attrName);
|
|
valueView = createValueViewForAttributeType (viewFactory, firstView, attrName, attrType);
|
|
}
|
|
if (valueView == nullptr) // fallcack if attributes.text template not defined
|
|
{
|
|
IController* controller = new UIAttributeControllers::TextController (this, *currentAttributeName);
|
|
auto* textEdit = new CTextEdit (r, this, -1);
|
|
textEdit->setText (attrValue.c_str ());
|
|
textEdit->setTransparency (true);
|
|
textEdit->setFontColor (kBlackCColor);
|
|
textEdit->setFont (kNormalFontSmall);
|
|
textEdit->setListener (controller);
|
|
valueView = textEdit;
|
|
valueView->setAttribute (kCViewControllerAttribute, controller);
|
|
}
|
|
if (valueView)
|
|
{
|
|
IController* controller = getViewController (valueView, true);
|
|
if (controller)
|
|
{
|
|
auto* c = dynamic_cast<UIAttributeControllers::Controller*>(controller);
|
|
if (c)
|
|
{
|
|
c->hasDifferentValues (hasDifferentValues);
|
|
c->setValue (attrValue);
|
|
attributeControllers.emplace_back (c);
|
|
}
|
|
}
|
|
r.setHeight (valueView->getHeight ());
|
|
valueView->setViewSize (r);
|
|
valueView->setMouseableArea (r);
|
|
result->addView (valueView);
|
|
r = result->getViewSize ();
|
|
r.setHeight (valueView->getHeight()+2);
|
|
result->setViewSize (r);
|
|
result->setMouseableArea (r);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::getConsolidatedAttributeNames (StringList& attrNames, const std::string& filter)
|
|
{
|
|
const auto* viewFactory =
|
|
dynamic_cast<const IViewFactoryEditingSupport*> (editDescription->getViewFactory ());
|
|
vstgui_assert (viewFactory);
|
|
if (!viewFactory)
|
|
return;
|
|
for (const auto& view : *selection)
|
|
{
|
|
StringList temp;
|
|
if (viewFactory->getAttributeNamesForView (view, temp))
|
|
{
|
|
StringList toRemove;
|
|
if (attrNames.empty ())
|
|
attrNames = temp;
|
|
else
|
|
{
|
|
for (auto& attrName : attrNames)
|
|
{
|
|
bool found = std::find (temp.begin (), temp.end (), attrName) != temp.end ();
|
|
if (!found)
|
|
{
|
|
toRemove.emplace_back (attrName);
|
|
temp.remove (attrName);
|
|
}
|
|
}
|
|
}
|
|
if (!filter.empty ())
|
|
{
|
|
for (auto rit = temp.rbegin (); rit != temp.rend (); ++rit)
|
|
{
|
|
std::string lowerCaseName (*rit);
|
|
std::transform (lowerCaseName.begin (), lowerCaseName.end (), lowerCaseName.begin (), ::tolower);
|
|
if (lowerCaseName.find (filter) == std::string::npos)
|
|
toRemove.emplace_back (*rit);
|
|
}
|
|
}
|
|
for (auto& attrName : toRemove)
|
|
{
|
|
attrNames.remove (attrName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::rebuildAttributesView ()
|
|
{
|
|
auto viewFactory =
|
|
dynamic_cast<const IViewFactoryEditingSupport*> (editDescription->getViewFactory ());
|
|
if (attributeView == nullptr || viewFactory == nullptr)
|
|
return;
|
|
|
|
attributeView->invalid ();
|
|
attributeView->removeAll ();
|
|
attributeControllers.clear ();
|
|
|
|
std::string filter (filterString);
|
|
std::transform (filter.begin (), filter.end (), filter.begin (), ::tolower);
|
|
|
|
if (viewNameLabel)
|
|
{
|
|
int32_t selectedViews = selection->total ();
|
|
if (selectedViews > 0)
|
|
{
|
|
UTF8StringPtr viewname = nullptr;
|
|
for (const auto& view : *selection)
|
|
{
|
|
UTF8StringPtr name = viewFactory->getViewDisplayName (view);
|
|
if (viewname != nullptr && UTF8StringView (name) != viewname)
|
|
{
|
|
viewname = nullptr;
|
|
break;
|
|
}
|
|
viewname = name;
|
|
}
|
|
if (viewname != nullptr)
|
|
{
|
|
if (selectedViews == 1)
|
|
viewNameLabel->setText (viewname);
|
|
else
|
|
{
|
|
std::stringstream str;
|
|
str << selectedViews << "x " << viewname;
|
|
viewNameLabel->setText (str.str ().c_str ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
std::stringstream str;
|
|
str << selectedViews << "x different views";
|
|
viewNameLabel->setText (str.str ().c_str ());
|
|
}
|
|
}
|
|
else
|
|
{
|
|
viewNameLabel->setText ("No Selection");
|
|
}
|
|
}
|
|
|
|
|
|
StringList attrNames;
|
|
getConsolidatedAttributeNames (attrNames, filter);
|
|
if (attrNames.empty ())
|
|
{
|
|
CRect r (attributeView->getViewSize ());
|
|
r.setHeight (0);
|
|
attributeView->setViewSize (r);
|
|
attributeView->setMouseableArea (r);
|
|
}
|
|
else
|
|
{
|
|
CCoord width = attributeView->getWidth () - (attributeView->getMargin ().left + attributeView->getMargin ().right);
|
|
for (const auto& name : attrNames)
|
|
{
|
|
currentAttributeName = &name;
|
|
CView* view = createViewForAttribute (name);
|
|
if (view)
|
|
{
|
|
CRect r = view->getViewSize ();
|
|
r.setWidth (width);
|
|
view->setViewSize (r);
|
|
view->setMouseableArea (r);
|
|
attributeView->addView (view);
|
|
}
|
|
}
|
|
currentAttributeName = nullptr;
|
|
attributeView->sizeToFit ();
|
|
attributeView->setMouseableArea (attributeView->getViewSize ());
|
|
}
|
|
attributeView->invalid ();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
void UIAttributesController::viewWillDelete (CView* view)
|
|
{
|
|
if (view == attributeView)
|
|
attributeView = nullptr;
|
|
else if (view == viewNameLabel)
|
|
viewNameLabel = nullptr;
|
|
|
|
view->unregisterViewListener (this);
|
|
}
|
|
|
|
} // VSTGUI
|
|
|
|
#endif // VSTGUI_LIVE_EDITING
|