Initial release

This commit is contained in:
civ
2026-08-16 18:24:52 +07:00
commit 876886a39a
13244 changed files with 2353959 additions and 0 deletions
@@ -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