Initial release
This commit is contained in:
+889
@@ -0,0 +1,889 @@
|
||||
// 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 "uigradientscontroller.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "uibasedatasource.h"
|
||||
#include "iaction.h"
|
||||
#include "uieditcontroller.h"
|
||||
#include "uidialogcontroller.h"
|
||||
#include "uicolorchoosercontroller.h"
|
||||
#include "uicolor.h"
|
||||
#include "../../lib/cgradientview.h"
|
||||
#include "../../lib/ifocusdrawing.h"
|
||||
#include "../../lib/cgraphicspath.h"
|
||||
#include "../../lib/cdrawcontext.h"
|
||||
#include "../../lib/events.h"
|
||||
#include "../../lib/controls/coptionmenu.h"
|
||||
#include <algorithm>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
struct IUIColorStopEditViewListener
|
||||
{
|
||||
virtual ~IUIColorStopEditViewListener () noexcept = default;
|
||||
virtual void onChange () = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
class UIColorStopEditView
|
||||
: public CView,
|
||||
protected ListenerProvider<UIColorStopEditView, IUIColorStopEditViewListener>,
|
||||
public IFocusDrawing,
|
||||
public UIColorListenerAdapter
|
||||
{
|
||||
public:
|
||||
UIColorStopEditView (UIColor* editColor);
|
||||
~UIColorStopEditView () override;
|
||||
|
||||
void setGradient (CGradient* gradient);
|
||||
|
||||
void selectNextColorStop ();
|
||||
void selectPrevColorStop ();
|
||||
void setEditColor (CColor color);
|
||||
void setCurrentStartOffset (double startOffset);
|
||||
double getSelectedColorStart () const { return editStartOffset; }
|
||||
const GradientColorStopMap& getColorStopMap () const { return colorStopMap; }
|
||||
|
||||
using ListenerProvider<UIColorStopEditView, IUIColorStopEditViewListener>::registerListener;
|
||||
using ListenerProvider<UIColorStopEditView, IUIColorStopEditViewListener>::unregisterListener;
|
||||
private:
|
||||
void draw (CDrawContext* context) override;
|
||||
bool drawFocusOnTop () override;
|
||||
bool getFocusPath (CGraphicsPath& outPath) override;
|
||||
void onKeyboardEvent (KeyboardEvent& event) override;
|
||||
CMouseEventResult onMouseDown (CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseUp (CPoint& where, const CButtonState& buttons) override;
|
||||
CMouseEventResult onMouseMoved (CPoint& where, const CButtonState& buttons) override;
|
||||
void uiColorChanged (UIColor* c) override;
|
||||
|
||||
double gradientStartPosFromMousePos (const CPoint& where) const;
|
||||
|
||||
void addColorStop (double startOffset);
|
||||
void removeColorStop (double startOffset);
|
||||
|
||||
SharedPointer<UIColor> editColor;
|
||||
SharedPointer<CGradient> gradient;
|
||||
GradientColorStopMap colorStopMap;
|
||||
double editStartOffset;
|
||||
CCoord stopWidth;
|
||||
|
||||
double mouseDownStartPosOffset;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorStopEditView::UIColorStopEditView (UIColor* editColor)
|
||||
: CView (CRect (0, 0, 0, 0))
|
||||
, editColor (editColor)
|
||||
, editStartOffset (-1.)
|
||||
, mouseDownStartPosOffset (0.)
|
||||
{
|
||||
editColor->registerListener (this);
|
||||
setWantsFocus (true);
|
||||
stopWidth = 12.;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIColorStopEditView::~UIColorStopEditView ()
|
||||
{
|
||||
editColor->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::selectNextColorStop ()
|
||||
{
|
||||
auto pos = colorStopMap.find (getSelectedColorStart ());
|
||||
pos++;
|
||||
if (pos == colorStopMap.end ())
|
||||
{
|
||||
pos = colorStopMap.begin ();
|
||||
}
|
||||
editStartOffset = pos->first;
|
||||
*editColor = pos->second;
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::selectPrevColorStop ()
|
||||
{
|
||||
auto pos = colorStopMap.find (getSelectedColorStart ());
|
||||
if (pos == colorStopMap.begin ())
|
||||
pos = colorStopMap.end ();
|
||||
pos--;
|
||||
editStartOffset = pos->first;
|
||||
*editColor = pos->second;
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::setEditColor (CColor color)
|
||||
{
|
||||
if (editColor)
|
||||
{
|
||||
editColor->beginEdit ();
|
||||
*editColor = color;
|
||||
editColor->endEdit ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::setCurrentStartOffset (double startOffset)
|
||||
{
|
||||
if (startOffset < 0.)
|
||||
startOffset = 0.;
|
||||
else if (startOffset > 1.)
|
||||
startOffset = 1.;
|
||||
auto pos = colorStopMap.find (getSelectedColorStart ());
|
||||
if (pos != colorStopMap.end () && pos->first != startOffset)
|
||||
{
|
||||
CColor color = pos->second;
|
||||
colorStopMap.erase (pos);
|
||||
colorStopMap.emplace (startOffset, color);
|
||||
editStartOffset = startOffset;
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
invalid ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::addColorStop (double startOffset)
|
||||
{
|
||||
colorStopMap.emplace (startOffset, editColor->base ());
|
||||
editStartOffset = startOffset;
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::removeColorStop (double startOffset)
|
||||
{
|
||||
if (colorStopMap.size () < 3)
|
||||
return;
|
||||
if (getSelectedColorStart () == startOffset)
|
||||
selectNextColorStop ();
|
||||
colorStopMap.erase (startOffset);
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::onKeyboardEvent (KeyboardEvent& event)
|
||||
{
|
||||
if (event.type != EventType::KeyDown)
|
||||
return;
|
||||
switch (event.virt)
|
||||
{
|
||||
case VirtualKey::Left:
|
||||
{
|
||||
if (event.modifiers.empty ())
|
||||
{
|
||||
selectPrevColorStop ();
|
||||
event.consumed = true;
|
||||
}
|
||||
else if (event.modifiers.is (ModifierKey::Alt))
|
||||
{
|
||||
setCurrentStartOffset (editStartOffset - 0.001);
|
||||
event.consumed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VirtualKey::Right:
|
||||
{
|
||||
if (event.modifiers.empty ())
|
||||
{
|
||||
selectNextColorStop ();
|
||||
event.consumed = true;
|
||||
}
|
||||
else if (event.modifiers.is(ModifierKey::Alt))
|
||||
{
|
||||
setCurrentStartOffset (editStartOffset + 0.001);
|
||||
event.consumed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VirtualKey::Back:
|
||||
{
|
||||
if (event.modifiers.empty ())
|
||||
{
|
||||
removeColorStop (getSelectedColorStart ());
|
||||
event.consumed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
double UIColorStopEditView::gradientStartPosFromMousePos (const CPoint& where) const
|
||||
{
|
||||
return (where.x - (getViewSize ().left + (stopWidth / 2.))) / (getWidth () - stopWidth);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorStopEditView::onMouseDown (CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
if (buttons.isDoubleClick ())
|
||||
{
|
||||
double pos = gradientStartPosFromMousePos (where);
|
||||
if (pos >= 0. && pos <= 1.)
|
||||
{
|
||||
addColorStop (pos);
|
||||
}
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
else if (buttons.isLeftButton ())
|
||||
{
|
||||
getFrame ()->setFocusView (this);
|
||||
double pos = gradientStartPosFromMousePos (where);
|
||||
double range = (stopWidth / getWidth ()) / 2.;
|
||||
for (auto& colorStop : colorStopMap)
|
||||
{
|
||||
if (pos >= colorStop.first - range && pos <= colorStop.first + range)
|
||||
{
|
||||
if (buttons.getModifierState () == kAlt)
|
||||
{
|
||||
removeColorStop (colorStop.first);
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
if (editStartOffset != colorStop.first)
|
||||
{
|
||||
editStartOffset = colorStop.first;
|
||||
*editColor = colorStop.second;
|
||||
forEachListener ([] (IUIColorStopEditViewListener* l) { l->onChange (); });
|
||||
}
|
||||
mouseDownStartPosOffset = pos - editStartOffset;
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
}
|
||||
}
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorStopEditView::onMouseUp (CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIColorStopEditView::onMouseMoved (CPoint& where, const CButtonState& buttons)
|
||||
{
|
||||
if (buttons.isLeftButton ())
|
||||
{
|
||||
double pos = gradientStartPosFromMousePos (where) - mouseDownStartPosOffset;
|
||||
setCurrentStartOffset (pos);
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
return kMouseEventNotHandled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::uiColorChanged (UIColor* c)
|
||||
{
|
||||
invalid ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::setGradient (CGradient* inGradient)
|
||||
{
|
||||
colorStopMap = inGradient->getColorStops ();
|
||||
auto it = colorStopMap.find (editStartOffset);
|
||||
if (it == colorStopMap.end ())
|
||||
editStartOffset = colorStopMap.begin ()->first;
|
||||
gradient = inGradient;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIColorStopEditView::draw (CDrawContext* context)
|
||||
{
|
||||
CDrawContext::Transform t (*context, CGraphicsTransform ().translate (getViewSize ().left, getViewSize ().top));
|
||||
|
||||
context->setDrawMode (kAliasing);
|
||||
|
||||
SharedPointer<CGraphicsPath> gradientPath = owned (context->createGraphicsPath ());
|
||||
gradientPath->addRect (CRect (stopWidth / 2., 0., getWidth () - stopWidth / 2., getHeight ()));
|
||||
context->fillLinearGradient (gradientPath, *gradient, CPoint (stopWidth / 2., 0), CPoint (getWidth () - stopWidth / 2, 0));
|
||||
|
||||
CCoord width = getWidth () - stopWidth;
|
||||
CCoord height = (getHeight () / 2.);
|
||||
SharedPointer<CGraphicsPath> path = owned (context->createGraphicsPath ());
|
||||
path->beginSubpath (CPoint (stopWidth / 2., 0));
|
||||
path->addLine (CPoint (0, height));
|
||||
path->addLine (CPoint (stopWidth, height));
|
||||
path->closeSubpath ();
|
||||
|
||||
context->setFrameColor (kBlackCColor);
|
||||
context->setLineWidth (1.1);
|
||||
context->setLineStyle (kLineSolid);
|
||||
context->setDrawMode (kAntiAliasing);
|
||||
|
||||
CColor selectedColor;
|
||||
|
||||
context->setGlobalAlpha (0.5f);
|
||||
for (auto& colorStop : colorStopMap)
|
||||
{
|
||||
if (colorStop.first == getSelectedColorStart ())
|
||||
{
|
||||
selectedColor = colorStop.second;
|
||||
}
|
||||
else
|
||||
{
|
||||
CGraphicsTransform offset;
|
||||
offset.translate (colorStop.first * width, getHeight () / 4.);
|
||||
if (colorStop.second.getLuma () < 127)
|
||||
context->setFrameColor (kWhiteCColor);
|
||||
else
|
||||
context->setFrameColor (kBlackCColor);
|
||||
context->drawGraphicsPath (path, CDrawContext::kPathStroked, &offset);
|
||||
}
|
||||
}
|
||||
|
||||
context->setGlobalAlpha (1.f);
|
||||
if (getSelectedColorStart () >= 0.)
|
||||
{
|
||||
CGraphicsTransform offset;
|
||||
offset.translate (getSelectedColorStart () * width, getHeight() / 4.);
|
||||
if (selectedColor.getLuma () < 127)
|
||||
context->setFrameColor (kWhiteCColor);
|
||||
else
|
||||
context->setFrameColor (kBlackCColor);
|
||||
context->setFillColor (selectedColor);
|
||||
context->drawGraphicsPath (path, CDrawContext::kPathFilled, &offset);
|
||||
context->drawGraphicsPath (path, CDrawContext::kPathStroked, &offset);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorStopEditView::drawFocusOnTop ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIColorStopEditView::getFocusPath (CGraphicsPath& outPath)
|
||||
{
|
||||
CRect r (getViewSize ());
|
||||
r.inset (stopWidth / 2 - 1, -1);
|
||||
outPath.addRect (r);
|
||||
r.inset (2, 2);
|
||||
outPath.addRect (r);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIGradientEditorController : public NonAtomicReferenceCounted,
|
||||
public IDialogController,
|
||||
public UIColorListenerAdapter,
|
||||
public IUIColorStopEditViewListener,
|
||||
public IController
|
||||
{
|
||||
public:
|
||||
UIGradientEditorController (const std::string& gradientName, CGradient* gradient, UIDescription* description, IActionPerformer* actionPerformer);
|
||||
~UIGradientEditorController () override;
|
||||
|
||||
void valueChanged (CControl* pControl) override;
|
||||
CView* verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
CView* createView (const UIAttributes& attributes, const IUIDescription* description) override;
|
||||
IController* createSubController (UTF8StringPtr name, const IUIDescription* description) override;
|
||||
void onDialogButton1Clicked (UIDialogController*) override;
|
||||
void onDialogButton2Clicked (UIDialogController*) override;
|
||||
void onDialogShow (UIDialogController*) override;
|
||||
protected:
|
||||
enum
|
||||
{
|
||||
kApplyTag = 1,
|
||||
kPositionTag = 2,
|
||||
kFunctionMenuTag = 3,
|
||||
};
|
||||
void uiColorChanged (UIColor* c) override;
|
||||
void onChange () override;
|
||||
void apply ();
|
||||
void updatePositionEdit ();
|
||||
|
||||
SharedPointer<UIDescription> editDescription;
|
||||
SharedPointer<UIColorStopEditView> colorStopEditView;
|
||||
SharedPointer<CGradient> gradient;
|
||||
SharedPointer<UIColor> editColor;
|
||||
CTextEdit* positionEdit {nullptr};
|
||||
IActionPerformer* actionPerformer;
|
||||
std::string gradientName;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIGradientEditorController::UIGradientEditorController (const std::string& gradientName, CGradient* gradient, UIDescription* description, IActionPerformer* actionPerformer)
|
||||
: editDescription(description)
|
||||
, gradient (gradient)
|
||||
, editColor (makeOwned<UIColor> ())
|
||||
, actionPerformer(actionPerformer)
|
||||
, gradientName (gradientName)
|
||||
{
|
||||
*editColor = gradient->getColorStops ().begin ()->second;
|
||||
editColor->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIGradientEditorController::~UIGradientEditorController ()
|
||||
{
|
||||
colorStopEditView->unregisterListener (this);
|
||||
editColor->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientEditorController::apply ()
|
||||
{
|
||||
CGradient* g = editDescription->getGradient (gradientName.data ());
|
||||
if (g->getColorStops () != gradient->getColorStops ())
|
||||
actionPerformer->performGradientChange (gradientName.data (), gradient);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientEditorController::updatePositionEdit ()
|
||||
{
|
||||
if (positionEdit && colorStopEditView)
|
||||
positionEdit->setValue (static_cast<float> (colorStopEditView->getSelectedColorStart ()));
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientEditorController::uiColorChanged (UIColor* c)
|
||||
{
|
||||
auto colorStopMap = gradient->getColorStops (); // create a copy
|
||||
auto it = colorStopMap.find (colorStopEditView->getSelectedColorStart ());
|
||||
if (it != colorStopMap.end () && it->second != editColor->base ())
|
||||
{
|
||||
it->second = editColor->base ();
|
||||
gradient = CGradient::create (colorStopMap);
|
||||
colorStopEditView->setGradient (gradient);
|
||||
updatePositionEdit ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientEditorController::onChange ()
|
||||
{
|
||||
gradient = CGradient::create (colorStopEditView->getColorStopMap ());
|
||||
colorStopEditView->setGradient (gradient);
|
||||
updatePositionEdit ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIGradientEditorController::onDialogButton1Clicked (UIDialogController*)
|
||||
{
|
||||
apply ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIGradientEditorController::onDialogButton2Clicked (UIDialogController*)
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UIGradientEditorController::onDialogShow (UIDialogController*)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IController* UIGradientEditorController::createSubController (UTF8StringPtr name, const IUIDescription* description)
|
||||
{
|
||||
if (UTF8StringView (name) == "ColorChooserController")
|
||||
{
|
||||
return new UIColorChooserController (this, editColor);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientEditorController::valueChanged (CControl* pControl)
|
||||
{
|
||||
switch (pControl->getTag ())
|
||||
{
|
||||
case kApplyTag:
|
||||
{
|
||||
if (pControl->getValue () > 0.f)
|
||||
apply ();
|
||||
break;
|
||||
}
|
||||
case kPositionTag:
|
||||
{
|
||||
colorStopEditView->setCurrentStartOffset (pControl->getValue ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
SharedPointer<COptionMenu> createColorMenu (IUIDescription& desc,
|
||||
const std::function<void (CColor)>& callback)
|
||||
{
|
||||
std::list<const std::string*> names;
|
||||
desc.collectColorNames (names);
|
||||
if (names.empty ())
|
||||
return {};
|
||||
auto menu = makeOwned<COptionMenu> ();
|
||||
std::for_each (names.begin (), names.end (), [&] (const auto& el) {
|
||||
CColor color;
|
||||
if (desc.getColor (el->data (), color))
|
||||
{
|
||||
auto item = new CCommandMenuItem (UTF8String (*el));
|
||||
item->setActions ([callback, color] (auto item) { callback (color); });
|
||||
item->setIcon (createColorIcon (color));
|
||||
menu->addEntry (item);
|
||||
}
|
||||
});
|
||||
return menu;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIGradientEditorController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
if (auto control = dynamic_cast<CTextEdit*>(view))
|
||||
{
|
||||
if (control->getTag () == kPositionTag)
|
||||
{
|
||||
control->setStringToValueFunction ([] (UTF8StringPtr txt, float& result, CTextEdit*) {
|
||||
UTF8StringView t (txt);
|
||||
result = t.toFloat ();
|
||||
return true;
|
||||
});
|
||||
positionEdit = control;
|
||||
updatePositionEdit ();
|
||||
}
|
||||
}
|
||||
else if (auto menu = dynamic_cast<COptionMenu*> (view))
|
||||
{
|
||||
if (menu->getTag () == kFunctionMenuTag)
|
||||
{
|
||||
auto item = new CCommandMenuItem ({"Select Next Color Stop"});
|
||||
item->setActions ([this] (auto) {
|
||||
if (colorStopEditView)
|
||||
{
|
||||
colorStopEditView->selectNextColorStop ();
|
||||
}
|
||||
});
|
||||
menu->addEntry (item);
|
||||
item = new CCommandMenuItem ({"Select Previous Color Stop"});
|
||||
item->setActions ([this] (auto) {
|
||||
if (colorStopEditView)
|
||||
{
|
||||
colorStopEditView->selectPrevColorStop ();
|
||||
}
|
||||
});
|
||||
menu->addEntry (item);
|
||||
menu->addSeparator ();
|
||||
auto descColorMenu = createColorMenu (*editDescription, [this] (auto color) {
|
||||
if (colorStopEditView)
|
||||
{
|
||||
colorStopEditView->setEditColor (color);
|
||||
}
|
||||
});
|
||||
menu->addEntry (descColorMenu, "Set to Description Color");
|
||||
auto cssColorMenu = createCSSColorMenu ([this] (auto color) {
|
||||
if (colorStopEditView)
|
||||
{
|
||||
colorStopEditView->setEditColor (color);
|
||||
}
|
||||
});
|
||||
menu->addEntry (cssColorMenu, "Set to CSS Color");
|
||||
}
|
||||
}
|
||||
return view;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIGradientEditorController::createView (const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
||||
if (name)
|
||||
{
|
||||
if (*name == "ColorStopEditView")
|
||||
{
|
||||
colorStopEditView = new UIColorStopEditView (editColor);
|
||||
colorStopEditView->setGradient (gradient);
|
||||
colorStopEditView->registerListener (this);
|
||||
return colorStopEditView;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIGradientsDataSource : public UIBaseDataSource
|
||||
{
|
||||
public:
|
||||
UIGradientsDataSource (UIDescription* description, IActionPerformer* actionPerformer, GenericStringListDataBrowserSourceSelectionChanged* delegate);
|
||||
~UIGradientsDataSource () override = default;
|
||||
|
||||
CGradient* getSelectedGradient ();
|
||||
std::string getSelectedGradientName ();
|
||||
|
||||
protected:
|
||||
void onUIDescGradientChanged (UIDescription* desc) override;
|
||||
void update () override;
|
||||
void getNames (std::list<const std::string*>& names) override;
|
||||
bool addItem (UTF8StringPtr name) override;
|
||||
bool removeItem (UTF8StringPtr name) override;
|
||||
bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) override;
|
||||
UTF8StringPtr getDefaultsName () override { return "UIGradientsDataSource"; }
|
||||
|
||||
void dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser) override;
|
||||
void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
|
||||
|
||||
CCoord getGradientIconWidth ();
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIGradientsDataSource::UIGradientsDataSource (
|
||||
UIDescription* description, IActionPerformer* actionPerformer,
|
||||
GenericStringListDataBrowserSourceSelectionChanged* delegate)
|
||||
: UIBaseDataSource (description, actionPerformer, delegate)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsDataSource::onUIDescGradientChanged (UIDescription* desc)
|
||||
{
|
||||
onUIDescriptionUpdate ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CGradient* UIGradientsDataSource::getSelectedGradient ()
|
||||
{
|
||||
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow() : CDataBrowser::kNoSelection;
|
||||
if (selectedRow != CDataBrowser::kNoSelection && selectedRow < (int32_t)names.size ())
|
||||
return description->getGradient (names.at (static_cast<uint32_t> (selectedRow)).data ());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
std::string UIGradientsDataSource::getSelectedGradientName ()
|
||||
{
|
||||
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow() : CDataBrowser::kNoSelection;
|
||||
if (selectedRow != CDataBrowser::kNoSelection && selectedRow < (int32_t)names.size ())
|
||||
return names[static_cast<uint32_t> (selectedRow)].getString ();
|
||||
return "";
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsDataSource::getNames (std::list<const std::string*>& names)
|
||||
{
|
||||
description->collectGradientNames (names);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIGradientsDataSource::addItem (UTF8StringPtr name)
|
||||
{
|
||||
actionPerformer->performGradientChange (name, CGradient::create (0, 1, kWhiteCColor, kBlackCColor));
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIGradientsDataSource::removeItem (UTF8StringPtr name)
|
||||
{
|
||||
actionPerformer->performGradientChange (name, nullptr, true);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsDataSource::update ()
|
||||
{
|
||||
UIBaseDataSource::update ();
|
||||
if (dataBrowser)
|
||||
{
|
||||
dbSelectionChanged (dataBrowser);
|
||||
dataBrowser->invalid ();
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CCoord UIGradientsDataSource::getGradientIconWidth ()
|
||||
{
|
||||
return dataBrowser ? dbGetRowHeight (dataBrowser) * 2. : 0.;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIGradientsDataSource::dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
if (buttons.isDoubleClick () && row >= 0 && row < static_cast<int32_t> (names.size ()))
|
||||
{
|
||||
auto r = browser->getCellBounds ({row, column});
|
||||
r.left = r.right - getGradientIconWidth ();
|
||||
if (r.pointInside (where))
|
||||
{
|
||||
delegate->dbRowDoubleClick (row, this);
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
}
|
||||
return UIBaseDataSource::dbOnMouseDown (where, buttons, row, column, browser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsDataSource::dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser)
|
||||
{
|
||||
GenericStringListDataBrowserSource::drawRowBackground (context, size, row, flags, browser);
|
||||
CRect r (size);
|
||||
r.right -= getGradientIconWidth ();
|
||||
GenericStringListDataBrowserSource::drawRowString (context, r, row, flags, browser);
|
||||
CGradient* gradient = nullptr;
|
||||
if ((gradient = description->getGradient (names.at (static_cast<uint32_t> (row)).data ())))
|
||||
{
|
||||
context->setFrameColor (kBlackCColor);
|
||||
context->setLineWidth (context->getHairlineSize ());
|
||||
context->setLineStyle (kLineSolid);
|
||||
context->setDrawMode (kAliasing);
|
||||
r = size;
|
||||
r.left = r.right - (getGradientIconWidth ());
|
||||
r.offset (-0.5, -0.5);
|
||||
r.inset (3, 2);
|
||||
SharedPointer<CGraphicsPath> path = owned (context->createGraphicsPath ());
|
||||
path->addRect (r);
|
||||
path->closeSubpath ();
|
||||
context->fillLinearGradient (path, *gradient, r.getTopLeft (), r.getTopRight ());
|
||||
context->drawGraphicsPath (path, CDrawContext::kPathStroked);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsDataSource::dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser)
|
||||
{
|
||||
UIBaseDataSource::dbCellSetupTextEdit(row, column, control, browser);
|
||||
CRect r (control->getViewSize ());
|
||||
r.right -= getGradientIconWidth ();
|
||||
control->setViewSize (r);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIGradientsDataSource::performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName)
|
||||
{
|
||||
actionPerformer->performGradientNameChange (oldName, newName);
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIGradientsController::UIGradientsController (IController* baseController, UIDescription* description, IActionPerformer* actionPerformer)
|
||||
: DelegationController (baseController)
|
||||
, editDescription (description)
|
||||
, actionPerformer (actionPerformer)
|
||||
, dataSource (nullptr)
|
||||
{
|
||||
dataSource = new UIGradientsDataSource (editDescription, actionPerformer, this);
|
||||
UIEditController::setupDataSource (dataSource);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIGradientsController::~UIGradientsController ()
|
||||
{
|
||||
dataSource->forget ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIGradientsController::createView (const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
||||
if (name)
|
||||
{
|
||||
if (*name == "GradientsBrowser")
|
||||
{
|
||||
CDataBrowser* dataBrowser = new CDataBrowser (CRect (0, 0, 0, 0), dataSource, CDataBrowser::kDrawRowLines|CScrollView::kHorizontalScrollbar|CScrollView::kVerticalScrollbar);
|
||||
return dataBrowser;
|
||||
}
|
||||
}
|
||||
return DelegationController::createView (attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIGradientsController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
CControl* control = dynamic_cast<CControl*> (view);
|
||||
if (control)
|
||||
{
|
||||
auto searchField = dynamic_cast<CSearchTextEdit*> (control);
|
||||
if (searchField && searchField->getTag () == kSearchTag)
|
||||
{
|
||||
dataSource->setSearchFieldControl (searchField);
|
||||
return searchField;
|
||||
}
|
||||
else if (control->getTag () == kEditTag)
|
||||
{
|
||||
editButton = control;
|
||||
editButton->setMouseEnabled (false);
|
||||
}
|
||||
}
|
||||
return controller->verifyView (view, attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IControlListener* UIGradientsController::getControlListener (UTF8StringPtr name)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsController::valueChanged (CControl* pControl)
|
||||
{
|
||||
switch (pControl->getTag ())
|
||||
{
|
||||
case kAddTag:
|
||||
{
|
||||
if (pControl->getValue () == pControl->getMax ())
|
||||
dataSource->add ();
|
||||
break;
|
||||
}
|
||||
case kRemoveTag:
|
||||
{
|
||||
if (pControl->getValue () == pControl->getMax ())
|
||||
dataSource->remove ();
|
||||
break;
|
||||
}
|
||||
case kEditTag:
|
||||
{
|
||||
if (pControl->getValue () == pControl->getMax ())
|
||||
showEditDialog ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsController::dbSelectionChanged (int32_t selectedRow, GenericStringListDataBrowserSource* source)
|
||||
{
|
||||
if (dataSource)
|
||||
{
|
||||
CGradient* gradient = dataSource->getSelectedGradient ();
|
||||
if (editButton)
|
||||
editButton->setMouseEnabled (gradient ? true : false);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsController::dbRowDoubleClick (int32_t row, GenericStringListDataBrowserSource* source)
|
||||
{
|
||||
showEditDialog ();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIGradientsController::showEditDialog ()
|
||||
{
|
||||
UIDialogController* dc = new UIDialogController (this, editButton->getFrame ());
|
||||
auto fsController = makeOwned<UIGradientEditorController> (
|
||||
dataSource->getSelectedGradientName (), dataSource->getSelectedGradient (), editDescription,
|
||||
actionPerformer);
|
||||
dc->run ("gradient.editor", "Gradient Editor", "OK", "Cancel", fsController,
|
||||
UIEditController::getEditorDescription ());
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
Reference in New Issue
Block a user