305 lines
7.9 KiB
C++
305 lines
7.9 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
|
|
|
|
#pragma once
|
|
|
|
#include "../iuidescription.h"
|
|
|
|
#if VSTGUI_LIVE_EDITING
|
|
|
|
#include "../uiattributes.h"
|
|
#include "../uidescriptionlistener.h"
|
|
#include "../../lib/cdatabrowser.h"
|
|
#include "../../lib/genericstringlistdatabrowsersource.h"
|
|
#include "../../lib/controls/csearchtextedit.h"
|
|
#include "../../lib/controls/cscrollbar.h"
|
|
#include <sstream>
|
|
#include <algorithm>
|
|
|
|
namespace VSTGUI {
|
|
|
|
//----------------------------------------------------------------------------------------------------
|
|
class UIBaseDataSource : public GenericStringListDataBrowserSource, public IControlListener, public UIDescriptionListenerAdapter
|
|
{
|
|
public:
|
|
using StringVector = GenericStringListDataBrowserSource::StringVector;
|
|
|
|
UIBaseDataSource (UIDescription* description, IActionPerformer* actionPerformer, GenericStringListDataBrowserSourceSelectionChanged* delegate = nullptr)
|
|
: GenericStringListDataBrowserSource (0, delegate) , description (description), actionPerformer (actionPerformer)
|
|
{
|
|
description->registerListener (this);
|
|
textInset.x = 4;
|
|
}
|
|
|
|
~UIBaseDataSource () override
|
|
{
|
|
description->unregisterListener (this);
|
|
}
|
|
|
|
void setSearchFieldControl (CSearchTextEdit* searchControl)
|
|
{
|
|
searchField = searchControl;
|
|
searchField->setListener (this);
|
|
}
|
|
|
|
virtual bool add ()
|
|
{
|
|
if (dataBrowser && actionPerformer)
|
|
{
|
|
std::string newName (filterString.empty () ? "New" : filterString.data ());
|
|
if (createUniqueName (newName))
|
|
{
|
|
addItem (newName.data ());
|
|
int32_t row = selectName (newName.data ());
|
|
if (row != -1)
|
|
{
|
|
dbOnMouseDown (CPoint (0, 0), CButtonState (kLButton|kDoubleClick), row, 0, dataBrowser);
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual bool remove ()
|
|
{
|
|
if (dataBrowser && actionPerformer)
|
|
{
|
|
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
|
if (selectedRow != CDataBrowser::kNoSelection)
|
|
{
|
|
removeItem (names.at (static_cast<uint32_t> (selectedRow)).data ());
|
|
dbSelectionChanged (dataBrowser);
|
|
dataBrowser->setSelectedRow (selectedRow);
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
virtual void setFilter (const UTF8String& filter)
|
|
{
|
|
if (filterString != filter)
|
|
{
|
|
filterString = filter;
|
|
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
|
|
std::string selectedName;
|
|
if (selectedRow != CDataBrowser::kNoSelection)
|
|
selectedName = names.at (static_cast<uint32_t> (selectedRow));
|
|
update ();
|
|
if (selectedRow != CDataBrowser::kNoSelection)
|
|
selectName (selectedName.data ());
|
|
}
|
|
}
|
|
|
|
virtual int32_t selectName (UTF8StringPtr name)
|
|
{
|
|
int32_t index = 0;
|
|
for (auto& it : names)
|
|
{
|
|
if (it == name)
|
|
{
|
|
dataBrowser->setSelectedRow (index, true);
|
|
if (delegate)
|
|
delegate->dbSelectionChanged (index, this);
|
|
return index;
|
|
}
|
|
++index;
|
|
}
|
|
return -1;
|
|
}
|
|
protected:
|
|
virtual void getNames (std::list<const std::string*>& names) = 0;
|
|
virtual bool addItem (UTF8StringPtr name) = 0;
|
|
virtual bool removeItem (UTF8StringPtr name) = 0;
|
|
virtual bool performNameChange (UTF8StringPtr oldName, UTF8StringPtr newName) = 0;
|
|
virtual UTF8StringPtr getDefaultsName () = 0;
|
|
|
|
virtual void update ()
|
|
{
|
|
if (textEditControl)
|
|
textEditControl->looseFocus ();
|
|
names.clear ();
|
|
std::list<const std::string*> tmpNames;
|
|
getNames (tmpNames);
|
|
|
|
std::string filter = filterString.getString ();
|
|
std::transform (filter.begin (), filter.end (), filter.begin (), ::tolower);
|
|
|
|
for (auto& name : tmpNames)
|
|
{
|
|
if (!filter.empty ())
|
|
{
|
|
std::string tmp (*name);
|
|
std::transform (tmp.begin (), tmp.end (), tmp.begin (), ::tolower);
|
|
if (tmp.find (filter) == std::string::npos)
|
|
continue;
|
|
}
|
|
if (name->find ("~ ") == 0)
|
|
continue; // don't show static items
|
|
names.emplace_back (UTF8String (*name));
|
|
}
|
|
bool vsbIsVisible = false;
|
|
if (dataBrowser)
|
|
{
|
|
if (auto vsb = dataBrowser->getVerticalScrollbar ())
|
|
vsbIsVisible = vsb->isVisible ();
|
|
}
|
|
setStringList (&names);
|
|
if (dataBrowser)
|
|
{
|
|
if (auto vsb = dataBrowser->getVerticalScrollbar ())
|
|
{
|
|
if (vsb->isVisible() != vsbIsVisible)
|
|
dataBrowser->recalculateLayout ();
|
|
}
|
|
}
|
|
}
|
|
|
|
void beforeUIDescSave (UIDescription* desc) override
|
|
{
|
|
saveDefaults ();
|
|
};
|
|
|
|
void onUIDescriptionUpdate ()
|
|
{
|
|
int32_t selectedRow = dataBrowser ? dataBrowser->getSelectedRow () : CDataBrowser::kNoSelection;
|
|
std::string selectedName;
|
|
if (selectedRow != CDataBrowser::kNoSelection)
|
|
selectedName = names.at (static_cast<uint32_t> (selectedRow));
|
|
update ();
|
|
if (selectedRow != CDataBrowser::kNoSelection)
|
|
selectName (selectedName.data ());
|
|
}
|
|
|
|
virtual void saveDefaults ()
|
|
{
|
|
UTF8StringPtr name = getDefaultsName ();
|
|
if (name)
|
|
{
|
|
auto attributes = description->getCustomAttributes (name, true);
|
|
if (attributes)
|
|
{
|
|
attributes->setAttribute ("FilterString", filterString.getString ());
|
|
if (dataBrowser)
|
|
{
|
|
int32_t selectedRow = dataBrowser->getSelectedRow ();
|
|
attributes->setIntegerAttribute ("SelectedRow", selectedRow);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
virtual void loadDefaults ()
|
|
{
|
|
UTF8StringPtr name = getDefaultsName ();
|
|
if (name)
|
|
{
|
|
auto attributes = description->getCustomAttributes (name, true);
|
|
if (attributes)
|
|
{
|
|
const std::string* str = attributes->getAttributeValue ("FilterString");
|
|
if (str)
|
|
setFilter (str->data ());
|
|
if (dataBrowser)
|
|
{
|
|
int32_t selectedRow;
|
|
if (attributes->getIntegerAttribute("SelectedRow", selectedRow))
|
|
dataBrowser->setSelectedRow (selectedRow, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void dbAttached (CDataBrowser* browser) override
|
|
{
|
|
GenericStringListDataBrowserSource::dbAttached (browser);
|
|
update ();
|
|
loadDefaults ();
|
|
if (searchField)
|
|
searchField->setText (filterString);
|
|
}
|
|
|
|
void dbRemoved (CDataBrowser* browser) override
|
|
{
|
|
saveDefaults ();
|
|
GenericStringListDataBrowserSource::dbRemoved (browser);
|
|
}
|
|
|
|
void valueChanged (CControl* control) override
|
|
{
|
|
CTextEdit* edit = dynamic_cast<CTextEdit*>(control);
|
|
if (edit)
|
|
setFilter (edit->getText ());
|
|
}
|
|
|
|
bool createUniqueName (std::string& name, int32_t count = 0)
|
|
{
|
|
std::stringstream str;
|
|
str << name;
|
|
if (count)
|
|
{
|
|
str << ' ';
|
|
str << count;
|
|
}
|
|
for (auto& it : names)
|
|
{
|
|
if (it == str.str ())
|
|
return createUniqueName (name, count+1);
|
|
}
|
|
name = str.str ();
|
|
return true;
|
|
}
|
|
|
|
CMouseEventResult dbOnMouseDown (const CPoint& where, const CButtonState& buttons, int32_t row, int32_t column, CDataBrowser* browser) override
|
|
{
|
|
if (buttons.isLeftButton () && buttons.isDoubleClick ())
|
|
{
|
|
browser->beginTextEdit (CDataBrowser::Cell (row, column), names.at (static_cast<uint32_t> (row)).data ());
|
|
}
|
|
return kMouseDownEventHandledButDontNeedMovedOrUpEvents;
|
|
}
|
|
|
|
void dbCellTextChanged (int32_t _row, int32_t column, UTF8StringPtr newText, CDataBrowser* browser) override
|
|
{
|
|
textEditControl = nullptr;
|
|
if (_row < 0 || _row >= static_cast<int32_t> (names.size ()))
|
|
return;
|
|
auto row = static_cast<size_t> (_row);
|
|
for (auto& name : names)
|
|
{
|
|
if (name == newText)
|
|
return;
|
|
}
|
|
auto& currentName = names.at (row);
|
|
if (performNameChange (currentName.data (), newText))
|
|
{
|
|
if (selectName (newText) == -1 && row < names.size ())
|
|
selectName (names.at (row).data ());
|
|
}
|
|
}
|
|
|
|
void dbCellSetupTextEdit (int32_t row, int32_t column, CTextEdit* control, CDataBrowser* browser) override
|
|
{
|
|
textEditControl = control;
|
|
textEditControl->setBackColor (kWhiteCColor);
|
|
textEditControl->setFontColor (fontColor);
|
|
textEditControl->setFont (drawFont);
|
|
textEditControl->setHoriAlign (textAlignment);
|
|
textEditControl->setTextInset (textInset);
|
|
}
|
|
|
|
SharedPointer<UIDescription> description;
|
|
SharedPointer<CSearchTextEdit> searchField;
|
|
SharedPointer<CTextEdit> textEditControl;
|
|
IActionPerformer* actionPerformer;
|
|
|
|
StringVector names;
|
|
UTF8String filterString;
|
|
};
|
|
|
|
} // VSTGUI
|
|
|
|
#endif // VSTGUI_LIVE_EDITING
|