Initial release
This commit is contained in:
+304
@@ -0,0 +1,304 @@
|
||||
// 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
|
||||
Reference in New Issue
Block a user