Initial release
This commit is contained in:
+956
@@ -0,0 +1,956 @@
|
||||
// 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 "uitemplatecontroller.h"
|
||||
|
||||
#if VSTGUI_LIVE_EDITING
|
||||
|
||||
#include "../iviewfactory.h"
|
||||
#include "../uiattributes.h"
|
||||
#include "../viewcreator/viewcreator.h"
|
||||
#include "../../lib/controls/ctextedit.h"
|
||||
#include "../../lib/controls/coptionmenu.h"
|
||||
#include "../../lib/controls/cscrollbar.h"
|
||||
#include "../../lib/algorithm.h"
|
||||
#include "../../lib/cgraphicspath.h"
|
||||
#include "../../lib/cdropsource.h"
|
||||
#include "../../lib/coffscreencontext.h"
|
||||
#include "../../lib/dragging.h"
|
||||
#include "../../lib/malloc.h"
|
||||
#include "uieditcontroller.h"
|
||||
#include "uiselection.h"
|
||||
#include "uiundomanager.h"
|
||||
#include "uiactions.h"
|
||||
#include "uieditmenucontroller.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace VSTGUI {
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UINavigationDataSource : public GenericStringListDataBrowserSource
|
||||
{
|
||||
public:
|
||||
UINavigationDataSource (GenericStringListDataBrowserSourceSelectionChanged* delegate)
|
||||
: GenericStringListDataBrowserSource (nullptr, delegate) { textInset.x = 4.; }
|
||||
|
||||
void dbOnKeyboardEvent (KeyboardEvent& event, CDataBrowser* browser) override
|
||||
{
|
||||
if (event.type == EventType::KeyDown &&
|
||||
dynamic_cast<CTextEdit*> (browser->getFrame ()->getFocusView ()) == nullptr)
|
||||
{
|
||||
if (event.virt == VirtualKey::Left)
|
||||
{
|
||||
if (auto parent = browser->getParentView ()->asViewContainer ())
|
||||
{
|
||||
if (parent->advanceNextFocusView (browser, true))
|
||||
{
|
||||
browser->unselectAll ();
|
||||
event.consumed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (event.virt == VirtualKey::Right)
|
||||
{
|
||||
if (auto parent = browser->getParentView ()->asViewContainer ())
|
||||
{
|
||||
if (parent->advanceNextFocusView (browser, false))
|
||||
{
|
||||
if (auto* focusView = browser->getFrame ()->getFocusView ())
|
||||
{
|
||||
auto* focusBrowser = dynamic_cast<CDataBrowser*>(focusView);
|
||||
parent = focusView->getParentView ()->asViewContainer ();
|
||||
while (!focusBrowser && parent != browser->getFrame ())
|
||||
{
|
||||
if (parent->getParentView () == nullptr)
|
||||
break;
|
||||
parent = parent->getParentView ()->asViewContainer ();
|
||||
focusBrowser = dynamic_cast<CDataBrowser*> (parent);
|
||||
}
|
||||
if (focusBrowser)
|
||||
{
|
||||
if (focusBrowser->getSelectedRow () == CDataBrowser::kNoSelection)
|
||||
focusBrowser->setSelectedRow (0);
|
||||
}
|
||||
}
|
||||
event.consumed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
GenericStringListDataBrowserSource::dbOnKeyboardEvent (event, browser);
|
||||
}
|
||||
virtual const UTF8String& getHeaderTitle () const { return headerTitle; }
|
||||
void dbDrawHeader (CDrawContext* context, const CRect& size, int32_t column, int32_t flags, CDataBrowser* browser) override
|
||||
{
|
||||
context->setDrawMode (kAliasing);
|
||||
if (!headerGradient)
|
||||
{
|
||||
headerGradient = UIEditController::getEditorDescription ()->getGradient ("shading.light");
|
||||
UIEditController::getEditorDescription ()->getColor ("shading.light.frame", headerLineColor);
|
||||
}
|
||||
if (headerGradient)
|
||||
{
|
||||
if (auto path = owned (context->createGraphicsPath ()))
|
||||
{
|
||||
path->addRect (size);
|
||||
context->fillLinearGradient (path, *headerGradient, CPoint (size.left, size.top), CPoint (size.left, size.bottom));
|
||||
}
|
||||
}
|
||||
if (!getHeaderTitle ().empty ())
|
||||
{
|
||||
if (headerFont == nullptr)
|
||||
{
|
||||
headerFont = makeOwned<CFontDesc> (*drawFont);
|
||||
headerFont->setStyle (kBoldFace);
|
||||
headerFont->setSize (headerFont->getSize ()-1);
|
||||
}
|
||||
context->setFont (headerFont);
|
||||
context->setFontColor (fontColor);
|
||||
context->drawString (getHeaderTitle ().getPlatformString (), size, kCenterText);
|
||||
}
|
||||
auto hairlineSize = context->getHairlineSize ();
|
||||
context->setLineWidth (hairlineSize);
|
||||
context->setFrameColor (headerLineColor);
|
||||
context->drawLine (CPoint (size.right-hairlineSize, size.top), CPoint (size.right-hairlineSize, size.bottom));
|
||||
context->drawLine (CPoint (size.left, size.bottom), CPoint (size.right-hairlineSize, size.bottom));
|
||||
}
|
||||
|
||||
static void drawTriangle (CDrawContext* context, const CRect& size)
|
||||
{
|
||||
if (auto path = owned (context->createGraphicsPath ()))
|
||||
{
|
||||
CRect r (size);
|
||||
r.left = r.right - r.getHeight ();
|
||||
r.inset (4, 4);
|
||||
path->beginSubpath (r.getTopLeft ());
|
||||
path->addLine (r.getBottomLeft ());
|
||||
path->addLine (r.right, r.top + r.getHeight () / 2.);
|
||||
path->closeSubpath ();
|
||||
context->setFillColor (CColor (0, 0, 0, 30));
|
||||
context->drawGraphicsPath (path);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
mutable UTF8String headerTitle;
|
||||
CColor headerLineColor {kBlackCColor};
|
||||
SharedPointer<CFontDesc> headerFont;
|
||||
SharedPointer<CGradient> headerGradient;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UITemplatesDataSource : public UINavigationDataSource
|
||||
{
|
||||
public:
|
||||
UITemplatesDataSource (GenericStringListDataBrowserSourceSelectionChanged* delegate, UIDescription* description, IActionPerformer* actionPerformer, const std::string* templateName);
|
||||
|
||||
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override;
|
||||
void dbCellTextChanged (int32_t row, int32_t column, UTF8StringPtr newText, CDataBrowser* browser) override;
|
||||
void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* textEditControl, CDataBrowser* browser) override;
|
||||
void dbAttached (CDataBrowser* browser) override;
|
||||
void dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser) override;
|
||||
protected:
|
||||
SharedPointer<UIDescription> description;
|
||||
IActionPerformer* actionPerformer;
|
||||
std::string firstSelectedTemplateName;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
class UIViewListDataSource : public UINavigationDataSource, public IUIUndoManagerListener
|
||||
{
|
||||
public:
|
||||
UIViewListDataSource (CViewContainer* view, const IViewFactory* viewFactory, UISelection* selection, UIUndoManager* undoManager ,GenericStringListDataBrowserSourceSelectionChanged* delegate);
|
||||
~UIViewListDataSource () override;
|
||||
|
||||
CViewContainer* getView () const { return view; }
|
||||
CView* getSubview (int32_t index);
|
||||
bool setSelectedView (CView* view, bool makeRowVisible = false);
|
||||
UIViewListDataSource* getNext () const { return next; }
|
||||
|
||||
bool update (CViewContainer* vc);
|
||||
void remove ();
|
||||
protected:
|
||||
UTF8String getViewDisplayString (CView* v) const
|
||||
{
|
||||
uint32_t outSize = 0;
|
||||
if (v->getAttributeSize (UIViewCreator::ViewCreator::labelAttrID, outSize))
|
||||
{
|
||||
Buffer<char> buffer (outSize);
|
||||
if (v->getAttribute (UIViewCreator::ViewCreator::labelAttrID, outSize, buffer.data (),
|
||||
outSize))
|
||||
{
|
||||
return buffer.data ();
|
||||
}
|
||||
}
|
||||
if (const auto* vfEditingSupport =
|
||||
dynamic_cast<const IViewFactoryEditingSupport*> (viewFactory))
|
||||
return vfEditingSupport->getViewDisplayName (v);
|
||||
return {};
|
||||
}
|
||||
const UTF8String& getHeaderTitle () const override
|
||||
{
|
||||
headerTitle = "";
|
||||
if (view)
|
||||
{
|
||||
headerTitle = getViewDisplayString (view);
|
||||
if (headerTitle.empty () && view->getParentView ())
|
||||
headerTitle = getViewDisplayString (view->getParentView ());
|
||||
}
|
||||
return headerTitle;
|
||||
}
|
||||
|
||||
CCoord calculateSubViewWidth (CViewContainer* view) const;
|
||||
void dbSelectionChanged (CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser) override;
|
||||
CMouseEventResult dbOnMouseMoved (const CPoint& where, const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser) override;
|
||||
void dbOnKeyboardEvent (KeyboardEvent& event, CDataBrowser* browser) override;
|
||||
void dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser) override;
|
||||
DragOperation dbOnDragEnterCell (int32_t row, int32_t column, const CPoint& where,
|
||||
IDataPackage* drag, CDataBrowser* browser) override;
|
||||
DragOperation dbOnDragMoveInCell (int32_t row, int32_t column, const CPoint& where,
|
||||
IDataPackage* drag, CDataBrowser* browser) override;
|
||||
void dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag,
|
||||
CDataBrowser* browser) override;
|
||||
bool dbOnDropInCell (int32_t row, int32_t column, const CPoint& where, IDataPackage* drag,
|
||||
CDataBrowser* browser) override;
|
||||
|
||||
// IUIUndoManagerListener
|
||||
void onUndoManagerChange () override;
|
||||
|
||||
CViewContainer* view;
|
||||
const IViewFactory* viewFactory;
|
||||
UIViewListDataSource* next;
|
||||
SharedPointer<UISelection> selection;
|
||||
SharedPointer<UIUndoManager> undoManager;
|
||||
CView* selectedView;
|
||||
StringVector names;
|
||||
std::vector<CView*> subviews;
|
||||
bool inUpdate;
|
||||
DragStartMouseObserver dragStartMouseObserver;
|
||||
int32_t dragRow {-1};
|
||||
int32_t dragDestinationRow {-1};
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UITemplateController::UITemplateController (IController* baseController, UIDescription* description, UISelection* selection, UIUndoManager* undoManager, IActionPerformer* actionPerformer)
|
||||
: DelegationController (baseController)
|
||||
, editDescription (description)
|
||||
, selection (selection)
|
||||
, undoManager (undoManager)
|
||||
, actionPerformer (actionPerformer)
|
||||
, templateView (nullptr)
|
||||
, templateDataBrowser (nullptr)
|
||||
, mainViewDataSource (nullptr)
|
||||
, selectedTemplateName (nullptr)
|
||||
{
|
||||
editDescription->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UITemplateController::~UITemplateController ()
|
||||
{
|
||||
if (templateDataBrowser)
|
||||
templateDataBrowser->unregisterViewListener (this);
|
||||
if (mainViewDataSource)
|
||||
mainViewDataSource->forget ();
|
||||
editDescription->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::setupDataBrowser (CDataBrowser* orignalBrowser, CDataBrowser* dataBrowser)
|
||||
{
|
||||
if (orignalBrowser)
|
||||
{
|
||||
dataBrowser->setTransparency (orignalBrowser->getTransparency ());
|
||||
dataBrowser->setBackgroundColor (orignalBrowser->getBackgroundColor ());
|
||||
dataBrowser->setAutosizeFlags (orignalBrowser->getAutosizeFlags ());
|
||||
dataBrowser->setStyle (orignalBrowser->getStyle ());
|
||||
dataBrowser->setScrollbarWidth (orignalBrowser->getScrollbarWidth ());
|
||||
CScrollbar* sb1 = orignalBrowser->getHorizontalScrollbar ();
|
||||
CScrollbar* sb2 = dataBrowser->getHorizontalScrollbar ();
|
||||
if (sb1 && sb2)
|
||||
{
|
||||
sb2->setScrollerColor (sb1->getScrollerColor ());
|
||||
sb2->setBackgroundColor (sb1->getBackgroundColor ());
|
||||
sb2->setFrameColor (sb1->getFrameColor ());
|
||||
}
|
||||
sb1 = orignalBrowser->getVerticalScrollbar ();
|
||||
sb2 = dataBrowser->getVerticalScrollbar ();
|
||||
if (sb1 && sb2)
|
||||
{
|
||||
sb2->setScrollerColor (sb1->getScrollerColor ());
|
||||
sb2->setBackgroundColor (sb1->getBackgroundColor ());
|
||||
sb2->setFrameColor (sb1->getFrameColor ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::selectTemplate (UTF8StringPtr name)
|
||||
{
|
||||
if (templateDataBrowser)
|
||||
{
|
||||
if (name == nullptr)
|
||||
{
|
||||
templateDataBrowser->unselectAll ();
|
||||
return;
|
||||
}
|
||||
int32_t index = 0;
|
||||
for (auto& templName : templateNames)
|
||||
{
|
||||
if (templName == name)
|
||||
{
|
||||
templateDataBrowser->setSelectedRow (index, true);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::dbSelectionChanged (int32_t selectedRow, GenericStringListDataBrowserSource* source)
|
||||
{
|
||||
if (source->getStringList () == &templateNames)
|
||||
{
|
||||
UTF8String* newName = nullptr;
|
||||
if (selectedRow == CDataBrowser::kNoSelection)
|
||||
newName = nullptr;
|
||||
else
|
||||
newName = &templateNames[static_cast<uint32_t> (selectedRow)];
|
||||
|
||||
if ((newName == nullptr && selectedTemplateName != nullptr)
|
||||
|| (newName != nullptr && selectedTemplateName == nullptr)
|
||||
|| (newName != selectedTemplateName && *newName != *selectedTemplateName))
|
||||
{
|
||||
selectedTemplateName = newName;
|
||||
auto attr = editDescription->getCustomAttributes ("UITemplateController", true);
|
||||
if (attr)
|
||||
{
|
||||
attr->setAttribute ("SelectedTemplate", selectedTemplateName ? selectedTemplateName->getString () : "");
|
||||
}
|
||||
|
||||
forEachListener ([] (IUITemplateControllerListener* l) { l->onTemplateSelectionChanged ();});
|
||||
}
|
||||
else if (templateView)
|
||||
{
|
||||
selection->setExclusive (templateView);
|
||||
}
|
||||
else
|
||||
selection->clear ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::onUIDescTemplateChanged (UIDescription* desc)
|
||||
{
|
||||
if (!templateDataBrowser)
|
||||
return;
|
||||
auto dataSource = dynamic_cast<GenericStringListDataBrowserSource*>(templateDataBrowser->getDelegate ());
|
||||
if (dataSource)
|
||||
{
|
||||
int32_t rowToSelect = templateDataBrowser->getSelectedRow ();
|
||||
int32_t index = 0;
|
||||
UTF8String selectedTemplateStr = selectedTemplateName ? selectedTemplateName->data () : "";
|
||||
templateNames.clear ();
|
||||
dataSource->setStringList (&templateNames);
|
||||
std::list<const std::string*> tmp;
|
||||
editDescription->collectTemplateViewNames (tmp);
|
||||
tmp.sort (UIEditController::std__stringCompare);
|
||||
for (auto& name : tmp)
|
||||
{
|
||||
templateNames.emplace_back (*name);
|
||||
if (*name == selectedTemplateStr)
|
||||
rowToSelect = index;
|
||||
++index;
|
||||
}
|
||||
if (rowToSelect < 0)
|
||||
rowToSelect = 0;
|
||||
dataSource->setStringList (&templateNames);
|
||||
templateDataBrowser->setSelectedRow (rowToSelect, true);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::setTemplateView (CViewContainer* view)
|
||||
{
|
||||
if (view != templateView && templateDataBrowser && templateDataBrowser->getParentView ())
|
||||
{
|
||||
templateView = view;
|
||||
if (mainViewDataSource)
|
||||
{
|
||||
mainViewDataSource->remove ();
|
||||
mainViewDataSource->forget ();
|
||||
mainViewDataSource = nullptr;
|
||||
}
|
||||
if (templateView && templateDataBrowser)
|
||||
{
|
||||
CViewContainer* parentView = static_cast<CViewContainer*>(templateDataBrowser->getParentView ());
|
||||
if (parentView)
|
||||
{
|
||||
const IViewFactory* viewFactory = editDescription->getViewFactory ();
|
||||
mainViewDataSource = new UIViewListDataSource (templateView, viewFactory, selection, undoManager, this);
|
||||
UIEditController::setupDataSource (mainViewDataSource);
|
||||
CRect r (templateDataBrowser->getViewSize ());
|
||||
r.offset (r.getWidth (), 0);
|
||||
CDataBrowser* browser = new CDataBrowser (r, mainViewDataSource);
|
||||
setupDataBrowser (templateDataBrowser, browser);
|
||||
parentView->addView (browser);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void UITemplateController::navigateTo (CView* view)
|
||||
{
|
||||
std::list<CView*> parents;
|
||||
CView* v = view;
|
||||
while (auto parent = v->getParentView ())
|
||||
{
|
||||
if (parent == parent->getFrame ())
|
||||
return; // view is not a child of the templateView
|
||||
if (parent == templateView)
|
||||
break;
|
||||
if (IViewFactory::getViewName (parent) == nullptr)
|
||||
{
|
||||
v = parent;
|
||||
continue;
|
||||
}
|
||||
parents.emplace_front (parent);
|
||||
v = parent;
|
||||
}
|
||||
UIViewListDataSource* dataSource = mainViewDataSource;
|
||||
for (auto parent : parents)
|
||||
{
|
||||
dataSource->setSelectedView (parent, true);
|
||||
dataSource = dataSource->getNext ();
|
||||
if (dataSource == nullptr)
|
||||
break;
|
||||
}
|
||||
if (dataSource)
|
||||
dataSource->setSelectedView (view, true);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::viewWillDelete (CView* view)
|
||||
{
|
||||
if (view == templateDataBrowser)
|
||||
{
|
||||
templateDataBrowser->unregisterViewListener (this);
|
||||
templateDataBrowser = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UITemplateController::createView (const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
const std::string* name = attributes.getAttributeValue (IUIDescription::kCustomViewName);
|
||||
if (name)
|
||||
{
|
||||
if (*name == "TemplateBrowser")
|
||||
{
|
||||
vstgui_assert (templateDataBrowser == nullptr);
|
||||
std::list<const std::string*> tmp;
|
||||
editDescription->collectTemplateViewNames (tmp);
|
||||
tmp.sort (UIEditController::std__stringCompare);
|
||||
for (auto& name2 : tmp)
|
||||
templateNames.emplace_back (*name2);
|
||||
|
||||
auto attr = editDescription->getCustomAttributes ("UITemplateController", true);
|
||||
const std::string* templateName = attr ? attr->getAttributeValue ("SelectedTemplate") : nullptr;
|
||||
UITemplatesDataSource* dataSource = new UITemplatesDataSource (this, editDescription, actionPerformer, templateName);
|
||||
dataSource->setStringList (&templateNames);
|
||||
UIEditController::setupDataSource (dataSource);
|
||||
templateDataBrowser = new CDataBrowser (CRect (0, 0, 0, 0), dataSource, CDataBrowser::kDrawRowLines|CScrollView::kAutoHideScrollbars|CScrollView::kHorizontalScrollbar|CScrollView::kVerticalScrollbar|CDataBrowser::kDrawHeader);
|
||||
dataSource->forget ();
|
||||
templateDataBrowser->registerViewListener (this);
|
||||
return templateDataBrowser;
|
||||
}
|
||||
}
|
||||
return DelegationController::createView (attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UITemplateController::verifyView (CView* view, const UIAttributes& attributes, const IUIDescription* description)
|
||||
{
|
||||
return DelegationController::verifyView (view, attributes, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
IController* UITemplateController::createSubController (UTF8StringPtr name, const IUIDescription* description)
|
||||
{
|
||||
return DelegationController::createSubController (name, description);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplateController::appendContextMenuItems (COptionMenu& contextMenu, CView* view, const CPoint& where)
|
||||
{
|
||||
CPoint w (where);
|
||||
view->localToFrame (w);
|
||||
templateDataBrowser->frameToLocal (w);
|
||||
if (!templateDataBrowser->hitTest (w))
|
||||
return;
|
||||
auto cell = templateDataBrowser->getCellAt (w);
|
||||
if (!cell.isValid ())
|
||||
return;
|
||||
auto dataSource = dynamic_cast<UITemplatesDataSource*> (templateDataBrowser->getDelegate ());
|
||||
auto templateName = dataSource->getStringList()->at (static_cast<uint32_t> (cell.row));
|
||||
vstgui_assert (dataSource);
|
||||
auto item = new CCommandMenuItem ("Duplicate Template '" + templateName + "'");
|
||||
item->setActions ([this, cell, dataSource] (CCommandMenuItem*) {
|
||||
std::list<const std::string*> tmp;
|
||||
editDescription->collectTemplateViewNames (tmp);
|
||||
std::string newName (dataSource->getStringList ()->at (static_cast<uint32_t> (cell.row)).data ());
|
||||
UIEditMenuController::createUniqueTemplateName (tmp, newName);
|
||||
actionPerformer->performDuplicateTemplate (dataSource->getStringList ()->at (static_cast<uint32_t> (cell.row)).data (), newName.data ());
|
||||
});
|
||||
contextMenu.addEntry (item);
|
||||
item = new CCommandMenuItem ("Delete Template '" + templateName + "'");
|
||||
item->setActions ([this, cell, dataSource] (CCommandMenuItem*) {
|
||||
actionPerformer->performDeleteTemplate (dataSource->getStringList ()->at (static_cast<uint32_t> (cell.row)).data ());
|
||||
});
|
||||
contextMenu.addEntry (item);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIViewListDataSource::UIViewListDataSource (
|
||||
CViewContainer* view, const IViewFactory* viewFactory, UISelection* selection,
|
||||
UIUndoManager* undoManager, GenericStringListDataBrowserSourceSelectionChanged* delegate)
|
||||
: UINavigationDataSource (delegate)
|
||||
, view (view)
|
||||
, viewFactory (viewFactory)
|
||||
, next (nullptr)
|
||||
, selection (selection)
|
||||
, undoManager (undoManager)
|
||||
, selectedView (nullptr)
|
||||
, inUpdate (false)
|
||||
{
|
||||
update (view);
|
||||
undoManager->registerListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UIViewListDataSource::~UIViewListDataSource ()
|
||||
{
|
||||
undoManager->unregisterListener (this);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CView* UIViewListDataSource::getSubview (int32_t index)
|
||||
{
|
||||
if (index >= 0 && index < (int32_t)subviews.size ())
|
||||
return subviews[static_cast<uint32_t> (index)];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIViewListDataSource::update (CViewContainer* vc)
|
||||
{
|
||||
inUpdate = true;
|
||||
names.clear ();
|
||||
subviews.clear ();
|
||||
vc->forEachChild ([&] (CView* subview) {
|
||||
auto viewName = getViewDisplayString (subview);
|
||||
if (!viewName.empty ())
|
||||
{
|
||||
names.emplace_back (std::move (viewName));
|
||||
subviews.emplace_back (subview);
|
||||
}
|
||||
});
|
||||
if (names.empty () && vc->getNbViews () > 0)
|
||||
{
|
||||
ViewIterator it (vc);
|
||||
while (*it)
|
||||
{
|
||||
if (auto subview = (*it)->asViewContainer ())
|
||||
{
|
||||
if (update (subview))
|
||||
{
|
||||
view = subview;
|
||||
inUpdate = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++it;
|
||||
}
|
||||
inUpdate = false;
|
||||
return false;
|
||||
}
|
||||
setStringList (&names);
|
||||
inUpdate = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CCoord UIViewListDataSource::calculateSubViewWidth (CViewContainer* inView) const
|
||||
{
|
||||
CCoord result = 0;
|
||||
|
||||
inView->forEachChild ([&result] (CView* subView) {
|
||||
result += subView->getViewSize ().getWidth ();
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIViewListDataSource::setSelectedView (CView* newView, bool makeRowVisible)
|
||||
{
|
||||
auto index = indexOf (subviews.begin (), subviews.end (), newView);
|
||||
if (!index)
|
||||
return false;
|
||||
|
||||
selectedView = newView;
|
||||
dataBrowser->selectRow (*index);
|
||||
if (makeRowVisible)
|
||||
dataBrowser->makeRowVisible (dataBrowser->getSelectedRow ());
|
||||
|
||||
if (next)
|
||||
{
|
||||
next->remove ();
|
||||
next = nullptr;
|
||||
}
|
||||
if (auto container = selectedView ? selectedView->asViewContainer () : nullptr)
|
||||
{
|
||||
UIViewListDataSource* dataSource = new UIViewListDataSource (container, viewFactory, selection, undoManager, delegate);
|
||||
UIEditController::setupDataSource (dataSource);
|
||||
CRect r (dataBrowser->getViewSize ());
|
||||
r.offset (r.getWidth (), 0);
|
||||
CDataBrowser* newDataBrowser = new CDataBrowser (r, dataSource);
|
||||
UITemplateController::setupDataBrowser (dataBrowser, newDataBrowser);
|
||||
CViewContainer* parentView = static_cast<CViewContainer*>(dataBrowser->getParentView ());
|
||||
parentView->addView (newDataBrowser);
|
||||
next = dataSource;
|
||||
dataSource->forget ();
|
||||
CScrollView* scrollView = dynamic_cast<CScrollView*>(parentView->getParentView ());
|
||||
if (scrollView)
|
||||
{
|
||||
CRect containerSize (scrollView->getContainerSize ());
|
||||
containerSize.right = calculateSubViewWidth (parentView);
|
||||
scrollView->setContainerSize (containerSize, true);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::dbSelectionChanged (CDataBrowser* browser)
|
||||
{
|
||||
CView* subview = getSubview (browser->getSelectedRow ());
|
||||
if (subview == selectedView || inUpdate)
|
||||
return;
|
||||
setSelectedView (subview);
|
||||
GenericStringListDataBrowserSource::dbSelectionChanged (dataBrowser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::remove ()
|
||||
{
|
||||
if (next)
|
||||
{
|
||||
next->remove ();
|
||||
next = nullptr;
|
||||
}
|
||||
if (dataBrowser)
|
||||
{
|
||||
CViewContainer* parentView = static_cast<CViewContainer*>(dataBrowser->getParentView ());
|
||||
CScrollView* scrollView = dynamic_cast<CScrollView*>(parentView->getParentView ());
|
||||
parentView->removeView (dataBrowser);
|
||||
if (scrollView)
|
||||
{
|
||||
CRect containerSize (scrollView->getContainerSize ());
|
||||
containerSize.right = calculateSubViewWidth (parentView);
|
||||
scrollView->setContainerSize (containerSize, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UIViewListDataSource::dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
if (buttons.isLeftButton ())
|
||||
{
|
||||
if (buttons.isDoubleClick ())
|
||||
{
|
||||
CView* subview = getSubview (row);
|
||||
if (subview)
|
||||
{
|
||||
if (buttons.getModifierState () & kControl)
|
||||
{
|
||||
if (selection->contains (subview))
|
||||
selection->remove (subview);
|
||||
else
|
||||
selection->add (subview);
|
||||
}
|
||||
else
|
||||
selection->setExclusive (subview);
|
||||
}
|
||||
}
|
||||
dragStartMouseObserver.init (where);
|
||||
}
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
CMouseEventResult UIViewListDataSource::dbOnMouseMoved (const CPoint& where,
|
||||
const CButtonState& buttons, int32_t row,
|
||||
int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
if (row >= 0 && buttons.isLeftButton () && dragStartMouseObserver.shouldStartDrag (where))
|
||||
{
|
||||
row = browser->getSelectedRow ();
|
||||
dragRow = row;
|
||||
|
||||
auto cellBounds = browser->getCellBounds ({row, column});
|
||||
auto offscreen = COffscreenContext::create (cellBounds.getSize (),
|
||||
browser->getFrame ()->getScaleFactor ());
|
||||
auto offscreenSize = cellBounds;
|
||||
offscreenSize.originize ();
|
||||
offscreen->beginDraw ();
|
||||
dbDrawCell (offscreen, offscreenSize, row, column, 0, browser);
|
||||
offscreen->endDraw ();
|
||||
|
||||
auto startPos = dragStartMouseObserver.getInitPosition ();
|
||||
DragDescription dd (CDropSource::create (&row, sizeof (int32_t), IDataPackage::kBinary),
|
||||
{cellBounds.left - startPos.x, cellBounds.top - startPos.y},
|
||||
shared (offscreen->getBitmap ()));
|
||||
auto callbackFunc = makeOwned<DragCallbackFunctions> ();
|
||||
auto Self = shared (this);
|
||||
callbackFunc->endedFunc = [Self] (IDraggingSession*, CPoint, DragOperation) {
|
||||
Self->dragRow = -1;
|
||||
Self->dragDestinationRow = -1;
|
||||
};
|
||||
|
||||
browser->doDrag (dd, callbackFunc);
|
||||
return kMouseMoveEventHandledButDontNeedMoreEvents;
|
||||
}
|
||||
return kMouseEventHandled;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
DragOperation UIViewListDataSource::dbOnDragEnterCell (int32_t row, int32_t column,
|
||||
const CPoint& where, IDataPackage* drag,
|
||||
CDataBrowser* browser)
|
||||
{
|
||||
if (dragRow >= 0)
|
||||
{
|
||||
if (dragDestinationRow >= 0)
|
||||
browser->invalidateRow (dragDestinationRow);
|
||||
if (dragRow == row)
|
||||
{
|
||||
dragDestinationRow = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
dragDestinationRow = row;
|
||||
browser->invalidateRow (dragDestinationRow);
|
||||
}
|
||||
return DragOperation::Move;
|
||||
}
|
||||
return DragOperation::None;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
DragOperation UIViewListDataSource::dbOnDragMoveInCell (int32_t row, int32_t column,
|
||||
const CPoint& where, IDataPackage* drag,
|
||||
CDataBrowser* browser)
|
||||
{
|
||||
if (dragRow >= 0)
|
||||
return DragOperation::Move;
|
||||
return DragOperation::None;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::dbOnDragExitCell (int32_t row, int32_t column, IDataPackage* drag,
|
||||
CDataBrowser* browser)
|
||||
{
|
||||
if (dragDestinationRow >= 0)
|
||||
{
|
||||
browser->invalidateRow (dragDestinationRow);
|
||||
dragDestinationRow = -1;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool UIViewListDataSource::dbOnDropInCell (int32_t row, int32_t column, const CPoint& where,
|
||||
IDataPackage* drag, CDataBrowser* browser)
|
||||
{
|
||||
bool result = false;
|
||||
if (row != dragRow && dragDestinationRow != -1 && row != -1)
|
||||
{
|
||||
int32_t dir = dragDestinationRow - dragRow;
|
||||
undoManager->pushAndPerform (new HierarchyMoveViewOperation (subviews[dragRow], selection, dir));
|
||||
result = true;
|
||||
}
|
||||
dragRow = dragDestinationRow = -1;
|
||||
browser->invalidateRow (row);
|
||||
return result;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::onUndoManagerChange ()
|
||||
{
|
||||
update (view);
|
||||
if (selectedView)
|
||||
{
|
||||
if (dataBrowser)
|
||||
{
|
||||
if (auto index = indexOf (subviews.begin (), subviews.end (), selectedView))
|
||||
{
|
||||
dataBrowser->setSelectedRow (*index, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
selectedView = nullptr;
|
||||
if (next)
|
||||
{
|
||||
next->remove ();
|
||||
next = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::dbOnKeyboardEvent (KeyboardEvent& event, CDataBrowser* browser)
|
||||
{
|
||||
if (event.type == EventType::KeyDown)
|
||||
{
|
||||
if (event.virt == VirtualKey::Return)
|
||||
{
|
||||
int32_t row = browser->getSelectedRow ();
|
||||
CView* subview = getSubview (row);
|
||||
if (subview)
|
||||
{
|
||||
selection->setExclusive (subview);
|
||||
event.consumed = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
UINavigationDataSource::dbOnKeyboardEvent (event, browser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UIViewListDataSource::dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser)
|
||||
{
|
||||
drawRowBackground (context, size, row, flags, browser);
|
||||
auto subview = getSubview (row);
|
||||
if (subview && subview->asViewContainer ())
|
||||
drawTriangle (context, size);
|
||||
drawRowString (context, size, row, flags, browser);
|
||||
if (dragDestinationRow == row)
|
||||
{
|
||||
CColor color = kRedCColor;
|
||||
UIEditController::getEditorDescription ()->getColor ("db.drag.indicator", color);
|
||||
context->setFrameColor (color);
|
||||
context->setLineWidth (1.);
|
||||
auto r = size;
|
||||
r.top += 1.;
|
||||
r.bottom -= 2.;
|
||||
if (dragDestinationRow < dragRow)
|
||||
context->drawLine (r.getTopLeft (), r.getTopRight ());
|
||||
else
|
||||
context->drawLine (r.getBottomLeft (), r.getBottomRight ());
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
UITemplatesDataSource::UITemplatesDataSource (GenericStringListDataBrowserSourceSelectionChanged* delegate, UIDescription* description, IActionPerformer* actionPerformer, const std::string* templateName)
|
||||
: UINavigationDataSource (delegate)
|
||||
, description (description)
|
||||
, actionPerformer (actionPerformer)
|
||||
{
|
||||
headerTitle = "Templates";
|
||||
if (templateName)
|
||||
firstSelectedTemplateName = *templateName;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
CMouseEventResult UITemplatesDataSource::dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser)
|
||||
{
|
||||
if (buttons.isLeftButton ())
|
||||
{
|
||||
if (buttons.isDoubleClick ())
|
||||
{
|
||||
browser->beginTextEdit (CDataBrowser::Cell (row, column), getStringList ()->at (static_cast<uint32_t> (row)).data ());
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
delegate->dbSelectionChanged (row, this);
|
||||
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
||||
}
|
||||
return UINavigationDataSource::dbOnMouseDown (where, buttons, row, column, browser);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplatesDataSource::dbCellTextChanged (int32_t row, int32_t column, UTF8StringPtr newText, CDataBrowser* browser)
|
||||
{
|
||||
auto oldName = getStringList ()->at (static_cast<uint32_t> (row));
|
||||
if (oldName != newText)
|
||||
{
|
||||
for (auto& name : *getStringList ())
|
||||
{
|
||||
if (name == newText)
|
||||
return;
|
||||
}
|
||||
actionPerformer->performTemplateNameChange (oldName.data (), newText);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplatesDataSource::dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* textEditControl, CDataBrowser* browser)
|
||||
{
|
||||
textEditControl->setBackColor (kWhiteCColor);
|
||||
textEditControl->setFontColor (fontColor);
|
||||
textEditControl->setFont (drawFont);
|
||||
textEditControl->setHoriAlign (kLeftText);
|
||||
textEditControl->setTextInset (textInset);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplatesDataSource::dbDrawCell (CDrawContext* context, const CRect& size, int32_t row, int32_t column, int32_t flags, CDataBrowser* browser)
|
||||
{
|
||||
drawRowBackground (context, size, row, flags, browser);
|
||||
drawTriangle (context, size);
|
||||
drawRowString (context, size, row, flags, browser);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void UITemplatesDataSource::dbAttached (CDataBrowser* browser)
|
||||
{
|
||||
UINavigationDataSource::dbAttached (browser);
|
||||
if (getStringList ())
|
||||
{
|
||||
if (firstSelectedTemplateName.empty ())
|
||||
{
|
||||
browser->setSelectedRow (0, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t index = 0;
|
||||
for (auto& name : *getStringList ())
|
||||
{
|
||||
if (name == firstSelectedTemplateName)
|
||||
{
|
||||
browser->setSelectedRow (static_cast<int32_t> (index), true);
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // VSTGUI
|
||||
|
||||
#endif // VSTGUI_LIVE_EDITING
|
||||
Reference in New Issue
Block a user